Add optional guidance on committing a CDEvent's canonical hash - #320
Add optional guidance on committing a CDEvent's canonical hash#320MarkovianProtocol wants to merge 4 commits into
Conversation
Adds an informational companion document describing two distinct properties: authenticity and integrity via DSSE, and existence-over-time via an optional commitment to the event canonical hash on an external timeline. Mechanism-agnostic per the discussion in cdevents#315: the document names the class of anchors without endorsing one. No schema changes; nothing is required of an implementer. Signed-off-by: Colin H Winter <hello@markovianprotocol.com>
c92881c to
0f085aa
Compare
| url | ||
| viewUrl | ||
| wpaper | ||
| CDF |
There was a problem hiding this comment.
Why was this section moved?
Typical ordering based is based on ASCII / unicode order which has capital letters first.
There was a problem hiding this comment.
Restored — my edit had re-sorted the file case-insensitively, which moved the capitalized block. The original ordering is back with the additions inserted in place, plus the missing canonicalization entry that caused the CI failure.
Restore the original ordering of .spellcheck-en-custom.txt (capitalized entries first) with additions inserted in place, and add the missing 'canonicalization' entry that failed CI. Move the worked example into examples/event-provenance/ per review preference and point the guide at the in-repo path. Signed-off-by: Colin H Winter <hello@markovianprotocol.com>
| Note on CloudEvents: a message-level signature profile for CloudEvents itself is an open | ||
| discussion in the CloudEvents project | ||
| ([cloudevents/spec#565](https://github.com/cloudevents/spec/issues/565)) rather than a | ||
| finished standard. Applying DSSE to the CDEvent document, as described here, does not |
There was a problem hiding this comment.
The PR is merged, so I believe the discussion is over - FYI @xibz.
Should we refer to that as the recommended approach for signatures (part 1)?
There was a problem hiding this comment.
Updated in the latest commit: the note now points at the merged verifiability extension and recommends it as the signing approach when a CDEvent travels as a CloudEvent — it's DSSE in both cases, so the extension and Part 1 align rather than compete. The extension's own non-goals (stream completeness, ordering, existence over time) are exactly what the Part 2 commitment adds, so the two compose.
| Which anchor to use is an operational and threat-model choice. The only thing CDEvents | ||
| tooling needs to agree on is the commitment itself: the canonicalization | ||
| (RFC 8785) and the hash (SHA-256). Everything about the anchor is out of scope for this | ||
| document and MUST NOT be assumed by consumers. |
afrittoli
left a comment
There was a problem hiding this comment.
Thanks for this PR @MarkovianProtocol - much appreciated!
I left a comment about DSSE and CloudEvents, let me know what you think.
I'm not sure if the CloudEvents SDK already supports DSSE. Do you think we should include something in the CDEvents SDKs to support the generation of the sea for the commitment side (part 2)?
I think the docs might benefit from a mermaid diagram showing which part is signed, where the signature is stored, on what the commitment is calculated on and where it is stored, but this can be done as a follow up.
- Add 'runnable' to the spellcheck wordlist (vendored example README) - Exempt event.canonical.json from JSON style linting: its exact bytes are the RFC 8785 canonical serialization the example commits to, so it cannot be reformatted - Update the CloudEvents note: the DSSE verifiability extension has merged; reference it as the recommended signing approach when a CDEvent travels as a CloudEvent, with Part 2 as the composing layer for the extension's stated non-goals Signed-off-by: Colin H Winter <hello@markovianprotocol.com>
|
Thanks for the review. Both CI failures are addressed in the new commit — one with a change worth flagging: On SDK support for the commitment side: yes, and it can stay small and neutral — a helper that emits the canonical bytes and their SHA-256 covers the part every anchor shares, while the anchor choice stays out of the SDK. Whether the CloudEvents SDKs ship DSSE for the verifiability extension yet I don't know; the extension specifies the SDK flow, so CDEvents inherits it wherever those SDKs land. On the diagram: agreed, and happy to contribute it as a follow-up — one sequence showing what is signed, where the signature rides, what the commitment is computed over, and where each is stored. |
|
Checks pass, the review comments are addressed, and the vendored example verifies from a fresh clone — the genuine event passes both checks, the tampered one fails both. Ready for review whenever the group has time. @xibz — I can't make the SIG call. If it's useful I can write the walkthrough up as a comment here for you to take to the group, or answer questions in the thread. |
|
Small follow-on to the Part 2 anchor discussion: the log used in the vendored worked example (examples/event-provenance/) now issues offline proof bundles (c2sp.org/tlog-proof) and accepts public submissions — a CDEvent's canonical-bytes sha256 can be notarized with one curl and the receipt re-verified with no network and no trust in the log operator. No spec impact; noting it because the example's anchor step is now reproducible end-to-end by any reviewer. |
|
Thanks for putting this together, and for taking the DSSE/anchoring distinction as far as a full worked example, that's a lot of careful work. Looking back at #315, though, I think this PR has grown past what we actually scoped there. What I originally asked for was a short paragraph on the authenticity-vs-existence-in-time distinction, to live in the DSSE guidance doc I was planning to write myself. What we're reviewing here is a full standalone document, and it includes the DSSE guidance itself (Part 1), a runnable example with its own dependency set, CI lint carve-outs, and new wordlist entries, plus a README entry that puts it on the same tier as spec.md and the schemas. I'd like to split this into two pieces that match what was actually agreed:
I also don't think this should say "Closes #315", since #315's original subject (the markovianroot/markovianverify extension attributes) was addressed by pointing to DSSE, not by this document. Appreciate the work either way, just want to make sure this goes through the process we agreed to before it lands. |
|
You're right, and I should have come back to #315 before writing rather than after. I'll cut this PR down to Part 2 — the anchor and pre-commitment guidance plus the worked example — and drop the DSSE guidance, the README tier entry, and the "Closes #315" line. Part 1 is yours; #315 was answered by pointing at DSSE, not by this. On Part 2, I'd rather walk it through at the SIG as you asked than keep it sitting in review. When does the SIG next meet, and is it enough to show up, or do you want something written circulated first? The example brings its own dependencies and a lint carve-out, so if the SIG would rather the guidance land without a runnable example, I can move the example to my own repo and cite it. |
Cuts this PR back to what cdevents#315 scoped and what the SIG has not yet discussed, per review: - drops Part 1 (DSSE guidance), which the maintainer is writing - drops the in-tree worked example, its dependency set and the eslint carve-out it needed - reverts the README key-assets entry - trims the wordlist to the terms the remaining text uses What is left is the optional hash commitment: RFC 8785 canonicalization, SHA-256, and an anchor the document deliberately does not pick. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018SdjRQgeydA1YSxbmMXmbZ
|
Cut, in c81e69c. Two files now: Part 1 is yours, so it's gone, along with the in-tree example, the eslint carve-out, the README entry, and the "Closes #315" line. What's left is the commitment and what it doesn't prove. Still happy to hold it for the SIG rather than merge. |
Adds an optional, informational document on one property a signature does not carry: that an event existed by a given time.
The mechanism is a commitment — canonicalize the CDEvent with RFC 8785 (JCS), hash the canonical bytes with SHA-256, record the digest on a timeline the emitter does not control. The document does not pick an anchor. RFC 3161 timestamp authorities, append-only transparency logs and public blockchain inclusion are named as a class; which one to use is an operational choice and explicitly out of scope. The only thing CDEvents tooling needs to agree on is the canonicalization and the hash.
The document also states what the commitment does not prove: authorship, that the anchoring party did not wait to see how something resolved before writing the anchor, and anything at all about events that were never committed.
Scope
event-provenance.md. Seven wordlist entries for the terms it uses.spec.mdor the README, no changes to CI configuration, no in-tree example.This PR was previously larger. Per @xibz's review it has been cut back: the DSSE guidance (Part 1) is out, since that is the document he is writing; the in-tree worked example, its dependency set and the eslint carve-out it required are out; the README entry is reverted. The worked example is kept outside this repository. This no longer closes #315 — that issue's original subject was answered by pointing at DSSE.
Happy to walk through what is left at the SIG before it merges, as agreed.