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.3.0+): 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.
What Audit Verification Proves vs. What It Does Not
- PROVES:
- No interior record between genesis and the verified head has been altered, reordered, or deleted without invalidating subsequent SHA-256 hashes.
- DOES NOT PROVE:
- Truthful execution of downstream side effects (authorization is not execution), complete history if tail truncation occurs without an external checkpoint, or regulatory compliance.
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.