One local tool call inside a governed harness. The harness fires PreToolUse and spawns
straza hook; the adapter normalizes the dialect to the canonical event; the cached
snapshot's ed25519 signature is verified against pinned keys; rules evaluate in-process under
deny-overrides (p99 < 100 µs) with no server and no database. The winning rule selects one of six
outcomes. A plain allow exits 0; a plain deny exits 2 with an actionable Straza: reason.
The three escalations act only on a winning allow. serverCheck re-checks at
POST /v1/decide against the live server snapshot (offline past grace fails closed).
classify runs the embedded heuristic classifier (interpreter-aware indirection scan,
no model, 1 s deadline); a clear signal or an unavailable classifier denies. approve
takes two shapes. A
hold (default class) blocks the gateway lane up to timeoutSeconds
(default 90, cap 3600), holding the socket itself at most 120 s (approval.gatewayHoldSeconds)
before the caller gets a pending reason it can await, while the hook lane denies with a retry-after-approval reference plus a
single-use exemption; denied or expired is deny-final. A ticket never blocks: it
denies now, a human decides within ticketTTL (default 24 h, cap 30 d), and a later real
call, even a fresh session, consumes a DB-durable grant within grantTTL (default 1 h, cap
24 h) bound to the human plus fingerprint; a within-window denial stays deny-final. Every outcome is
spooled, drained to /v1/audit/batch, and appended to the tamper-evident hash chain. All
paths fail closed.