fix(standards): make the IETF draft describe the protocol that ships - #96
Open
ucekmez wants to merge 1 commit into
Open
fix(standards): make the IETF draft describe the protocol that ships#96ucekmez wants to merge 1 commit into
ucekmez wants to merge 1 commit into
Conversation
`docs/standards/draft-eep-protocol-core-00.md` and
`schemas/v0.1/eep-manifest.json` had drifted until not one field name
matched except `eep_version`:
draft requires publisher_did, endpoints.discovery,
endpoints.subscribe, endpoints.stream,
supported_layers, delivery_methods,
conformance_level
schema requires did, eep_version, layers,
supported_content_types, pqc_ready, x402_enabled
A publisher conformant to the shipped schema fails every MUST in the
Internet-Draft, and vice versa. Nothing in CI noticed, because nothing
compared them. ROADMAP.md targets IETF/W3C submission at v0.2, so this
is the document reviewers would read first.
Direction: the draft is rewritten to match the schema, not the reverse.
The schema is implemented by both middleware packages, both reference
implementations and the compliance CLI; the draft has no
implementations at all. Changing the schema instead would be a breaking
change to a published v0.1 artifact for no protocol benefit.
Changes:
- Layer 1 field table restated against `eep-manifest.json`, with the
`layers` object documented and the rule that at least one Layer 2
endpoint must be populated.
- `endpoints.stream` / `endpoints.subscribe` references replaced with
`layers.layer2_sse` / `layers.layer2_webhook`.
- Envelope section documents `eep_version` (what implementations emit)
instead of `eepversion` / `eepdelivery` (which nothing emits).
- Editor's note recording that the shipped `eep_`-prefixed names violate
the CloudEvents v1.0.2 attribute-naming rule, which excludes the
underscore. This is a real problem that becomes load-bearing in binary
content mode, where attributes become `ce-`-prefixed headers. Recorded
as an open question rather than silently renamed: no implementation
emits the compliant spelling today.
- `scripts/check-draft-schema-parity.mjs` plus a CI job, so this class of
drift is a build failure. The gate parses the draft's delimited field
table and diffs names and required-ness against the schema; verified
by injecting drift and confirming a non-zero exit.
No schema changed, so the types drift gate is a no-op here.
Refs: EEP audit 2026-08 finding A1
Signed-off-by: Ugur Cekmez <ucekmez@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR 4 of a stacked series. Base is #95. Not for merge without review.
docs/standards/draft-eep-protocol-core-00.mdandschemas/v0.1/eep-manifest.jsonhave drifted until not one field name matches excepteep_version:publisher_diddidendpoints.discoveryendpoints.subscribelayers.layer2_webhookendpoints.streamlayers.layer2_sseendpoints.pulselayers.layer3_wssupported_layers(array)layers(object)delivery_methodsconformance_levelsupported_content_types,pqc_ready,x402_enabledA publisher conformant to the shipped schema fails every
MUSTin the Internet-Draft, and vice versa. Nothing in CI noticed, because nothing compared them.ROADMAP.mdtargets IETF/W3C submission at v0.2 (Q3 2026). This is the document a standards reviewer reads first.Direction taken — please confirm
The draft is rewritten to match the schema, not the reverse.
The schema is implemented by both middleware packages, both reference implementations, and the compliance CLI. The draft has no implementations at all. Changing the schema instead would be a breaking change to a published v0.1 artifact for no protocol benefit.
That said — the draft's shape is arguably the better one for IETF review: a flat
endpointsobject and an explicitconformance_levelread more naturally than alayersobject whose members encode tier numbers. If you'd rather carry that shape into a v0.2 schema break, this PR is the wrong direction and I'll redo it. Flagging rather than assuming.What changed
eep-manifest.json, with thelayersobject documented and the rule that at least one Layer 2 endpoint must be populated.endpoints.*references replaced withlayers.layer2_sse/layers.layer2_webhook.eep_version— what implementations actually emit — instead ofeepversion/eepdelivery, which nothing emits.scripts/check-draft-schema-parity.mjs+ CI job so this drift becomes a build failure.An open question the draft surfaced
The draft's invented
eepversionspelling was arguably more correct than what ships. CloudEvents v1.0.2 restricts context attribute names to lowercase ASCII letters and digits — the underscore is excluded. Soeep_version,eep_subscription_id,eep_trust_scoreand the rest are all non-conformant CloudEvents extension attribute names.In structured JSON mode this is harmless in practice. It becomes load-bearing in binary content mode, where attributes are carried as
ce--prefixed HTTP headers.I recorded this as an Editor's note in the draft rather than silently renaming: no implementation emits the compliant spelling today, and a rename is a breaking change that deserves its own decision. Options are (a) rename with a deprecation window, or (b) keep underscores in structured mode and define an explicit binary-mode mapping.
Scope
Checklist
schemas/v0.1/changed — only the draft, which has no implementations.Verification
node scripts/check-draft-schema-parity.mjsgit diff --name-only schemas/node scripts/codegen-schema-types.mjs --checktests/Notes for reviewers
I verified the gate by injecting drift (adding
gates_urlto the schema'srequired) and confirming a non-zero exit with a readable message, rather than only confirming it passes on a clean tree. A gate that has only ever been seen to pass is not evidence of anything.The gate deliberately allows the draft to omit optional schema properties — the draft scopes itself to the Core tier and shouldn't have to restate the full manifest surface. It only fails on a field the draft invents, a required-ness mismatch, or a schema-required field the draft misses.
Separately: while checking field names I found that the Node reference implementation reads
body.callback_urlon subscribe, whilesubscription.request.jsonmandatesdelivery_url— so a conformant subscriber's delivery target is silently dropped. Both middleware packages get this right. That's a distinct bug and is coming as its own PR rather than being folded in here.