GVNR
Every decision leaves a receipt: allows as well as refusals. Not a log line, a record with the fields an audit asks for, in a chain that shows if anyone edits it.
This is a real receipt, written when an agent tried to read a .env file:
{
"ts": "2026-09-25T17:35:38.094Z",
"agent": "claude:7c1e9a",
"verdict": "ask",
"reason": "would read or write credentials",
"source": "capability",
"rule": "read or write credentials",
"tool": "Read",
"model": "",
"tokens": 0,
"operator": "sam@acme.dev",
"client": "?acme-api",
"meter": "transcript",
"policy": "unreachable",
"hash": "6b3f1a0106d445b6608266d51c2d99d11030202477354f11992b8422ea585819"
}
verdict is allow, rewrite, ask or deny; reason says why in words, and source says which check decided: the rules (capability) or spend and rates.rule names the rule that fired, and rewrote is set when the command was rewritten.agent is the Claude Code session, model the model that answered and tokens its cost-weighted spend so far.operator is the person the agent acted for, from the operator setting. client is the project, taken from the folder the work is in; a leading ? means it was inferred rather than set.meter says where the money figure came from: Claude Code's own cost via the status line, or the transcript.policy is what your organisation's policy said about a matched rule: silent when the workspace has no policy for agent actions, which is the default, or unreachable when it could not be asked (signed out, or the network was down).hash is the SHA-256 of the previous receipt's hash followed by this entry. That is the chain.What a receipt never holds: the command text, file contents or prompts.
On your machine, one line per decision in ~/.enforcer-governor/receipts.jsonl. /enforcer-governor:verify walks the whole file and names the first line that does not add up.
Signed in to an Enforcer workspace, receipts are also shipped in the background after each session, so the team has one record. The workspace can recompute each install's chain on its own, and the console shows spend and decisions by person, project, model and rule. The local file stays either way. shipOn switches shipping off.
Edit or delete a single entry and the chain visibly breaks. That is the difference between a log, which anyone with write access can quietly revise, and a record you can put in front of someone with a reason to doubt you.
If GVNR cannot read its own state, a refusal is still recorded, deliberately without a hash: there is no chain tail to hash against, and verify counts that line as unverifiable rather than as a break. Recording nothing would hide a real refusal; forging a link would cry tampering on an honest file.