Safety model
Fail closed.
Recover deliberately.
Kirra's safety model is three postures and a promise: when anything is unproven — a node unattested, a sensor silent, a cache stale, a command unclassified — the system moves toward stillness, and it never talks itself back into motion.
Posture state machine
Three states. Asymmetric exits.
Getting into a safe state is automatic and fast. Getting out is slow and evidence-gated: Degraded recovers only after five consecutive healthy reports inside a ten-second window, and LockedOut recovers only through a human. Down is easy; up requires proof.
src/recovery_hysteresis.rssrc/verifier.rsdocs/safety/SAFE_STATE_SPECIFICATION.md
The Degraded contract
Degraded is not a crawl.
It is a controlled stop.
Motivated by the October 2023 Cruise incident — a post-collision pullover executed at ~3 m/s under a 5 m/s “crawl ceiling” — Kirra's Degraded posture admits a command only if it converges to a stop. The governor never authors re-acceleration.
Three conditions, all required
(a) inside the minimum-risk decel envelope; (b) non-increasing speed — |proposed| ≤ |current|;
(c) no re-initiation: once at rest (≤0.05 m/s), any command to move again is denied and the vehicle
holds. A reversal through zero counts as re-initiation.
crates/kirra-core/src/kinematics_contract.rsdocs/safety/SAFE_STATE_SPECIFICATION.md
Enforced at four points
The same decel-to-stop gate runs at the HTTP actuator gateway, the fabric asset governor, the ROS 2 trajectory validator, and the parko MRC profile — which also gates the independent angular-velocity channel for differential drive.
docs/adr/0011-degraded-http-actuator-503-vs-decel-gate.mdtests/posture_gate_integration.rs
Machine-checked
Kani proofs K4 and K5 verify — over exhaustive f64 case splits — that Degraded re-initiation
and speed increases are denied. Not tested on samples: proved on the domain.
Liveness
Silence is a fault
A safety system that only reacts to bad messages misses the worst failure of all: no message. Kirra's watchdogs treat absence as evidence.
| Signal | Threshold | Consequence |
|---|---|---|
| AV telemetry silence | 1,000 ms warn · 2,000 ms fault | Node marked untrusted; posture recomputed (sweep every 100 ms) |
| Posture cache age | > 5,000 ms | Routing fails closed — treated as LockedOut |
| Attestation nonce age | > 30,000 ms | Challenge expires; proof must restart |
| Federation report age | > 5,000 ms | Report rejected (replay window) |
| Armed-but-silent VRU channel | freshness budget | MRC-floor speed cap — the ego stops rather than drives blind |
src/telemetry_watchdog.rssrc/posture_cache.rscrates/kirra-trajectory/src/vru_channel.rs
Per-class envelopes
No default vehicle class
A sidewalk courier and a robotaxi must not share an envelope. The vehicle class is mandatory configuration — unset, empty, or unknown aborts startup, because a wrong class would select another class's physics. Every number below is normative in the repository and marked validation-pending until signed off.
| Limit | Courier (sidewalk) | Delivery AV (road pod) | Robotaxi (frozen ref.) |
|---|---|---|---|
| Max speed | 3.0 m/s | 12.0 m/s | 35.0 m/s |
| ODD speed cap | 2.5 m/s | 11.0 m/s | 22.35 m/s |
| Braking decel | 3.0 m/s² | 4.0 m/s² | 4.5 m/s² |
| Lateral accel | 1.5 m/s² | 2.5 m/s² | 3.5 m/s² |
| RSS lateral band | 0.6 m | 2.0 m | 4.0 m |
docs/CONTRACT_PROFILES.mdsrc/gateway/contract_profiles.rsdocs/adr/0028-sidewalk-courier-odd.mddocs/adr/0001-occy-odd-speed-cap.md
Invariants
Rules that have survived being attacked
The repository maintains a list of security invariants that submissions have repeatedly tried to weaken — and that are rejected outright. A few of the load-bearing ones:
Envelope cap beats rate limits
The governor clamps to the absolute hard boundary first, then applies rate-of-change limits. The envelope always wins.
Unknown is denied everywhere
The Unknown command class is denied in all postures — including Nominal. The early return is never removed.
Attestation is never mocked
Trust requires a per-node Ed25519 proof over a fresh challenge, checked against the registered key. No registered key, malformed proof, bad signature — rejected.
Actuator topics never replay
DDS actuator topics must use Volatile durability, so a reconnecting subscriber can never receive a stale command as if it were fresh.
SECURITY.mddocs/v1_security_invariants.mdsrc/startup_sentinel.rs
READ THE SOURCE
Read the safe-state specification.
KIRRA-SSS-001 assigns a safe state to every fault-severity class — and the repository's tests hold the code to it.