Technical note, 5 September 2026
An automated system did something consequential, and somebody now wants to know that the record of it is the record that was written at the time. This is the part of AI record-keeping that is easiest to claim and hardest to check, and most of what is written about it answers a narrower question than the one being asked.
Nothing here is specific to any format or product. The distinctions apply to whatever you already log.
Altered by whom? Almost every scheme in use protects against a different party than the one people assume, and the difference decides whether the record is worth anything in a dispute.
Internal audit asking about a team's own system, or a customer asking about a supplier's, is always asking the second question. So is a court.
| Mechanism | Detects an outsider's edit | Detects the operator's edit | Cost |
|---|---|---|---|
| Append-only storage | partly | no | free |
| Hash of each entry | yes | no | free |
| Hash chain | yes | no | free |
| Digital signature | yes | no, the key holder re-signs | key management |
| RFC 3161 timestamp | yes | yes, for time and content | free, one HTTP call |
| Transparency log | yes | yes, and detects omission | infrastructure |
Append-only storage is a property of your code path behaving. It is a real control against the ordinary case and it is not evidence, because whoever administers the database can still write to it.
A hash chain makes each entry commit to the one before it, so an edit in the middle breaks everything after. Strong against an outsider and worth nothing against the party that can recompute the whole chain, which is the party that wrote it.
A signature binds the record to a key. Better, and it moves the question rather than settling it: whoever holds the key can sign a different record just as validly. It helps when the key is held somewhere the operator cannot reach.
An RFC 3161 timestamp is the cheapest thing that changes the answer. A Time Stamp Authority signs the pair of your digest and the current time, with its own key. The operator cannot forge that signature, cannot backdate it, and cannot alter the record without the digest ceasing to match. Free authorities operate it, it underpins qualified electronic timestamps under eIDAS, and a verifier checks it with openssl rather than with anything of yours.
A transparency log in the style of RFC 9162 is stronger again, because it also detects omission: a record that was never submitted is visible as a gap. It is the right answer at scale and it needs infrastructure somebody has to run.
Hash the records you want to fix, ask an authority to sign the digest, and keep the token beside them.
# the digest of whatever you are fixing in time sha256sum records.jsonl # ask an authority to sign it openssl ts -query -data records.jsonl -sha256 -cert -out request.tsq curl -s -H "Content-Type: application/timestamp-query" \ --data-binary @request.tsq http://timestamp.digicert.com > token.tsr # what it says openssl ts -reply -in token.tsr -text
Anybody you later hand the records and the token to checks them against their own certificate store, with no cooperation from you:
openssl ts -verify -in token.tsr -data records.jsonl \ -CAfile /etc/ssl/certs/ca-certificates.crt Verification: OK
And what a failure looks like, which is the half nobody prints. One byte changed anywhere in the file:
error:17800067:time stamp routines:ts_check_imprints:message imprint mismatch Verification: FAILED
Note what that does and does not tell you. It says the file is not the one the authority signed. It does not say who changed it, when, or which byte, and it cannot distinguish a malicious edit from a trailing newline an editor added on save. Hash a canonical form rather than the file as it happens to sit on disk, or you will spend a morning investigating whitespace.
That is the whole mechanism. The common mistakes are worth knowing
because they are silent: a DER integer that is not minimally encoded
produces a token strict parsers reject, and roughly half of hand-built
requests hit it depending on one random byte. If you build the request
yourself rather than with openssl ts -query, check your
output parses before you rely on it.
That the record is true. A system can record precisely what it believed, sign it, timestamp it, and be wrong about all of it. Integrity protects the entry, not the claim inside it.
That the record is complete. Everything above fixes what you submitted. Only a transparency log makes what you did not submit visible, and even then only for records that were meant to be there.
That a different record was not produced and discarded. A timestamp proves this one existed at that time, not that it was the only one.
Anyone selling you integrity as an answer to accuracy is selling you the wrong thing, and the distinction is the first one an auditor will make.
There is a record published at a record you can check without us, with its token, its digest, and the three commands above run against real files. It is in the Testimony Record format, which is one way to write these things down and not the only one. The mechanism on this page works with whatever you already log.