Skip to content
English

The checkpoint chain

Audit records have to be able to show they were not tampered with. The system does this in three layers: each row is stamped, each interval is sealed, signed, and linked to the one before it, and a copy of each sealing event is sent out. “A piece was removed from the middle” and “a whole stretch was deleted and covered up” become detectable events, and both stay distinguishable from a lawful purge on expiry.

Every record entering the database has an HMAC computed over its key fields as it is written, along with the version of the stamping key. The stamping key is a versioned key the system generates, wrapped by the master key at rest. At first startup the system anchors a baseline, and older data from before it is presented under a separate count rather than mixed into the mismatched ones.

Row-level verification answers whether the content of those rows is genuine.

The system periodically seals a stretch of records: it takes the identifier and stamp result of every row in the interval, aggregates them into one fingerprint, and signs that with Ed25519 together with the sequence number, the interval’s start and end, the row count, the hash of the previous checkpoint, the sealing time, the signing key version, and a snapshot of role assignments at that time. The verification page adds a Role assignments column; a mismatch names the account and the role and links to the invalidation event. Reconciliation of live roles runs inside the product; an offline tool checks the payload and the signature. It triggers on whichever of two thresholds arrives first, time or row count, shipped as every hour or every ten thousand rows. After a trigger it waits a short while before scanning, so that transactions in flight can land.

An interval with no new data gets an empty seal, so the chain does not break when the system sits idle. The checkpoint table forbids deletion, and the only updatable columns are the anchoring state and the few related to purging.

Checkpoint verification answers whether anything is missing from the sequence.

Newer checkpoints also aggregate the AI agent tool call ledger. Verification follows the checkpoint’s format version, so older seals are verified with their original format.

After a successful sealing, the anchoring event is forwarded over syslog, carrying the sequence number, interval, row count, interval fingerprint, signature, and key version. The anchoring state has three values: handed to the local side and awaiting forwarding, not sent (dropped on a full buffer), and off. While it is off, the checkpoint verification page shows a banner that cannot be dismissed, explaining that the offsite backup is off and pointing at where to set it up. See Log forwarding and notifications.

The Checkpoint Verification page is read-only and open to the administrator and auditor roles. It shows the structural result for the whole chain as soon as it loads, with no parameters to fill in. An interval has one of nine states:

Status Meaning
Passed The stretch is whole and the signature is valid
Purged under the retention policy A lawful purge, with proof attached
Purged without valid proof The data is gone with no proof of a lawful purge
Row count mismatch The rows present differ from the count at sealing
Digest mismatch The content does not match the fingerprint from sealing
Extra records present The interval holds more records than it did, awaiting a human decision
Invalid signature The signature does not verify
Broken link It does not join to the previous checkpoint
Sequence gap A checkpoint is missing in between

Row-by-row content verification asks for a start and end sequence number first, because it rechecks every record and a wider range takes longer. Arriving from the investigation workbench fills the sequence numbers in, without running it.

The page also offers the signing public key, its version, and its fingerprint, so an outside reviewer can verify signatures offline.

The system also runs two layers of automatic verification on a schedule: checking the intervals of the last few days after a sealing completes, and walking the whole chain on a cycle. Each round has a row budget, and the newest interval at the end of the chain and any failing interval that has yet to be closed are always verified. Automatic verification is read-only and writes no audit rows.

The page shows, for each layer, the last run time, the result, the period checked, the cycle, the sequence number it has rechecked up to, whether it finished a full pass, and how many anomalous intervals have yet to be confirmed as recovered. These are operational status rather than proof of integrity in itself, and the page says so.

The audit mechanism speaks up when it breaks. A failed database write, a broken forwarder or an overflowing buffer, a failed recording, and an anomaly in chain verification each carry their own machine code and alert, and events still land in a file while it is degraded. A structural anomaly, a content anomaly, and a failure of the verification itself are reported separately rather than flattened into one code. What goes out carries the machine code and counts only.

  • The verification state per interval, along with each stretch’s sequence number, record number range, the row count at sealing and the rows present, and the offsite anchoring state.
  • The page carries a section on the scope and boundaries of this protection, saying what carries each situation, which is what a reviewer uses to judge how far the mechanism reaches.
  • Purge records on expiry line up with the checkpoint intervals; see Retention, purging, and observability.