Baniloo Baniloo

August 2, 2026

Audit is a view, not a ledger

loomed audit and loomed revoke don't add a new commit log — they're both derived from the same chain scan that already answers whether a consent token has been used

Phase 3 Session 3 closes out consent tokens with the two commands that make issuance and enforcement actually operable: loomed revoke to kill a token early, and loomed audit to see what’s been granted. Neither adds a new source of truth. Both read the one that already exists.

One scan, three callers agree

commit.rs’s find_and_authorize_token used to do its own bespoke walk of the chain to check whether a presented token had already been spent. That walk now lives in a new shared module, token_chain.rs, behind two functions — scan_all_tokens() and find_token() — and loomed commit --token, loomed revoke, and loomed audit all call into it instead of each maintaining their own idea of what “used” or “revoked” means. That matters more than it sounds: three independent traversals of the same chain are three independent chances for one of them to disagree with the other two about a token’s state. One scan, three callers, one answer.

Revocation itself is a token_revocation commit — no separate flag or side table, just another entry in the same signed chain, checked the same way a use is checked. loomed revoke <token_id> validates the token_id format before opening the vault (the same fail-fast discipline loomed commit --token already established), confirms the token exists and isn’t already revoked, then writes the revocation self-authored.

Deriving the trail instead of storing it

Spec §11 defines an access_event schema with fields like accessed_by_name and records_accessed. loomed audit doesn’t implement that schema, and says so directly in its own module doc rather than pretending otherwise: accessed_by_name needs a participant registry that doesn’t exist until Phase 5, and records_accessed only matters once a single token can be presented more than once — which v1’s single-use tokens never are. For this version, “issued” and “consumed” are already a 1:1 relationship for every write, so there’s nothing records_accessed would tell you that the issuance and the consuming commit don’t already show.

So loomed audit is a projection, not a new commit type: one entry per issued token — active, used, expired, or revoked — built entirely from data three other commit types already put in the chain, optionally filtered with --entity <participant_id>. Adding a real access-event log later, once read-token presentation actually exists as a flow, is a schema decision that can wait until there’s a real event to log; building it now against a command that doesn’t exist yet would be guessing.

17 new tests cover this, including cross-command proof that a token revoked via loomed revoke is then rejected by loomed commit --token — the two commands sharing one scan is what makes that guarantee automatic rather than something each command has to separately get right.

Consent tokens are now issuable, enforceable, auditable, and revocable. What’s still open is everything upstream of a token even mattering: Phase 4-lite’s identity work, landing the same day, starts on that.