Skip to content

[RFC] Proposal: Identity Linking, Identity Management, and Loyalty #355

@amithanda

Description

@amithanda

RFC: Identity Linking, Identity Management, and Loyalty

Field Value
Status Proposal
Authors amithanda
Created 2026-04-12
TC Decision Pending
Relates to #354, #337, #251, #340, #330, #265, #329, #287, #343

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:

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:

  1. Independently useful — delivers real value to implementers without
    requiring subsequent phases.
  2. Non-breaking by default — additive changes; breaking changes are
    called out explicitly and require the two-week community notice period.
  3. Reviewable in isolation — scoped to one capability or one extension,
    so reviewers can assess correctness without holding the full vision in mind.
  4. 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.

OAuth 2.0 with RFC 8414 discovery (Layer 2 — auth mechanism):

Forward-compatibility provisions:

  • 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.

"dev.ucp.common.identity_linking": [{
  "config": {
    "capabilities": {
      "dev.ucp.shopping.checkout": {},
      "dev.ucp.shopping.order": {
        "auth_required": true,
        "scopes": ["read", "manage"]
      }
    }
  }
}]

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)

  • Delegated identity providers (Phase 2)
  • Multi-mechanism negotiation and wallet_attestation (Phase 3)
  • Device authorization grant RFC 8628 (Phase 3)
  • Identity management operations (Phase 7, Account Lifecycle)

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.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.

Schema shape

"dev.ucp.common.identity_linking": [{
  "config": {
    "providers": {
      "com.google": {
        "auth_url": "https://accounts.google.com/"
      },
      "com.example.merchant": {
        "auth_url": "https://merchant.example.com/"
      }
    },
    "capabilities": {
      "dev.ucp.shopping.order": {
        "auth_required": true,
        "scopes": ["read", "manage"]
      }
    }
  }
}]

Non-breaking guarantee

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).
    • 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).
  • 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.

Schema shape

"dev.ucp.common.identity_linking": [{
  "config": {
    "mechanisms": [
      {
        "type": "oauth2",
        "auth_url": "https://merchant.example.com/"
      },
      {
        "type": "wallet_attestation",
        "provider_jwks": "https://verifier.example.com/.well-known/jwks.json",
        "attestation_endpoint": "https://verifier.example.com/v1/attest"
      }
    ],
    "capabilities": {
      "dev.ucp.shopping.checkout": {}
    }
  }
}]

Relationship to Phase 2

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.


Phase 4 — Loyalty Checkout Extension (Revised PR #340 / #251 Baseline) [Proposal]

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:

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

  • Five-concept hierarchy (PR feat: loyalty extension for checkout capability #340 model):
    • 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.
  • Earning forecast: per-transaction point/mile/cashback estimate with
    per-item breakdown (addresses tpindel's review comment on feat: Add basic schema for loyalty extension #251).
  • Cart support added alongside checkout, per amithanda's review comment on feat: Add basic schema for loyalty extension #251.

What is explicitly out of scope (deferred to Phases 5/6)

  • Full tier catalog and enrollment conditions in checkout/cart responses
    (static brochure data — moved to Phase 5 loyalty discovery operation).
  • Membership sign-up / tier upgrade (write operations — Phase 6).
  • Reward transfer or cross-program redemption (advanced — Phase 6+).

Schema sketch

"loyalty": {
  "memberships": [
    {
      "id": "membership_1",
      "member_id": "member_id_1",
      "name": "Example Rewards",
      "tracks": [
        {
          "id": "track_standard",
          "name": "Standard Member",
          "tiers": [
            {
              "id": "tier_gold",
              "name": "Gold",
              "benefits": [
                {
                  "id": "BEN_001",
                  "title": "Free Standard Shipping",
                  "description": "Complimentary standard shipping on all orders",
                  "applies_on": "$.discounts.applied[0]"
                }
              ]
            }
          ],
          "activated_tiers": ["tier_gold"]
        }
      ],
      "activated_tracks": ["track_standard"],
      "rewards": [
        {
          "currency": { "name": "LoyaltyStars", "code": "LST" },
          "balance": { "available": 1000 },
          "earning_forecast": {
            "amount": 10,
            "projected_balance": 1010,
            "breakdown": [
              {
                "id": "rule_base",
                "amount": 10,
                "description": "1 point per dollar spent"
              }
            ]
          }
        }
      ],
      "provisional": false,
      "eligibility": "com.example.loyalty"
    }
  ]
}

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.
  • Membership cancellation / pause: within the scope of PR feat: Add basic schema for loyalty extension #251's lifecycle
    coverage, scoped to status field transitions (active → paused → cancelled).

Out of scope (deferred)

  • Cross-program reward transfers (network-level feature, requires separate EP).
  • Points expiry management (monitoring concern; future extension).

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?

Option A: Dedicated identity_management capability (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_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:

  1. Force implementors to ship a scope migration in a future update — a
    significant effort for any production system that has hardcoded tokens.
  2. 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.

What is included in the backport

Change Justification for backport
Canonical scope token format (dev.ucp.shopping.*) Fixes the #329 revert gap; no wire-format change
config.capabilities map on identity linking New normative definition; additive
Three-tier access model (public / agent / buyer) Clarification; no schema change
scopes_supported MUST in RFC 8414 metadata Security / interoperability requirement
PKCE S256 MUST, iss MUST, exact redirect_uri MUST Security hardening; additive requirement
issuer byte-for-byte match rule Prevents RFC 9207 mix-up attack; additive
Strict 2-tier discovery (abort on non-404 errors) Security; tightens undefined behavior

What 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

Phase 1: OAuth 2.0 Foundation (PR #354)
    │
    ├── Phase 2: Delegated IdP (PR #330)
    │       │
    │       └── Phase 3: Mechanism Extensibility (PR: new, +EP #287)
    │
    ├── Phase 4: Loyalty Checkout Extension (PR: revised #340/#251)
    │       │
    │       └── Phase 5: Loyalty Membership Discovery (PR: new capability)
    │               │
    │               └── Phase 6: Loyalty Membership Operations (PR: new)
    │
    └── Phase 7: Identity Management — Account Lifecycle (PR: new, Layer 4)

Implementation Sequence and Suggested PR Titles

Phase Layer Suggested PR Title
1 1–2 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.

  1. 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.

  2. 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.

  3. 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.


Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions