A record that shows when it has been edited.
Every decision becomes a block. Every block carries the hash of the one before it. Changing an old record changes every hash that follows, which is the point.
{
"block": 84920,
"prev": "sha256:41b…7ac",
"hash": "sha256:8dc…e91",
"org_id": "acme-42",
"agent_id": "agent-01",
"action": "read:.env",
"policy": "deny-dotenv-read",
"verdict": "deny",
"payload_retained": false
}What is kept —
and what is not.
The record covers the decision: who asked, for what, under which rule, and what was decided. The payload itself is not kept unless it has been approved for retention.
Linked, not just timestamped
A timestamp is a claim. A hash chain is a check: recompute the chain and any altered block fails to reproduce the hashes that follow it.
Scoped by org_id
Blocks are row-scoped at the routing layer, so an export for one tenant cannot include another tenant's decisions.
The chain is a linear SHA-256 hash chain, optionally Ed25519-signed (0.1.3+): each record's hash can carry a signature, so a forged chain with every hash recomputed fails on the signature — previously it verified clean. There is no Merkle tree and no blockchain. Verification recomputes hashes from an earlier head, so it shows tampering to a holder of that head — it does not prove truthfulness and does not prevent deletion. The honest limit: signing proves attribution to the key, not to a third party.
Why, and
what would happen.
Two questions come up after an incident. Both are answerable without reconstructing logs by hand.
| Command | Answers | Side effects |
|---|---|---|
cirvix why <block> | Which rule produced this verdict, and what the request looked like when it did. | None — read only |
cirvix replay <block> | What the current rule set would decide about that same request. | Re-evaluates. Never re-executes. |
cirvix audit | The chain as the CLI sees it, with each record linked to the one before. | None — read only |
GET /v1/export | A structured JSON trail with linked records and hash metadata. An API call, not a CLI subcommand. | None — read only |
Replay is deliberately incapable of running the original action. It answers "what would we decide now", which is the question worth asking, and it cannot cause the side effect a second time.
Generate evidence for a review
Export a coherent trail instead of assembling raw logs by hand.
Bring every agent
under control.
Set durable policy, preserve a verifiable record, and give teams a safer way to put intelligent systems to work.