Raised by @l33tdawg in agentrust-io/.github discussion #15, who suggested trace-spec as the home for it. Opening it here rather than leaving him to file it.
Problem
To anchor a TRACE record's transparency field and verify inclusion independently, a third party needs the Merkle anchor and inclusion-proof format. That format is specified: docs/anchor-format.md in agentrust-io/trace-registry is normative and explicitly written so a conforming verifier can be built from the document alone.
trace-registry is private for operational reasons, not because the format is unsettled. The effect is that the one document an external verifier needs is the one they cannot read, which undercuts the "verify without trusting the operator" property the registry exists to provide. An inclusion proof nobody outside can check is not much of a transparency log.
Proposal
Publish the anchor format as a public document. Options, in rough order of preference:
- Move it into
trace-spec as a companion spec document, since this is the public spec home and @l33tdawg suggested it. The registry keeps its implementation private; the format it commits to becomes public.
- Make
trace-registry public. Cleanest for auditability, largest decision.
- Publish on the docs site only. Fastest, but splits the spec across two homes.
Whichever way, the reference verifier (src/trace_verify/_verify.py, RFC 9162 inclusion check) should be reachable too, since "here is the algorithm, and here is one implementation that is not the definition" is the useful pairing.
What the document has to state, since these are the parts people get wrong
- RFC 6962 CT Merkle trees; RFC 9162 inclusion-proof check.
- The anchored unit is the complete signed claim, signature included, not a pre-signature payload.
canonical_claim_bytes is sorted-key JSON: json.dumps(claim, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode("ascii"), no trailing newline.
leaf = SHA-256(0x00 || canonical_claim_bytes); interior node = SHA-256(0x01 || left || right).
- Proof shape
{leaf_index, audit_path} against a checkpoint carrying merkle_root, leaf_count, ts, producer, batch_id.
The trap that most deserves prominence: the registry anchor uses sorted-key JSON, while TRACE record signing uses RFC 8785 (JCS). Two canonicalizations at two layers. An implementer who reasonably assumes JCS at the leaf will produce proofs that never verify, with no useful error. That warning belongs in the published document, not only in a discussion thread.
Related: TRACE v0.2 made transparency optional below Level 2 (see #109), since an unanchored Level 0/1 record has no receipt to name. Publishing the anchor format is what makes Level 2 independently checkable.
Raised by @l33tdawg in agentrust-io/.github discussion #15, who suggested trace-spec as the home for it. Opening it here rather than leaving him to file it.
Problem
To anchor a TRACE record's
transparencyfield and verify inclusion independently, a third party needs the Merkle anchor and inclusion-proof format. That format is specified:docs/anchor-format.mdinagentrust-io/trace-registryis normative and explicitly written so a conforming verifier can be built from the document alone.trace-registryis private for operational reasons, not because the format is unsettled. The effect is that the one document an external verifier needs is the one they cannot read, which undercuts the "verify without trusting the operator" property the registry exists to provide. An inclusion proof nobody outside can check is not much of a transparency log.Proposal
Publish the anchor format as a public document. Options, in rough order of preference:
trace-specas a companion spec document, since this is the public spec home and @l33tdawg suggested it. The registry keeps its implementation private; the format it commits to becomes public.trace-registrypublic. Cleanest for auditability, largest decision.Whichever way, the reference verifier (
src/trace_verify/_verify.py, RFC 9162 inclusion check) should be reachable too, since "here is the algorithm, and here is one implementation that is not the definition" is the useful pairing.What the document has to state, since these are the parts people get wrong
canonical_claim_bytesis sorted-key JSON:json.dumps(claim, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode("ascii"), no trailing newline.leaf = SHA-256(0x00 || canonical_claim_bytes); interiornode = SHA-256(0x01 || left || right).{leaf_index, audit_path}against a checkpoint carryingmerkle_root,leaf_count,ts,producer,batch_id.The trap that most deserves prominence: the registry anchor uses sorted-key JSON, while TRACE record signing uses RFC 8785 (JCS). Two canonicalizations at two layers. An implementer who reasonably assumes JCS at the leaf will produce proofs that never verify, with no useful error. That warning belongs in the published document, not only in a discussion thread.
Related: TRACE v0.2 made
transparencyoptional below Level 2 (see #109), since an unanchored Level 0/1 record has no receipt to name. Publishing the anchor format is what makes Level 2 independently checkable.