Files
git.stella-ops.org/docs/airgap/controller.md
StellaOps Bot 7503c19b8f Add determinism tests for verdict artifact generation and update SHA256 sums script
- Implemented comprehensive tests for verdict artifact generation to ensure deterministic outputs across various scenarios, including identical inputs, parallel execution, and change ordering.
- Created helper methods for generating sample verdict inputs and computing canonical hashes.
- Added tests to validate the stability of canonical hashes, proof spine ordering, and summary statistics.
- Introduced a new PowerShell script to update SHA256 sums for files, ensuring accurate hash generation and file integrity checks.
2025-12-24 02:17:34 +02:00

101 lines
3.6 KiB
Markdown

# AirGap Controller
The AirGap Controller is the tenant-scoped state keeper for sealed-mode operation. It records whether an installation is sealed, what policy hash is active, which time anchor is in force, and what staleness budgets apply.
For workflow context, start at `docs/airgap/overview.md` and `docs/airgap/airgap-mode.md`.
## Responsibilities
- Maintain the current AirGap state per tenant (sealed/unsealed, policy hash, time anchor, staleness budgets).
- Provide a deterministic, auditable status snapshot for operators and automation.
- Enforce sealed/unsealed transitions via Authority scopes.
- Emit telemetry signals suitable for dashboards and forensics timelines.
Non-goals:
- Bundle signature validation and import staging (owned by the importer; see `docs/airgap/importer.md`).
- Cryptographic signing (Signer/Attestor).
## API
Base route group: `/system/airgap` (requires authorization).
### `GET /system/airgap/status`
Required scope: `airgap:status:read`
Response: `AirGapStatusResponse` (current state + staleness evaluation).
Notes:
- Tenant routing uses `x-tenant-id` (defaults to `default` if absent).
- `driftSeconds` and `secondsRemaining` are derived from the active time anchor and staleness budget evaluation.
- `contentStaleness` contains per-category staleness evaluations (clients should treat keys as case-insensitive).
### `POST /system/airgap/seal`
Required scope: `airgap:seal`
Body: `SealRequest`
- `policyHash` (required): binds the sealed state to a specific policy revision.
- `timeAnchor` (optional): time anchor record (from the AirGap Time service).
- `stalenessBudget` (optional): default staleness budget.
- `contentBudgets` (optional): per-category staleness budgets (e.g., `advisories`, `vex`, `scanner`).
Behavior:
- Rejects requests missing `policyHash` (`400 { \"error\": \"policy_hash_required\" }`).
- Records the sealed state and returns an updated status snapshot.
### `POST /system/airgap/unseal`
Required scope: `airgap:seal`
Behavior:
- Clears the sealed state and returns an updated status snapshot.
- Staleness is returned as `Unknown` after unseal (clients should treat this as "not applicable").
### `POST /system/airgap/verify`
Required scope: `airgap:verify`
Purpose: verify replay / bundle verification requests against the currently active AirGap state.
## State model (per tenant)
Canonical fields captured by the controller (see `src/AirGap/StellaOps.AirGap.Controller`):
- `tenantId`
- `sealed`
- `policyHash` (nullable)
- `timeAnchor` (`TimeAnchor`, may be `Unknown`)
- `stalenessBudget` (`StalenessBudget`)
- `contentBudgets` (`Dictionary<string, StalenessBudget>`)
- `driftBaselineSeconds` (baseline used to keep drift evaluation stable across transitions)
- `lastTransitionAt` (UTC)
Determinism requirements:
- Use UTC timestamps only.
- Use ordinal comparisons for keys and stable serialization settings for JSON responses.
- Never infer state from wall-clock behavior other than the injected `TimeProvider`.
## Telemetry
The controller emits:
- Structured logs: `airgap.status.read`, `airgap.sealed`, `airgap.unsealed`, `airgap.verify` (include `tenant_id`, `policy_hash`, and drift/staleness).
- Metrics: `airgap_seal_total`, `airgap_unseal_total`, `airgap_status_read_total`, and gauges for drift/budget/remaining seconds.
- Timeline events (optional): `airgap.sealed`, `airgap.unsealed`, `airgap.staleness.warning`, `airgap.staleness.breach`.
## References
- `docs/airgap/overview.md`
- `docs/airgap/sealed-startup-diagnostics.md`
- `docs/airgap/staleness-and-time.md`
- `docs/airgap/time-api.md`
- `docs/airgap/importer.md`