Prove

Show an auditor what was stored, and that it was not rewritten.

The engine keeps a hash chain over every published generation, erasure and external signature. An evidence pack bundles the chain, its verification, your retention, activity and erasures under one digest that anyone can recompute with the Python standard library.

The ledger

One append-only file. Each entry commits to the one before it.

Every checkpoint, published erasure and external anchor appends an entry whose head is a SHA-256 over the previous head and the entry’s canonical JSON. Rewriting any earlier entry changes its head and breaks every link after it. The format is the formula; nothing about it needs Traza to check.

head = sha256("traza-ledger/1\n" + prev + "\n" + canonical_json(entry without "head"))
check_ledger.py — the engine guide’s whole verifier
import hashlib, json, sys
prev, ok = "0" * 64, True
for n, line in enumerate(open(sys.argv[1], encoding="utf-8")):
    entry = json.loads(line); head = entry.pop("head")
    body = json.dumps(entry, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
    want = hashlib.sha256(f"traza-ledger/1\n{prev}\n{body}".encode()).hexdigest()
    good = entry["seq"] == n and entry["prev"] == prev and head == want
    print(entry["seq"], entry["kind"], head, "ok" if good else "BROKEN")
    prev, ok = head, ok and good
sys.exit(0 if ok else 2)

Evidence packs

Everything an auditor asks for, under one digest.

GET /v1/evidence returns one document: the chain entries in your window and the chain’s verification, the retention that applies to you right now, your usage counters, activity by day, and the erasures settled in the window with their receipts. Its digest covers every field.

A project’s pack contains only its own tenant’s activity and erasures. Other tenants’ erasure entries become stubs you can follow the chain across but cannot attribute.

curl -s "https://api.trazadb.com/v1/evidence?since=1790812800000000000" \
  -H "Authorization: Bearer $TRAZA_API_KEY" -o pack.json
jq '{format, intact: .ledger.verification.intact, digest}' pack.json

Timestamps are Unix nanoseconds, above 253: parse them with an exact integer type, or recomputed digests will not match.

Anchors

A chain alone has no secret. An anchor held elsewhere does the work.

Anyone who can write the ledger file can rewrite it and recompute every head. What makes a rewrite detectable is a countersignature over a head, kept outside the store. The engine records anchors and checks their target; it never calls a notary itself. On Traza Cloud, ours does.

  1. Every hour, for each cell whose ledger has moved, the notary reads the ledger head and signs a canonical statement of it with its Ed25519 key.

  2. It records the anchor back into that cell’s ledger, where it appears whole in every tenant’s evidence pack.

  3. It appends the statement to a public, hash-chained transparency log at app.trazadb.com/notary/log, beside the published keys at /.well-known/traza-notary.json. No tenant data appears in either.

  4. On Team, it also signs evidence packs on request: it re-verifies the pack’s digest over its exact bytes, signs an attestation statement naming your org, project, window and digest, and keeps the pack with it for download.

Proof links

One run, one link, a signature anyone can check.

From any run in the console, create a proof link: a read-only certificate page with the run’s tape summary, the ledger head when it was created, and the notary’s signature over the run, the tape’s digest, that head and the time of issue. The page carries the public key’s location and an openssl recipe, so whoever you send it to can verify it without an account and without trusting the page.

Links expire, and you can revoke one at any time. On Pro and up, like share links.

  1. Pick the run in the console and create the link; choose how long it lives.

  2. The notary signs a canonical statement of {run, tape digest, ledger head, issued_at} with its Ed25519 key, the same key published at /.well-known/traza-notary.json.

  3. Anyone with the link sees the summary and checks the signature with openssl; nobody without it can find the page.

Stated plainly

What it proves, and what it does not.

Abridged from the engine’s ledger guide. Read the whole section before relying on it.

It proves

  • The current state matches a committed manifest: every file the live generation names is re-digested.
  • History was not rewritten after an anchor, if the anchored head or the notary’s signature is kept outside the store.
  • A recorded erasure still holds, and every settled erasure was recorded.

It does not prove

  • Anything about history without an anchor. The chain has no secret in it.
  • When things happened. Times are the server’s clock and the notary’s claim, not trusted timestamps.
  • Anything about data that was never sent, or that files were untampered before the checkpoint that digested them.

The full account, in the ledger guide

Erasure with a receipt

Deleting a project leaves a receipt, not a promise.

The engine erases a trace, a session or a whole tenant from every domain it keeps, then re-checks each domain by name and says what it found. When you delete a project on Traza Cloud, its tenant is erased on its cell and the erasure’s receipt id is kept with the deleted project.

Checking a receipt offline, on a self-hosted store
traza-server verify --erasure 1 --data-dir /var/lib/traza

A receipt reports result (erased or not-erased, from what the walk found) and conclusive, for each of the write buffer, live tail, write-ahead log, segments, annotations, eval records, payload files, derived caches, pins and generation metadata. A receipt offered as proof should be both erased and conclusive; a backup pin that still holds the bytes is named.