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.

01

The envelope

{
"session_id": "3f8a2c1d-…",
← UUID, constant across the session
"agent_id": "loan-officer-agent",
← who was running
"seq": 3,
← monotonic, reordering is detectable
"event_type": "TOOL_CALL",
← CHAIN_SEAL is type-blocked in the SDK
"timestamp": "2026-07-04T09:12:08Z",
← operator clock, see RFC 3161 below
"payload": { "args_hash": "b2e8…" },
← hashes only. raw content never stored
"prev_hash": "4d1a7f3b…",
← commits to all prior events
"event_hash": "b2e8d4a0…"
← SHA-256 over RFC 8785 canonical JSON
}

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.

02

The Archeion authority boundary

AGENT PROCESS · OPERATOR TRUST BOUNDARY
SDK records events → JSONL
SDK cannot emit CHAIN_SEAL (EventType.is_sdk_authority, enforced at the type level)
│POST /seal · hashes only, no content
ARCHEION SEALING SERVER · SECURITY TEAM BOUNDARY
verifies hash chain integrity
appends CHAIN_SEAL with Ed25519 signature
returns sealed JSONL → AUTHORITATIVE_EVIDENCE (when verified with --trust-key)

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.

03

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. [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. [2/5]The hash, only the hash, goes to Freetsa
  3. [3/5]The TSA signs: “this hash existed at this time”
  4. [4/5]The token is committed into the chain
  5. [5/5]The rest of the session chains from the new hash
SESSION_START seq=0
payload: { sdk_version, ts_utc }
event_hash: ff4be53f333aa85e7491961e0d944093…
│ POST /tsr → freetsa.org (32-byte digest only, never content)
RFC 3161 TSA /O=Free TSA/OU=TSA/CN=www.freetsa.org · independent of the operator
│ signed token returns → embedded in payload → hash recomputed
SESSION_END seq=N
prev_hash chains to:
04

Adversary model

idattackdefense
A1Event injectionprev_hash chain; out-of-sequence seq rejected
A2Tampering on the way to the sealerNOT 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
A3Event deletionseq gap and broken prev_hash link (there is no Merkle tree; the chain tip is the root). Rebuilding the chain afterwards is A5
A4Event reorderingseq monotonically increases; prev_hash links
A5Full chain rewriteNOT 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
A6Rewrite and re-seal under an attacker keyRejected only if the verifier pins the Archeion key (--trust-key). Unpinned it verifies as SELF_SEALED_EVIDENCE, never AUTHORITATIVE
A7Rewrite and strip the sealCOMPROMISED with --trust-key or --require-seal; otherwise INTACT with NON_AUTHORITATIVE_EVIDENCE and a warning
A8Rewrite, then have the genuine Archeion seal itNOT 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.”