# Air-Gapped Time Anchors & Staleness Budgets > **Audience:** AirGap Time/Controller/Policy guilds, DevOps > > **Purpose:** Document how air-gapped installations maintain trusted time anchors, compute staleness windows, and expose drift telemetry. ## 1. Overview Air-gapped clusters cannot contact external NTP servers. StellaOps distributes signed time anchor tokens alongside mirror bundles so services can reason about freshness and seal state without external clocks. Key goals: - Provide deterministic time anchors signed by the mirror authority. - Track drift and staleness budgets for scanner reports, advisories, and runtime evidence. - Surface warnings to operators (UI/CLI/Notifier) before anchors expire. ## 2. Components | Component | Responsibility | |-----------|----------------| | AirGap Controller | Stores the active `time_anchor` token and enforces sealed/unsealed transitions. | | AirGap Time service | Parses anchor bundles, validates signatures, records monotonic offsets, and exposes drift metrics. | | Scheduler & Policy Engine | Query the time service to gate scheduled runs and evidence evaluation. | | UI / Notifier | Display remaining budget and raise alerts when thresholds are crossed. | ## 3. Time Anchor Tokens - Distributed as part of mirror/offline bundles (`airgap/time-anchor.json`). - Signed with mirror key; includes issuance time, validity window, and monotonic counter. - Validation steps: 1. Verify detached signature. 2. Compare bundle counter to previously applied anchors. 3. Persist anchor with checksum for audit. ## 4. Staleness Budgets Each tenant/configuration defines budgets: - **Advisory freshness** – maximum age of advisory/VEX data before rescans are required. - **Scanner evidence** – acceptable drift between last scan and current anchor. - **Runtime posture** – tolerated drift before Notifier raises incidents. AirGap Time calculates drift = `now(monotonic) - anchor.issued_at` and exposes: - `/api/v1/time/status` – current anchor metadata, drift, remaining budget. - `/api/v1/time/metrics` – Prometheus counters (`airgap_anchor_drift_seconds`, `airgap_anchor_expiry_seconds`). ## 5. Operator Workflow 1. Import new mirror bundle (includes time anchor). 2. AirGap Time validates and stores the anchor; Controller records audit entry. 3. Services subscribe to change events and recompute drift. 4. UI displays badge (green/amber/red) based on thresholds. 5. Notifier sends alerts when drift exceeds warning or expiry limits. ## 6. Implementation Notes - Use `IAirGapTimeStore` for persistence; default implementation relies on Mongo with tenant partitioning. - Ensure deterministic JSON serialization (UTC ISO-8601 timestamps, sorted keys). - Test vectors located under `src/AirGap/StellaOps.AirGap.Time/fixtures/`. - For offline testing, simulate monotonic clock via `ITestClock` to avoid system clock drift in CI. ## 7. References - `docs/airgap/airgap-mode.md` - `src/AirGap/StellaOps.AirGap.Time` - `src/AirGap/StellaOps.AirGap.Controller` - `src/AirGap/StellaOps.AirGap.Policy`