From 4c2265f3ae9749e61287a436782df73af3723cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Fern=C3=A1ndez?= Date: Thu, 11 Jun 2026 17:53:48 +0200 Subject: [PATCH 1/3] fix(schema): allow hyphenated reverse-domain namespaces --- source/schemas/common/types/reverse_domain_name.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/schemas/common/types/reverse_domain_name.json b/source/schemas/common/types/reverse_domain_name.json index e328935ba..2fd11b24e 100644 --- a/source/schemas/common/types/reverse_domain_name.json +++ b/source/schemas/common/types/reverse_domain_name.json @@ -2,7 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://ucp.dev/schemas/common/types/reverse_domain_name.json", "title": "Reverse Domain Name", - "description": "Reverse-domain identifier used for collision-safe namespacing of capabilities, services, handlers, eligibility claims, and extension-contributed keys. Must contain at least two dot-separated segments (e.g., 'dev.ucp.shopping.checkout', 'com.example.loyalty_gold').", + "description": "Reverse-domain identifier used for collision-safe namespacing of capabilities, services, handlers, eligibility claims, and extension-contributed keys. Must contain at least two dot-separated segments (e.g., 'dev.ucp.shopping.checkout', 'com.example-shop.loyalty_gold'). Hyphens are allowed inside segments to support domain-derived namespaces, but segments must not start or end with a hyphen.", "type": "string", - "pattern": "^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$" + "pattern": "^[a-z][a-z0-9]*(?:\\.[a-z](?:[a-z0-9_-]*[a-z0-9_])?)+$" } From d760e84139a4f386f34789af30a45d6ac753d1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Fern=C3=A1ndez?= Date: Wed, 8 Jul 2026 08:40:44 +0200 Subject: [PATCH 2/3] Revert "fix(schema): allow hyphenated reverse-domain namespaces" This reverts commit 4c2265f3ae9749e61287a436782df73af3723cf9. --- source/schemas/common/types/reverse_domain_name.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/schemas/common/types/reverse_domain_name.json b/source/schemas/common/types/reverse_domain_name.json index 2fd11b24e..e328935ba 100644 --- a/source/schemas/common/types/reverse_domain_name.json +++ b/source/schemas/common/types/reverse_domain_name.json @@ -2,7 +2,7 @@ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://ucp.dev/schemas/common/types/reverse_domain_name.json", "title": "Reverse Domain Name", - "description": "Reverse-domain identifier used for collision-safe namespacing of capabilities, services, handlers, eligibility claims, and extension-contributed keys. Must contain at least two dot-separated segments (e.g., 'dev.ucp.shopping.checkout', 'com.example-shop.loyalty_gold'). Hyphens are allowed inside segments to support domain-derived namespaces, but segments must not start or end with a hyphen.", + "description": "Reverse-domain identifier used for collision-safe namespacing of capabilities, services, handlers, eligibility claims, and extension-contributed keys. Must contain at least two dot-separated segments (e.g., 'dev.ucp.shopping.checkout', 'com.example.loyalty_gold').", "type": "string", - "pattern": "^[a-z][a-z0-9]*(?:\\.[a-z](?:[a-z0-9_-]*[a-z0-9_])?)+$" + "pattern": "^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$" } From e8cd221b20925dcc5728e22ec25a724bca39e537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Fern=C3=A1ndez?= Date: Wed, 8 Jul 2026 08:32:04 +0200 Subject: [PATCH 3/3] docs(fulfillment): align rendering contract with totals schema --- docs/specification/fulfillment.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/specification/fulfillment.md b/docs/specification/fulfillment.md index 195b8c309..93a85de02 100644 --- a/docs/specification/fulfillment.md +++ b/docs/specification/fulfillment.md @@ -175,7 +175,7 @@ human-readable fields that platforms render directly. | --------------------- | ------------- | -------- | ------------------------------------------------------- | | `groups[].options[]` | `title` | Yes | Primary label that distinguishes from siblings | | `groups[].options[]` | `description` | No | Supplementary context for the title | -| `groups[].options[]` | `total` | Yes | Price in minor units (may be null if not yet available) | +| `groups[].options[]` | `totals` | Yes | Pricing breakdown entries for the option in minor units | | `available_methods[]` | `description` | No | Standalone explanation of alternative availability | ### Business Responsibilities @@ -188,7 +188,7 @@ human-readable fields that platforms render directly. **For `options[].description`:** -* **MUST NOT** repeat `title` or `total`—provides supplementary context only +* **MUST NOT** repeat `title` or pricing already conveyed in `totals`—provides supplementary context only * **SHOULD** include timing, carrier, or other decision-relevant details * **SHOULD** be a complete phrase (e.g., "Arrives Dec 12-15 via FedEx") * **MAY** be omitted if title is self-explanatory @@ -209,7 +209,7 @@ human-readable fields that platforms render directly. Platforms **SHOULD** treat fulfillment as a generic, renderable structure: -* Render each option as a card using `title`, `description`, and `total` +* Render each option as a card using `title`, `description`, and pricing from `totals` * Present options in the order provided by the business * Present all methods returned—method selection is a buyer decision * Use `available_methods[].description` to surface alternatives to the buyer @@ -217,7 +217,7 @@ Platforms **SHOULD** treat fulfillment as a generic, renderable structure: Platforms **MAY** provide enhanced UX for recognized method types (store selectors for pickup, carrier logos for shipping), but this is optional. The baseline -contract is: **`title` + `description` + `total` is sufficient to render any +contract is: **`title` + `description` + `totals` together are sufficient to render any option.** When a buyer selects an option the platform cannot fully process, the