docs(spec): publish the registry anchor and inclusion-proof format (#111) - #134
Conversation
) The format was already normative and already written so that a conforming verifier could be built from it alone. It lived in trace-registry, which is private, so the one document an external verifier needs was the one they could not read. An inclusion proof nobody outside can check is not transparency. spec/registry-anchor-v1.md publishes it here, in the public spec home, as proposed in the discussion that raised the issue. RFC 6962 trees, RFC 9162 inclusion check, the complete signed claim as the anchored unit, entry fields, proof shape, and a conformance section. Section 0 leads with the trap rather than burying it. TRACE canonicalizes with RFC 8785 JCS for signing and with sorted-key JSON for the anchor leaf. The two agree on ASCII-only records carrying integer numbers, which is most records, which is what makes assuming JCS at the leaf dangerous: the proofs simply never verify and the failure has no useful diagnostic. Section 8 requires that the append-only property be externally checkable rather than asserted. An operator issuing verifiable proofs while publishing nothing an outsider can audit is running a log, not a transparency log. Checked rather than asserted: an implementation written from the published text alone verifies the registry's real anchored sample, and verifies all five proofs of a five-leaf batch built by the registry's own tool, which exercises the odd-node promotion branch that the single-leaf sample does not. A tampered claim is rejected. Also fixed, found while writing this: Four documents told readers to send signed records to registry.agentrust.io, which resolves to third-party parked addresses. Same defect the v0.2 profile cutover fixed in the identifier, missed in the prose. Moved to the host the SDK's adapters already emit. The v0.1 spec keeps its original values, since it is superseded and stands as a record of what was published. The anchoring tutorial documented an API that does not exist: POST a signed record to a SCITT endpoint at that parked domain, read a receipt_uri from the response. Rewritten against the actual mechanism, and it carries a dated note saying what it used to say, because anyone who built against it should know nothing they sent was received. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Reviewed by implementing §1 to §5.1 from the document text alone, since that is the document's own claim, and by checking its two structural assertions rather than reading past them. Both hold. One defect in the package §7 names, one row missing from §0's table, two minor notes. Escapes throughout below, so nothing here depends on how a terminal renders it. Verified§3's equivalence claim is true. "Level by level, promote the odd node unchanged, and this yields the same tree as the RFC 6962 recursive split at the largest power of two" is the kind of sentence that is usually approximately true. I built both constructions independently and compared roots for every batch size from 1 to 200: no mismatch. The document is implementable without the code. §1, §2, §3 and §5.1 written from the text alone, then every leaf of every batch size from 1 to 40 verified against its own root, and a tampered claim rejected against a valid proof. §5.1 is faithful to RFC 9162 §2.1.3.2, including the right-edge promotion shift, which is the part that usually gets dropped. §1 matches the shipped verifier exactly.
|
Closes #111.
The format was already normative and already written so a conforming verifier could be built from it alone. It lived in
trace-registry, which is private, so the one document an external verifier needs was the one they could not read. An inclusion proof nobody outside can check is not transparency.This takes option 1 from the issue, which @l33tdawg proposed: publish it here, in the public spec home, and leave the registry implementation where it is. That decouples publishing the format from the larger decision about repo visibility.
spec/registry-anchor-v1.mdRFC 6962 trees, RFC 9162 inclusion check, the complete signed claim as the anchored unit, entry fields, proof shape, conformance.
§0 leads with the trap rather than burying it, per the issue. TRACE canonicalizes with RFC 8785 (JCS) for signing and sorted-key JSON for the anchor leaf. The two agree on ASCII-only records carrying integer numbers, which is most records, which is exactly what makes assuming JCS at the leaf dangerous: proofs never verify and the failure has no useful diagnostic. The section names the test that catches it.
§8 requires the append-only property to be externally checkable, not asserted. An operator issuing verifiable proofs while publishing nothing an outsider can audit is running a log, not a transparency log.
Verified, not asserted
The point of the document is that someone can implement from it without reading our code, so I checked that rather than claiming it. An implementation written from the published text alone:
leaf_count 1, empty audit path);tools/anchor.py, which exercises the odd-node promotion branch the single-leaf sample never touches (leaf 4gets a 1-element path, leaves 0 to 3 get 3);Two things found while writing it
Four documents told readers to send signed records to a domain we do not own.
docs/integration/agt.md,docs/integration/cmcp.md,docs/trust-levels.mdanddocs/verification.mdnamedregistry.agentrust.io, which resolves to third-party parked addresses. Same defect the v0.2 profile cutover fixed in the identifier, missed in the prose. Moved toregistry.agentrust-io.com, which is what the SDK's adapters already emit.spec/trace-v0.1.mdkeeps its original values: it is superseded and stands as a record of what was published.The anchoring tutorial documented an API that does not exist. It told readers to POST a signed Trust Record to a SCITT HTTP endpoint at that parked domain and read a
receipt_urifrom the response. There is no such endpoint. Rewritten against the actual mechanism: submit to staging, retrieve the inclusion proof, verify it yourself against the published entry. It also still describedtransparencyas a required string, which 0.5.1 changed. The page carries a dated note stating what it used to say, because anyone who built against it should know that nothing they sent was received.Not in this PR
Making
trace-registrypublic. That is a separate decision with a licensing blocker in front of it, covered in the go-public runbook, and this PR is deliberately independent of it.🤖 Generated with Claude Code