AEGIS — air-gapped change-validation architecture A proposed network-config change travels along a teal current through a containerlab digital-twin gate where BGP sessions reconverge, then a deterministic verification chain — guard, batfish, diff, compliance — stamps it before an amber sha256 wax seal locks onto a PCI/SOC2/NIST evidence badge, all inside a dashed air-gapped perimeter that nothing crosses outward. AIR-GAPPED intent / config generate (LLM) containerlab twin spawn · apply · BGP converge · diff guard precheck batfish static diff risk tier compliance PCI·SOC2·NIST deterministic verification — no AI after this point PCI DSS v4 SOC2 CC8.1 NIST CM-3 sha256 egress:none sealed evidence bundle tamper-evident · examiner-ready PDF AEGIS Air-gapped Evidence-Grade Inspection System preflight every change against a real digital twin — the LLM proposes inside the wall, only a sealed badge ever leaves
Apache-2.0 v0.1.0 · Phase 2 egress none Python 3.10+

AEGIS

Air-gapped Evidence-Grade Inspection System — preflight network changes against a real digital twin, entirely inside your perimeter.

No cloud. No data egress. Ever. A self-hosted LLM proposes config inside the wall; the twin verifies; a human authorizes; only a sealed compliance badge leaves.

0invariant runs
0invariants
0violations
0concurrent runs
0test suites
0cmd corpus
Overview

The air-gapped answer to cloud-by-architecture

AEGIS is a self-hosted Python tool that preflights network changes against a real containerlab digital twin entirely inside an air-gapped perimeter, then emits a tamper-evident, framework-mapped, examiner-ready evidence bundle.

It is the air-gapped answer to cloud-by-architecture tools like Forward Predict and NetPilot, serving regulated networks that legally cannot send topology or config off-prem.

It runs a guarded-agentic loop — a self-hosted LLM proposes config and every step afterward is deterministic verification — so the LLM proposes inside the wall, the twin verifies, a human authorizes, and only a sealed compliance badge ever leaves.

Key Features

Guarded, verified, sealed

Every capability traces back to a single invariant: the LLM proposes, the pipeline deterministically verifies, and nothing crosses the wall but a sealed badge.

Architecture

Inside the perimeter

Everything runs inside an air-gapped perimeter. The operator submits a change, a self-hosted Qwen3 proposes config, a throwaway containerlab twin verifies it, and an auditor consumes the sealed PDF — no actor or line ever reaches outside the wall. The codebase splits into four layers: an orchestrator that drives the loop, backends that abstract where work runs, evidence that seals and renders the output, and a promote layer that gates a verified bundle toward production.

System Context flowchart

No actor or config line ever reaches outside the air-gapped wall; the operator submits a change, a self-hosted Qwen3 proposes config, a throwaway containerlab twin verifies it, and only a sealed PDF badge leaves to the auditor.

flowchart LR
    OP([Operator]):::actor
    APP([Approver]):::actor
    AUD([Auditor]):::actor
    subgraph PERIM["Air-gapped perimeter - egress none"]
        direction LR
        AEGIS{{"AEGIS preflight + evidence engine"}}:::core
        QWEN[/"Self-hosted Qwen3 - only AI dep"/]:::ai
        TWIN[("containerlab twin - multi-vendor")]:::twin
        DCN["DCN_Network_Tool :5757"]:::svc
    end
    PROD[("Production devices")]:::prod
    OP -->|intent or config| AEGIS
    APP -->|approval token| AEGIS
    AEGIS -->|generate_config| QWEN
    AEGIS -->|spawn apply converge| TWIN
    AEGIS -.->|live tier| DCN
    AEGIS -->|sealed PDF bundle| AUD
    AEGIS -.->|gated dry-run| PROD
    classDef actor fill:#475569,stroke:#94a3b8,color:#f8fafc
    classDef core fill:#0d9488,stroke:#2dd4bf,color:#f0fdfa
    classDef ai fill:#7c3aed,stroke:#a78bfa,color:#faf5ff
    classDef twin fill:#059669,stroke:#34d399,color:#ecfdf5
    classDef svc fill:#0ea5e9,stroke:#38bdf8,color:#f0f9ff
    classDef prod fill:#9f1239,stroke:#fb7185,color:#fff1f2
    class PERIM core
Container & Component Map flowchart

The orchestrator drives the loop, the backends abstract where work runs, evidence seals and renders the output, and promote gates a verified bundle toward production behind a dry-run connector.

flowchart TB
    UI["serve.py + ui/preflight_screen.html"]:::edge
    subgraph ORCH["core/orchestrator"]
        PIPE["pipeline.py run_preflight"]:::core
        GUARD["guards.py precheck + risk_tier"]:::core
        ROLL["rollback.py build_rollback_plan"]:::core
    end
    subgraph BACK["core/backends Protocol"]
        BASE["base.py Backend Protocol"]:::proto
        SIM["simulator.py seeded"]:::svc
        HTTP["http_backend.py :5757"]:::svc
    end
    subgraph EVID["evidence"]
        BUND["bundler.py sha256 seal"]:::data
        COMP["compliance.py crosswalk"]:::accent
        PDF["pdf.py examiner PDF"]:::accent
    end
    subgraph PROM["core/promote"]
        GATE["gate.py G1-G4"]:::accent
        CONN["connectors.py DryRun"]:::edge
    end
    UI --> PIPE
    PIPE --> GUARD
    PIPE --> BASE
    BASE --> SIM
    BASE --> HTTP
    PIPE --> COMP
    PIPE --> ROLL
    PIPE --> BUND
    BUND --> PDF
    BUND --> GATE
    GATE --> CONN
    classDef edge fill:#475569,stroke:#94a3b8,color:#f8fafc
    classDef core fill:#0d9488,stroke:#2dd4bf,color:#f0fdfa
    classDef proto fill:#7c3aed,stroke:#a78bfa,color:#faf5ff
    classDef svc fill:#0ea5e9,stroke:#38bdf8,color:#f0f9ff
    classDef data fill:#059669,stroke:#34d399,color:#ecfdf5
    classDef accent fill:#d97706,stroke:#fbbf24,color:#fffbeb
How it works

One preflight run, end to end

The guard layer prechecks before any twin is spawned, the backend proposes and verifies against a throwaway twin, and the bundler seals the result — the twin is always torn down in a finally block.

Primary Preflight Sequence sequenceDiagram
sequenceDiagram
    autonumber
    actor Op as Operator
    participant Srv as serve.py
    participant Pipe as run_preflight
    participant G as guards
    participant B as Backend
    participant Ev as bundler
    Op->>Srv: POST /api/preflight/run intent, lab, frameworks
    Srv->>Pipe: run_preflight(SimulatorBackend)
    Pipe->>G: precheck_intent
    alt unsafe input
        G-->>Srv: PreflightError to HTTP 400
    else valid
        Pipe->>B: generate_config (only AI step)
        Pipe->>B: batfish_check static analysis
        Pipe->>B: spawn_twin + apply_and_converge
        Pipe->>B: state_diff routes and sessions
        Pipe->>G: risk_tier + approval_required
        Pipe->>Ev: build_bundle sha256 seal, egress none
        Note over Pipe,B: finally teardown_twin always
        Ev-->>Srv: sealed JSON bundle
        Srv-->>Op: bundle plus optional PDF
    end
Verdict & Promotion-Gate Decision Tree stateDiagram-v2

The verdict resolves to blocked, needs_approval, or ship_ready from batfish errors, twin convergence, and BGP regression; a promotable bundle then passes the four-rule Phase 2 gate, dry-run by default.

stateDiagram-v2
    [*] --> Verdict
    Verdict --> Blocked: batfish errors or BGP regression
    Verdict --> NeedsApproval: medium or high risk
    Verdict --> ShipReady: clean and low risk
    Blocked --> [*]
    NeedsApproval --> Gate: approver + token
    ShipReady --> Gate
    state Gate {
        [*] --> G1
        G1 --> G2: integrity re-verified
        G2 --> G3: verdict promotable
        G3 --> G4: approval token valid
        G4 --> DryRun: safe default
        G4 --> Live: explicit opt-in
    }
    Gate --> Record: sealed promotion record
    Record --> [*]

The deterministic pipeline, step by step

Tech Stack

Pure-stdlib core, no cloud

A backend-agnostic Python core, a single self-hosted LLM as the only AI dependency, and a real containerlab twin — assembled so an air-gapped profile can run with network_mode: none.

Components

Modules & responsibilities

Each module maps to a real file in the repo. The orchestrator drives the loop, guards stay pure and auditable, backends abstract where work runs, and evidence seals and renders the proof.

Quickstart

Run it inside your perimeter

The community sim tier needs zero external dependencies. Bring up the dashboard, or carry a signed Docker tar across the gap and run fully air-gapped.

Docker — fastest path
docker compose up                 # then open http://localhost:8088/preflight
Python — local sim tier
pip install -r requirements.txt
python -m aegis.serve             # from the directory ABOVE aegis/
Air-gapped offline install
docker compose build && docker save aegis:local -o aegis-local.tar   # online, once
docker load -i aegis-local.tar
docker compose -f docker-compose.yml -f docker-compose.airgap.yml up  # network_mode: none
Test suites
python -m aegis.tests.stress_test 25000      # pipeline invariants (8, adversarial)
python -m aegis.tests.contract_test          # HttpBackend parsers vs :5757 shapes
python -m aegis.tests.pdf_test               # evidence PDF validity
python -m aegis.tests.promote_test           # Phase 2 approval-gate safety