Fail-Closed System Posture
Every assurance surface answers its own question. The Posture answers the only one an operator truly needs: is everything trustworthy and correctly configured, right now? It composes attestation, the safety interlock, the Trust Console, the Adoption Lighthouse, and the Resilience Report into one signed severity — and adds a readiness check of the deployment itself.
Fail-closed by construction
Silent degradation is the enemy. The Posture enforces one invariant: any unreadable or unconfigured source forces severity ≥ WARNING, and any hard failure — a halted interlock, an unverified attestation chain, a suspicious Lighthouse, a degraded Resilience report, or a readiness blocker — forces SEVERE. A source that times out is reported as degraded, never mistaken for healthy.
- Every source is probed in parallel with a per-source timeout, so one slow dependency cannot hang the report.
- Readiness checks required env, signing-key validity, scheduler-secret presence (production), database reachability, and applied migrations — never emitting a secret value.
GET /api/v1/raillab/posture (ISSUER API key)
{
"posture": {
"severity": "OK",
"ready": true,
"surfaces": {
"attestation": { "verified": true, "chain_ok": true },
"safety": { "halted": false, "reason": null },
"console": { "severity": "OK", "degraded": false },
"lighthouse": { "degraded": false, "suspicious": false },
"resilience": { "severity": "OK", "survives": true }
},
"checks": [
{ "name": "required_env", "ok": true, "blocking": true, "detail": "all required env present" },
{ "name": "signing_key", "ok": true, "blocking": true, "detail": "valid ed25519 private key" },
{ "name": "database", "ok": true, "blocking": true, "detail": "reachable" }
],
"blockers": [],
"degraded": false,
"degraded_reasons": []
},
"snapshot": { "content_hash": "…", "signature": "…", "public_key": "…", "algorithm": "ed25519" }
}Severity
- SEVERE — a hard assurance failure or a readiness blocker. Never cached.
- WARNING — a readable-but-degraded source, or an unreadable one. Never cached.
- OK — every surface healthy and the deployment ready; cached for 60s, privately.
Verify it offline
Signed with the same key as /api/v1/receipts/monetary. Remove snapshot, recompute sha256(canonicalJson(body, keys sorted)), then verify the Ed25519 signature over utf8(content_hash).
Agent autarky
const p = new PassportClient({ apiKey: "pp_…", baseUrl: "https://passport.metis.gold" });
const { posture } = await p.getPosture(); // ISSUER key
if (!posture.ready || posture.severity !== "OK") {
// halt autonomous work until the posture is green; inspect posture.blockers / degraded_reasons.
}