This walkthrough demonstrates how a HATS verifier detects a chain discontinuity caused by a deleted node. The original session contained three nodes (indices 0, 1, 2). Node 1 has been removed from the bundle, leaving only nodes 0 and 2. Node 2's predecessor_hash still references the hash of the deleted node 1, creating a gap in the chain.
The expected verifier output is CHAIN_BREAK at position 2 (the first node whose predecessor cannot be resolved).
predecessor_hash does not match the SHA3-256 digest of the immediately preceding node in the bundle. Indicates that one or more intermediate nodes have been removed.predecessor_hash field against the computed hash of the preceding node in the bundle. If the preceding node's hash does not match, the chain is broken.The following bundle contains only two nodes: the original node 0 and the original node 2. Node 1 (COMPUTE_EXECUTE) has been deleted. Note that node indices have been renumbered to 0 and 1, but the predecessor_hash of the second node still references the deleted node's hash.
{
"schema_version": "1.0.0",
"bundle_id": "b8f3c2a1-4e5d-4a6b-9c8d-7e6f5a4b3c2d",
"session_id": "s-20260515-143000-a1b2c3",
"tenant_id": "t-9f8e7d6c-5b4a-3c2d-1e0f-a9b8c7d6e5f4",
"created_at": "2026-05-15T14:30:00.000Z",
"nodes": [
{
"node_index": 0,
"action_type": "POLICY_BIND",
"payload_hash": "a3f1b2c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1",
"timestamp": "2026-05-15T14:30:00.000Z",
"predecessor_hash": "0000000000000000000000000000000000000000000000000000000000000000",
"node_hash": "c7a8b9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7",
"signatures": {
"ml_dsa_65": "ML-DSA-65:3045022100...truncated...b8c9d0e1f2",
"falcon_512": "FALCON-512:3045022100...truncated...a1b2c3d4e5",
"slh_dsa": "SLH-DSA-SHA2-128f:3045022100...truncated...f6a7b8c9d0"
}
},
{
"node_index": 1,
"action_type": "RESULT_RECORD",
"payload_hash": "f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6",
"timestamp": "2026-05-15T14:30:02.891Z",
"predecessor_hash": "e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5",
"node_hash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1",
"signatures": {
"ml_dsa_65": "ML-DSA-65:3045022100...truncated...d0e1f2a3b4",
"falcon_512": "FALCON-512:3045022100...truncated...c3d4e5f6a7",
"slh_dsa": "SLH-DSA-SHA2-128f:3045022100...truncated...b8c9d0e1f2"
}
}
]
}Node 1's predecessor_hash is e5f6a7b8...d4e5, which was the node_hash of the deleted COMPUTE_EXECUTE node. The actual preceding node in the bundle (node 0) has node_hash = c7a8b9d0...f6a7. These do not match.
$ hats verify broken-chain.jsonFor each node at position i > 0, the verifier:
predecessor_hash from node i.CHAIN_BREAK at position i.| Field | Expected (from node 0) | Declared (in node 1) | Match |
|---|---|---|---|
predecessor_hash |
c7a8b9d0e1f2a3b4...e5f6a7 |
e5f6a7b8c9d0e1f2...d4e5 |
NO |
The expected predecessor hash is the SHA3-256 of node 0's canonical serialization (c7a8b9d0...e5f6a7). The declared predecessor hash in node 1 is e5f6a7b8...d4e5, which corresponds to the deleted node. The mismatch proves that at least one node was removed between nodes 0 and 1.
The verifier detects that a chain break occurred but cannot determine:
These limitations are inherent to hash-chain integrity checking. The verifier reports the structural fact; interpretation is the auditor's responsibility.
$ hats verify broken-chain.json
HATS Verifier v1.0.0
Bundle: b8f3c2a1-4e5d-4a6b-9c8d-7e6f5a4b3c2d
Session: s-20260515-143000-a1b2c3
Checking schema .............. OK
Checking chain integrity ..... FAILED
CHAIN_BREAK at position 1:
predecessor_hash declared: e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5
predecessor_hash expected: c7a8b9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7
preceding node hash: c7a8b9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7
Result: CHAIN_BREAK
Position: 1 (node_index: 1, action_type: RESULT_RECORD)
Gap: predecessor references hash not matching any adjacent node
Impact: Bundle integrity cannot be established; one or more nodes missing
Duration: 3ms{
"status": "CHAIN_BREAK",
"bundle_id": "b8f3c2a1-4e5d-4a6b-9c8d-7e6f5a4b3c2d",
"failure": {
"type": "CHAIN_BREAK",
"position": 1,
"node_index": 1,
"action_type": "RESULT_RECORD",
"declared_predecessor": "e5f6a7b8c9d0e1f2...d4e5",
"expected_predecessor": "c7a8b9d0e1f2a3b4...f6a7",
"message": "Predecessor hash at position 1 does not match hash of preceding node. One or more nodes may have been deleted."
},
"nodes_checked": 2,
"chain_links_checked": 1,
"chain_links_passed": 0,
"duration_ms": 3
}A chain break and a tampered receipt produce different failure types and are detected by different checks:
| Property | Chain Break | Tampered Receipt |
|---|---|---|
| Detection check | Chain integrity | Node hash verification |
| Failure type | CHAIN_BREAK | NODE_HASH_MISMATCH |
| Root cause | Missing node(s) | Modified field(s) |
| Signatures affected | Not checked (halted at chain) | All signatures on tampered node |
| Node content preserved | No (deleted) | Yes (modified) |
A verifier implementation is conformant with this walkthrough if, given the input bundle above, it produces the CHAIN_BREAK status at position 1 (or position 2 if using 1-indexed positions, with the position value documented). The declared and expected predecessor hashes MUST be included in the failure output.
Conformance test vector ID: HATS-VW-003-BROKEN-CHAIN