You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This proposal defines a unified, incrementally-deliverable roadmap for identity
and loyalty support in UCP. It sequences a set of focused PRs — from the
foundational OAuth 2.0 authority model through delegated identity providers,
extended authentication mechanisms, loyalty benefit recognition, program
discovery, membership operations, and buyer profile management — so that each
PR is independently reviewable, non-breaking, and delivers real value on its
own while advancing the overall vision.
The proposal is motivated by three clusters of open work that are related to each other:
This RFC provides the architectural framing that lets all three clusters land
cleanly.
Motivation
The Four-Layer Model
We propose breaking overall Identity and loyalty work in a four-layered stack. Each layer depends on
the one below it; landing them in order is the core idea
of this RFC:
┌────────────────────────────────────────────────────────────┐
│ Layer 4: Loyalty Management (Phases 6–7) │
│ Write operations on membership state: enrollment, tier │
│ progression, reward redemption, cancellation — Phase 6 │
│ (`memberships` capability). Account lifecycle: creation, │
│ deletion, profile management — Phase 7 (`identity_ │
│ management`, pending TC resolution on scope). │
├────────────────────────────────────────────────────────────┤
│ Layer 3: Loyalty Data (Phases 4–5) │
│ Loyalty benefit recognition in checkout/cart — Phase 4 │
│ (`loyalty` extension). Program structure, tier catalog, │
│ and enrollment conditions — Phase 5 (`memberships` │
│ capability, read/discovery operations). │
├────────────────────────────────────────────────────────────┤
│ Layer 2: Identity Authority (Phase 2-3) │
│ How the business establishes and extends trust in who │
│ the buyer is: business-hosted OAuth 2.0, delegated IdP, │
│ wallet attestation, multi-mechanism negotiation │
├────────────────────────────────────────────────────────────┤
│ Layer 1: Discovery and Scope Contract (Phase 1) │
│ How platforms and businesses agree on what is available │
│ and at what auth level: UCP /.well-known/ucp profile, │
│ capability-driven scope naming │
└────────────────────────────────────────────────────────────┘
Layer 1 (discovery and scope contract) is the foundation everything else
depends on. It has two components:
UCP discovery profile (/.well-known/ucp): the business's published
capability set, including the dev.ucp.common.identity_linking config that
declares which capabilities offer buyer-scoped features and what scopes they
carry. Platforms read this profile before attempting any identity flow — it
is the contract that determines what auth the business requires.
Scope naming and the three-tier access model: capability names are the
scope tokens (dev.ucp.shopping.checkout, dev.ucp.shopping.order:read).
Both the scope naming convention and the access tier model is proposed to
be standardized before delegated IdP or multi-mechanism negotiation can be
specified, because those higher layers derive their scope sets from this
foundation.
This is why Phase 1 (PR #354) is the highest-priority fix. The scope naming
in the current spec (ucp:scopes:checkout_session style) is incorrect and
diverges from the capability name convention. Every implementor reading the
current spec is wiring the wrong scope strings. That bug needs to be in
implementors' hands fast — ideally via a backport to the most recently
released version — not held until the next full protocol release.
Layer 2 (identity authority) is what dev.ucp.common.identity_linking
covers. It should remain focused on authentication mechanics: how does the
business establish trust in the buyer's claimed identity, and via which
mechanism? Phase 1 specifies business-hosted OAuth 2.0 as the v1 baseline.
Phases 2 and 3 extend this layer with delegated IdPs and additional mechanism
types (wallet attestation, verifiable credentials) without changing the Layer 1
scope contract.
Layer 3 (loyalty data) covers what the business knows about the buyer's
loyalty relationship: benefit entitlements in an active checkout or cart session
(Phase 4, loyalty extension), and the full program structure — tiers,
enrollment conditions, reward rules — available for discovery outside of a
transaction (Phase 5, memberships capability). This layer is read-oriented;
it surfaces state but does not mutate it.
Layer 4 (loyalty management) covers write operations that change the
buyer's relationship with the business: membership enrollment, tier progression,
reward redemption, and cancellation (Phase 6, write operations on memberships).
It also covers account lifecycle operations — creation, deletion, and profile
management — addressed by Phase 7, whose exact capability placement (standalone identity_management or absorbed into memberships) is pending TC resolution.
Sample changes across four layers:
Concern
Layer
Where it belongs
Scope naming and access tiers
1
identity_linking config in discovery profile
Authenticate buyer identity
2
identity_linking — OAuth server
Delegated IdP / mechanism type
2
identity_linking config (Phase 2/3 extension)
Loyalty benefit display
3
loyalty extension on checkout/cart
Program and tier discovery
3
memberships capability (read operations)
Membership enrollments
4
memberships capability write operations
Reward redemption
4
Applied via discount extension & more
Account creation / deletion
4
identity_management capability
Membership profile management
4
identity_management capability
Why Incrementally?
The full vision spans eight distinct units of work. Attempting to land all of
it in one or two PRs might be sub-optimal (#265 reverted, #337 in-progress, #251
under review). Each phase below is:
Independently useful — delivers real value to implementers without
requiring subsequent phases.
Non-breaking by default — additive changes; breaking changes are
called out explicitly and require the two-week community notice period.
Reviewable in isolation — scoped to one capability or one extension,
so reviewers can assess correctness without holding the full vision in mind.
Forward-compatible — each phase leaves deliberate extension points for
subsequent phases, specified normatively.
Proposed Phases
Phase 1 — Discovery Profile, Scope Contract, and OAuth 2.0 Foundation (PR #354) [In Progress — Urgent]
Capability:dev.ucp.common.identity_linking Type: Breaking (!) — removes the identity_scopes annotation approach introduced in #265 (reverted in #329, but the replacement scope model is a protocol-level clarification that warrants ! per CONTRIBUTING.md) Urgency: High — scope naming bug affects every current implementor Blocks: Phases 2, 3, 4, 7 Backport target:v2026-04-08 patch release (see Backport Proposal)
Why this is urgent
The current spec (as of v2026-04-08) does not define normative scope token
names for buyer-authenticated capabilities. PR #265 introduced ucp:scopes:checkout_session-style tokens; that PR was reverted in #329 but
the scope naming gap was never filled. As a result, implementors building
against the current release either:
(a) invent their own scope strings, producing incompatible implementations, or
(b) skip buyer-authenticated flows entirely, which silently breaks loyalty,
order history, and personalized pricing use cases.
This is not a future-version concern. Implementors shipping today are wiring
the wrong scope strings and will require a painful migration if the fix waits
for the next full protocol version. The Phase 1 PR (currently in review as #354) contains the complete fix and should be backported to v2026-04-08
as a patch.
What lands
Discovery profile (Layer 1 — scope contract):
Normative definition of the dev.ucp.common.identity_linking entry in the
UCP /.well-known/ucp business profile. This is the machine-readable
contract that platforms read before attempting any identity flow.
Capability-driven scope model: scopes declared in config.capabilities on
the identity linking config — not annotated on individual capability schemas
(that approach caused the feat!: redesign identity linking with mechanism registry and capability-driven scopes #265 bug). Capabilities are never excluded from
the negotiated capability set based on identity linking presence.
Three access tiers formally defined: public (no auth), agent-
authenticated (platform credentials only), buyer-authenticated
(platform + buyer identity token). Each capability operates at all three
tiers simultaneously; buyer auth upgrades the experience rather than gating
the capability.
Canonical scope token format: capability name directly as the scope token
(dev.ucp.shopping.checkout), with sub-scope operation groups joined by
colon on the wire (dev.ucp.shopping.order:read). Replaces and supersedes
any prior ucp:scopes:* naming.
auth_required: true on a config.capabilities entry signals that the business
returns identity_required for requests without a buyer token; omitting it
means identity is optional (upgrades the experience).
scopes_supported MUST be present in RFC 8414 server metadata and MUST list
the capability-derived scope tokens the server accepts.
Business-hosted OAuth 2.0 as the v1 auth mechanism. Strict 2-tier discovery:
RFC 8414 /.well-known/oauth-authorization-server primary; OIDC /.well-known/openid-configuration fallback on HTTP 404 only; all other
errors MUST abort (no silent fallback).
config.additionalProperties: true with normative platform ignore rule:
platforms encountering unrecognized config fields MUST ignore them and
proceed using OAuth 2.0 with RFC 8414 discovery on the business domain.
Schema $comment names two reserved extension points: config.providers
(Phase 2 — delegated IdP) and config.mechanisms (Phase 3 — mechanism
negotiation). These are deliberate design hooks, not accidental open fields.
Schema shape (stable after Phase 1)
The config.capabilities map is the core artifact of Phase 1. Its shape is
final; Phases 2 and 3 add sibling keys (providers, mechanisms) alongside
it without modifying it.
Capability:dev.ucp.common.identity_linking (extension of Phase 1 config) Type: Non-breaking additive extension Depends on: Phase 1 Note: Phase 3 can land independently of Phase 2 (Phase 2 recommended but not required for mechanism extensibility)
Problem statement
Phase 1 requires a full OAuth dance per merchant. In agentic commerce where a
platform shops across N businesses, this means N authorization redirects — each
requiring a buyer interaction. Delegated IdP allows a business to declare trust
in a third-party identity provider (e.g., a commerce super-app's platform
IdP, Google, Shop). A buyer who has authenticated with that IdP once can be
recognized at any business that trusts it, without a new redirect.
What lands
config.providers map (the Phase 1 reserved extension point), keyed by
reverse-domain provider identifier. Each entry carries auth_url for
RFC 8414 discovery.
Two distinct flows:
Account Linking: Standard Authorization Code + PKCE with the IdP.
One-time per provider; business issues its own access token after
receiving the IdP-issued token.
Accelerated IdP Flow (Identity Chaining): Platform already holds a
valid IdP token, exchanges it for a business-scoped token without a
browser redirect. Implements the two-phase pattern from
draft-ietf-oauth-identity-chaining-08: (1) platform requests JWT
authorization grant from IdP via RFC 8693 token exchange; (2) platform
presents JWT grant to business token endpoint via RFC 7523 JWT bearer
assertion; (3) business validates, resolves buyer identity, issues its
own token. Refresh tokens MUST NOT be issued per the chaining draft.
IdP controls consent: IdP MUST NOT issue grants for businesses the buyer
has not authorized. Businesses MAY auto-provision accounts or return continue_url for buyer onboarding.
Two independent token lifecycles with independent revocation paths.
Provider selection: when providers contains multiple entries, the business
signals preference via the mechanisms array (Phase 3). In Phase 2 (before mechanisms is defined), platforms MAY attempt providers in any order; the
spec will define a normative selection rule (e.g., explicit ordering via a preferred_provider hint) before Phase 2 ships.
Platforms that do not implement delegated IdP ignore the providers map (per
the Phase 1 normative ignore rule) and fall back to business-hosted OAuth 2.0
using the business's own auth_url. No existing implementation breaks.
Phase 3 — Mechanism Extensibility (New PR) [Optional - Proposal]
Capability:dev.ucp.common.identity_linking (adds config.mechanisms alongside Phase 1's config.capabilities) Type: Non-breaking additive extension Depends on: Phase 1 (Phase 2 recommended but not required) Relates to: EP #287 (Wallet Attestation)
Problem statement
OAuth 2.0 is the right default for account-bearing commerce but not the only
valid identity mechanism. Wallet attestation (EP #287) establishes buyer
identity via cryptographically signed on-chain state, with no redirect and no
account. Verifiable credentials extend this to off-chain claims. Both are valid
mechanisms for specific commerce verticals (token-gated merchandise, NFT-gated
access, B2B credentialed purchasing). Phase 3 introduces the mechanism
negotiation layer that lets businesses declare and platforms select among
supported mechanism types.
What lands
config.mechanisms ordered array (the Phase 1 second reserved extension
point). Each entry is a mechanism object with a type discriminator string.
Business-preference ordering: platforms select the first type they support,
abort if none match (no partial or fallback flows permitted).
Initial mechanism types:
oauth2 — business-hosted OAuth 2.0 (Phase 1 behavior; default when mechanisms is absent). Fields: auth_url (optional; falls back to
RFC 8414 discovery on the business domain).
Device authorization grant (RFC 8628) for headless agent flows added as an
optional grant type on oauth2 entries.
When mechanisms is absent, protocol falls back to Phase 1 behavior
(business-hosted OAuth 2.0 with RFC 8414 discovery). No existing
implementation breaks.
config.providers (Phase 2) and config.mechanisms (Phase 3) are
complementary. providers is a map of trusted OAuth issuers (who can vouch for
the buyer). mechanisms is an ordered list of authentication schemes (how the
platform establishes identity). When both are present, mechanisms governs
selection; oauth2 entries resolve their provider set from providers plus the
business's own domain.
Extension of:dev.ucp.shopping.checkout, dev.ucp.shopping.cart Capability name:dev.ucp.shopping.loyalty (extension) Type: Non-breaking additive extension Depends on: Phase 1 (for identity_required / buyer-scoped loyalty state) TC review: PR #251 under active TC review; PR #340 is proposed as the
focused baseline — this phase resolves the two proposals
Problem statement
Two competing proposals exist:
PR feat: Add basic schema for loyalty extension #251: Comprehensive loyalty covering the full membership lifecycle
(sign-up, tier upgrade, redemption, discovery), using a
Membership → Tier → Benefits + Rewards hierarchy.
PR feat: loyalty extension for checkout capability #340: A focused baseline covering benefit recognition for known members
at checkout, using a Membership → Track → Tier → Benefits + Rewards hierarchy
that separates enrollment tracks from achievement tiers.
Phase 4 adopts PR #340's focused scope and five-concept hierarchy
(tracks separate from tiers), resolves the read/write concern by restricting
this phase to read-only benefit recognition, and defers program discovery
and membership operations to Phases 5 and 6.
Membership: the program brand umbrella and the buyer's enrollment
status within it. Carries member_id for platform-side correlation.
Track: distinct enrollment pathway (credit card holder vs. standard
member). A buyer may hold multiple tracks simultaneously. Introduced to
normalize the Hybrid Loyalty Model without data collisions.
Tier: achievement rank within a track (Gold, Platinum). Each track
has one activated tier per buyer.
Benefit: ongoing perk at the current tier (free shipping, early
access). Read-only in this phase.
Reward: fungible balance available for redemption (points, miles).
Balance display and earning forecast in this phase; actual redemption via
discount extension (Phase 6).
loyalty object on checkout and cart responses, keyed off the loyalty
extension name.
Eligibility/provisional wiring: integrates with the eligibility claim
pattern (feat: eligibility claims & verification contract #250) — buyer claims membership eligibility in the request;
business verifies and returns confirmed membership state.
Request-side membership_id field: addresses amithanda's review comment on feat: Add basic schema for loyalty extension #251 — platforms with a known membership identifier MUST be able to send it
in the request so businesses can correlate without requiring a separate
identity lookup.
Discount linkage: reward redemptions appear as discount extension entries;
benefit descriptions reference the applied discount via applies_on
(JSONPath). Benefits and discounts remain in separate objects — the loyalty
extension declares what the buyer is entitled to; the discount extension
declares what was applied.
Phase 5 — Loyalty Membership Discovery (New Capability) [Proposal]
Capability:dev.ucp.shopping.memberships (new) Type: New capability — no breaking changes Depends on: Phase 4 schema definitions (reuses types) Resolves: igrigorik's architectural concern on #251
Problem statement
Static program data — all possible tiers, enrollment conditions, benefit
descriptions, program terms — is currently bundled into checkout/cart
responses. This is wasteful (unchanged per-transaction), muddles the semantic
contract ("checkout response should reflect what's negotiated for this session,
not the full program brochure"), and makes it impossible to implement simple
caching.
What lands
New dev.ucp.shopping.memberships capability for requesting the loyalty
program brochure independently of a transaction.
Two use cases:
Anonymous discovery (no buyer identity): returns full program
structure with all tiers, enrollment conditions, non-member benefits. Used
for upsell ("join to save $5").
Member-authenticated discovery (with buyer identity): returns the
buyer's activated track/tier plus the full program structure for context.
Supports "you are two purchases away from Platinum" UI patterns.
Enrollment conditions split from active benefits: enrollment_conditions
describes how a buyer qualifies for a tier; benefits on the active response
describes what the buyer currently holds. This resolves the Phase 4 scope
restriction by moving discovery-only fields out of the checkout response.
Phase 6 — Loyalty Membership Operations (New PR) [Proposal]
Builds on:dev.ucp.shopping.memberships (Phase 5 capability) Type: Non-breaking additive (new write operations on the memberships capability) Depends on: Phase 1 (identity required for sign-up), Phase 5 (memberships capability) Recommended prerequisite: Phase 4 (loyalty extension provides benefit/reward context)
What lands
Membership enrollment: buyer requests sign-up after reviewing program
terms (from Phase 5 discovery). Flow: platform presents program terms →
buyer consents → platform sends enrollment request → business registers and
returns confirmed membership object. Integrates with buyer_consent
extension for terms acceptance.
Tier progression signals: business can include next_tier_progress on
the loyalty response — amount remaining, qualifying actions. Read-only from
the spec's perspective; businesses compute progress server-side.
Reward redemption: platform specifies redeem amount on a reward
currency in the checkout request; business applies it as a discount entry
and returns the updated balance. Redemption is executed via the discount
extension (applied array) with loyalty extension showing the updated
balance post-redemption. This maintains the read/write separation: loyalty
declares state; discount declares the applied effect.
Phase 7 — Identity Management: Open Discussion [Under Discussion]
Status: This phase is not yet a concrete proposal. It is an open question
for TC discussion. No implementation work should begin until the TC has
resolved the framing question below.
The question
Should account lifecycle operations — account creation, deletion, and profile
management — be a separate dev.ucp.common.identity_management capability, or
should they be absorbed into the dev.ucp.shopping.memberships capability
introduced in Phase 5/6 as part of membership operations?
Account lifecycle is distinct from loyalty membership. A buyer can have an
account with a business without being a loyalty member, and account operations
(creation, deletion) carry different consent, legal, and data-portability
obligations than membership enrollment or tier progression. Under this model, dev.ucp.common.identity_management is a new Layer 4 capability that depends
on the Phase 1 authentication token but is independent of the loyalty stack.
Platforms that need account management but have no loyalty program can adopt it
without pulling in Phases 4–6.
Argument for: Clean separation of concerns; account lifecycle is not
loyalty-specific. Aligns with PR #337's original goals without conflating
identity and loyalty.
Argument against: Adds another capability for implementors to support.
If the majority of account lifecycle events (sign-up, cancellation) are
triggered through the membership enrollment flow, splitting them into a
separate capability creates coordination overhead with no clear benefit.
Option B: Account lifecycle as part of memberships (Phase 6 extension)
Account creation and deletion could be operations on the dev.ucp.shopping.memberships capability — specifically as preconditions or
postconditions of membership enrollment and cancellation. Account creation is
a natural part of the sign-up flow; account deletion maps to membership
cancellation taken to its logical conclusion. Under this model, Phase 7 is
dissolved and its operations are incorporated into Phase 6.
Argument for: Simpler protocol surface; fewer capabilities for platforms
to register and discover. The membership enrollment flow already requires
buyer consent and identity, so the infrastructure is already present.
Argument against: Conflates commerce-layer loyalty operations with
identity-layer account management. Businesses that want to offer account
deletion under GDPR/CCPA obligations should not have to implement the full
loyalty membership stack to do so.
Recommendation request
The TC is asked to decide: should Phase 7 proceed as a standalone capability,
be merged into Phase 6, or be deferred entirely to a future RFC focused on
buyer data rights and account portability?
Backport Proposal
Target release:v2026-04-08 patch Scope: Phase 1 changes only — discovery profile scope contract and security
hardening. No delegated IdP, no mechanism negotiation.
Rationale
The scope naming gap introduced by the #265 revert (#329) is present in the
current stable release v2026-04-08. Every implementor building against that
release faces two bad choices: invent non-standard scope strings, or skip
buyer-authenticated flows entirely. Neither is acceptable for a protocol
claiming to standardize agentic commerce.
Waiting for the next full protocol version to fix scope naming would:
Force implementors to ship a scope migration in a future update — a
significant effort for any production system that has hardcoded tokens.
Create an interoperability gap: early adopters build against incompatible
scope namespaces and must coordinate a flag day to migrate.
Backporting the Phase 1 scope contract as a patch release avoids all these
outcomes at low risk — the changes are purely additive to the discovery profile
and spec text; no existing wire format is modified.
Phases 2–7 are excluded. The backport carries only what is needed to unblock
implementors today: the scope naming contract and OAuth 2.0 security baseline.
Delegated IdP, mechanism negotiation, loyalty, and identity management are
new-version features that follow the normal proposal lifecycle.
feat!: identity linking OAuth 2.0 foundation with capability-driven scopes
2
2
feat: identity linking — delegated IdP and accelerated identity chaining
3
2
feat: identity linking — mechanism extensibility with wallet attestation
4
3
feat: loyalty checkout/cart extension — benefit recognition and rewards
5
3
feat: loyalty memberships capability — program discovery and enrollment
6
4
feat: loyalty — membership enrollment, tier progression, and redemption
7
4 (pending TC)
feat: identity management — account creation, portability, and deletion
TC Review Questions
The following questions require explicit TC resolution before this RFC advances to Provisional.
Phase structure and sequencing: Does the TC agree with decomposing this
work into the seven phases defined above, and with the proposed sequencing?
Specifically: are the dependency relationships between phases correct, and is
the decision to keep Phases 2–7 gated behind individual TC votes — rather
than pre-approving the full roadmap now — the right governance posture? If
the TC has concerns about specific phase boundaries (e.g., whether Phase 5
and 6 should be merged, or whether Phase 7 belongs in a separate RFC), this
is the point to surface them.
Backport approval: Does the TC approve backporting the Phase 1 scope
contract and OAuth 2.0 security baseline to the current stable release
(v2026-04-08) as a patch? The backport is limited to the changes listed in
the "What is included in the backport" table — no delegated IdP, no loyalty,
no identity management. The rationale is that the scope naming gap introduced
by the feat!: redesign identity linking with mechanism registry and capability-driven scopes #265 revert is causing real interoperability pain for implementors
today and the fix is purely additive. TC should confirm: (a) the patch scope
is appropriately bounded, and (b) the security hardening requirements (PKCE
S256 MUST, iss MUST, exact redirect_uri MUST) are correct and do not
constitute breaking changes for existing compliant implementations.
Identity management scope and framing: Does the TC agree with the
Layer 2 / Layer 4 separation — identity_linking stays as the
authentication authority (Layer 2) and account lifecycle operations land at
Layer 4 alongside membership management? If so, the remaining question is
whether those account lifecycle operations (creation, deletion, profile
management) should be a dedicated identity_management capability at
Layer 4, or absorbed into the memberships capability already established
by Phases 5 and 6. The former keeps identity concerns separate from loyalty
concerns but adds a capability for implementors to support; the latter
simplifies the protocol surface but couples account lifecycle to the loyalty
stack. See Phase 7 for the full framing of both options.
RFC: Identity Linking, Identity Management, and Loyalty
Summary
This proposal defines a unified, incrementally-deliverable roadmap for identity
and loyalty support in UCP. It sequences a set of focused PRs — from the
foundational OAuth 2.0 authority model through delegated identity providers,
extended authentication mechanisms, loyalty benefit recognition, program
discovery, membership operations, and buyer profile management — so that each
PR is independently reviewable, non-breaking, and delivers real value on its
own while advancing the overall vision.
The proposal is motivated by three clusters of open work that are related to each other:
a reverted breaking change, and need for discussion around delegated IdPs and
multi-mechanism negotiation.
of
identity_linkingwithidentity_managementthat mixes the OAuthauthority layer with the profile data layer.
scope creep concerns from reviewers and a focused baseline version.
This RFC provides the architectural framing that lets all three clusters land
cleanly.
Motivation
The Four-Layer Model
We propose breaking overall Identity and loyalty work in a four-layered stack. Each layer depends on
the one below it; landing them in order is the core idea
of this RFC:
Layer 1 (discovery and scope contract) is the foundation everything else
depends on. It has two components:
/.well-known/ucp): the business's publishedcapability set, including the
dev.ucp.common.identity_linkingconfig thatdeclares which capabilities offer buyer-scoped features and what scopes they
carry. Platforms read this profile before attempting any identity flow — it
is the contract that determines what auth the business requires.
scope tokens (
dev.ucp.shopping.checkout,dev.ucp.shopping.order:read).Both the scope naming convention and the access tier model is proposed to
be standardized before delegated IdP or multi-mechanism negotiation can be
specified, because those higher layers derive their scope sets from this
foundation.
This is why Phase 1 (PR #354) is the highest-priority fix. The scope naming
in the current spec (
ucp:scopes:checkout_sessionstyle) is incorrect anddiverges from the capability name convention. Every implementor reading the
current spec is wiring the wrong scope strings. That bug needs to be in
implementors' hands fast — ideally via a backport to the most recently
released version — not held until the next full protocol release.
Layer 2 (identity authority) is what
dev.ucp.common.identity_linkingcovers. It should remain focused on authentication mechanics: how does the
business establish trust in the buyer's claimed identity, and via which
mechanism? Phase 1 specifies business-hosted OAuth 2.0 as the v1 baseline.
Phases 2 and 3 extend this layer with delegated IdPs and additional mechanism
types (wallet attestation, verifiable credentials) without changing the Layer 1
scope contract.
Layer 3 (loyalty data) covers what the business knows about the buyer's
loyalty relationship: benefit entitlements in an active checkout or cart session
(Phase 4,
loyaltyextension), and the full program structure — tiers,enrollment conditions, reward rules — available for discovery outside of a
transaction (Phase 5,
membershipscapability). This layer is read-oriented;it surfaces state but does not mutate it.
Layer 4 (loyalty management) covers write operations that change the
buyer's relationship with the business: membership enrollment, tier progression,
reward redemption, and cancellation (Phase 6, write operations on
memberships).It also covers account lifecycle operations — creation, deletion, and profile
management — addressed by Phase 7, whose exact capability placement (standalone
identity_managementor absorbed intomemberships) is pending TC resolution.Sample changes across four layers:
identity_linkingconfig in discovery profileidentity_linking— OAuth serveridentity_linkingconfig (Phase 2/3 extension)loyaltyextension on checkout/cartmembershipscapability (read operations)membershipscapability write operationsdiscountextension & moreidentity_managementcapabilityidentity_managementcapabilityWhy Incrementally?
The full vision spans eight distinct units of work. Attempting to land all of
it in one or two PRs might be sub-optimal (#265 reverted, #337 in-progress, #251
under review). Each phase below is:
requiring subsequent phases.
called out explicitly and require the two-week community notice period.
so reviewers can assess correctness without holding the full vision in mind.
subsequent phases, specified normatively.
Proposed Phases
Phase 1 — Discovery Profile, Scope Contract, and OAuth 2.0 Foundation (PR #354)
[In Progress — Urgent]Capability:
dev.ucp.common.identity_linkingType: Breaking (
!) — removes theidentity_scopesannotation approach introduced in #265 (reverted in #329, but the replacement scope model is a protocol-level clarification that warrants!per CONTRIBUTING.md)Urgency: High — scope naming bug affects every current implementor
Blocks: Phases 2, 3, 4, 7
Backport target:
v2026-04-08patch release (see Backport Proposal)Why this is urgent
The current spec (as of
v2026-04-08) does not define normative scope tokennames for buyer-authenticated capabilities. PR #265 introduced
ucp:scopes:checkout_session-style tokens; that PR was reverted in #329 butthe scope naming gap was never filled. As a result, implementors building
against the current release either:
(a) invent their own scope strings, producing incompatible implementations, or
(b) skip buyer-authenticated flows entirely, which silently breaks loyalty,
order history, and personalized pricing use cases.
This is not a future-version concern. Implementors shipping today are wiring
the wrong scope strings and will require a painful migration if the fix waits
for the next full protocol version. The Phase 1 PR (currently in review as
#354) contains the complete fix and should be backported to
v2026-04-08as a patch.
What lands
Discovery profile (Layer 1 — scope contract):
dev.ucp.common.identity_linkingentry in theUCP
/.well-known/ucpbusiness profile. This is the machine-readablecontract that platforms read before attempting any identity flow.
config.capabilitiesonthe identity linking config — not annotated on individual capability schemas
(that approach caused the feat!: redesign identity linking with mechanism registry and capability-driven scopes #265 bug). Capabilities are never excluded from
the negotiated capability set based on identity linking presence.
authenticated (platform credentials only), buyer-authenticated
(platform + buyer identity token). Each capability operates at all three
tiers simultaneously; buyer auth upgrades the experience rather than gating
the capability.
(
dev.ucp.shopping.checkout), with sub-scope operation groups joined bycolon on the wire (
dev.ucp.shopping.order:read). Replaces and supersedesany prior
ucp:scopes:*naming.auth_required: trueon aconfig.capabilitiesentry signals that the businessreturns
identity_requiredfor requests without a buyer token; omitting itmeans identity is optional (upgrades the experience).
scopes_supportedMUST be present in RFC 8414 server metadata and MUST listthe capability-derived scope tokens the server accepts.
OAuth 2.0 with RFC 8414 discovery (Layer 2 — auth mechanism):
RFC 8414
/.well-known/oauth-authorization-serverprimary; OIDC/.well-known/openid-configurationfallback on HTTP 404 only; all othererrors MUST abort (no silent fallback).
issclaim validationMUST (RFC 9207 mix-up attack prevention), exact
redirect_urimatching MUST,issuerbyte-for-byte match with no normalization.Forward-compatibility provisions:
config.additionalProperties: truewith normative platform ignore rule:platforms encountering unrecognized
configfields MUST ignore them andproceed using OAuth 2.0 with RFC 8414 discovery on the business domain.
$commentnames two reserved extension points:config.providers(Phase 2 — delegated IdP) and
config.mechanisms(Phase 3 — mechanismnegotiation). These are deliberate design hooks, not accidental open fields.
Schema shape (stable after Phase 1)
The
config.capabilitiesmap is the core artifact of Phase 1. Its shape isfinal; Phases 2 and 3 add sibling keys (
providers,mechanisms) alongsideit without modifying it.
The RFC 8414 metadata published by the business MUST reflect the same scope
tokens:
{ "issuer": "https://merchant.example.com", "authorization_endpoint": "https://merchant.example.com/oauth/authorize", "token_endpoint": "https://merchant.example.com/oauth/token", "scopes_supported": [ "dev.ucp.shopping.checkout", "dev.ucp.shopping.order:read", "dev.ucp.shopping.order:manage" ] }What is explicitly out of scope (deferred)
wallet_attestation(Phase 3)Phase 2 — Delegated Identity Providers (PR #330)
[Proposal]Capability:
dev.ucp.common.identity_linking(extension of Phase 1 config)Type: Non-breaking additive extension
Depends on: Phase 1
Note: Phase 3 can land independently of Phase 2 (Phase 2 recommended but not required for mechanism extensibility)
Problem statement
Phase 1 requires a full OAuth dance per merchant. In agentic commerce where a
platform shops across N businesses, this means N authorization redirects — each
requiring a buyer interaction. Delegated IdP allows a business to declare trust
in a third-party identity provider (e.g., a commerce super-app's platform
IdP, Google, Shop). A buyer who has authenticated with that IdP once can be
recognized at any business that trusts it, without a new redirect.
What lands
config.providersmap (the Phase 1 reserved extension point), keyed byreverse-domain provider identifier. Each entry carries
auth_urlforRFC 8414 discovery.
One-time per provider; business issues its own access token after
receiving the IdP-issued token.
valid IdP token, exchanges it for a business-scoped token without a
browser redirect. Implements the two-phase pattern from
draft-ietf-oauth-identity-chaining-08: (1) platform requests JWT
authorization grant from IdP via RFC 8693 token exchange; (2) platform
presents JWT grant to business token endpoint via RFC 7523 JWT bearer
assertion; (3) business validates, resolves buyer identity, issues its
own token. Refresh tokens MUST NOT be issued per the chaining draft.
has not authorized. Businesses MAY auto-provision accounts or return
continue_urlfor buyer onboarding.providerscontains multiple entries, the businesssignals preference via the
mechanismsarray (Phase 3). In Phase 2 (beforemechanismsis defined), platforms MAY attempt providers in any order; thespec will define a normative selection rule (e.g., explicit ordering via a
preferred_providerhint) before Phase 2 ships.Schema shape
Non-breaking guarantee
Platforms that do not implement delegated IdP ignore the
providersmap (perthe Phase 1 normative ignore rule) and fall back to business-hosted OAuth 2.0
using the business's own
auth_url. No existing implementation breaks.Phase 3 — Mechanism Extensibility (New PR)
[Optional - Proposal]Capability:
dev.ucp.common.identity_linking(addsconfig.mechanismsalongside Phase 1'sconfig.capabilities)Type: Non-breaking additive extension
Depends on: Phase 1 (Phase 2 recommended but not required)
Relates to: EP #287 (Wallet Attestation)
Problem statement
OAuth 2.0 is the right default for account-bearing commerce but not the only
valid identity mechanism. Wallet attestation (EP #287) establishes buyer
identity via cryptographically signed on-chain state, with no redirect and no
account. Verifiable credentials extend this to off-chain claims. Both are valid
mechanisms for specific commerce verticals (token-gated merchandise, NFT-gated
access, B2B credentialed purchasing). Phase 3 introduces the mechanism
negotiation layer that lets businesses declare and platforms select among
supported mechanism types.
What lands
config.mechanismsordered array (the Phase 1 second reserved extensionpoint). Each entry is a mechanism object with a
typediscriminator string.Business-preference ordering: platforms select the first
typethey support,abort if none match (no partial or fallback flows permitted).
oauth2— business-hosted OAuth 2.0 (Phase 1 behavior; default whenmechanismsis absent). Fields:auth_url(optional; falls back toRFC 8414 discovery on the business domain).
wallet_attestation— wallet-based identity per EP Wallet Attestation — Identity Mechanism + Eligibility Extension #287.Fields:
provider_jwks(required),attestation_endpoint(optional).Scope contribution: zero (stateless, self-contained).
optional grant type on
oauth2entries.mechanismsis absent, protocol falls back to Phase 1 behavior(business-hosted OAuth 2.0 with RFC 8414 discovery). No existing
implementation breaks.
Schema shape
Relationship to Phase 2
config.providers(Phase 2) andconfig.mechanisms(Phase 3) arecomplementary.
providersis a map of trusted OAuth issuers (who can vouch forthe buyer).
mechanismsis an ordered list of authentication schemes (how theplatform establishes identity). When both are present,
mechanismsgovernsselection;
oauth2entries resolve their provider set fromprovidersplus thebusiness's own domain.
Phase 4 — Loyalty Checkout Extension (Revised PR #340 / #251 Baseline)
[Proposal]Extension of:
dev.ucp.shopping.checkout,dev.ucp.shopping.cartCapability name:
dev.ucp.shopping.loyalty(extension)Type: Non-breaking additive extension
Depends on: Phase 1 (for
identity_required/ buyer-scoped loyalty state)TC review: PR #251 under active TC review; PR #340 is proposed as the
focused baseline — this phase resolves the two proposals
Problem statement
Two competing proposals exist:
(sign-up, tier upgrade, redemption, discovery), using a
Membership → Tier → Benefits + Rewards hierarchy.
at checkout, using a Membership → Track → Tier → Benefits + Rewards hierarchy
that separates enrollment tracks from achievement tiers.
Phase 4 adopts PR #340's focused scope and five-concept hierarchy
(tracks separate from tiers), resolves the read/write concern by restricting
this phase to read-only benefit recognition, and defers program discovery
and membership operations to Phases 5 and 6.
What lands
status within it. Carries
member_idfor platform-side correlation.member). A buyer may hold multiple tracks simultaneously. Introduced to
normalize the Hybrid Loyalty Model without data collisions.
has one activated tier per buyer.
access). Read-only in this phase.
Balance display and earning forecast in this phase; actual redemption via
discount extension (Phase 6).
loyaltyobject on checkout and cart responses, keyed off theloyaltyextension name.
eligibilityclaimpattern (feat: eligibility claims & verification contract #250) — buyer claims membership eligibility in the request;
business verifies and returns confirmed membership state.
membership_idfield: addresses amithanda's review comment onfeat: Add basic schema for loyalty extension #251 — platforms with a known membership identifier MUST be able to send it
in the request so businesses can correlate without requiring a separate
identity lookup.
benefit descriptions reference the applied discount via
applies_on(JSONPath). Benefits and discounts remain in separate objects — the loyalty
extension declares what the buyer is entitled to; the discount extension
declares what was applied.
per-item breakdown (addresses tpindel's review comment on feat: Add basic schema for loyalty extension #251).
What is explicitly out of scope (deferred to Phases 5/6)
(static brochure data — moved to Phase 5 loyalty discovery operation).
Schema sketch
Phase 5 — Loyalty Membership Discovery (New Capability)
[Proposal]Capability:
dev.ucp.shopping.memberships(new)Type: New capability — no breaking changes
Depends on: Phase 4 schema definitions (reuses types)
Resolves: igrigorik's architectural concern on #251
Problem statement
Static program data — all possible tiers, enrollment conditions, benefit
descriptions, program terms — is currently bundled into checkout/cart
responses. This is wasteful (unchanged per-transaction), muddles the semantic
contract ("checkout response should reflect what's negotiated for this session,
not the full program brochure"), and makes it impossible to implement simple
caching.
What lands
dev.ucp.shopping.membershipscapability for requesting the loyaltyprogram brochure independently of a transaction.
structure with all tiers, enrollment conditions, non-member benefits. Used
for upsell ("join to save $5").
buyer's activated track/tier plus the full program structure for context.
Supports "you are two purchases away from Platinum" UI patterns.
enrollment_conditionsdescribes how a buyer qualifies for a tier;
benefitson the active responsedescribes what the buyer currently holds. This resolves the Phase 4 scope
restriction by moving discovery-only fields out of the checkout response.
Phase 6 — Loyalty Membership Operations (New PR)
[Proposal]Builds on:
dev.ucp.shopping.memberships(Phase 5 capability)Type: Non-breaking additive (new write operations on the memberships capability)
Depends on: Phase 1 (identity required for sign-up), Phase 5 (memberships capability)
Recommended prerequisite: Phase 4 (loyalty extension provides benefit/reward context)
What lands
terms (from Phase 5 discovery). Flow: platform presents program terms →
buyer consents → platform sends enrollment request → business registers and
returns confirmed membership object. Integrates with
buyer_consentextension for terms acceptance.
next_tier_progressonthe loyalty response — amount remaining, qualifying actions. Read-only from
the spec's perspective; businesses compute progress server-side.
redeemamount on a rewardcurrency in the checkout request; business applies it as a discount entry
and returns the updated balance. Redemption is executed via the
discountextension (
appliedarray) withloyaltyextension showing the updatedbalance post-redemption. This maintains the read/write separation: loyalty
declares state; discount declares the applied effect.
coverage, scoped to
statusfield transitions (active → paused → cancelled).Out of scope (deferred)
Phase 7 — Identity Management: Open Discussion
[Under Discussion]The question
Should account lifecycle operations — account creation, deletion, and profile
management — be a separate
dev.ucp.common.identity_managementcapability, orshould they be absorbed into the
dev.ucp.shopping.membershipscapabilityintroduced in Phase 5/6 as part of membership operations?
Option A: Dedicated
identity_managementcapability (Layer 4)Account lifecycle is distinct from loyalty membership. A buyer can have an
account with a business without being a loyalty member, and account operations
(creation, deletion) carry different consent, legal, and data-portability
obligations than membership enrollment or tier progression. Under this model,
dev.ucp.common.identity_managementis a new Layer 4 capability that dependson the Phase 1 authentication token but is independent of the loyalty stack.
Platforms that need account management but have no loyalty program can adopt it
without pulling in Phases 4–6.
Argument for: Clean separation of concerns; account lifecycle is not
loyalty-specific. Aligns with PR #337's original goals without conflating
identity and loyalty.
Argument against: Adds another capability for implementors to support.
If the majority of account lifecycle events (sign-up, cancellation) are
triggered through the membership enrollment flow, splitting them into a
separate capability creates coordination overhead with no clear benefit.
Option B: Account lifecycle as part of
memberships(Phase 6 extension)Account creation and deletion could be operations on the
dev.ucp.shopping.membershipscapability — specifically as preconditions orpostconditions of membership enrollment and cancellation. Account creation is
a natural part of the sign-up flow; account deletion maps to membership
cancellation taken to its logical conclusion. Under this model, Phase 7 is
dissolved and its operations are incorporated into Phase 6.
Argument for: Simpler protocol surface; fewer capabilities for platforms
to register and discover. The membership enrollment flow already requires
buyer consent and identity, so the infrastructure is already present.
Argument against: Conflates commerce-layer loyalty operations with
identity-layer account management. Businesses that want to offer account
deletion under GDPR/CCPA obligations should not have to implement the full
loyalty membership stack to do so.
Recommendation request
The TC is asked to decide: should Phase 7 proceed as a standalone capability,
be merged into Phase 6, or be deferred entirely to a future RFC focused on
buyer data rights and account portability?
Backport Proposal
Target release:
v2026-04-08patchScope: Phase 1 changes only — discovery profile scope contract and security
hardening. No delegated IdP, no mechanism negotiation.
Rationale
The scope naming gap introduced by the #265 revert (#329) is present in the
current stable release
v2026-04-08. Every implementor building against thatrelease faces two bad choices: invent non-standard scope strings, or skip
buyer-authenticated flows entirely. Neither is acceptable for a protocol
claiming to standardize agentic commerce.
Waiting for the next full protocol version to fix scope naming would:
significant effort for any production system that has hardcoded tokens.
scope namespaces and must coordinate a flag day to migrate.
Backporting the Phase 1 scope contract as a patch release avoids all these
outcomes at low risk — the changes are purely additive to the discovery profile
and spec text; no existing wire format is modified.
What is included in the backport
dev.ucp.shopping.*)config.capabilitiesmap on identity linkingscopes_supportedMUST in RFC 8414 metadataissMUST, exactredirect_uriMUSTissuerbyte-for-byte match ruleWhat is excluded from the backport
Phases 2–7 are excluded. The backport carries only what is needed to unblock
implementors today: the scope naming contract and OAuth 2.0 security baseline.
Delegated IdP, mechanism negotiation, loyalty, and identity management are
new-version features that follow the normal proposal lifecycle.
Dependency Graph
Implementation Sequence and Suggested PR Titles
feat!: identity linking OAuth 2.0 foundation with capability-driven scopesfeat: identity linking — delegated IdP and accelerated identity chainingfeat: identity linking — mechanism extensibility with wallet attestationfeat: loyalty checkout/cart extension — benefit recognition and rewardsfeat: loyalty memberships capability — program discovery and enrollmentfeat: loyalty — membership enrollment, tier progression, and redemptionfeat: identity management — account creation, portability, and deletionTC Review Questions
The following questions require explicit TC resolution before this RFC advances to Provisional.
Phase structure and sequencing: Does the TC agree with decomposing this
work into the seven phases defined above, and with the proposed sequencing?
Specifically: are the dependency relationships between phases correct, and is
the decision to keep Phases 2–7 gated behind individual TC votes — rather
than pre-approving the full roadmap now — the right governance posture? If
the TC has concerns about specific phase boundaries (e.g., whether Phase 5
and 6 should be merged, or whether Phase 7 belongs in a separate RFC), this
is the point to surface them.
Backport approval: Does the TC approve backporting the Phase 1 scope
contract and OAuth 2.0 security baseline to the current stable release
(
v2026-04-08) as a patch? The backport is limited to the changes listed inthe "What is included in the backport" table — no delegated IdP, no loyalty,
no identity management. The rationale is that the scope naming gap introduced
by the feat!: redesign identity linking with mechanism registry and capability-driven scopes #265 revert is causing real interoperability pain for implementors
today and the fix is purely additive. TC should confirm: (a) the patch scope
is appropriately bounded, and (b) the security hardening requirements (PKCE
S256 MUST,
issMUST, exactredirect_uriMUST) are correct and do notconstitute breaking changes for existing compliant implementations.
Identity management scope and framing: Does the TC agree with the
Layer 2 / Layer 4 separation —
identity_linkingstays as theauthentication authority (Layer 2) and account lifecycle operations land at
Layer 4 alongside membership management? If so, the remaining question is
whether those account lifecycle operations (creation, deletion, profile
management) should be a dedicated
identity_managementcapability atLayer 4, or absorbed into the
membershipscapability already establishedby Phases 5 and 6. The former keeps identity concerns separate from loyalty
concerns but adds a capability for implementors to support; the latter
simplifies the protocol surface but couples account lifecycle to the loyalty
stack. See Phase 7 for the full framing of both options.