Repository navigation
Align the spec with the SDKs: free-text fields, x402 ids, rail_ref, conformance - #2
Merged
Merged
Conversation
…formance - docs/FIELDS.md lists the free-text fields checked for card numbers, adding payee.website, payee.resource_url and label keys, and says identifiers and evidence values are never checked. - rail_ref keys are closed per rail, as the schema already says; the docs no longer say receivers ignore unknown rail_ref keys. - docs/MAPPINGS.md defines the x402 payment_id for every stage, including payment.requested, which was unspecified. - conformance/: 40 events with expected verdicts, the signing vector and canonical-JSON vectors, checked in CI by npm test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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.
Why
The server and three SDKs (Node.js, Python, and the new Dart SDK in halvorAI/ingest-dart) each implement APE v0.1. Where the spec is silent or contradicts itself, each SDK picked its own answer. This PR writes the answers down here, the contract they all follow, and adds shared test data so they can be checked against it.
The JSON Schema (
ape/v0.1.json) is unchanged. Every change is to the docs, plus a newconformance/folder.Changes
1. The card-number check lists its fields (
docs/FIELDS.md,README.md)The spec said receivers reject "free-text fields" containing a possible card number, but never said which fields. Each SDK copied the TypeScript list. This PR lists them exactly, and adds
payee.website,payee.resource_urlandlabelskeys: query strings and label keys can carry anything.It also says what is not checked, and why:
payment_id,rail_ref.*,instrument.*,related.*): card networks issue numeric transaction ids that pass the Luhn check about one time in ten, so checking them would corrupt or reject real events.evidence[].value: a third party's signed proof, which redaction would break.2. x402
payment_idfor every stage (docs/MAPPINGS.md)x402:<network>:<nonce>already covered the later stages. This PR adds that it is never the tx hash (the Python SDK uses the tx hash on settlement today, which breaks the lifecycle join). It also definespayment.requested, which was unspecified:x402:<network>:requested, Pythonx402:<network>:challenge. Both give every challenge on a network the same id.x402:<network>:requested:<event id>, with thepayment.authorizedevent that answers it settingrelated.previous_event_id.3.
rail_refkeys are closed (docs/FIELDS.md,README.md)The README said receivers ignore unknown
rail_refkeys, but the schema setsadditionalProperties: falsefor every rail, and all three SDKs reject them. The docs now match the schema.labelsandevidence[].valuestay open. Forward compatibility comes fromape_version: receivers pick the schema by version.4. Shared test data (
conformance/,scripts/, CI)conformance/events.json: 40 events with the verdict every implementation must give (valid, orinvalidwith ruleschemaorpan).conformance/sign-vector.json: the cross-language signing vector, the same one ingest-python uses.conformance/jcs-vectors.json: canonical-JSON vectors from the TypeScriptcanonicalize, including RFC 8785 appendix B.npm testchecks all of it, plusexamples/, against the schema and the card-number rule. A new workflow runs it on every PR. 82 checks pass locally.Where the SDKs stand
The 40 cases were run through each SDK's own validator:
halvorai_ingest)payee.website,payee.resource_url, label keys (new in this PR)null-optional-field: it acceptsnullfor optional fields, which the schema rejects (an existing bug)Decisions needed from reviewers
pan_detected.payment.requestedid (change 2). Node.js and Python both need to change. The alternative is to keepx402:<network>:requestedand accept that challenges can't be told apart.rail_ref(change 3). The alternative is openingrail_refin the schema, which changes every validator.Notes
conformance/will be public there, which is useful because SDKs can fetch it.package.jsonandscripts/will be too, which is harmless.docs/FIELDS.mdsays it is generated from the schema, but no generator is in this repo. If one exists elsewhere, it needs the same "Cross-field rules" text.null).Please don't merge until the decisions above are agreed.
🤖 Generated with Claude Code