Verify the audit chain

Check the tamper-evident hash chain and read the result.

Every administrative mutation writes an entry to an append-only audit log. Each entry’s hash digests the previous entry’s hash together with the acting principal, so the log forms a chain: altering or removing any historical entry invalidates verification for every entry after it.

What this does and does not prove

It proves the log has not been edited. Delete a row, change an actor, or backdate an action, and verification fails at that point and stays failed.

It does not prove an action was authorised — only that the record of it is intact and attributed to a specific principal. Tamper-evidence, not tamper-proofing.

Steps

1. Open /audit-logs.

Audit Logs

Each entry records the actor, the action, the affected resource, and a before/after snapshot for mutations. The before-image is captured inside the same transaction as the write, so the audit record and the data cannot disagree.

2. Filter to the window you care about — actor, resource type, or date.

3. Verify the chain. Verification walks the chain and recomputes each hash from its predecessor. A pass means every entry in the range is intact and unbroken.

Chains are per-tenant

public.audit_logs carries control-plane events. Each provisioned tenant has its own chain in its own schema, starting from its own genesis entry.

The chains never interleave, and this matters when you verify: verifying the public chain says nothing about a tenant’s chain, and vice versa. Verify the chain that holds the events you are asking about. Chain tooling takes an explicit --tenant for the same reason.

Reading a verification failure

A failure reports the sequence number where the recomputed hash stopped matching. Everything before that point is still proven intact — the break is a lower bound on where interference occurred, not a statement about the whole log.

Investigate in this order:

  1. Was the row deleted or edited directly in the database? The overwhelmingly common cause. Application code cannot produce a broken chain.
  2. Was a restore performed from a partial backup? Restoring a truncated audit_logs breaks the chain exactly as tampering does.
  3. Is it the right chain? Verifying a tenant chain against public expectations produces a break that is not a break.
ScreenPurpose
/admin-sessionsAdministrative session history
/change-requestsDual-control approvals — a second identity in the record
/compliance-reportsPoint-in-time exportable artifacts
/key-ceremoniesSigning-key rotation events

Exporting for an auditor

/compliance-reports generates a report over a window. Export the report rather than a database dump: the report carries the verification result alongside the entries, which is what an auditor needs in order to rely on it.