Summary
audit.export reports the wrong content_hash_hex for format-v2 entries, so an exported chain that has switched to v2 does not link.
The export computes each entry's hash as BLAKE3(signing_data) (crates/astrid-kernel/src/kernel_router/admin/audit_handlers.rs, content_hash_hex: ContentHash::hash(&signing_data)). That is the content hash of a format-v1 entry. For a format-v2 entry (#2005), the signing data is the signature wrapper of the entry hash, while chain links, audit.heads and prune receipts use the SHA-256 entry hash of the canonical body. So from the first v2 entry on, an exported entry's content_hash_hex matches neither the next entry's previous_hash_hex nor the head hash in audit.heads. A verifier following an export (the purpose of #1996) cannot link the chain.
Reproduction Steps
- Append two entries to a principal's chain with the default format (v1).
- Enable format v2 (
[audit] entry_format = "v2", or AuditLog::enable_entry_v2) and append three more entries.
- Export the chain with
audit.export.
- Compare each exported
content_hash_hex with the next entry's previous_hash_hex, and the last one with the chain's head in the page and in audit.heads.
Expected Behavior
Each exported content_hash_hex is the value the next entry's previous_hash_hex links to, in either format: BLAKE3(signing_data) for v1, the SHA-256 entry hash for v2. The last one equals the chain head in the page and in audit.heads. For v1 entries nothing changes.
Actual: for v2 entries the exported hash is BLAKE3 of the signature wrapper; the links and the head check fail from the first v2 entry.
Environment
Summary
audit.exportreports the wrongcontent_hash_hexfor format-v2 entries, so an exported chain that has switched to v2 does not link.The export computes each entry's hash as
BLAKE3(signing_data)(crates/astrid-kernel/src/kernel_router/admin/audit_handlers.rs,content_hash_hex: ContentHash::hash(&signing_data)). That is the content hash of a format-v1 entry. For a format-v2 entry (#2005), the signing data is the signature wrapper of the entry hash, while chain links,audit.headsand prune receipts use the SHA-256 entry hash of the canonical body. So from the first v2 entry on, an exported entry'scontent_hash_hexmatches neither the next entry'sprevious_hash_hexnor the head hash inaudit.heads. A verifier following an export (the purpose of #1996) cannot link the chain.Reproduction Steps
[audit] entry_format = "v2", orAuditLog::enable_entry_v2) and append three more entries.audit.export.content_hash_hexwith the next entry'sprevious_hash_hex, and the last one with the chain's head in the page and inaudit.heads.Expected Behavior
Each exported
content_hash_hexis the value the next entry'sprevious_hash_hexlinks to, in either format:BLAKE3(signing_data)for v1, the SHA-256 entry hash for v2. The last one equals the chain head in the page and inaudit.heads. For v1 entries nothing changes.Actual: for v2 entries the exported hash is
BLAKE3of the signature wrapper; the links and the head check fail from the first v2 entry.Environment
mainat 4925a9c (after feat(audit): canonical, fully signed entry format (v2) with registered-key verification #2005)entry_format = "v2"; v1 exports are unaffected.