portage-ucp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +15 -0
- data/LICENSE +21 -0
- data/README.md +97 -0
- data/exe/portage-ucp-check +25 -0
- data/lib/portage/ucp/adapter.rb +58 -0
- data/lib/portage/ucp/authenticator.rb +26 -0
- data/lib/portage/ucp/capabilities/cart.rb +16 -0
- data/lib/portage/ucp/capabilities/catalog.rb +11 -0
- data/lib/portage/ucp/capabilities/checkout.rb +17 -0
- data/lib/portage/ucp/capabilities/identity_linking.rb +13 -0
- data/lib/portage/ucp/capabilities/order.rb +11 -0
- data/lib/portage/ucp/capability.rb +27 -0
- data/lib/portage/ucp/capability_negotiator.rb +40 -0
- data/lib/portage/ucp/capability_registry.rb +21 -0
- data/lib/portage/ucp/check.rb +96 -0
- data/lib/portage/ucp/configuration.rb +35 -0
- data/lib/portage/ucp/dispatcher.rb +39 -0
- data/lib/portage/ucp/errors.rb +12 -0
- data/lib/portage/ucp/manifest.rb +58 -0
- data/lib/portage/ucp/mcp/server.rb +83 -0
- data/lib/portage/ucp/observability.rb +31 -0
- data/lib/portage/ucp/payment_token_guard.rb +41 -0
- data/lib/portage/ucp/rack/manifest_endpoint.rb +49 -0
- data/lib/portage/ucp/rack/webhook_endpoint.rb +54 -0
- data/lib/portage/ucp/rate_limiter.rb +27 -0
- data/lib/portage/ucp/resolver.rb +133 -0
- data/lib/portage/ucp/schema_validator.rb +53 -0
- data/lib/portage/ucp/support/amounts.rb +43 -0
- data/lib/portage/ucp/support/api_error.rb +39 -0
- data/lib/portage/ucp/support/checkout_state.rb +42 -0
- data/lib/portage/ucp/support/http_client.rb +54 -0
- data/lib/portage/ucp/support/idempotency.rb +26 -0
- data/lib/portage/ucp/support/line_item_status.rb +44 -0
- data/lib/portage/ucp/support/not_found.rb +25 -0
- data/lib/portage/ucp/support/token_exchange.rb +43 -0
- data/lib/portage/ucp/support/totals.rb +31 -0
- data/lib/portage/ucp/value_objects.rb +186 -0
- data/lib/portage/ucp/version.rb +5 -0
- data/lib/portage/ucp/wire_envelope.rb +25 -0
- data/lib/portage/ucp.rb +44 -0
- data/schemas/2026-04-08/schemas/capability.json +70 -0
- data/schemas/2026-04-08/schemas/payment_handler.json +67 -0
- data/schemas/2026-04-08/schemas/service.json +190 -0
- data/schemas/2026-04-08/schemas/shopping/cart.json +134 -0
- data/schemas/2026-04-08/schemas/shopping/catalog_lookup.json +207 -0
- data/schemas/2026-04-08/schemas/shopping/catalog_search.json +64 -0
- data/schemas/2026-04-08/schemas/shopping/checkout.json +131 -0
- data/schemas/2026-04-08/schemas/shopping/discount.json +148 -0
- data/schemas/2026-04-08/schemas/shopping/fulfillment.json +154 -0
- data/schemas/2026-04-08/schemas/shopping/order.json +113 -0
- data/schemas/2026-04-08/schemas/shopping/payment.json +16 -0
- data/schemas/2026-04-08/schemas/shopping/types/adjustment.json +69 -0
- data/schemas/2026-04-08/schemas/shopping/types/amount.json +8 -0
- data/schemas/2026-04-08/schemas/shopping/types/attribution.json +11 -0
- data/schemas/2026-04-08/schemas/shopping/types/available_payment_instrument.json +22 -0
- data/schemas/2026-04-08/schemas/shopping/types/business_fulfillment_config.json +38 -0
- data/schemas/2026-04-08/schemas/shopping/types/buyer.json +25 -0
- data/schemas/2026-04-08/schemas/shopping/types/category.json +20 -0
- data/schemas/2026-04-08/schemas/shopping/types/context.json +42 -0
- data/schemas/2026-04-08/schemas/shopping/types/description.json +22 -0
- data/schemas/2026-04-08/schemas/shopping/types/detail_option_value.json +22 -0
- data/schemas/2026-04-08/schemas/shopping/types/error_code.json +17 -0
- data/schemas/2026-04-08/schemas/shopping/types/error_response.json +31 -0
- data/schemas/2026-04-08/schemas/shopping/types/expectation.json +62 -0
- data/schemas/2026-04-08/schemas/shopping/types/fulfillment.json +25 -0
- data/schemas/2026-04-08/schemas/shopping/types/fulfillment_available_method.json +45 -0
- data/schemas/2026-04-08/schemas/shopping/types/fulfillment_destination.json +16 -0
- data/schemas/2026-04-08/schemas/shopping/types/fulfillment_event.json +67 -0
- data/schemas/2026-04-08/schemas/shopping/types/fulfillment_group.json +45 -0
- data/schemas/2026-04-08/schemas/shopping/types/fulfillment_method.json +67 -0
- data/schemas/2026-04-08/schemas/shopping/types/fulfillment_option.json +56 -0
- data/schemas/2026-04-08/schemas/shopping/types/info_code.json +13 -0
- data/schemas/2026-04-08/schemas/shopping/types/input_correlation.json +24 -0
- data/schemas/2026-04-08/schemas/shopping/types/item.json +33 -0
- data/schemas/2026-04-08/schemas/shopping/types/line_item.json +46 -0
- data/schemas/2026-04-08/schemas/shopping/types/link.json +25 -0
- data/schemas/2026-04-08/schemas/shopping/types/media.json +36 -0
- data/schemas/2026-04-08/schemas/shopping/types/message.json +18 -0
- data/schemas/2026-04-08/schemas/shopping/types/message_error.json +49 -0
- data/schemas/2026-04-08/schemas/shopping/types/message_info.json +37 -0
- data/schemas/2026-04-08/schemas/shopping/types/message_warning.json +53 -0
- data/schemas/2026-04-08/schemas/shopping/types/option_value.json +20 -0
- data/schemas/2026-04-08/schemas/shopping/types/order_confirmation.json +26 -0
- data/schemas/2026-04-08/schemas/shopping/types/order_line_item.json +69 -0
- data/schemas/2026-04-08/schemas/shopping/types/pagination.json +62 -0
- data/schemas/2026-04-08/schemas/shopping/types/payment_credential.json +17 -0
- data/schemas/2026-04-08/schemas/shopping/types/payment_instrument.json +58 -0
- data/schemas/2026-04-08/schemas/shopping/types/platform_fulfillment_config.json +14 -0
- data/schemas/2026-04-08/schemas/shopping/types/postal_address.json +44 -0
- data/schemas/2026-04-08/schemas/shopping/types/price.json +22 -0
- data/schemas/2026-04-08/schemas/shopping/types/price_filter.json +17 -0
- data/schemas/2026-04-08/schemas/shopping/types/price_range.json +21 -0
- data/schemas/2026-04-08/schemas/shopping/types/product.json +89 -0
- data/schemas/2026-04-08/schemas/shopping/types/product_option.json +25 -0
- data/schemas/2026-04-08/schemas/shopping/types/rating.json +34 -0
- data/schemas/2026-04-08/schemas/shopping/types/retail_location.json +28 -0
- data/schemas/2026-04-08/schemas/shopping/types/reverse_domain_name.json +8 -0
- data/schemas/2026-04-08/schemas/shopping/types/search_filters.json +20 -0
- data/schemas/2026-04-08/schemas/shopping/types/selected_option.json +25 -0
- data/schemas/2026-04-08/schemas/shopping/types/shipping_destination.json +26 -0
- data/schemas/2026-04-08/schemas/shopping/types/signals.json +22 -0
- data/schemas/2026-04-08/schemas/shopping/types/signed_amount.json +7 -0
- data/schemas/2026-04-08/schemas/shopping/types/total.json +75 -0
- data/schemas/2026-04-08/schemas/shopping/types/totals.json +98 -0
- data/schemas/2026-04-08/schemas/shopping/types/variant.json +193 -0
- data/schemas/2026-04-08/schemas/shopping/types/warning_code.json +13 -0
- data/schemas/2026-04-08/schemas/transports/embedded_config.json +27 -0
- data/schemas/2026-04-08/schemas/ucp.json +364 -0
- data/schemas/2026-04-08/services/shopping/embedded.openrpc.json +634 -0
- data/schemas/2026-04-08/services/shopping/mcp.openrpc.json +492 -0
- metadata +283 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/price.json",
|
|
4
|
+
"title": "Price",
|
|
5
|
+
"description": "Price with explicit currency.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"amount",
|
|
9
|
+
"currency"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"amount": {
|
|
13
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/amount.json",
|
|
14
|
+
"description": "Amount in ISO 4217 minor units. Use 0 for free items."
|
|
15
|
+
},
|
|
16
|
+
"currency": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "ISO 4217 currency code (e.g., 'USD', 'EUR', 'GBP').",
|
|
19
|
+
"pattern": "^[A-Z]{3}$"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/price_filter.json",
|
|
4
|
+
"title": "Price Filter",
|
|
5
|
+
"description": "Price range filter denominated in context.currency. When context.currency matches the presentment currency, businesses apply the filter directly. When it differs, businesses SHOULD convert filter values to the presentment currency before applying; if conversion is not supported, businesses MAY ignore the filter and SHOULD indicate this via a message. When context.currency is absent, filter denomination is ambiguous and businesses MAY ignore it.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"min": {
|
|
9
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/amount.json",
|
|
10
|
+
"description": "Minimum price in ISO 4217 minor units."
|
|
11
|
+
},
|
|
12
|
+
"max": {
|
|
13
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/amount.json",
|
|
14
|
+
"description": "Maximum price in ISO 4217 minor units."
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/price_range.json",
|
|
4
|
+
"title": "Price Range",
|
|
5
|
+
"description": "A price range representing minimum and maximum values (e.g., across product variants).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"min",
|
|
9
|
+
"max"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"min": {
|
|
13
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/price.json",
|
|
14
|
+
"description": "Minimum price in the range."
|
|
15
|
+
},
|
|
16
|
+
"max": {
|
|
17
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/price.json",
|
|
18
|
+
"description": "Maximum price in the range."
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/product.json",
|
|
4
|
+
"title": "Product",
|
|
5
|
+
"description": "A product in the catalog with variants and options.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"id",
|
|
9
|
+
"title",
|
|
10
|
+
"description",
|
|
11
|
+
"price_range",
|
|
12
|
+
"variants"
|
|
13
|
+
],
|
|
14
|
+
"properties": {
|
|
15
|
+
"id": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Global ID (GID) uniquely identifying this product."
|
|
18
|
+
},
|
|
19
|
+
"handle": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "URL-safe slug for SEO-friendly URLs (e.g., 'blue-runner-pro'). Use id for stable API references."
|
|
22
|
+
},
|
|
23
|
+
"title": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"description": "Product title."
|
|
26
|
+
},
|
|
27
|
+
"description": {
|
|
28
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/description.json",
|
|
29
|
+
"description": "Product description in one or more formats."
|
|
30
|
+
},
|
|
31
|
+
"url": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"format": "uri",
|
|
34
|
+
"description": "Canonical product page URL."
|
|
35
|
+
},
|
|
36
|
+
"categories": {
|
|
37
|
+
"type": "array",
|
|
38
|
+
"items": {
|
|
39
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/category.json"
|
|
40
|
+
},
|
|
41
|
+
"description": "Product categories with optional taxonomy identifiers."
|
|
42
|
+
},
|
|
43
|
+
"price_range": {
|
|
44
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/price_range.json",
|
|
45
|
+
"description": "Price range across all variants."
|
|
46
|
+
},
|
|
47
|
+
"list_price_range": {
|
|
48
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/price_range.json",
|
|
49
|
+
"description": "List price range before discounts (for strikethrough display)."
|
|
50
|
+
},
|
|
51
|
+
"media": {
|
|
52
|
+
"type": "array",
|
|
53
|
+
"items": {
|
|
54
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/media.json"
|
|
55
|
+
},
|
|
56
|
+
"description": "Product media (images, videos, 3D models). First item is the featured media for listings."
|
|
57
|
+
},
|
|
58
|
+
"options": {
|
|
59
|
+
"type": "array",
|
|
60
|
+
"items": {
|
|
61
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/product_option.json"
|
|
62
|
+
},
|
|
63
|
+
"description": "Product options (Size, Color, etc.)."
|
|
64
|
+
},
|
|
65
|
+
"variants": {
|
|
66
|
+
"type": "array",
|
|
67
|
+
"items": {
|
|
68
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/variant.json"
|
|
69
|
+
},
|
|
70
|
+
"minItems": 1,
|
|
71
|
+
"description": "Purchasable variants of this product. First item is the featured variant for listings."
|
|
72
|
+
},
|
|
73
|
+
"rating": {
|
|
74
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/rating.json",
|
|
75
|
+
"description": "Aggregate product rating."
|
|
76
|
+
},
|
|
77
|
+
"tags": {
|
|
78
|
+
"type": "array",
|
|
79
|
+
"items": {
|
|
80
|
+
"type": "string"
|
|
81
|
+
},
|
|
82
|
+
"description": "Product tags for categorization and search."
|
|
83
|
+
},
|
|
84
|
+
"metadata": {
|
|
85
|
+
"type": "object",
|
|
86
|
+
"description": "Business-defined custom data extending the standard product model."
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/product_option.json",
|
|
4
|
+
"title": "Product Option",
|
|
5
|
+
"description": "A product option such as size, color, or material.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"name",
|
|
9
|
+
"values"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"name": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Option name (e.g., 'Size', 'Color')."
|
|
15
|
+
},
|
|
16
|
+
"values": {
|
|
17
|
+
"type": "array",
|
|
18
|
+
"items": {
|
|
19
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/option_value.json"
|
|
20
|
+
},
|
|
21
|
+
"minItems": 1,
|
|
22
|
+
"description": "Available values for this option."
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/rating.json",
|
|
4
|
+
"title": "Rating",
|
|
5
|
+
"description": "Product rating aggregate.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"value",
|
|
9
|
+
"scale_max"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"value": {
|
|
13
|
+
"type": "number",
|
|
14
|
+
"minimum": 0,
|
|
15
|
+
"description": "Average rating value."
|
|
16
|
+
},
|
|
17
|
+
"scale_min": {
|
|
18
|
+
"type": "number",
|
|
19
|
+
"minimum": 0,
|
|
20
|
+
"default": 1,
|
|
21
|
+
"description": "Minimum value on the rating scale (e.g., 1 for 1-5 stars)."
|
|
22
|
+
},
|
|
23
|
+
"scale_max": {
|
|
24
|
+
"type": "number",
|
|
25
|
+
"minimum": 1,
|
|
26
|
+
"description": "Maximum value on the rating scale (e.g., 5 for 5-star)."
|
|
27
|
+
},
|
|
28
|
+
"count": {
|
|
29
|
+
"type": "integer",
|
|
30
|
+
"minimum": 0,
|
|
31
|
+
"description": "Number of reviews contributing to the rating."
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/retail_location.json",
|
|
4
|
+
"title": "Retail Location",
|
|
5
|
+
"description": "A pickup location (retail store, locker, etc.).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"ucp_shared_request": true,
|
|
8
|
+
"required": [
|
|
9
|
+
"id",
|
|
10
|
+
"name"
|
|
11
|
+
],
|
|
12
|
+
"additionalProperties": true,
|
|
13
|
+
"properties": {
|
|
14
|
+
"id": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "Unique location identifier.",
|
|
17
|
+
"ucp_request": "omit"
|
|
18
|
+
},
|
|
19
|
+
"name": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Location name (e.g., store name)."
|
|
22
|
+
},
|
|
23
|
+
"address": {
|
|
24
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/postal_address.json",
|
|
25
|
+
"description": "Physical address of the location."
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/reverse_domain_name.json",
|
|
4
|
+
"title": "Reverse Domain Name",
|
|
5
|
+
"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').",
|
|
6
|
+
"type": "string",
|
|
7
|
+
"pattern": "^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$"
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/search_filters.json",
|
|
4
|
+
"title": "Search Filters",
|
|
5
|
+
"description": "Filter criteria to narrow search results. All specified filters combine with AND logic.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"categories": {
|
|
9
|
+
"type": "array",
|
|
10
|
+
"items": {
|
|
11
|
+
"type": "string"
|
|
12
|
+
},
|
|
13
|
+
"description": "Filter by product categories (OR logic — matches products in any listed categories). Values match against the value field in product category entries. Valid values can be discovered from the categories field in search results, merchant documentation, or standard taxonomies that businesses may align with."
|
|
14
|
+
},
|
|
15
|
+
"price": {
|
|
16
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/price_filter.json"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"additionalProperties": true
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/selected_option.json",
|
|
4
|
+
"title": "Selected Option",
|
|
5
|
+
"description": "A specific option selection on a variant (e.g., Size: Large).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"name",
|
|
9
|
+
"label"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"name": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Option name (e.g., 'Size')."
|
|
15
|
+
},
|
|
16
|
+
"id": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Optional option value identifier from option_value.id. When present, the server SHOULD use it for matching; name and label remain required for display."
|
|
19
|
+
},
|
|
20
|
+
"label": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Selected option label (e.g., 'Large')."
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/shipping_destination.json",
|
|
4
|
+
"title": "Shipping Destination",
|
|
5
|
+
"description": "Shipping destination.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"ucp_shared_request": true,
|
|
8
|
+
"allOf": [
|
|
9
|
+
{
|
|
10
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/postal_address.json"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"id": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "ID specific to this shipping destination.",
|
|
18
|
+
"ucp_request": "optional"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"required": [
|
|
22
|
+
"id"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/signals.json",
|
|
4
|
+
"title": "Signals",
|
|
5
|
+
"description": "Environment data provided by the platform to support authorization and abuse prevention. Values MUST NOT be buyer-asserted claims — platforms provide signals based on direct observation or independently verifiable third-party attestations. All signal keys MUST use reverse-domain naming to ensure provenance and prevent collisions when multiple extensions contribute to the shared namespace.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"propertyNames": {
|
|
8
|
+
"pattern": "^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$",
|
|
9
|
+
"description": "Reverse-domain identifier (e.g., dev.ucp.buyer_ip, com.example.device_id)."
|
|
10
|
+
},
|
|
11
|
+
"properties": {
|
|
12
|
+
"dev.ucp.buyer_ip": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Client's IP address (IPv4 or IPv6)."
|
|
15
|
+
},
|
|
16
|
+
"dev.ucp.user_agent": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Client's HTTP User-Agent header or equivalent."
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"additionalProperties": true
|
|
22
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/signed_amount.json",
|
|
4
|
+
"title": "Signed Amount",
|
|
5
|
+
"description": "Monetary amount in the currency's minor unit as defined by ISO 4217. Refer to the currency's exponent to determine minor-to-major ratio (e.g., 2 for USD, 0 for JPY, 3 for KWD). May be negative — the sign is intrinsic to the value (e.g., discounts are negative, charges are positive).",
|
|
6
|
+
"type": "integer"
|
|
7
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/total.json",
|
|
4
|
+
"title": "Total",
|
|
5
|
+
"description": "A cost breakdown entry with a category, amount, and optional display text.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"type",
|
|
9
|
+
"amount"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"type": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Cost category. Well-known values: subtotal, items_discount, discount, fulfillment, tax, fee, total. Businesses MAY use additional values.",
|
|
15
|
+
"ucp_request": "omit"
|
|
16
|
+
},
|
|
17
|
+
"display_text": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "Text to display against the amount. Should reflect appropriate method (e.g., 'Shipping', 'Delivery').",
|
|
20
|
+
"ucp_request": "omit"
|
|
21
|
+
},
|
|
22
|
+
"amount": {
|
|
23
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/signed_amount.json",
|
|
24
|
+
"ucp_request": "omit"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"allOf": [
|
|
28
|
+
{
|
|
29
|
+
"if": {
|
|
30
|
+
"properties": {
|
|
31
|
+
"type": {
|
|
32
|
+
"enum": [
|
|
33
|
+
"discount",
|
|
34
|
+
"items_discount"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"required": [
|
|
39
|
+
"type"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"then": {
|
|
43
|
+
"properties": {
|
|
44
|
+
"amount": {
|
|
45
|
+
"exclusiveMaximum": 0
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"if": {
|
|
52
|
+
"properties": {
|
|
53
|
+
"type": {
|
|
54
|
+
"enum": [
|
|
55
|
+
"subtotal",
|
|
56
|
+
"fulfillment",
|
|
57
|
+
"tax",
|
|
58
|
+
"fee"
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"required": [
|
|
63
|
+
"type"
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
"then": {
|
|
67
|
+
"properties": {
|
|
68
|
+
"amount": {
|
|
69
|
+
"minimum": 0
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://ucp.dev/2026-04-08/schemas/shopping/types/totals.json",
|
|
4
|
+
"title": "Totals",
|
|
5
|
+
"description": "Pricing breakdown provided by the business. MUST contain exactly one subtotal and one total entry. Detail types (tax, fee, discount, fulfillment) may appear multiple times for itemization. Platforms MUST render all entries in order using display_text and amount.",
|
|
6
|
+
"type": "array",
|
|
7
|
+
"items": {
|
|
8
|
+
"allOf": [
|
|
9
|
+
{
|
|
10
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/total.json"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"lines": {
|
|
16
|
+
"type": "array",
|
|
17
|
+
"items": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"required": [
|
|
20
|
+
"display_text",
|
|
21
|
+
"amount"
|
|
22
|
+
],
|
|
23
|
+
"properties": {
|
|
24
|
+
"display_text": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"description": "Human-readable label for this sub-line."
|
|
27
|
+
},
|
|
28
|
+
"amount": {
|
|
29
|
+
"$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/signed_amount.json"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"description": "Sub-line entry. Additional metadata MAY be included."
|
|
33
|
+
},
|
|
34
|
+
"description": "Optional itemized breakdown. The parent entry is always rendered; lines are supplementary. Sum of line amounts MUST equal the parent entry amount.",
|
|
35
|
+
"ucp_request": "omit"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"if": {
|
|
41
|
+
"properties": {
|
|
42
|
+
"type": {
|
|
43
|
+
"not": {
|
|
44
|
+
"enum": [
|
|
45
|
+
"subtotal",
|
|
46
|
+
"items_discount",
|
|
47
|
+
"discount",
|
|
48
|
+
"fulfillment",
|
|
49
|
+
"tax",
|
|
50
|
+
"fee",
|
|
51
|
+
"total"
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"required": [
|
|
57
|
+
"type"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"then": {
|
|
61
|
+
"required": [
|
|
62
|
+
"display_text"
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"allOf": [
|
|
69
|
+
{
|
|
70
|
+
"contains": {
|
|
71
|
+
"properties": {
|
|
72
|
+
"type": {
|
|
73
|
+
"const": "subtotal"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"required": [
|
|
77
|
+
"type"
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
"minContains": 1,
|
|
81
|
+
"maxContains": 1
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"contains": {
|
|
85
|
+
"properties": {
|
|
86
|
+
"type": {
|
|
87
|
+
"const": "total"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"required": [
|
|
91
|
+
"type"
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
"minContains": 1,
|
|
95
|
+
"maxContains": 1
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|