Skip to content

refactor: organize specification hierarchy by domain verticals (Shopping, Payment, Common) - #723

Merged
niranjanmanjunath merged 15 commits into
mainfrom
refactor/vertical-support
Aug 20, 2026
Merged

refactor: organize specification hierarchy by domain verticals (Shopping, Payment, Common) #723
niranjanmanjunath merged 15 commits into
mainfrom
refactor/vertical-support

Conversation

@niranjanmanjunath

@niranjanmanjunath niranjanmanjunath commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR builds on @jingyli 's RFC #520 specifically addressing Phase 1. Please note there's changes in this implementation from the original RFC, however the intent remains the same.

Summary

This PR refactors the specification documentation structure by grouping specification documents into dedicated, domain-aligned namespaces and vertical directories (shopping/, payment/, common/, and overview/). This allows us to add more verticals in the future along the same hierarchy.

It aligns the documentation information architecture with the UCP protocol taxonomy ({reverse-domain}.{service}.{capability}), simplifies navigation, updates all internal links and macros, and implements comprehensive backwards-compatible redirects for legacy URLs.

Key Changes & Restructuring

1. Shopping Vertical (docs/specification/shopping/)

• Checkout Capability: Moved to shopping/checkout/ (index.md, rest.md, mcp.md, a2a.md, embedded.md).
• Cart Capability: Moved to shopping/cart/ (index.md, rest.md, mcp.md, embedded.md).
• Catalog Capability: Moved to shopping/catalog/ (index.md, search.md, lookup.md, rest.md, mcp.md).
• Order Capability: Moved to shopping/order/ (index.md, rest.md, mcp.md).
• Playground: Relocated from specification/playground.md to specification/shopping/playground.md.

2. Payment Vertical (docs/specification/payment/)

• Core Guides & Protocols: Moved to payment/ (guide.md, template.md, tokenization.md, authentication.md, split-payments.md).
• Payment Actions: Grouped into payment/actions/ (device-data-collection.md, three-ds-challenge.md).
• Payment Examples: Grouped into payment/examples/ (processor-tokenizer-payment-handler.md, platform-tokenizer-payment-handler.md, encrypted-credential-
payment-handler.md).

3. Common Vertical (docs/specification/common/)

• Identity Linking: Moved to common/identity-linking/index.md to establish the domain-agnostic common services namespace.

4. Overview (docs/specification/overview/)

• Moved overview.md to overview/index.md for consistent directory-style routing.

5. Navigation & LLM Indexing (mkdocs.yml)

• Sidebar Navigation: Reorganized nav -> Specification into symmetrical top-level vertical groupings:
• Overview
• Common
• Shopping
• Payment
• Signatures
• Reference
• llmstxt Plugin: Synchronized all section headings and path mappings to preserve accurate LLM context indexing for AI agents.

6. Backward Compatibility & Redirects

• Configured 29 explicit mappings in plugins.redirects.redirect_maps so that all legacy paths (e.g. /specification/checkout.md, /specification/payment-
handler-guide.md, /specification/playground.md) cleanly forward to their new vertical endpoints without 404s.
---

Category (Required)

Please select one or more categories that apply to this change.

  • Core Protocol: Changes to the base communication layer, global context, or breaking refactors. (Requires Technical Council approval)
  • Governance/Contributing: Updates to GOVERNANCE.md, CONTRIBUTING.md, or CODEOWNERS. (Requires Governance Council approval)
  • Capability: New schemas (Discovery, Cart, etc.) or extensions. (Requires Maintainer approval)
  • Documentation: Updates to README, or documentations regarding schema or capabilities. (Requires Maintainer approval)
  • Infrastructure: CI/CD, Linters, or build scripts. (Requires DevOps Maintainer approval)
  • Maintenance: Version bumps, lockfile updates, or minor bug fixes. (Requires DevOps Maintainer approval)
  • SDK: Language-specific SDK updates and releases. (Requires DevOps Maintainer approval)
  • Samples / Conformance: Maintaining samples and the conformance suite. (Requires Maintainer approval)
  • UCP Schema: Changes to the ucp-schema tool (resolver, linter, validator). (Requires Maintainer approval)
  • Community Health (.github): Updates to templates, workflows, or org-level configs. (Requires DevOps Maintainer approval)

Related Issues

#520

Checklist

  • I have followed the Contributing Guide (including Conventional Commits title requirements and ! for breaking changes).
  • I have updated the documentation (if applicable).
  • My changes pass all local linting and formatting checks.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • (For Core/Capability) I have included/updated the relevant JSON schemas.
  • I have regenerated Python Pydantic models by running generate_models.sh under python_sdk.

Screenshots / Logs (if applicable)

image

@damaz91 damaz91 added the status:needs-triage Signal that the PR is ready for human triage label Aug 13, 2026
@niranjanmanjunath
niranjanmanjunath force-pushed the refactor/vertical-support branch from 9845d0a to 7737eb1 Compare August 13, 2026 23:46
@niranjanmanjunath niranjanmanjunath changed the title Refactor/vertical support: organize specification hierarchy by domain verticals (Shopping, Payment, Common) refactor/vertical support: organize specification hierarchy by domain verticals (Shopping, Payment, Common) Aug 13, 2026
@niranjanmanjunath niranjanmanjunath changed the title refactor/vertical support: organize specification hierarchy by domain verticals (Shopping, Payment, Common) refactor: organize specification hierarchy by domain verticals (Shopping, Payment, Common) Aug 13, 2026
@damaz91 damaz91 added status:under-review gov:needs-tc-review Requires review and approval from the Technical Council documentation Improvements or additions to documentation and removed status:needs-triage Signal that the PR is ready for human triage gov:needs-tc-review Requires review and approval from the Technical Council labels Aug 14, 2026
@draspall draspall added the TC review Ready for TC review label Aug 14, 2026
@damaz91 damaz91 added the gov:needs-tc-review Requires review and approval from the Technical Council label Aug 17, 2026
@igrigorik igrigorik added this to the 2026-08-24 milestone Aug 17, 2026
@igrigorik

Copy link
Copy Markdown
Contributor

Overall, agree with the direction. Found a few issues to address before we ship...

Local preview topology

There are 29 redirect failures, which appear to come from the local preview not matching production. Production replaces the root specification/ output with specification -> latest/specification; build_local.sh --draft-only leaves root-mode redirect pages in local_preview/specification/, while their canonical targets exist only under latest. The checker is therefore validating a topology we never deploy.

Rec: Could we make the local preview reproduce production's alias before running check_links.py—for example, by replacing local_preview/specification with the same latest/specification symlink after merging the versioned directories? That seems preferable to suppressing the errors and would test root links against the artifact users actually receive.

Catalog-generated links

Three calls in docs/specification/shopping/catalog/rest.md:74, :204, and :356 still pass catalog/rest to method_fields. main.py uses that argument to generate entity links, so the rendered output points at the legacy redirect shell rather than the canonical Shopping Catalog page.

Rec: Update those three arguments to shopping/catalog/rest, rebuild, and confirm the rendered page contains no generated /specification/catalog/rest/ entity links.

Markdown failures

Markdownlint reports three table-alignment failures in docs/specification/glossary.md and one invalid local-fragment failure for Checkout's [Totals](#totals) link. Should be simple mechanical fixes.


I like payment/ as a top-level, cross-cutting documentation domain, but it does not literally mirror {reverse-domain}.{service}.{capability}. Payment Authentication and Split Payments remain dev.ucp.shopping.* extensions, dev.ucp.payment.* identifies Action types rather than a Payment service, and payment handlers use a separate registry. Nit but let's describe payment/ as a cross-cutting documentation domain rather than protocol-taxonomy alignment? The current layout seems reasonable; deeper extensions/, actions/, and handlers/ subdivisions can wait until growth justifies them.

@niranjanmanjunath

Copy link
Copy Markdown
Collaborator Author

Thanks for the feedback.
Some of the failure are because of a recent merge from upstream. I'll fix it shortly and update the PR

…lignments

- Parameterize schema URLs and capability identifiers with {{ ucp_version }} across core concepts, identity linking, permalink, and order docs
- Update method_fields and schema_fields macro reference paths in shopping catalog REST and MCP docs
- Align table columns in glossary Commerce section
- Fix Total heading and local fragment links in checkout and cart docs
- Mirror production specification symlink in build_local.sh for accurate local redirect validation
…t-terms

- Update relative links in fulfillment.md to point to shopping/catalog, shopping/checkout, and shopping/cart
- Update relative links in payment-terms.md to point to payment/split-payments, overview/index, and shopping/checkout
- Format mkdocs.yml navigation and redirect_maps lines to be <= 80 characters
- Wrap templated OpenRPC schema URL in order/mcp.md with angle brackets
- Nest duplicate Request format heading under AP2 completion in checkout/a2a.md
@amithanda
amithanda requested a review from gsmith85 August 19, 2026 01:49
@iantrainor iantrainor added the area:payments Issues and pull requests related to the Payments vertical label Aug 19, 2026

@igrigorik igrigorik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing earlier feedback. A few additional nits/suggestions, otherwise LGTM.

Comment thread docs/specification/shopping/checkout/index.md Outdated
Comment thread docs/specification/shopping/checkout/index.md Outdated
Comment thread docs/specification/shopping/cart/index.md Outdated
Comment thread docs/documentation/core-concepts.md Outdated

@gsmith85 gsmith85 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Approving to land Phase 1 of RFC #520.

Context from Tech Council Deep Dive (2026-08-20): At today's TC Deep Dive, the council confirmed that payment constructs will remain in the common protocol namespace** (dev.ucp.common.* / dev.ucp.common.payments rather than dev.ucp.payments.*), reflecting payments as a shared horizontal capability across all
verticals.

For this PR, we are aligned on keeping docs/specification/payment/ as an organized, top-level documentation domain for developer discoverability (guides, actions, and handler examples). We will handle schema placement (source/schemas/common/) and any subsequent docs/nav path adjustments in #741 and follow-up PRs without blocking this restructure.

@gsmith85

gsmith85 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Non-blocking Nits / Consistency Cleanups

  1. Stale capability spec URLs in docs/specification/shopping/playground.md (lines 493, 500):
    To match the updates in docs/documentation/core-concepts.md (commit 12145d8), these should point to the namespaced paths:

       capabilities: {
         "dev.ucp.shopping.checkout": [
           {
             version: "{{ ucp_version }}",
    -        spec: "https://ucp.dev/{{ ucp_version }}/specification/checkout",
    +        spec: "https://ucp.dev/{{ ucp_version }}/specification/shopping/checkout",
             schema: "https://ucp.dev/{{ ucp_version }}/schemas/shopping/checkout.json"
           }
         ],
         "dev.ucp.shopping.order": [
           {
             version: "{{ ucp_version }}",
    -        spec: "https://ucp.dev/{{ ucp_version }}/specification/order",
    +        spec: "https://ucp.dev/{{ ucp_version }}/specification/shopping/order",
             schema: "https://ucp.dev/{{ ucp_version }}/schemas/shopping/order.json"
           }
         ],
  2. Comment reference in docs/specification/signatures.md (line 684):

    -    // overview.md#identity-resolution-algorithm).
    +    // overview/index.md#identity-resolution-algorithm).

@niranjanmanjunath
niranjanmanjunath merged commit 53c1b91 into main Aug 20, 2026
18 checks passed
@niranjanmanjunath
niranjanmanjunath deleted the refactor/vertical-support branch August 20, 2026 21:37
jingyli added a commit that referenced this pull request Aug 21, 2026
igrigorik added a commit that referenced this pull request Aug 25, 2026
* Extend retail_location.json with more fields and move it out of shopping/ to generally represent any physical location (to be referenced by Location capability).

* Add appropriate transition annotation to set proper expectation on field presence.

* Add common location capability.

* Minor wording updates in documentation and also fix rendering issues.

* Minor fix on fulfillment retail location reference.

* Fix on rendering links.

* More fixes on rendering links.

* Fix location_filter file name.

* Clean up remaining broken links and minor style updates.

* Address comments that involve minor schema changes.

* Address rest of the comments from feedback.

* Fix broken doc build link.

* fix(location): mark custom filters as extensible

Location search intentionally permits Business-defined filters, but the schema
relied on JSON Schema's implicit open-object default while the prose named
additionalProperties as the extension mechanism.

Declare the extension point explicitly so schema readers and generated
documentation can distinguish intentional extensibility from omission. Strict
resolution remains a caller-selected closed-world override.

* docs(location): remove catalog copy-paste

Location documentation inherited Catalog-specific descriptions, rendering
contexts, and a severity policy that Location never defined. It also documented
a singular REST path and a filter name that do not exist in the binding/schema.

Use Location-specific llms.txt descriptions and render scopes, remove the
unsupported severity claim, and align the visible endpoint and filter names with
their canonical definitions.

* Add location into UCP glossary to resolve feedback on PR#642.

* Add security & privacy considerations.

* Address feedback on simplifying service area representation on location responses and finetune request filters.

* Update hours representation to be more consistent with standard schema representation.

* Relax exact quantity based search and instead leverage availability status based coarse search during discovery phase.

* Standardize amenities vocabulary and also restructure filtering model between it and dynamic inventory filter.

* Address bounded location representation problem and clean up misc/unused ucp annotation for fulfillment related files.

* Fix broken reference rendering.

* Fix example on REST to follow proper exception_hour representation.

* Clean up legacy field description.

* Fix signature definition in MCP JSONRPC transport schema definition.

* Add validation rule for timezone in location.json.

* Loosen language on what is being considered as a search inputs to give more flexible combination of request inputs.

* Add some implementation guidance on how to deal with context-only search requests.

* Add more validation on the filter schema and tighten up prose around how business should handle contextual hints fallback.

* fix!: define deterministic operating hours for Location service (#687)

* define deterministic operating hours

   The current Location PR introduces weekly and exceptional operating hours,
   but leaves several wire and evaluation semantics ambiguous. In particular,
   closures rely on an artificial midnight interval, `open_now` depends on an
   implicit server clock, exception date bounds are unclear, and the specification
   does not define timezone, overnight, DST, overlap, or precedence behavior.

   Close those gaps with a UCP-native schedule model informed by Schema.org's
   OpeningHoursSpecification:
   https://schema.org/OpeningHoursSpecification

   Schema.org is design input only. UCP owns the field names, values, and
   evaluation rules defined here.

   Make weekly intervals explicit and reusable:

       "hours": [
         {
           "day": "tuesday",
           "opens": "09:00",
           "closes": "12:00"
         },
         {
           "day": "tuesday",
           "opens": "13:00",
           "closes": "21:00"
         }
       ]

   Rename `open` and `close` to `opens` and `closes`, and define `day` as a
   stable UCP weekday identifier rather than localized display text. Multiple
   entries for one day represent split shifts, and an interval whose closing time
   is earlier than its opening time continues into the next local date.

   Refactor the shared time interval schema so `opens` and `closes` are an
   optional but inseparable pair. Weekly hours require both fields, while
   exception hours may omit both to represent a full closure. Reject the ambiguous
   `00:00` to `00:00` pair and reserve `00:00` to `23:59` as the full-local-day
   sentinel.

   Replace the previous exception shape:

       {
         "from": "2026-11-26",
         "through": "2026-11-27",
         "label": "Thanksgiving",
         "open": "00:00",
         "close": "00:00"
       }

   with inclusive local-date bounds and an actual closure representation:

       {
         "title": "Thanksgiving",
         "valid_from": "2026-11-26",
         "valid_through": "2026-11-26"
       }

   Rename `from`, `through`, and `label` to `valid_from`, `valid_through`, and
   `title`. Treat `title` as optional presentation metadata that does not affect
   schedule evaluation. Allow timed exceptions with paired `opens` and `closes`,
   including multiple entries with identical bounds for split shifts.

   Define every returned schedule in the Location's Business-owned IANA timezone.
   Require `timezone` whenever regular or exception hours are present, and keep
   the canonical schedule independent of the requesting Platform or Buyer's
   timezone.

   Specify deterministic evaluation:

   - convert an exact instant into each Location's local date, weekday, and time
   - use half-open timed intervals, except for the reserved full-day sentinel
   - let overnight intervals carry into the following local date
   - replace regular hours with exception hours at local midnight
   - treat omitted weekdays as having no interval starting that day
   - treat absent schedules as unknown rather than closed
   - evaluate DST gaps and folds pointwise without shifting nonexistent times
   - reject equal time pairs and intersecting non-identical exception ranges as
     Business conformance errors where JSON Schema cannot express the constraint

   Remove the redundant `open_now` filter. It makes results depend on an implicit
   processing clock and creates undefined precedence when combined with
   `open_at`. Require one caller-supplied RFC 3339 instant instead:

       "filters": {
         "hours": {
           "open_at": "2026-05-18T17:00:00Z"
         }
       }

   Require `open_at` to include `Z` or a numeric offset. The offset identifies the
   instant only; the Business still evaluates that instant using each candidate
   Location's authoritative IANA timezone. Keep the nested hours filter open so
   extensions can add qualifiers without changing the standard predicate.

   Move complete Search and Lookup examples into the transport-neutral capability
   documents. Cover hours with serviceability and amenities, inventory with
   distance, split shifts, full closures, and partial Lookup success there.

   Reduce REST and MCP examples to equivalent binding envelopes that link to the
   same canonical payload examples. This keeps both transports on equal footing,
   avoids duplicating domain semantics, and prevents one binding's examples from
   becoming more complete or authoritative than the other. Preserve MCP's
   required `meta["ucp-agent"].profile` contract while separating protocol
   metadata from the Location request.

   This is a breaking correction to the Location PR's draft wire shape:

   - `open` becomes `opens`
   - `close` becomes `closes`
   - `from` becomes `valid_from`
   - `through` becomes `valid_through`
   - `label` becomes `title`
   - `open_now` is removed
   - full closures omit both time fields instead of using `00:00` to `00:00`

* s/weekday/day of week

* clarify operating-hours semantics

   Define `open_at` as the caller-selected instant relevant to the request, such
   as an expected arrival or pickup time. This avoids framing it as a request for
   the Business's receipt-time notion of "now": normal request latency does not
   change the question, and the Business evaluates the supplied instant against
   each Location's schedule.

   Describe operating hours more directly as local dates and clock times
   interpreted using the Location's IANA timezone. Clarify that temporary closures
   retain the regular `hours` schedule and override it with a date-bounded
   `exception_hours` entry that omits `opens` and `closes`.

   Mirror omitted-schedule semantics in the Location schema for implementers who
   read generated references:

   - an omitted day has no regular interval beginning that day
   - an interval from the preceding day may still carry into it
   - omission of the entire `hours` property means the schedule is unknown

   Make `time_interval` genuinely reusable by limiting it to generic `HH:MM`
   opening and closing fields. Location-specific recurrence and timezone
   interpretation remain with the containing daily, exception, and Location
   schemas.

   Remove the schema check that rejected only `00:00`–`00:00`. The actual
   authoring rule rejects every pair where `opens` equals `closes`, but standard
   JSON Schema cannot compare sibling values; enforcing one special case would
   misleadingly imply that other equal pairs are valid. Continue enforcing paired
   field presence and time formatting mechanically, while keeping unequal times
   as a normative Business conformance requirement and requiring Platforms not to
   infer openness from invalid schedule data.

* define authority for hours filtering

   The TC discussion converged on keeping one `open_at` filter, but left open
   whether both the Platform and Business could apply timing tolerance when
   interpreting immediate intent.

   After further consideration, assign that flexibility to one side only. The
   Platform owns the interpretation of Buyer intent and selects the instant to
   query. It may use its current time, choose an expected arrival, pickup, or
   order-acceptance time, and round or adjust that choice to the granularity
   appropriate to the interaction. Once encoded, however, `open_at` identifies one
   specific RFC 3339 instant.

   Require the Business to evaluate that instant exactly as supplied using each
   Location's authoritative timezone. It must not round, shift, substitute request
   receipt time, or otherwise reinterpret the value. Allowing both parties to
   apply independent tolerance would make the evaluated question unknowable and
   could produce different matches for identical requests near an opening or
   closing boundary.

   Apply normal positive-match filter semantics: return a Location only when the
   Business can establish that it is open at `open_at`. Missing, invalid,
   out-of-range, or otherwise unusable schedule data is a non-match rather than a
   reason to guess or adjust the requested instant.

   Clarify that the numeric offset in `open_at` identifies the queried instant,
   not the Location's timezone. The Business converts that instant using the
   Location's authoritative IANA timezone before evaluating its local schedule.

   State closing-boundary behavior concretely: a `10:00`–`17:00` interval is open
   immediately before `17:00` and closed at `17:00`. This avoids ambiguity over
   whether `HH:MM` values represent exact boundaries or minute-sized buckets.

   Keep exception payloads useful for planning without accumulating stale history.
   Businesses should remove entries once they cannot affect any current or future
   instant and publish known future exceptions through the horizon for which their
   schedule is authoritative.

   Remove the request-language localization recommendation for exception `title`.
   The field remains optional presentation metadata, but this capability does not
   define a localization guarantee for it.

* Cleanup incorrectly placed signature headers in meta object definition.

* Address feedback on existing contracts consistency.

* Remodel amenities as reverse-DNS string arrays.

* Fix documentation examples.

* Fix serves(target) contextual fallback algorithm.

* Revert back the changes to retail_destination.json to decouple the scope.

* Remove transition annotation from location_base.json as this is now being treated as a net new schema type.

* fix!: Location spatial relations and Lookup correlation (#753)

* separate location spatial relations from filters

   The previous filters.geo shape mixed predicates about a Location with
   relations to Platform-supplied points and addresses. That made context
   fallback ambiguous and coupled proximity with serviceability even when
   they need different operands.

   Promote distance and serves to independent request-root relations in Search
   and Lookup. Keep filters for inherent or current Location facts, preserve
   its open extension model, and combine every explicit relation and predicate
   with AND. Keeping the relations separate allows a request to measure
   distance from one point while testing serviceability to another, without
   hidden operand inheritance.

   Require distance.center plus inclusive distance.max in meters and define
   matching against the unrounded shortest WGS 84 ellipsoidal geodesic. Reject
   unsupported radii rather than silently clamping, substituting operands, or
   falling back to context, signals, or IP-derived locality.

   Model serves as exactly one point, coarse locality, or negotiated
   reverse-domain target. Treat a match as provisional evidence that at least
   one currently available method can serve the target, without exposing
   coverage geometry or promising checkout success. Reject targets that cannot
   be evaluated rather than ignoring them or broadening results.

   Keep query and contextual hints non-authoritative: they may influence ranking
   or bounded selection but cannot create or relax spatial proof. Preserve
   empty, hint-only, pagination-only, and filters-only Search requests as
   bounded browse forms, with the existing default page size of 10.

* mirror Catalog correlation in Location Lookup

   Location Lookup supports secondary identifiers and aliases, but returning only
   the canonical Location.id makes unordered batch results ambiguous when inputs
   converge on one Location or fan out to several.

   Mirror Catalog's lookup API shape by requiring inputs[] on every returned
   Location. Each entry preserves one identifier exactly as requested; a Location
   resolved by multiple inputs is returned once with all correlations, while one
   input may resolve to multiple Locations. Requiring inputs for direct ID matches
   adds minor payload overhead but preserves one uniform, schema-enforceable rule
   across Catalog and Location.

   Keep the correlation record inline and omit Catalog's match classification
   because Location has no product-to-featured-variant resolution distinction.
   Businesses must support canonical Location.id values and may additionally
   support aliases or secondary identifiers.

   Apply batch limits after deduplication. Process the first N distinct identifiers
   in request order and return a successful partial response with a
   batch_limit_applied informational message, leaving the omitted suffix retryable
   rather than reporting it as unresolved or failing at the transport layer.

* drop geo disclosure for distance matches

* Minor tweaks to language & remove unnecessary ucp_request annotation from fields that are already required in the enclosing type.

* make pagination defaults Business-defined

   The shared pagination schema fixed `limit.default` at 10, while Catalog
   and Location described different omission behavior. This made one shared
   type carry divergent semantics and could cause clients or generated SDKs
   to materialize 10 before the Business could apply its own policy.

   Require every Business to apply a default page size when `limit` is
   omitted, recommend 10 without making it a fixed value or supported floor,
   and allow the Business to choose another default. Requested and default
   page sizes remain targets rather than guaranteed result counts, so a
   Business may return fewer results when enforcing its maximum and a
   Platform must not assume count equality. Platforms that need a particular
   page size can continue to send an explicit `limit`.

   Remove the JSON Schema `default` annotation so the wire schema does not
   misrepresent a Business-specific policy. Align Catalog and Location on
   the shared contract, and have REST and MCP conformance link to the
   operation-level pagination rules instead of duplicating a default value.

   Keep Location's spatial semantics independent: pagination flexibility
   never permits reducing or silently clamping an explicit `distance.max`.

* clarify Location spatial constraint wording

   Attach the context-signal prohibition to the Business actor and separate
   that normative obligation from the factual consequence: contextual hints
   may influence ranking or bounded selection, but prove neither proximity
   nor serviceability and cannot replace explicit spatial operands.

   Remove the self-referential "`max` is not an alias" sentence from the
   distance schema. `max` is already the canonical required property, and
   documenting abandoned candidate names adds design-history noise without
   strengthening the contract.

   Preserve the existing requirements to evaluate the supplied radius
   exactly and reject requests whose radius cannot be honored rather than
   clamping or substituting another value.

---------

Co-authored-by: Jing Li <jingyli@google.com>

* Refactor Location specification documentation to follow the same pattern #723 is enforcing.

* Fix broken links.

* Address outstanding feedback around using cosolidated location_summary.json representation and normative amenity language.

* Fix outstanding broken references.

* Minor tweaks to the language to maintain consistency.

* Fix rendering link issues.

* Add location response schame in ucp.json and correct the last missing deeplink to lookup location.

* Fix one more typo on the rendering.

* Address feedback.

* fix!: make Location amenities self-describing (#765)

* make Location amenities self-describing

   Amenity identifiers use an open reverse-DNS vocabulary, so Platforms cannot
   derive buyer-facing text or safely present unfamiliar Business-defined
   amenities from the key alone.

   Replace amenity arrays with maps whose values require a short, buyer-facing
   description. Define exact-key filter matching and require filtered results to
   disclose requested keys so Platforms can verify each match.

   The presentation contract recommends presenting every returned amenity from
   Business-provided text, permits enhanced UX for known identifiers, and
   prohibits allowlist filtering or inferred semantics for unknown identifiers.

* clarify Location fulfillment handoff

   A Location ID identifies a destination, not a fulfillment mode. Treating it
   as a pickup signal conflated destination selection with the method contract
   and could make discovery results appear binding.

   Document that Platforms submit Location IDs only on applicable methods, whose
   type determines the mode. Businesses revalidate current availability and
   terms; recognizing an ID neither reserves inventory nor guarantees
   eligibility.

* repair Location routes and generated references

   Location documentation moved under specification/common/location, but
   discovery examples and MkDocs metadata still referenced the old paths. The
   REST binding also linked to a Lookup Location entity that it did not render.

   Point capability links and route metadata at the canonical Location paths.
   Add the generated Lookup Location section so its anchor and schema fields are
   available, and refresh route summaries to match the current Location model.

* align Location terminology and metadata

   Location documentation and bindings mixed legacy actor names with stale
   schema metadata. The rich Location schema also described a removed Base
   Location layer, while location destinations retained metadata used only by a
   deleted generator.

   Use glossary actor terms consistently across documentation and service
   bindings, normalize Location and Lookup naming, and make independent
   capability adoption an explicit BCP 14 permission.

   Describe the rich Location as composing Location Summary and remove the final
   retired ucp_shared_request marker.

* remove idempotency from read-only Location tools

   Location Search and Lookup are read-only operations, but their MCP metadata
   exposed an optional idempotency key borrowed from mutating operations. That
   implied retry-deduplication and replay semantics the capability does not
   define.

   Remove the parameter so retries follow ordinary read-only request semantics.
   The REST binding already carries no equivalent idempotency requirement.

* review feedback on the self-describing amenities change:

   - Amenity presentation (index.md): adopt Platform presentation
     autonomy — a Platform MAY decide whether and where amenities appear;
     the contract binds only when it presents them. Keep identifier-based
     suppression at MUST NOT (review proposed SHOULD NOT): self-description
     exists so unrecognized identifiers carry no presentation penalty, and
     weakening it would make extension amenities second-class — the footgun
     this PR closes. Adopt the reviewer's "solely because unrecognized"
     scoping, which permits uniform policies such as truncation.

   - Stable Identifiers (index.md): stop restating Fulfillment's contract
     in Location docs. The bullet is now informative — a Location ID
     selects only the physical entity — and defers to fulfillment.md's
     Selection and Location Identity, which owns selected_destination_id
     semantics including revalidation.

   - Amenity filter rejection (search.md): reword the Platform rejection
     sentence for flow; semantics unchanged.

   - Search example prose (search.md): group the hours sentences by moving
     the custom-amenity note after the Operating Hours reference; the
     sentence stays because the example deliberately shows a namespaced
     custom amenity remaining presentable.

* fix: replace Location inventory filtering with item availability (#766)

* fix!: replace Location inventory filtering with item availability

The inventory filter mixed stock, order-acceptance, lifecycle, and timing
semantics in an open per-item status vocabulary, while Location returns only
aggregate Location matches.

Replace it with `filters.items`, a nonempty array of distinct,
Business-scoped item identifiers shared by Search and Lookup. A Location
matches only when every item is available there under the Business's current
data; unknown, unavailable, or non-evaluable items are ordinary non-matches.

Keep hours, quantity, and fulfillment methods outside this predicate. Catalog
with Fulfillment describes item-level methods for a shortlisted Location, Cart
carries configuration and quantity, and Checkout with Fulfillment revalidates
basket feasibility and final terms.

* tighten Location availability framing

   Restore the distinction between root spatial relations and filters over
   Location facts, and keep Common Location guidance independent of
   Shopping-specific handoffs.

   Use consistent spatial terminology and stop enumerating open filter fields in
   shared schema and service descriptions, reducing drift without changing
   filters.items behavior.

* Remove unused wording (geofence) from the custom-words ignore list as part of final cleanup.

* Final reference fix post refactoring merge.

---------

Co-authored-by: Ilya Grigorik <ilya@grigorik.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:payments Issues and pull requests related to the Payments vertical documentation Improvements or additions to documentation gov:needs-tc-review Requires review and approval from the Technical Council status:under-review TC review Ready for TC review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants