feat: eligibility claims & verification contract#250
Conversation
ACSchil
left a comment
There was a problem hiding this comment.
This LGTM. I like the direction we ended up taking; it works elegantly within the broader spec.
|
The For instrument-bound claims (RedCard BIN check), the Business can verify locally. For non-instrument claims — loyalty tiers, on-chain holdings, membership status — the Business needs something to verify against. A minimal option: let |
Terminology:
- "claims that influenced the checkout" → "accepted claims" throughout,
aligning with the accepted/not-accepted partition (maximenajim, ACSchil)
- "not applied" → "not accepted" for consistency
Verification semantics:
- Clarify that verification failure MUST only affect the messages array,
not checkout state (line items, totals, discounts, etc.) (maximenajim)
- Add path field to eligibility_invalid example for machine-readable
partial failure identification (ACSchil)
Messages contract:
- Add MAY use type: "info" to explain effects of accepted claims,
complementing SHOULD warn on rejection (maximenajim)
Catalog:
- Add non-binding pricing contract to "Relationship to Checkout" section:
catalog responses are not transactional commitments, checkout is
authoritative, responses SHOULD NOT be reused across sessions
without re-validation (maximenajim)
|
@maximenajim ty, great feedback, ptal at updated draft. @douglasborthwick-crypto we're intentionally leaving the verification mechanism open — "UCP does not prescribe how verification occurs" — because the proof model varies by claim type:
A companion attestation mechanism (sig + kid against a published JWKS) is a great candidate for a capability extension that complements eligibility. Additive and non-breaking: platforms that can provide attestations send them alongside the claim; businesses that require them check, others ignore. |
|
That's the right split — prescribing verification in core would overfit to one claim type. The capability extension model keeps eligibility clean. Happy to draft that extension. The shape I have in mind: {
"context": {
"eligibility": [{
"type": "token_holder",
"label": "USDC holder discount",
"attestation": {
"sig": "<base64 ECDSA signature>",
"kid": "insumer-attest-v1",
"jwks_uri": "https://insumermodel.com/.well-known/jwks.json",
"condition_hash": "<SHA-256 of evaluated condition>",
"attested_at": "2026-03-12T16:40:00Z",
"expires_at": "2026-03-12T17:10:00Z"
}
}]
}
}The Business verifies the signature against the JWKS, checks This is already the pattern in #203 ( |
lemonmade
left a comment
There was a problem hiding this comment.
I really like where you landed with this 👏
| "eligibility": { | ||
| "$ref": "../ucp.json#/$defs/reverse_domain_name", | ||
| "description": "The eligibility claim accepted by the Business for this discount. Corresponds to a value from context.eligibility. Omitted for code-based and non-eligibility automatic discounts." | ||
| }, |
There was a problem hiding this comment.
Something doesn’t quite sit right with me about this. I think it’s that we are providing details about the source of one kind of automatic discount with a top-level field. If we wanted to indicate the source of other automatic discounts (from identity linking, based on the line items, etc), we would need additional fields. Did you consider any design for this that broadened this field a bit to leave space for more detail on other discount types?
There was a problem hiding this comment.
Good prompt. There is potential for "provenance proliferation" here, but so far I haven't spotted a generic schema. If you squint, codes and eligibility are both string[] — but they carry different lifecycle contracts that you'd want to capture and distinguish, so a generic source would still need type-specific semantics. All we'd have done is push the modeling complexity down one layer.
Open to suggestions.
|
@douglasborthwick-crypto 👍 modulo one gotcha on example you shared...
^ either that or on cart/checkout object similar to discount extension. |
Introduce `context.eligibility` — buyer claims about eligible benefits
(loyalty membership, payment instrument perks, etc.) that Businesses
can act on across the shopping lifecycle.
Processing model:
- Platform provides claims via context.eligibility on any request
- Business MAY act on recognized claims (adjust pricing, product
access, provisional discounts); MUST ignore unrecognized claims
- At checkout completion, all claims that influenced the checkout
MUST be resolved: verified against proof, or rescinded by Platform
- Unresolved claims block completion (invalid_eligibility error)
- Business MUST NOT mutate checkout on verification failure
Layering:
- context.json: eligibility array with reverse-domain $ref validation
- checkout.md: normative verification contract (core obligation)
- discount.json: provisional + eligibility fields on applied_discount
for structured attribution when discount extension is active
- catalog/index.md: MAY adjust price/list_price for eligible claims
- error_code.json: invalid_eligibility standard error
Key design decision: eligibility lives on context (not PaymentInstrument)
enabling full-funnel coverage from catalog through checkout. Verification
is a core checkout concern; the discount extension adds attribution.
Co-authored-by: Alex Schillinger <alexcschillinger@gmail.com>
Co-authored-by: Alex Schillinger <alexcschillinger@gmail.com>
Terminology:
- "claims that influenced the checkout" → "accepted claims" throughout,
aligning with the accepted/not-accepted partition (maximenajim, ACSchil)
- "not applied" → "not accepted" for consistency
Verification semantics:
- Clarify that verification failure MUST only affect the messages array,
not checkout state (line items, totals, discounts, etc.) (maximenajim)
- Add path field to eligibility_invalid example for machine-readable
partial failure identification (ACSchil)
Messages contract:
- Add MAY use type: "info" to explain effects of accepted claims,
complementing SHOULD warn on rejection (maximenajim)
Catalog:
- Add non-binding pricing contract to "Relationship to Checkout" section:
catalog responses are not transactional commitments, checkout is
authoritative, responses SHOULD NOT be reused across sessions
without re-validation (maximenajim)
Standardize codes for the three eligibility message types: eligibility_not_accepted (warning), eligibility_accepted (info), and eligibility_invalid (error at completion).
c0fc5ee to
f8e70b4
Compare
raginpirate
left a comment
There was a problem hiding this comment.
Looks great! This matches my initial reaction to first model this above payments before we take it into payments.
And the path of associating a discount to an eligibility signal highlights how we can take this to other independent primitives across ucp in the future; payments can eventually adopt this connective tissue too if we find the use case benefits people beyond this simple version.
Per TC discussion, this is already captured via messages flow.
amithanda
left a comment
There was a problem hiding this comment.
Looks great, thanks for addressing all the feedback.
Adds a capability extension that complements eligibility (Universal-Commerce-Protocol#250) with cryptographic attestation proofs. Platforms relay signed attestations alongside eligibility claims; Businesses verify offline via JWKS. Follows the discount extension pattern (allOf on Cart/Checkout). Discussed in Universal-Commerce-Protocol#203 and Universal-Commerce-Protocol#250 — igrigorik invited this as a companion extension ("a great candidate, additive and non-breaking"). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a capability extension that complements eligibility (Universal-Commerce-Protocol#250) with cryptographic attestation proofs. Platforms relay signed attestations alongside eligibility claims; Businesses verify offline via JWKS. Follows the discount extension pattern (allOf on Cart/Checkout). Discussed in Universal-Commerce-Protocol#203 and Universal-Commerce-Protocol#250 — igrigorik invited this as a companion extension ("a great candidate, additive and non-breaking").
* feat: eligibility claims & verification contract
Introduce `context.eligibility` — buyer claims about eligible benefits
(loyalty membership, payment instrument perks, etc.) that Businesses
can act on across the shopping lifecycle.
Processing model:
- Platform provides claims via context.eligibility on any request
- Business MAY act on recognized claims (adjust pricing, product
access, provisional discounts); MUST ignore unrecognized claims
- At checkout completion, all claims that influenced the checkout
MUST be resolved: verified against proof, or rescinded by Platform
- Unresolved claims block completion (invalid_eligibility error)
- Business MUST NOT mutate checkout on verification failure
Layering:
- context.json: eligibility array with reverse-domain $ref validation
- checkout.md: normative verification contract (core obligation)
- discount.json: provisional + eligibility fields on applied_discount
for structured attribution when discount extension is active
- catalog/index.md: MAY adjust price/list_price for eligible claims
- error_code.json: invalid_eligibility standard error
Key design decision: eligibility lives on context (not PaymentInstrument)
enabling full-funnel coverage from catalog through checkout. Verification
is a core checkout concern; the discount extension adds attribution.
* align error code to noun_adjective pattern
* fix: address PR #250 review feedback
Terminology:
- "claims that influenced the checkout" → "accepted claims" throughout,
aligning with the accepted/not-accepted partition (maximenajim, ACSchil)
- "not applied" → "not accepted" for consistency
Verification semantics:
- Clarify that verification failure MUST only affect the messages array,
not checkout state (line items, totals, discounts, etc.) (maximenajim)
- Add path field to eligibility_invalid example for machine-readable
partial failure identification (ACSchil)
Messages contract:
- Add MAY use type: "info" to explain effects of accepted claims,
complementing SHOULD warn on rejection (maximenajim)
Catalog:
- Add non-binding pricing contract to "Relationship to Checkout" section:
catalog responses are not transactional commitments, checkout is
authoritative, responses SHOULD NOT be reused across sessions
without re-validation (maximenajim)
* add eligibility message codes for warning and info
Standardize codes for the three eligibility message types:
eligibility_not_accepted (warning), eligibility_accepted (info),
and eligibility_invalid (error at completion).
* remove display MUST from provisional
Per TC discussion, this is already captured via messages flow.
---------
Co-authored-by: Alex Schillinger <alexcschillinger@gmail.com>
Add 6 missed post-release changes discovered during full audit of 58 PRs merged after the 2026-01-23 branch was cut: Universal-Commerce-Protocol#16 — Optional request/response signing headers (PR Universal-Commerce-Protocol#156) [Additive] Universal-Commerce-Protocol#17 — Eligibility claims & provisional discounts (PR Universal-Commerce-Protocol#250) [High/Breaking] Universal-Commerce-Protocol#18 — Optional signals field on cart and checkout (PR Universal-Commerce-Protocol#203) [Additive] Universal-Commerce-Protocol#19 — Fulfillment method id/type optional on update (PR Universal-Commerce-Protocol#143/Universal-Commerce-Protocol#196) [Low] Universal-Commerce-Protocol#20 — intent field added to context (PR Universal-Commerce-Protocol#95) [Additive] Universal-Commerce-Protocol#21 — available_instruments added to payment handler (PR Universal-Commerce-Protocol#187) [Additive] Also updates PR_URLS map and changes/visible counts from 15 → 21. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add 6 missed post-release changes discovered during full audit of 58 PRs merged after the 2026-01-23 branch was cut: Universal-Commerce-Protocol#16 — Optional request/response signing headers (PR Universal-Commerce-Protocol#156) [Additive] Universal-Commerce-Protocol#17 — Eligibility claims & provisional discounts (PR Universal-Commerce-Protocol#250) [High/Breaking] Universal-Commerce-Protocol#18 — Optional signals field on cart and checkout (PR Universal-Commerce-Protocol#203) [Additive] Universal-Commerce-Protocol#19 — Fulfillment method id/type optional on update (PR Universal-Commerce-Protocol#143/Universal-Commerce-Protocol#196) [Low] Universal-Commerce-Protocol#20 — intent field added to context (PR Universal-Commerce-Protocol#95) [Additive] Universal-Commerce-Protocol#21 — available_instruments added to payment handler (PR Universal-Commerce-Protocol#187) [Additive] Also updates PR_URLS map and changes/visible counts from 15 → 21. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a capability extension that complements eligibility (Universal-Commerce-Protocol#250) with cryptographic attestation proofs. Platforms relay signed attestations alongside eligibility claims; Businesses verify offline via JWKS. Follows the discount extension pattern (allOf on Cart/Checkout). Discussed in Universal-Commerce-Protocol#203 and Universal-Commerce-Protocol#250 — igrigorik invited this as a companion extension ("a great candidate, additive and non-breaking").
Adds a capability extension that complements eligibility (Universal-Commerce-Protocol#250) with cryptographic attestation proofs. Platforms relay signed attestations alongside eligibility claims; Businesses verify offline via JWKS. Follows the discount extension pattern (allOf on Cart/Checkout). Discussed in Universal-Commerce-Protocol#203 and Universal-Commerce-Protocol#250 — igrigorik invited this as a companion extension ("a great candidate, additive and non-breaking").
Adds a capability extension that complements eligibility (Universal-Commerce-Protocol#250) with cryptographic attestation proofs. Platforms relay signed attestations alongside eligibility claims; Businesses verify offline via JWKS. Follows the discount extension pattern (allOf on Cart/Checkout). Discussed in Universal-Commerce-Protocol#203 and Universal-Commerce-Protocol#250 — igrigorik invited this as a companion extension ("a great candidate, additive and non-breaking").
Context: #214 (comment). Supersedes #214, closes #137.
Introduce
context.eligibility— buyer claims about eligible benefits (loyalty membership, payment instrument perks, etc.) that Businesses can act on across the shopping lifecycle.Processing model:
Layering:
Eligibility lives on context (not PaymentInstrument) enabling full-funnel coverage from catalog through checkout. Verification is a core checkout concern; the discount extension adds attribution.
Checklist