Files
git.stella-ops.org/docs/airgap/controller-scaffold.md
StellaOps Bot d63af51f84
Some checks failed
api-governance / spectral-lint (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
devportal-offline / build-offline (push) Has been cancelled
up
2025-11-26 20:23:28 +02:00

3.6 KiB
Raw Blame History

AirGap Controller Scaffold (Draft) — PREP-AIRGAP-CTL-56-001/002/57-001/57-002/58-001

Status: Draft (2025-11-20) Owners: AirGap Controller Guild · Observability Guild · AirGap Time Guild · DevOps Guild Scope: Define the baseline project skeleton, APIs, telemetry, and staleness fields needed to unblock controller tasks 56-001 through 58-001.

1) Project layout

  • Project: src/AirGap/StellaOps.AirGap.Controller (net10.0, minimal API host).
  • Tests: tests/AirGap/StellaOps.AirGap.Controller.Tests with xunit + deterministic time provider.
  • Shared contracts: DTOs under Endpoints/Contracts, domain state under Domain/AirGapState.cs.
  • Persistence: in-memory store by default; Mongo store activates when AirGap:Mongo:ConnectionString is set.

2) State model

  • Persistent document airgap_state (Mongo):
    • id (const singleton), tenant_id, sealed (bool), policy_hash, time_anchor (nullable), last_transition_at (UTC), staleness_budget_seconds (int?, optional per bundle), notes.
    • Index on {tenant_id}; unique on singleton within tenant.
  • In-memory cache with monotonic timestamp to avoid stale reads; cache invalidated on transitions.

Mongo wiring (optin)

  • Config section:
"AirGap": {
  "Mongo": {
    "ConnectionString": "mongodb://localhost:27017",
    "Database": "stellaops_airgap",
    "Collection": "airgap_state"
  }
}
  • The DI extension AddAirGapController chooses Mongo when ConnectionString is present; otherwise falls back to in-memory.
  • Collection index: unique on {tenant_id, id} to enforce singleton per tenant.

3) Endpoints (56-002 baseline)

  • GET /system/airgap/status → returns current state + staleness summary:
    • {sealed, policy_hash, time_anchor:{source, anchored_at, drift_seconds}, staleness:{seconds_remaining?, budget_seconds?}, last_transition_at}.
  • POST /system/airgap/seal → body {policy_hash, time_anchor?, staleness_budget_seconds?}; requires Authority scopes airgap:seal + effective:write.
  • POST /system/airgap/unseal → requires airgap:seal.
  • Validation: reject seal if missing policy_hash or time anchor when platform requires sealed mode.

4) Telemetry (57-002)

  • Structured logs: airgap.sealed, airgap.unsealed, airgap.status.read with tenant_id, policy_hash, time_anchor_source, drift_seconds.
  • Metrics (Prometheus/OpenTelemetry): counters airgap_seal_total, airgap_unseal_total; gauges airgap_time_anchor_drift_seconds, airgap_staleness_budget_seconds.
  • Timeline events (Observability stream): airgap.sealed, airgap.unsealed with correlation_id.

5) Staleness & time (58-001)

  • Staleness computation: drift_seconds = now_utc - time_anchor.anchored_at; seconds_remaining = max(0, staleness_budget_seconds - drift_seconds).
  • Time anchors accept Roughtime or RFC3161 token parsed via AirGap Time component (imported service).
  • Status response includes drift and remaining budget; sealed mode refuses to run if budget exceeded.

6) Determinism & offline rules

  • No external network calls; time source injected IClock seeded in tests.
  • All timestamps RFC3339 UTC; responses sorted properties (serializer config).

7) Open decisions

  • Final scopes list (Authority) for status read vs seal/unseal.
  • Whether to require dual authorization for seal (two-man rule) in sealed environments.
  • Retention/rotation policy for airgap_state audit trail (append-only vs mutation).

8) Handoff

This document satisfies PREP-AIRGAP-CTL-56-001 through 58-001. Update once Authority scopes and time-anchor token format are finalized; then promote to v1 schema doc and wire tests accordingly.