docs(spec): state what receipts and checkpoints prove and how their tree sizes relate - #139
Conversation
…ree sizes relate The receipt description said nothing about what the COSE signature covers or how the receipt's tree size relates to /checkpoint, and the checkpoint description named an ed25519 note.pub signer the log does not use. A verifier reading only the spec can conclude that walking the inclusion path proves inclusion, or that a receipt whose tree size lags the current checkpoint is stale or invalid. Receipt: the signature covers the protected header and the attached event; the VDP fields are unsigned; a log may return a receipt minted against an earlier checkpoint unchanged, so its tree size may lag /checkpoint, and the two heads are related through the checkpoint signed at the receipt's size (/v1/log/checkpoint/history) or a consistency proof built from the tiles. Checkpoint: signed with the keys advertised at /root-keys under the same 4-byte key hash receipts carry as kid, ECDSA P-256 over the note body; golang.org/x/mod/sumdb/note cannot verify it. A verified checkpoint proves the log signed that head, not consistency with earlier heads or a shared view across clients. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: kperry <kperry@godaddy.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The documentation incorrectly claims the entire sumdb/note package only accepts Ed25519 signers.
Review effort: Balanced
Findings: 2
Open (2)
What changed in this PR
Clarifies the transparency log’s receipt and checkpoint verification guarantees.
Changes:
- Documents unsigned receipt inclusion-proof fields and tree-size relationships.
- Corrects checkpoint signing and verification guidance.
| File | Description |
|---|---|
spec/api-spec-tl-v2.yaml |
Updates canonical TL API documentation. |
internal/adapter/docsui/openapi/tl.yaml |
Synchronizes embedded API documentation. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
… parser The checkpoint description said golang.org/x/mod/sumdb/note cannot verify these notes. note.Open verifies with any caller-supplied note.Verifier, and this repository signs notes through note.Sign with an ECDSA signer; only the built-in note.NewVerifier parser is Ed25519-only and derives a different key hash, so it is /root-keys lines it cannot consume. Say that instead, and re-sync the embedded copy. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: kperry <kperry@godaddy.com>
…l publication check Mirror the ANS-4 wording: the receipt is the log's authenticated statement that it sealed the event and that signature is the check for a relying party; the inclusion proof supports a separate, optional publication check against the checkpoint at the same tree size, which does not establish the log's honesty. A receipt whose tree size lags the current checkpoint is not an invalid receipt, identity, or signature. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: kperry <kperry@godaddy.com>
csnitker-godaddy
left a comment
There was a problem hiding this comment.
Reviewed both PRs together (#139 and agentnameservice/ans-sdk-go#86). These changes address my earlier concerns: checkpoint verification is clearly optional, immutable receipts are handled correctly in the documented model, and a tree-size mismatch is not treated as an authentication failure.
I also verified the signature-order fix and interoperability between the log’s signers and the SDK, including an unchanged receipt after tree growth. The documentation and implementation now agree. No further concerns from me.

The TL contract's receipt entry said nothing about what the COSE signature covers or how the receipt's tree size relates to
/checkpoint, and the checkpoint entry described an ed25519note.pubsigner the log does not use. A relying party reading only this file can conclude that walking the inclusion path proves inclusion, or that a receipt whose tree size lags the current checkpoint is stale. Both came up while integrating a verifier against the SDK (agentnameservice/ans-sdk-go#86). The normative text is in ANS-4 §5.2 (agentnameservice/ans-registry#70); this is the endpoint-level statement./v1/agents/{agentId}/receipt: the signature covers the protected header and the attached event; the VDP fields are unsigned; a log may return a receipt minted against an earlier checkpoint unchanged, so its tree size may lag/checkpoint; the two ways to relate the heads (the checkpoint at that size from the history endpoint, or a consistency proof from the tiles)./checkpoint: signed with the keys advertised at/root-keysunder the same 4-byte key hash receipts carry askid, ECDSA P-256 (ASN.1 DER) over the note body;golang.org/x/mod/sumdb/notecannot verify it; what a verified checkpoint proves.internal/adapter/docsui/openapi/tl.yamlre-synced withmake docs-sync;TestEmbeddedSpecs_MatchCanonicalpasses.AI assistance
Assisted-by: Claude Code (claude-fable-5-1)
🤖 Generated with Claude Code