Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR-0019: Admission ledger for external inputs

Status: accepted | Date: 2026-08-04

References: ADR-0003, ADR-0018, RFC-0001

Context

Every external input was volatile, unrecorded, or both. Steer text was lost on pod death after read-then-blank. Approve/deny/rescope were in-memory mutex slots (double approve, silent overwrite, lost on pod death). Set-budget/pause reverted on resume. No idempotency keys existed.

Decision

Append-only NDJSON file (state/admissions.jsonl) with a two-state machine per idempotency key: exactly one "admitted", then at most one "settled". Adapted from flue's AgentSubmissionStore. Three rules: admission precedes effect (fsync before mutation), idempotency converges (same key+payload returns original), ledger is authoritative for operator inputs. Derived grant keys link approvals to asks. Settlement is keyed to turn completion. File mechanics live in forge::ndjson (flock-guarded append, torn-tail-tolerant fold).

Consequences

The control bridge no longer writes STEER.md. Two durable logs can disagree after a crash (one declared authoritative). Each admission costs an fsync. The file is never compacted.

Alternatives Considered

Append-only NDJSON ledger with two-state machine per idempotency key (accepted)

In-memory mutex slots with checkpoint snapshots to disk (rejected)

  • Rejected because: Snapshots are point-in-time and lose inputs between checkpoints. The append-only ledger records every admission with fsync-before-effect, so no input is lost on crash.