Closes the last remaining 2026-05-19 audit finding by documenting the
existing transitive guarantee rather than restructuring the hook
contract.
The audit observed that PostToolUse hooks receive raw tool output
before the firewall scan runs, and proposed reordering or splitting
the event into raw-local-only and redacted-for-LLM variants. After
Wave 1 (SafeProvider boundary at every router arm + non-engine
provider consumer), the audit's threat model is closed transitively:
- Shell hooks see raw output but never reach an LLM.
- Prompt hooks route Stream calls through routerStreamer → router →
arm.Provider, every arm.Provider is now *SafeProvider, outgoing
messages are scanned at the boundary.
- Agent hooks spawn an elf whose engine has Firewall set;
buildRequest scans inline.
Reordering would regress legitimate shell-hook use cases (audit,
forensic, local alert) that need raw access. Splitting the contract
forces every existing hook config to migrate and introduces a
wrong-variant footgun. Neither is justified by the residual risk.
Three changes ship with the ADR:
- ADR-004 records the decision and the conditions for re-opening it.
- Doc comments on hook.PostToolUse and the dispatcher call site in
the engine point at the ADR.
- internal/hook/posttooluse_redaction_test.go locks in the invariant:
a prompt PostToolUse hook firing on a secret-bearing tool result
produces a redacted prompt at the inner provider. If this test
fails, ADR-004's Position A is no longer correct and the audit
finding re-opens.
Plugins are now verified against ~/.config/gnoma/plugins.pins.toml at
load time. Each plugin's plugin.json bytes are hashed (SHA-256) and:
- recorded automatically on first load (TOFU) with a prominent warning
- compared on subsequent loads
- refused with a clear error if the hash drifted, without overwriting
the pin so the user can review and re-enrol deliberately
Pin-store I/O failures degrade to load-without-pinning rather than
locking the user out of previously-trusted plugins.
Closes audit finding C2. See ADR-003 for the decision rationale and
docs/plugins-trust.md for the end-user trust model.