up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
sdk-generator-smoke / sdk-smoke (push) Has been cancelled
SDK Publish & Sign / sdk-publish (push) Has been cancelled
api-governance / spectral-lint (push) Has been cancelled
oas-ci / oas-validate (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-27 07:46:56 +02:00
parent d63af51f84
commit ea970ead2a
302 changed files with 43161 additions and 1534 deletions

View File

@@ -9,6 +9,7 @@ Scope: Define the baseline project skeleton, APIs, telemetry, and staleness fiel
- 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.
- Tests: Mongo2Go-backed store tests live under `tests/AirGap`; see `tests/AirGap/README.md` for OpenSSL shim note.
## 2) State model
- Persistent document `airgap_state` (Mongo):
@@ -34,16 +35,24 @@ Scope: Define the baseline project skeleton, APIs, telemetry, and staleness fiel
## 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}`.
- `{sealed, policy_hash, time_anchor:{source, anchored_at, drift_seconds}, staleness:{age_seconds, warning_seconds, breach_seconds, seconds_remaining}, 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`.
- Metrics (Prometheus/OpenTelemetry): counters `airgap_seal_total`, `airgap_unseal_total`, `airgap_startup_blocked_total`; gauges `airgap_time_anchor_age_seconds`, `airgap_staleness_budget_seconds`.
- Timeline events (Observability stream): `airgap.sealed`, `airgap.unsealed` with correlation_id.
### Startup diagnostics wiring (57-001)
- Config section `AirGap:Startup` now drives sealed-mode startup validation:
- `TenantId` (default `default`).
- `EgressAllowlist` (array; required when sealed).
- `Trust:RootJsonPath`, `Trust:SnapshotJsonPath`, `Trust:TimestampJsonPath` (all required when sealed; parsed via TUF validator).
- `Rotation:ActiveKeys`, `Rotation:PendingKeys`, `Rotation:ApproverIds` (base64-encoded keys; dual approval enforced when pending keys exist).
- Failures raise `sealed-startup-blocked:<reason>` and increment `airgap_startup_blocked_total{reason}`.
## 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).