FORMAT
HELM v3 Evidence Bundle Format
Canonicalization
00_INDEX.json MUST be canonical JSON:
- Keys sorted lexicographically (recursive)
- No trailing whitespace
- UTF-8 encoded
- No BOM
- Single trailing newline
This matches JCS (RFC 8785).
Manifest Root Hash
manifest_root_hash = sha256(canonical_bytes(00_INDEX.json))
Identity of the bundle. Cache key. Single hash that pins the entire evidence tree.
Merkle Tree
Leaves are the sha256 hex strings from each 00_INDEX.json entry, sorted ascending by path string. Each hex string is decoded to 32 bytes before hashing.
Construction
leaf_hash = sha256(0x00 || entry_sha256_bytes) # domain separator: leaf
internal = sha256(0x01 || left_hash || right_hash) # domain separator: node
odd_leaf → duplicate last leaf
merkle_root = root hash (hex)
Ordering
Leaves are sorted by canonical path string (ascending, lexicographic). This prevents order drift across implementations.
Verification Algorithm
1. Read 00_INDEX.json
2. Sort entries by path ascending
3. Decode each entry.sha256 from hex → 32 bytes
4. Hash each: leaf = sha256(0x00 || bytes)
5. Build tree bottom-up:
a. If odd number of leaves, duplicate last
b. Parent = sha256(0x01 || left || right)
6. Root = final hash (hex)
7. Compare to attestation merkle_root
Attestation
{
"format": "helm-attestation-v3",
"release_tag": "v0.9.1",
"asset_name": "helm-evidence-v0.9.1.tar",
"asset_sha256": "abc123...",
"manifest_root_hash": "def456...",
"merkle_root": "789abc...",
"created_at": "2026-02-21T12:00:00Z",
"profiles_version": "1.0.0"
}
Signed with Ed25519. Signature is over sha256(canonical_bytes(attestation_json)).
Public Key
Shipped in CLI as pinned constant. Key rotation via versioned key list.