Skip to main content
Every snapshot is hashed at write time and linked to the previous snapshot. This allows any party with a copy of the data to independently verify that state has not been tampered with.

Envelope hash

The envelope_hash stored on each snapshot is computed as:
SHA-256( RFC_8785_canonicalize( entityStateEnvelopeV1 ) )
RFC 8785 (JSON Canonicalization Scheme) deterministically orders keys and normalizes Unicode, producing a stable byte sequence regardless of serialization differences. This means the hash can be independently reproduced from the raw envelope without any platform-specific logic.

Chain linkage

Each snapshot stores a prev_hash pointing to the envelope_hash of the preceding version. This forms a hash chain:
snapshot_1: envelope_hash = H1, prev_hash = null
snapshot_2: envelope_hash = H2, prev_hash = H1
snapshot_3: envelope_hash = H3, prev_hash = H2
A valid chain means that to tamper with any historical snapshot you would need to recompute all subsequent hashes — which is detectable.

Server-side verification

Pass the verify query parameter on any snapshot read:
ValueBehavior
noneNo verification (default).
hashRe-computes the RFC 8785 hash and compares against envelope_hash.
chainValidates the full prev_hash chain back to the root snapshot.
The response includes a verification block:
{
  "verification": {
    "valid": true,
    "computed_hash": "adf11c84...",
    "stored_hash": "adf11c84...",
    "matches": {
      "rfc8785": true
    }
  }
}

Offline verification

Export the full ledger with GET .../snapshots/export and run the tally verify-ledger CLI against the bundle to verify hashes and chain integrity without any network dependency.

Chain proof endpoint

GET .../chain-proof returns an ordered list of snapshot_id, envelope_hash, and prev_hash values — the minimum data needed for an independent chain audit without transferring full envelope payloads.