AirGap Time API
The AirGap Time service tracks trusted time in sealed, air-gapped deployments. It ingests signed time anchors (Roughtime or RFC 3161 tokens), verifies them against sealed trust roots, and reports anchor freshness so that downstream gates can fail closed when time drifts too far. This reference documents its HTTP surface, configuration, and startup behaviour; it is written for operators and integrators.
Related guides: Time Anchor Trust Roots (trust-root bundle format) and Staleness and time (the freshness model).
Endpoints
POST /api/v1/time/anchor- Auth: requires a StellaOps access token with
airgap:seal. - Tenant: the effective tenant comes from the
stellaops:tenantclaim. If the bodytenantIdis supplied, it must match the claim or the request fails withtenant-mismatch. - Body (JSON):
tenantId(string, required)hexToken(string, required) — hex-encoded Roughtime or RFC 3161 token.format(string/enum, required) -RoughtimeorRfc3161.trustRootKeyId(string, optional local harness override only)trustRootAlgorithm(string, optional local harness override only)trustRootPublicKeyBase64(string, optional local harness override only) — public key (Ed25519 for Roughtime, RSA for RFC 3161).warningSeconds(number, optional)breachSeconds(number, optional)
- Production trust roots: loaded from sealed/configured trust-root files or stores. Request-supplied trust roots are rejected with
request-supplied-trust-roots-disabled. - Response:
TimeStatusDto(anchor + staleness snapshot) or 400 with reason (token-hex-invalid,roughtime-signature-invalid,rfc3161-verify-failed:*, etc.). - Example:
curl -s -X POST http://localhost:5000/api/v1/time/anchor \ -H 'authorization: Bearer <token-with-airgap:seal>' \ -H 'content-type: application/json' \ -d '{ "tenantId":"tenant-default", "hexToken":"01020304deadbeef", "format":"Roughtime", "warningSeconds":3600, "breachSeconds":7200 }'
- Auth: requires a StellaOps access token with
GET /api/v1/time/status?tenantId=<id>- Auth: requires a StellaOps access token with
airgap:status:read. - Tenant: the effective tenant comes from the
stellaops:tenantclaim. IftenantIdis supplied, it must match the claim. - Returns
TimeStatusDtowith anchor metadata and staleness flags.
- Auth: requires a StellaOps access token with
GET /healthz/ready- Health check:
Healthywhen anchor present and not stale;Degradedwhen warning threshold crossed;Unhealthywhen missing/stale. Uses configured tenant/budgets.
- Health check:
Config
appsettings.json (see docs/modules/airgap/schemas/time-config-sample.json):
{
"AirGap": {
"TenantId": "tenant-default",
"Staleness": {
"WarningSeconds": 3600,
"BreachSeconds": 7200
},
"TrustRootFile": "/etc/stellaops/airgap/time-anchor-trust-roots.json",
"AllowUntrustedAnchors": false,
"AllowRequestSuppliedTrustRoots": false
}
}
Startup validation
- The host runs sealed-mode validation at startup using the configured tenant and budgets.
- Fails closed with
sealed-startup-blocked:<reason>if anchor is missing/stale or budgets mismatch.
Notes
- The Roughtime verifier checks Ed25519 signatures (message || signature framing).
- The RFC 3161 verifier uses
SignedCmssignature verification and the signing-time attribute for anchor time. - DTO serialization is stable (ISO 8601 UTC timestamps; fixed field set).
AllowRequestSuppliedTrustRoots=trueis honoured only inDevelopmentorTestingand is intended for explicit local harnesses. It must remainfalsein production. See Time Anchor Trust Roots.
