feat: Introduce anyOf constraint with payments example - #757
Merged
Conversation
8 tasks
gsmith85
approved these changes
Aug 21, 2026
jamesandersen
approved these changes
Aug 21, 2026
* docs: complete abridged payment instrument examples Both examples elided id, handler_id, and type behind a "more required fields" comment, and one also omitted credential.type. They validated only because shipped ucp-schema never applied the self-root allOf requirements in selected_payment_instrument, so payment.instruments[] was never checked against payment_instrument's required members. Showing the fields costs one line each, keeps both examples validated once that resolver bug is fixed, and removes a comment that promised required fields while showing none. * feat: require non-empty anyOf branches in the constraint grammar An empty Object Constraint is a valid no-op at every other position, but an empty anyOf branch is satisfied by every object, so it neutralizes the alternation rather than doing nothing. The grammar should not admit a branch that silently disables the alternation it belongs to. A minProperties sibling on the recursive $ref is legal 2020-12 composition: siblings to $ref apply alongside the referenced schema, so the branch stays an ordinary Object Constraint while gaining the non-empty requirement, at every nesting depth. Mirrors the constraint into both grammar tables, since the schema and its companion prose are one unit. * docs: discriminate the anyOf credential example The undiscriminated form accepts nonsense: a credential declaring any card_number_type at all satisfies the cvc branch as long as it carries a cvc, so the example teaches an idiom that does not enforce what the surrounding prose claims. Pinning card_number_type with const in each branch, and naming it in that branch's required, makes a branch match only the shape it describes. Documents the consequence that pinning creates: because every branch pins the discriminator, the branch set also closes the accepted values, so a dpan credential valid under card_credential.json satisfies neither branch. That closure is the rule a per-branch conditional cannot express, and it is load-bearing enough to state. Replaces the "would restate the path" justification, which understated the case. Request Constraints conjoin, so two separately targeted constraints would require both cvc and cryptogram; the real alternative is discriminating in the path filter, which puts conditional logic in the selector. Adds the two grammar mechanics the example relies on next to the composition rules rather than in the Business guidelines: branches are alternatives rather than a partition, and properties asserts nothing about an absent member. Both are consequences of how the grammar composes, not conformance requirements, so they carry no BCP 14 keywords and belong with the grammar they describe.
A bare "$ref": "#" names the schema being rendered and carries no
filename of its own, so create_link derived an empty anchor and emitted
a broken "<page>/##" link. The docs build's link check fails on it,
which is why build_and_verify_main has been red on this branch since
the first push.
Recursive references cannot be inlined -- ucp-schema preserves them
even under --bundle, and the docs macro deliberately resolves without
bundling so that $refs survive for hyperlink generation. The docs layer
is therefore the only place that can give a self-root ref a name.
Resolve "#" against the enclosing schema's own $id at each of the three
sites that turn a $ref into a link: direct, array items, and oneOf
branches.
The array-items path is the one the constraint grammar's anyOf trips
today. The oneOf path has the identical defect -- a named property with
oneOf: [{"$ref": "#"}, ...] renders the same broken anchor -- and is
fixed alongside it rather than left to be rediscovered.
raginpirate
force-pushed
the
raginpirate/anyof-constraint
branch
from
August 21, 2026 23:34
899935e to
e8da3e8
Compare
amithanda
approved these changes
Aug 22, 2026
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.
Description
Resolving our open follow-up to #655, introducing the anyOf constraint to the base UCP constraints grammar.
Added a simple example using it with payments, and #424 is stacked on top of this to extend the usage of constraints across payments normatively.
Category (Required)
Please select one or more categories that apply to this change.
ucp-schematool (resolver, linter, validator). (Requires Maintainer approval)Checklist
!for breaking changes).