← Documentation

Chain Verification

Chain Verification

Every ledger entry is cryptographically linked to the entry before it using SHA-256. This makes the audit trail tamper-evident: modifying any historical entry invalidates all subsequent hashes, and the break is immediately detectable.

How the chain is built

For each new ledger entry, Imara computes:

1

Serialize the full entry payload to canonical JSON (sorted keys, no whitespace).

2

Concatenate the previous entry's hash (hex string) with the serialized payload.

3

SHA-256 hash the concatenated bytes. This becomes the current entry's hash.

4

The genesis entry uses a zero hash (64 hex zeros) as the previous value.

hash_n = SHA256( hash_{n-1} + canonical_json(entry_n) )

Ledger entry schema

Each entry written to the ledger and replicated to S3 contains:

{
  "timestamp":        "2026-04-21T14:32:01.882Z",
  "fintech_id":       "acme-bank",
  "session_id":       "sess_01HXXXXX",
  "classified_act":   "ACTION_PAYMENT_INITIATE",
  "status":           "SUCCESS",
  "raw_intent":       "Initiate a payment of $500 to account 9876",
  "estimated_tokens": 142,
  "latency_ms":       38,
  "prev_hash":        "a3f9c2d8e1b4...",
  "hash":             "b7e1a4f2c9d3..."
}

Verifying via the API

The runtime exposes a chain verification endpoint that recomputes every hash and reports the first broken link.

curl http://localhost:7070/ledger/chain \
  -H 'X-Imara-Token: stratus-dev-token-change-me' | jq .

Intact chain response:

{
  "chain_valid":  true,
  "entry_count":  42,
  "head_hash":    "d1a9e5c3b7f2...",
  "broken_at":    null
}

Tampered chain response:

{
  "chain_valid":  false,
  "entry_count":  42,
  "head_hash":    "d1a9e5c3b7f2...",
  "broken_at":    7,
  "expected":     "c8d3b6e1f2a4...",
  "got":          "ffffffffffffffff..."
}

Verifying independently

Any party with read access to the replicated S3 objects can verify the chain without trusting Imara. The algorithm is standard SHA-256 — no custom library or SDK required.

#!/usr/bin/env python3
import json, hashlib, boto3

s3  = boto3.client("s3")
objs = s3.list_objects_v2(Bucket="stratus-audit", Prefix="ledger/acme-bank/")
entries = sorted(o["Key"] for o in objs.get("Contents", []))

prev_hash = "0" * 64
for key in entries:
    body  = s3.get_object(Bucket="stratus-audit", Key=key)["Body"].read()
    entry = json.loads(body)
    data  = prev_hash + json.dumps(entry, sort_keys=True, separators=(",",":"))
    computed = hashlib.sha256(data.encode()).hexdigest()
    assert computed == entry["hash"], f"Chain broken at {key}"
    prev_hash = computed

print("Chain intact ✓", len(entries), "entries")

Portal chain view

The regulator portal at /chain performs the same verification client-side using the ledger data fetched from S3. It highlights the broken entry and shows the expected vs. actual hash diff. No access to the Imara runtime is needed — the portal reads S3 directly.