Does the EU AI Act require tamper-evident logs?
Updated 2026-10-10. Sasana 2.0.0 corrects how verification results should be read. Versions 1.0.0 and 1.1.0 reported AUTHORITATIVE_EVIDENCE for a valid seal even when the verifier had not been given the Archeion public key, and accepted a log whose seal had been removed even when a key was pinned. This post has been revised to match 2.0.0. See the 2.0.0 changelog.
Short answer: no, not in those words. Article 12 requires that high-risk AI systems record events. It does not say those records have to be tamper-evident. If you are only trying to satisfy the literal text, an ordinary log file clears the bar.
That is also the wrong question to stop on. The regulation is not the moment your log gets tested. The dispute is. And the first thing anyone on the other side of a dispute asks about a log is whether it could have been changed after the fact. If the answer is “yes, but we promise it wasn’t,” you do not have evidence. You have a claim in a database.
So the useful version of the question is: what does Article 12 actually ask for, where does that leave you when the log has to hold up, and what closes the gap?
What Article 12 actually says
The text is narrow and specific: “High-risk AI systems shall be designed and developed with capabilities enabling the automatic recording of events (‘logs’) throughout the lifetime of the AI system.” The operative word is recording. There is no mention of hashing, signing, timestamping, or immutability. Analysts who point out that “Article 12 does not require tamper-evident logging” are reading it correctly.
A note on dates, because they moved. The Digital Omnibus (Regulation (EU) 2026/1744) entered into force on 27 July 2026. It moved the start of the high-risk obligations to 2 December 2027 for stand-alone systems (Annex III) and 2 August 2028 for AI built into products already regulated under Annex I. Article 12 is a requirement for high-risk systems, so it applies from the date that applies to your system; check which category yours falls in and confirm the dates against the Official Journal text. There is no August 2026 cliff. The useful way to read the change is lead time: audit infrastructure, key custody and retention take months to stand up, and starting well before your date is cheaper than starting late.
Recording is not the same as proving
Here is the structural problem with treating “we record events” as done. LangSmith, Arize, Langfuse, Helicone, Datadog: good tools, built for debugging and observability. What they produce is mutable records in storage the operator controls. An administrator with database or filesystem access can change or delete a record after the session, and nothing in the log shows it happened. The record still exists. It still satisfies Article 12’s recording requirement. It just cannot prove it has not been touched.
Now read Article 12 next to Article 9, which requires a risk-management system for high-risk AI. When something goes wrong, a credit model produces a discriminatory decision, a medical tool is challenged, a hiring agent is investigated, and a regulator or counterparty asks for your logs, “we have logs but cannot prove they weren’t modified” is a hole in that risk-management system. The regulation never demands cryptographic integrity protection. Defending yourself with the log does.
That is the real answer to the headline. Article 12 asks for logs. A dispute asks for evidence. Those are different standards, and the gap between them is where tamper-evidence lives.
What makes a log hold up: three properties
A log that survives scrutiny needs three things, and each is a separate technical problem.
Integrity. Any change to a past event has to be detectable. Sasana hashes every event with SHA-256 over RFC 8785 canonical JSON and chains each event to the previous one through a prev_hash field. Change one byte in one past event and every hash after it stops matching. This is what the verifier means by an intact chain: no individual event has been edited, inserted, removed or reordered relative to the chain. On its own it is not proof that the whole file was not rewritten (see Independence).
Attribution.A hash chain proves the log is internally consistent. It does not prove who wrote it. Per-session Ed25519 signatures bind events to a key recorded in the log itself, so they show consistency rather than identity: someone rewriting the log can generate a new key and re-sign everything. At best that is “whoever held this key attests these events happened,” which is still the operator vouching for the operator.
Independence. This is the one that matters when the operator is a party to the dispute, and it is the one a hash chain alone cannot give you. An operator who controls the storage can throw the log away and write a brand new chain: every hash correct, every event fabricated, and it verifies as intact, because internal consistency is all a chain can prove. To close that, the entity that seals the log has to be structurally separate from the entity thatruns the agent. That separation is what Archeion is.
Where Archeion comes in
Archeion is a small self-hosted sealing server. Its whole job is to be the independent party in the sentence “an independent party attests this log existed in this exact state.” It is the difference between a log the operator signed and a log carrying a seal the operator cannot produce, provided you verify that seal against Archeion’s public key and the operator cannot get Archeion to seal a rewrite (more on that below).
The design starts from a rule enforced in code, not in documentation. Sasana events fall into two authority classes. The SDK, which runs inside the agent process, may produce ordinary session events: SESSION_START, TOOL_CALL,SESSION_END, and so on. Only Archeion may produce a CHAIN_SEAL. This is not a naming convention. The ledger checks it on every write:
# sasana ledger: the boundary is enforced at write time
def record(self, event):
if not EventType.is_sdk_authority(event.event_type):
return # a CHAIN_SEAL submitted through the SDK is silently dropped
... # the agent process literally cannot write a sealSo the agent cannot emit its own seal even if its code is fully compromised. It has no path to write that event type, and it does not hold the key that would make one valid. Archeion loads its Ed25519 keypair from ~/.archeion/server_key.b64 (permissions 0600) or an injected environment variable, and that key never touches the agent side of the boundary.
Sealing is a single request. You POST the completed session JSONL to Archeion, and it does something important before it signs anything: it re-verifies the entire hash chain itself. If the chain is broken, if the session never ended, or if events were dropped mid-session, Archeion refuses.
POST /seal → 200 sealed JSONL returned
POST /seal (broken) → 422 "Cannot seal: session is COMPROMISED"
POST /seal (gaps) → 422 "Cannot seal: session has LOG_DROP event(s)"
POST /seal (sealed) → 409 "Session is already sealed"This matters more than it looks. A sealing authority that rubber-stamps whatever it is handed is worthless. Archeion will only put its name on a log it has independently checked, and it will not seal a partial log, because a seal on an incomplete record would falsely imply the record is complete.
When it does seal, it appends one CHAIN_SEAL event, signs the event hash with its own key, and returns the extended log:
{
"seq": 8,
"event_type": "CHAIN_SEAL",
"session_id": "3f8a2c1d-...",
"timestamp": "2026-07-18T14:22:07.481920Z",
"payload": {
"session_hash": "db37c1d4...",
"sealed_by": "archeion",
"server_pubkey": "9Kf2c1...=",
"timestamp_imprint_match": true
},
"prev_hash": "db37c1d4...", // links into the session's own chain
"event_hash": "a17c93e0...",
"signature": "b/4f... (ed25519 over event_hash)"
}The seal’s prev_hashis the last event’s hash, so the seal is part of the same chain as the session it certifies. You cannot lift a genuine seal off one session and staple it onto another, because the chain would break. Archeion also compares the RFC 3161 token, if the session carries one, with the session’s start hash and records whether the imprint matches (timestamp_imprint_match). That is not verified time: neither Archeion nor sasana verifychecks the TSA’s signature or the time the token claims.
Verification does not require trusting Archeion’s word later. Archeion exposes GET /pubkey. Record that key when you deploy Archeion, over a channel you trust (a key copied from the file you are verifying proves nothing), and pass it as --trust-key. From then on anyone can verify a sealed session offline, with no server, using only the log file and the key. The pin does two jobs: the seal must be signed by exactly that key, and a session with no seal at all fails. If a seal signature does not check out, the verifier does not quietly downgrade it. It reports COMPROMISED, because a broken seal is stronger evidence of tampering than no seal at all. Verified without the pin, the same sealed file reports SELF_SEALED_EVIDENCE and a warning: the key is carried inside the seal, so anyone can produce a seal under a key of their own.
$ sasana verify session.jsonl --trust-key <archeion-pubkey> --strict
Sasana Verifier v2.0.0
Events: 5 Evidence: AUTHORITATIVE_EVIDENCE
Trusted key: pinned (--trust-key)
Canonicalization: jcs-rfc8785
[1/5] Structural validity ... PASS
[2/5] Sequence integrity ... PASS
[3/5] Hash chain integrity ... PASS
[4/5] Session completeness ... PASS
[5/5] Seal signature ... PASS (signed by the pinned key)
Result: INTACT ✅
$ sasana verify session.jsonl
Evidence: SELF_SEALED_EVIDENCE
Trusted key: none (seal key NOT trusted)
...
[5/5] Seal signature ... SELF-SIGNED (valid against its own embedded key only)
⚠ seal not verified against a trusted key; anyone can produce this
Result: INTACT ✅That top line, AUTHORITATIVE_EVIDENCE, is the class you cannot reach without an independent sealer and a pinned key. It is the verifier saying the sealing authority, not the agent or anyone with access to the file, vouches for this chain head. Everything below it on the ladder, down to a plain local hash chain, is the operator vouching for the operator to some degree. This is exactly the boundary the architecture page walks through structure by structure.
One deployment detail is the whole point rather than an afterthought: Archeion runs inside your security perimeter, operated by your security team, not by the people who build the agent. The closest familiar analogy is HashiCorp Vault, which organisations run inside their own perimeter to hold secrets. A single vendor running both your agent and a cloud sealing service would not give you independence, because the two roles would collapse back into one authority. Self-hosting keeps them apart, which is the property that makes the seal mean anything. Network access is the other half of that separation: Archeion has no caller authentication, so whoever can reach POST /seal can get a chain sealed.
So, back to the regulation
Article 12 requires logs. It does not require any of the machinery above. But the reason to record events at all is so you can rely on them later, and the moment you rely on them in front of a regulator or a court, the operator being able to edit the record silently is the failure mode. An independently sealed log answers the one question a plain log cannot: not just “was this changed since it was written,” but “could the party holding it have written whatever they wanted.” With Archeion in the chain, its key pinned in the verifier, and Archeion out of the operator’s reach, the answer is no, and that answer does not depend on trusting the operator.
The honest limits
Two things Archeion does not do, because a security tool that hides its assumptions is not a security tool.
It does not stop an agent from lying while the log is being written. If the agent records a false event, Archeion will happily seal a log containing that false event. What a pinned seal shows is narrow and worth stating precisely: this chain head was presented to the sealing key, at the time recorded in the seal. It does not show the record was honest at write time. Nor does it stop a rewrite by someone who can still reach Archeion: Archeion authenticates no callers and remembers nothing it has sealed, so a rewritten copy of an earlier session, sealed later, verifies as AUTHORITATIVE_EVIDENCE too (we tested exactly this). The protection is the separation: keep Archeion unreachable from the people being audited, seal at session end, and treat a seal made long after the session ended as a red flag. Authoritative evidence reduces the trust you place in the operator; it does not reduce it to zero.
And it is still true that the EU AI Act does not, today, make any of this mandatory. Tamper-evidence is not the regulatory minimum. It is what the difference between a log you filed and a log you can defend actually costs. If your high-risk system will ever have to prove what it did to someone who does not have to take your word for it, that is the standard you are really building for.
Further reading
- Sasana compliance mapping · EU AI Act Article 12, SOC 2, HIPAA
- Your AI agent logs satisfy Article 12. They won’t survive a dispute.
- Your tamper-evident log can still be backdated. Here’s what closes that.
- Try to tamper with a hash-chained log and watch the chain break
- EU AI Act Article 12 · EUR-Lex official text