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

63 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:
```json
"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.