Audit-Chain Anchoring
Anchor the per-workspace SHA-256 audit chain to an external append-only ledger (immudb, Azure Confidential Ledger, or a WORM file) so tampering is detectable by a third party — even against the platform operator.
Why anchoring
The per-workspace audit log is a SHA-256 hash chain — altering any row breaks verification from that row forward, so it is tamper-evident. But it is not, by itself, tamper-proof against the platform operator: someone with database write access could rewrite a row and recompute every following hash. Anchoring closes that gap by publishing each workspace's current chain head hash to an external append-only ledger the operator cannot retroactively edit. Once a head is anchored, any later forgery is detectable by a third party, and the ledger's own cryptographic receipt proves the anchor was not backdated. Available on Enterprise and Sovereign plans (immutable_ledger feature).


Ledger Backends
Select a backend with the LEDGER_BACKEND env var; anchoring is disabled when it is empty. A Celery Beat task anchors every LEDGER_ANCHOR_INTERVAL_HOURS (default 1h), and you can anchor on demand via the API or CLI.
| `LEDGER_BACKEND` | Ledger | How the anchor is written |
|---|---|---|
| `immudb` | immudb (tamper-proof Merkle tree) | Verified set; the response carries an inclusion proof |
| `azure_cl` | Azure Confidential Ledger (hardware-backed CCF) | Append transaction; a signed receipt is returned |
| `file` | Append-only JSONL on a WORM volume (air-gapped / sovereign) | One JSON line appended per anchor |
API & CLI
Each stored anchor keeps the external ledger's transaction id and the verbatim receipt, so verification does not depend on trusting the platform database. The anchored record pins head_hash (the most recent entry hash) — because each entry's hash covers the previous one, fixing the head fixes every entry before it.
1# Anchor the current chain head (ops/admin)
2curl -X POST "https://sovereign.yourcompany.com/api/v1/audit/anchors?workspace_id=ws-prod" \
3 -H "Authorization: Bearer $PAT"
4
5# List past anchors + their ledger receipts
6curl "https://sovereign.yourcompany.com/api/v1/audit/anchors?workspace_id=ws-prod" \
7 -H "Authorization: Bearer $PAT"
8
9# Recompute the live head and compare to the latest anchor
10curl -X POST "https://sovereign.yourcompany.com/api/v1/audit/anchors/verify?workspace_id=ws-prod" \
11 -H "Authorization: Bearer $PAT"
12
13# Same, from the CLI (verify-anchor exits 2 on mismatch)
14oss audit anchor ws-prod
15oss audit verify-anchor ws-prodThird-Party Verification
An external auditor who does not trust the operator obtains the anchor independently from the external ledger (not from the platform DB) — for immudb, fetching the anchor key returns the value with an inclusion proof against its Merkle tree; for Azure Confidential Ledger, the signed CCF receipt is verified against the ledger's identity. The auditor then re-fetches the audit entries, recomputes the chain head, and confirms it equals the independently-obtained anchored head. A mismatch proves the log was altered after anchoring.