# component_architecture_airgap.md - **Stella Ops AirGap** (2025Q4) > Air-gapped deployment controller, importer, and time anchor services. > **Scope.** Implementation-ready architecture for **AirGap**: the controller, importer, and time anchor subsystems enabling StellaOps operation in disconnected/air-gapped environments with sealed-mode state management. --- ## 0) Mission & boundaries **Mission.** Enable **fully offline, air-gapped operation** of StellaOps with sealed-mode state management, bundle-based updates, and cryptographic time anchors for staleness detection. **Boundaries.** * AirGap **does not** connect to external networks in sealed mode. * AirGap **does not** generate vulnerability data. It imports pre-packaged bundles. * Bundle verification is **mandatory**. Unsigned or tampered bundles are rejected. * Time anchors are **cryptographically verified** using Roughtime or RFC3161. --- ## 1) Solution & project layout ``` src/AirGap/ ├─ StellaOps.AirGap.Controller/ # Seal/unseal state machine, status APIs │ ├─ Services/ │ │ ├─ ISealingController.cs # Sealing state interface │ │ ├─ SealingController.cs # State machine implementation │ │ └─ StatusService.cs # Health and status endpoints │ └─ Models/ │ ├─ SealState.cs # sealed | unsealed | transitioning │ └─ SealTransition.cs # Transition metadata │ ├─ StellaOps.AirGap.Importer/ # Bundle verification and import │ ├─ Services/ │ │ ├─ IBundleVerifier.cs # DSSE/TUF verification │ │ ├─ BundleVerifier.cs # Verification implementation │ │ ├─ ICatalogImporter.cs # Catalog update interface │ │ └─ CatalogImporter.cs # Import orchestration │ └─ Models/ │ ├─ ImportBundle.cs # Bundle metadata │ └─ ImportResult.cs # Import outcome │ ├─ StellaOps.AirGap.Time/ # Time anchor verification │ ├─ Services/ │ │ ├─ ITimeAnchorService.cs # Time anchor interface │ │ ├─ RoughtimeAnchor.cs # Roughtime implementation │ │ └─ Rfc3161Anchor.cs # RFC3161 timestamp │ └─ Models/ │ ├─ TimeAnchor.cs # Anchor record │ └─ StalenessResult.cs # Staleness calculation │ ├─ StellaOps.AirGap.Policy/ # Air-gap specific policy rules │ ├─ StellaOps.AirGap.Policy/ │ ├─ StellaOps.AirGap.Policy.Analyzers/ │ └─ StellaOps.AirGap.Policy.Tests/ │ ├─ __Libraries/ │ ├─ StellaOps.AirGap.Bundle/ # Bundle format and parsing │ └─ StellaOps.AirGap.Persistence/ # State persistence │ ├─ __Tests/ # Test projects │ ├─ scripts/ # Operational scripts │ └─ AGENTS.md # Guild charter ``` --- ## 2) External dependencies * **PostgreSQL** - State persistence, import history * **Authority** - Scope enforcement (`airgap:seal`, `airgap:status:read`) * **Cryptography** - Bundle signature verification * **Object storage** - Bundle staging and quarantine --- ## 3) Contracts & data model ### 3.1 Seal State ```csharp public enum SealState { Unsealed, // Normal operation, network allowed Transitioning, // Sealing or unsealing in progress Sealed // Air-gapped, no network egress } public sealed record SealStatus { public required SealState State { get; init; } public required DateTimeOffset LastTransition { get; init; } public required string TransitionedBy { get; init; } public DateTimeOffset? SealedSince { get; init; } public TimeAnchor? LastTimeAnchor { get; init; } } ``` ### 3.2 Import Bundle ```json { "bundleId": "airgap-2025-01-15-abc123", "bundleType": "advisory-update", "version": "2025.01.15.001", "createdAt": "2025-01-15T10:30:00Z", "contents": [ { "type": "concelier-snapshot", "digest": "sha256:abc123...", "path": "data/concelier-2025-01-15.tar.zst" }, { "type": "trivy-db", "digest": "sha256:def456...", "path": "data/trivy-db-2025-01-15.tar.gz" } ], "signature": { "keyId": "sha256:sigkey...", "algorithm": "ecdsa-p256", "value": "base64..." }, "timeAnchor": { "source": "roughtime", "timestamp": "2025-01-15T10:25:00Z", "proof": "base64..." } } ``` ### 3.3 Time Anchor ```csharp public sealed record TimeAnchor { public required string Source { get; init; } // roughtime, rfc3161 public required DateTimeOffset Timestamp { get; init; } public required byte[] Proof { get; init; } // Cryptographic proof public required string[] Servers { get; init; } // Servers used public required bool Verified { get; init; } } public sealed record StalenessResult { public required TimeSpan Age { get; init; } public required bool IsStale { get; init; } public required TimeSpan StalenessThreshold { get; init; } public string? Warning { get; init; } } ``` --- ## 4) REST API (Controller + Importer) All under `/api/v1/airgap`. Auth: **OpTok** with airgap scopes. ### Controller APIs ``` GET /status → { state, lastTransition, timeAnchor } POST /seal → { transitionId, status: "transitioning" } POST /unseal → { transitionId, status: "transitioning" } GET /transitions/{id} → { transition details } ``` ### Importer APIs ``` POST /bundles/upload multipart → { bundleId, status: "pending" } POST /bundles/{id}/verify → { valid: bool, details } POST /bundles/{id}/import → { importId, status: "importing" } GET /bundles/{id}/status → { status, progress, errors } GET /bundles → { bundles: BundleSummary[] } ``` ### Time APIs ``` GET /time/anchor → { anchor: TimeAnchor, staleness } POST /time/anchor { source, proof } → { anchor, verified } GET /time/staleness → { staleness: StalenessResult } ``` --- ## 5) Configuration (YAML) ```yaml AirGap: Controller: InitialState: "unsealed" TransitionTimeoutSeconds: 300 RequireApproval: true Importer: StagingPath: "/data/airgap/staging" QuarantinePath: "/data/airgap/quarantine" MaxBundleSizeMb: 10240 TrustRoots: - "sha256:abc123..." # StellaOps signing key AllowedBundleTypes: - "advisory-update" - "trivy-db" - "policy-pack" Time: StalenessThresholdHours: 168 # 7 days RoughtimeServers: - "roughtime.cloudflare.com" - "roughtime.google.com" Rfc3161Servers: - "http://timestamp.digicert.com" RequireMultipleServers: true MinServerQuorum: 2 Quarantine: TtlDays: 30 MaxQuotaMb: 51200 Postgres: ConnectionString: "Host=postgres;Database=airgap;..." ``` --- ## 6) Sealing State Machine ``` ┌──────────────┐ │ Unsealed │ └──────┬───────┘ │ seal() ▼ ┌──────────────┐ │ Transitioning│ └──────┬───────┘ │ complete ▼ ┌──────────────┐ │ Sealed │ └──────┬───────┘ │ unseal() ▼ ┌──────────────┐ │ Transitioning│ └──────┬───────┘ │ complete ▼ ┌──────────────┐ │ Unsealed │ └──────────────┘ ``` ### Transition Actions **Seal transition:** 1. Verify pending work is complete 2. Capture final time anchor 3. Disable network egress 4. Update state to Sealed **Unseal transition:** 1. Verify network connectivity 2. Refresh time anchor 3. Enable network egress 4. Update state to Unsealed --- ## 7) Bundle Import Flow ``` 1. Upload bundle to staging └─ Validate manifest structure 2. Verify bundle ├─ Check signature against trust roots ├─ Verify content digests └─ Validate time anchor 3. Import bundle ├─ Extract contents ├─ Update target catalogs (Concelier, Trivy, etc.) └─ Record import in history 4. Cleanup or quarantine ├─ Success: Remove from staging └─ Failure: Move to quarantine with TTL ``` --- ## 8) Security & compliance * **Signature verification**: All bundles must be signed * **Trust roots**: Configurable trust root keys * **Quarantine**: Failed imports isolated with TTL * **Audit trail**: All imports and state changes logged * **Scope enforcement**: Authority scopes for all operations * **Rollback prevention**: Version monotonicity enforced --- ## 9) Performance targets * **Seal/unseal transition**: < 30s * **Bundle verification**: < 10s for 1GB bundle * **Bundle import**: < 60s for typical advisory update * **Time anchor verification**: < 5s --- ## 10) Observability **Metrics:** * `airgap.state{state=sealed|unsealed|transitioning}` * `airgap.bundles.imported_total{type,result}` * `airgap.bundles.quarantined_total{reason}` * `airgap.time.staleness_seconds` * `airgap.time.anchor_age_seconds` **Tracing:** Spans for transitions, imports, verifications. --- ## 11) Testing matrix * **Seal/unseal tests**: State machine transitions * **Bundle tests**: Verification and import flows * **Quarantine tests**: Failed import handling * **Time tests**: Staleness calculations, anchor verification * **Integration tests**: Full offline workflow simulation --- ## Related Documentation * Evidence reconciliation: `./evidence-reconciliation.md` * Exporter coordination: `./exporter-cli-coordination.md` * Mirror DSSE plan: `./mirror-dsse-plan.md` * Offline Kit: `../../24_OFFLINE_KIT.md` * Time anchor schema: `../../airgap/time-anchor-schema.md`