MECHANISM, NOT MARKETING
Every guarantee traces to a specific structure.
Four structures carry the whole system: the envelope, the authority boundary, the time anchor, and an adversary model honest about its own limits.
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 page has been revised to match 2.0.0. See the 2.0.0 changelog.
The envelope
Every event carries the same envelope. The hash is computed over RFC 8785 canonical JSON, a deterministic serialization. Without it, two implementations can hash the same logical object to different bytes: different hashes for identical content, or identical hashes for different content. Canonicalization is what makes the hash a statement about meaning, not formatting. Since 2.0.0 each session declares its algorithm in the hashed SESSION_START payload (canonicalization: jcs-rfc8785); logs from 1.x carry no declaration and are verified with their original encoding. The verifier reads the declaration once and never tries both.
Payloads contain digests, not data. You cannot reconstruct a prompt from a Sasana log, which is why the log itself can cross a compliance boundary that raw transcripts cannot (GDPR, HIPAA: no PHI, no PII in the trail).
If events are dropped under backpressure, the SDK records a LOG_DROP marker, the chain stays intact but the verifier downgrades the result to PARTIAL. Honest about its own gaps.
The Archeion authority boundary
A hash chain proves internal consistency, not authorship. An operator who controls the storage can discard the log and write a fresh, internally-consistent chain where every hash is correct and every event is fabricated.
The fix is structural, not procedural: the entity that seals the log is separate from the entity that operatesthe agent. Archeion runs inside your security perimeter, controlled by your security team, not the agent developers. The SDK is type-blocked from emitting a seal. The agent cannot produce a seal that verifies against Archeion’s key.
This is a structural guarantee, not a policy, provided the verifier pins Archeion’s public key (--trust-key). Without the pin a seal only shows the file is self-consistent: anyone can generate a key and seal a rewritten log.
What a seal shows is narrow: this chain head was presented to Archeion, at the time recorded in the seal. Archeion authenticates no callers and keeps no record of what it has sealed, so anyone who can reach POST /seal can get any consistent chain sealed, including a rewrite of an earlier session (A8). The separation protects only against people who cannot reach it.
RFC 3161: anchoring time to an independent authority
A hash chain detects edits to events. It cannot prove when “written” was. A session backdated to 2020 verifies INTACT. The two-pass write below embeds a token an independent authority signed; checking that signature is what turns it into a time claim. sasana verify checks only that the token matches (imprint) and does not verify the signature or the time. Scroll through it. These are the real hashes from the live run.
- [1/5]SESSION_START is written, without a token
On open_session(), the first event is committed and hashed over canonical JSON. This hash is the exact 32 bytes the TSA will see.
- [2/5]The hash, only the hash, goes to Freetsa
- [3/5]The TSA signs: “this hash existed at this time”
- [4/5]The token is committed into the chain
- [5/5]The rest of the session chains from the new hash
Adversary model
| id | attack | defense |
|---|---|---|
| A1 | Event injection | prev_hash chain; out-of-sequence seq rejected |
| A2 | Tampering on the way to the sealer | NOT defended end to end: Archeion re-verifies the chain it receives but seals any consistent chain it is sent. Protect the path from agent to Archeion |
| A3 | Event deletion | seq gap and broken prev_hash link (there is no Merkle tree; the chain tip is the root). Rebuilding the chain afterwards is A5 |
| A4 | Event reordering | seq monotonically increases; prev_hash links |
| A5 | Full chain rewrite | NOT defended in local mode; requires a seal from Archeion verified against a pinned key (--trust-key). RFC 3161 does not defend this: a rewrite simply gets a new token with a new time. See also A8 |
| A6 | Rewrite and re-seal under an attacker key | Rejected only if the verifier pins the Archeion key (--trust-key). Unpinned it verifies as SELF_SEALED_EVIDENCE, never AUTHORITATIVE |
| A7 | Rewrite and strip the seal | COMPROMISED with --trust-key or --require-seal; otherwise INTACT with NON_AUTHORITATIVE_EVIDENCE and a warning |
| A8 | Rewrite, then have the genuine Archeion seal it | NOT defended by the seal: Archeion authenticates no callers and remembers nothing it has sealed, so a rewritten copy of a session verifies as AUTHORITATIVE if it can reach POST /seal. Keep Archeion unreachable from the people being audited, seal at session end, and check the seal time against SESSION_END |
A5 is stated in red on purpose. A security tool that hides its own trust assumptions is not a security tool. In local, unsealed mode, a full chain rewrite by the operator is undetectable. That is the gap the Archeion boundary exists to close, when the verifier pins its key. RFC 3161 addresses a different gap, when the session started. It is also why the verifier reports an evidence classinstead of a binary “valid.”