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.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +15 -0
  3. data/LICENSE +21 -0
  4. data/README.md +97 -0
  5. data/exe/portage-ucp-check +25 -0
  6. data/lib/portage/ucp/adapter.rb +58 -0
  7. data/lib/portage/ucp/authenticator.rb +26 -0
  8. data/lib/portage/ucp/capabilities/cart.rb +16 -0
  9. data/lib/portage/ucp/capabilities/catalog.rb +11 -0
  10. data/lib/portage/ucp/capabilities/checkout.rb +17 -0
  11. data/lib/portage/ucp/capabilities/identity_linking.rb +13 -0
  12. data/lib/portage/ucp/capabilities/order.rb +11 -0
  13. data/lib/portage/ucp/capability.rb +27 -0
  14. data/lib/portage/ucp/capability_negotiator.rb +40 -0
  15. data/lib/portage/ucp/capability_registry.rb +21 -0
  16. data/lib/portage/ucp/check.rb +96 -0
  17. data/lib/portage/ucp/configuration.rb +35 -0
  18. data/lib/portage/ucp/dispatcher.rb +39 -0
  19. data/lib/portage/ucp/errors.rb +12 -0
  20. data/lib/portage/ucp/manifest.rb +58 -0
  21. data/lib/portage/ucp/mcp/server.rb +83 -0
  22. data/lib/portage/ucp/observability.rb +31 -0
  23. data/lib/portage/ucp/payment_token_guard.rb +41 -0
  24. data/lib/portage/ucp/rack/manifest_endpoint.rb +49 -0
  25. data/lib/portage/ucp/rack/webhook_endpoint.rb +54 -0
  26. data/lib/portage/ucp/rate_limiter.rb +27 -0
  27. data/lib/portage/ucp/resolver.rb +133 -0
  28. data/lib/portage/ucp/schema_validator.rb +53 -0
  29. data/lib/portage/ucp/support/amounts.rb +43 -0
  30. data/lib/portage/ucp/support/api_error.rb +39 -0
  31. data/lib/portage/ucp/support/checkout_state.rb +42 -0
  32. data/lib/portage/ucp/support/http_client.rb +54 -0
  33. data/lib/portage/ucp/support/idempotency.rb +26 -0
  34. data/lib/portage/ucp/support/line_item_status.rb +44 -0
  35. data/lib/portage/ucp/support/not_found.rb +25 -0
  36. data/lib/portage/ucp/support/token_exchange.rb +43 -0
  37. data/lib/portage/ucp/support/totals.rb +31 -0
  38. data/lib/portage/ucp/value_objects.rb +186 -0
  39. data/lib/portage/ucp/version.rb +5 -0
  40. data/lib/portage/ucp/wire_envelope.rb +25 -0
  41. data/lib/portage/ucp.rb +44 -0
  42. data/schemas/2026-04-08/schemas/capability.json +70 -0
  43. data/schemas/2026-04-08/schemas/payment_handler.json +67 -0
  44. data/schemas/2026-04-08/schemas/service.json +190 -0
  45. data/schemas/2026-04-08/schemas/shopping/cart.json +134 -0
  46. data/schemas/2026-04-08/schemas/shopping/catalog_lookup.json +207 -0
  47. data/schemas/2026-04-08/schemas/shopping/catalog_search.json +64 -0
  48. data/schemas/2026-04-08/schemas/shopping/checkout.json +131 -0
  49. data/schemas/2026-04-08/schemas/shopping/discount.json +148 -0
  50. data/schemas/2026-04-08/schemas/shopping/fulfillment.json +154 -0
  51. data/schemas/2026-04-08/schemas/shopping/order.json +113 -0
  52. data/schemas/2026-04-08/schemas/shopping/payment.json +16 -0
  53. data/schemas/2026-04-08/schemas/shopping/types/adjustment.json +69 -0
  54. data/schemas/2026-04-08/schemas/shopping/types/amount.json +8 -0
  55. data/schemas/2026-04-08/schemas/shopping/types/attribution.json +11 -0
  56. data/schemas/2026-04-08/schemas/shopping/types/available_payment_instrument.json +22 -0
  57. data/schemas/2026-04-08/schemas/shopping/types/business_fulfillment_config.json +38 -0
  58. data/schemas/2026-04-08/schemas/shopping/types/buyer.json +25 -0
  59. data/schemas/2026-04-08/schemas/shopping/types/category.json +20 -0
  60. data/schemas/2026-04-08/schemas/shopping/types/context.json +42 -0
  61. data/schemas/2026-04-08/schemas/shopping/types/description.json +22 -0
  62. data/schemas/2026-04-08/schemas/shopping/types/detail_option_value.json +22 -0
  63. data/schemas/2026-04-08/schemas/shopping/types/error_code.json +17 -0
  64. data/schemas/2026-04-08/schemas/shopping/types/error_response.json +31 -0
  65. data/schemas/2026-04-08/schemas/shopping/types/expectation.json +62 -0
  66. data/schemas/2026-04-08/schemas/shopping/types/fulfillment.json +25 -0
  67. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_available_method.json +45 -0
  68. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_destination.json +16 -0
  69. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_event.json +67 -0
  70. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_group.json +45 -0
  71. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_method.json +67 -0
  72. data/schemas/2026-04-08/schemas/shopping/types/fulfillment_option.json +56 -0
  73. data/schemas/2026-04-08/schemas/shopping/types/info_code.json +13 -0
  74. data/schemas/2026-04-08/schemas/shopping/types/input_correlation.json +24 -0
  75. data/schemas/2026-04-08/schemas/shopping/types/item.json +33 -0
  76. data/schemas/2026-04-08/schemas/shopping/types/line_item.json +46 -0
  77. data/schemas/2026-04-08/schemas/shopping/types/link.json +25 -0
  78. data/schemas/2026-04-08/schemas/shopping/types/media.json +36 -0
  79. data/schemas/2026-04-08/schemas/shopping/types/message.json +18 -0
  80. data/schemas/2026-04-08/schemas/shopping/types/message_error.json +49 -0
  81. data/schemas/2026-04-08/schemas/shopping/types/message_info.json +37 -0
  82. data/schemas/2026-04-08/schemas/shopping/types/message_warning.json +53 -0
  83. data/schemas/2026-04-08/schemas/shopping/types/option_value.json +20 -0
  84. data/schemas/2026-04-08/schemas/shopping/types/order_confirmation.json +26 -0
  85. data/schemas/2026-04-08/schemas/shopping/types/order_line_item.json +69 -0
  86. data/schemas/2026-04-08/schemas/shopping/types/pagination.json +62 -0
  87. data/schemas/2026-04-08/schemas/shopping/types/payment_credential.json +17 -0
  88. data/schemas/2026-04-08/schemas/shopping/types/payment_instrument.json +58 -0
  89. data/schemas/2026-04-08/schemas/shopping/types/platform_fulfillment_config.json +14 -0
  90. data/schemas/2026-04-08/schemas/shopping/types/postal_address.json +44 -0
  91. data/schemas/2026-04-08/schemas/shopping/types/price.json +22 -0
  92. data/schemas/2026-04-08/schemas/shopping/types/price_filter.json +17 -0
  93. data/schemas/2026-04-08/schemas/shopping/types/price_range.json +21 -0
  94. data/schemas/2026-04-08/schemas/shopping/types/product.json +89 -0
  95. data/schemas/2026-04-08/schemas/shopping/types/product_option.json +25 -0
  96. data/schemas/2026-04-08/schemas/shopping/types/rating.json +34 -0
  97. data/schemas/2026-04-08/schemas/shopping/types/retail_location.json +28 -0
  98. data/schemas/2026-04-08/schemas/shopping/types/reverse_domain_name.json +8 -0
  99. data/schemas/2026-04-08/schemas/shopping/types/search_filters.json +20 -0
  100. data/schemas/2026-04-08/schemas/shopping/types/selected_option.json +25 -0
  101. data/schemas/2026-04-08/schemas/shopping/types/shipping_destination.json +26 -0
  102. data/schemas/2026-04-08/schemas/shopping/types/signals.json +22 -0
  103. data/schemas/2026-04-08/schemas/shopping/types/signed_amount.json +7 -0
  104. data/schemas/2026-04-08/schemas/shopping/types/total.json +75 -0
  105. data/schemas/2026-04-08/schemas/shopping/types/totals.json +98 -0
  106. data/schemas/2026-04-08/schemas/shopping/types/variant.json +193 -0
  107. data/schemas/2026-04-08/schemas/shopping/types/warning_code.json +13 -0
  108. data/schemas/2026-04-08/schemas/transports/embedded_config.json +27 -0
  109. data/schemas/2026-04-08/schemas/ucp.json +364 -0
  110. data/schemas/2026-04-08/services/shopping/embedded.openrpc.json +634 -0
  111. data/schemas/2026-04-08/services/shopping/mcp.openrpc.json +492 -0
  112. metadata +283 -0
@@ -0,0 +1,190 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/service.json",
4
+ "title": "UCP Service",
5
+ "description": "Service binding for a specific transport. Each transport binding is a separate entry in the service array.",
6
+ "$defs": {
7
+ "base": {
8
+ "allOf": [
9
+ {
10
+ "$ref": "https://ucp.dev/2026-04-08/schemas/ucp.json#/$defs/entity"
11
+ },
12
+ {
13
+ "type": "object",
14
+ "required": [
15
+ "transport"
16
+ ],
17
+ "properties": {
18
+ "transport": {
19
+ "type": "string",
20
+ "enum": [
21
+ "rest",
22
+ "mcp",
23
+ "a2a",
24
+ "embedded"
25
+ ],
26
+ "description": "Transport protocol for this service binding."
27
+ },
28
+ "endpoint": {
29
+ "type": "string",
30
+ "format": "uri",
31
+ "description": "Endpoint URL for this transport binding."
32
+ }
33
+ }
34
+ }
35
+ ]
36
+ },
37
+ "platform_schema": {
38
+ "title": "Service (Platform Schema)",
39
+ "description": "Full service declaration for platform-level discovery. All transports require `version`, `spec`, and `transport`. REST, MCP, and embedded additionally require `schema`.",
40
+ "allOf": [
41
+ {
42
+ "$ref": "#/$defs/base"
43
+ },
44
+ {
45
+ "required": [
46
+ "spec"
47
+ ]
48
+ },
49
+ {
50
+ "anyOf": [
51
+ {
52
+ "properties": {
53
+ "transport": {
54
+ "const": "rest"
55
+ }
56
+ },
57
+ "required": [
58
+ "schema"
59
+ ]
60
+ },
61
+ {
62
+ "properties": {
63
+ "transport": {
64
+ "const": "mcp"
65
+ }
66
+ },
67
+ "required": [
68
+ "schema"
69
+ ]
70
+ },
71
+ {
72
+ "properties": {
73
+ "transport": {
74
+ "const": "a2a"
75
+ }
76
+ }
77
+ },
78
+ {
79
+ "properties": {
80
+ "transport": {
81
+ "const": "embedded"
82
+ }
83
+ },
84
+ "required": [
85
+ "schema"
86
+ ]
87
+ }
88
+ ]
89
+ }
90
+ ]
91
+ },
92
+ "business_schema": {
93
+ "title": "Service (Business Schema)",
94
+ "description": "Service binding for business/merchant configuration. May override platform endpoints.",
95
+ "allOf": [
96
+ {
97
+ "$ref": "#/$defs/base"
98
+ },
99
+ {
100
+ "anyOf": [
101
+ {
102
+ "properties": {
103
+ "transport": {
104
+ "const": "rest"
105
+ }
106
+ },
107
+ "required": [
108
+ "endpoint"
109
+ ]
110
+ },
111
+ {
112
+ "properties": {
113
+ "transport": {
114
+ "const": "mcp"
115
+ }
116
+ },
117
+ "required": [
118
+ "endpoint"
119
+ ]
120
+ },
121
+ {
122
+ "properties": {
123
+ "transport": {
124
+ "const": "a2a"
125
+ }
126
+ },
127
+ "required": [
128
+ "endpoint"
129
+ ]
130
+ },
131
+ {
132
+ "properties": {
133
+ "transport": {
134
+ "const": "embedded"
135
+ },
136
+ "config": {
137
+ "$ref": "https://ucp.dev/2026-04-08/schemas/transports/embedded_config.json"
138
+ }
139
+ }
140
+ }
141
+ ]
142
+ }
143
+ ]
144
+ },
145
+ "response_schema": {
146
+ "title": "Service (Response Schema)",
147
+ "description": "Service binding in API responses. Includes per-resource transport configuration via typed config.",
148
+ "allOf": [
149
+ {
150
+ "$ref": "#/$defs/base"
151
+ },
152
+ {
153
+ "anyOf": [
154
+ {
155
+ "properties": {
156
+ "transport": {
157
+ "const": "rest"
158
+ }
159
+ }
160
+ },
161
+ {
162
+ "properties": {
163
+ "transport": {
164
+ "const": "mcp"
165
+ }
166
+ }
167
+ },
168
+ {
169
+ "properties": {
170
+ "transport": {
171
+ "const": "a2a"
172
+ }
173
+ }
174
+ },
175
+ {
176
+ "properties": {
177
+ "transport": {
178
+ "const": "embedded"
179
+ },
180
+ "config": {
181
+ "$ref": "https://ucp.dev/2026-04-08/schemas/transports/embedded_config.json"
182
+ }
183
+ }
184
+ }
185
+ ]
186
+ }
187
+ ]
188
+ }
189
+ }
190
+ }
@@ -0,0 +1,134 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/cart.json",
4
+ "name": "dev.ucp.shopping.cart",
5
+ "title": "Cart",
6
+ "description": "Shopping cart with estimated pricing before checkout. Lightweight pre-purchase exploration with no payment info or complex status states.",
7
+ "$defs": {
8
+ "checkout": {
9
+ "title": "Checkout with Cart",
10
+ "description": "Checkout extended with cart capability. Adds cart_id to create_checkout for cart-to-checkout conversion.",
11
+ "allOf": [
12
+ {
13
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/checkout.json"
14
+ },
15
+ {
16
+ "type": "object",
17
+ "properties": {
18
+ "cart_id": {
19
+ "type": "string",
20
+ "description": "Cart ID to convert to checkout. Business MUST use cart contents (line_items, context, buyer) and MUST ignore overlapping fields in checkout payload.",
21
+ "ucp_request": {
22
+ "create": "optional",
23
+ "update": "omit"
24
+ }
25
+ }
26
+ }
27
+ }
28
+ ]
29
+ }
30
+ },
31
+ "type": "object",
32
+ "required": [
33
+ "ucp",
34
+ "id",
35
+ "line_items",
36
+ "currency",
37
+ "totals"
38
+ ],
39
+ "additionalProperties": true,
40
+ "properties": {
41
+ "ucp": {
42
+ "$ref": "https://ucp.dev/2026-04-08/schemas/ucp.json#/$defs/response_cart_schema",
43
+ "ucp_request": "omit"
44
+ },
45
+ "id": {
46
+ "type": "string",
47
+ "description": "Unique cart identifier.",
48
+ "ucp_request": {
49
+ "create": "omit",
50
+ "update": "required"
51
+ }
52
+ },
53
+ "line_items": {
54
+ "type": "array",
55
+ "items": {
56
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/line_item.json"
57
+ },
58
+ "description": "Cart line items. Same structure as checkout. Full replacement on update.",
59
+ "ucp_request": {
60
+ "create": "required",
61
+ "update": "required"
62
+ }
63
+ },
64
+ "context": {
65
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/context.json",
66
+ "description": "Buyer signals for localization (country, region, postal_code). Merchant uses for pricing, availability, currency. Falls back to geo-IP if omitted.",
67
+ "ucp_request": {
68
+ "create": "optional",
69
+ "update": "optional"
70
+ }
71
+ },
72
+ "signals": {
73
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/signals.json",
74
+ "ucp_request": {
75
+ "create": "optional",
76
+ "update": "optional"
77
+ }
78
+ },
79
+ "attribution": {
80
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/attribution.json",
81
+ "ucp_request": {
82
+ "create": "optional",
83
+ "update": "optional"
84
+ }
85
+ },
86
+ "buyer": {
87
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/buyer.json",
88
+ "description": "Optional buyer information for personalized estimates.",
89
+ "ucp_request": {
90
+ "create": "optional",
91
+ "update": "optional"
92
+ }
93
+ },
94
+ "currency": {
95
+ "type": "string",
96
+ "description": "ISO 4217 currency code. Determined by merchant based on context or geo-IP.",
97
+ "ucp_request": "omit"
98
+ },
99
+ "totals": {
100
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/totals.json",
101
+ "description": "Estimated cost breakdown. May be partial if shipping/tax not yet calculable.",
102
+ "ucp_request": "omit"
103
+ },
104
+ "messages": {
105
+ "type": "array",
106
+ "items": {
107
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/message.json"
108
+ },
109
+ "description": "Validation messages, warnings, or informational notices.",
110
+ "ucp_request": "omit"
111
+ },
112
+ "links": {
113
+ "type": "array",
114
+ "items": {
115
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/link.json"
116
+ },
117
+ "description": "Optional merchant links (policies, FAQs).",
118
+ "ucp_request": "omit"
119
+ },
120
+ "continue_url": {
121
+ "type": "string",
122
+ "format": "uri",
123
+ "description": "URL for cart handoff and session recovery. Enables sharing and human-in-the-loop flows.",
124
+ "ucp_request": "omit"
125
+ },
126
+ "expires_at": {
127
+ "type": "string",
128
+ "format": "date-time",
129
+ "description": "Cart expiry timestamp (RFC 3339). Optional.",
130
+ "ucp_request": "omit"
131
+ }
132
+ },
133
+ "version": "2026-04-08"
134
+ }
@@ -0,0 +1,207 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/catalog_lookup.json",
4
+ "name": "dev.ucp.shopping.catalog.lookup",
5
+ "title": "Catalog Lookup",
6
+ "description": "Product/variant lookup by identifier. Supports batch retrieval (lookup_catalog) and single-product detail (get_product).",
7
+ "type": "object",
8
+ "$defs": {
9
+ "lookup_variant": {
10
+ "description": "Variant with required correlation metadata for lookup responses.",
11
+ "allOf": [
12
+ {
13
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/variant.json"
14
+ },
15
+ {
16
+ "required": [
17
+ "inputs"
18
+ ],
19
+ "properties": {
20
+ "inputs": {
21
+ "type": "array",
22
+ "items": {
23
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/input_correlation.json"
24
+ },
25
+ "minItems": 1,
26
+ "description": "Which request identifiers resolved to this variant, and how. Each entry maps a request ID to its match type."
27
+ }
28
+ }
29
+ }
30
+ ]
31
+ },
32
+ "lookup_request": {
33
+ "type": "object",
34
+ "description": "Request body for catalog lookup.",
35
+ "required": [
36
+ "ids"
37
+ ],
38
+ "properties": {
39
+ "ids": {
40
+ "type": "array",
41
+ "items": {
42
+ "type": "string"
43
+ },
44
+ "minItems": 1,
45
+ "description": "Identifiers to lookup. Implementations MUST support product ID and variant ID; MAY support secondary identifiers (SKU, handle, etc.)."
46
+ },
47
+ "filters": {
48
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/search_filters.json",
49
+ "description": "Filter criteria to narrow returned products and variants. All specified filters combine with AND logic."
50
+ },
51
+ "context": {
52
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/context.json"
53
+ },
54
+ "signals": {
55
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/signals.json"
56
+ },
57
+ "attribution": {
58
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/attribution.json"
59
+ }
60
+ }
61
+ },
62
+ "lookup_response": {
63
+ "type": "object",
64
+ "required": [
65
+ "ucp",
66
+ "products"
67
+ ],
68
+ "properties": {
69
+ "ucp": {
70
+ "$ref": "https://ucp.dev/2026-04-08/schemas/ucp.json#/$defs/response_catalog_schema"
71
+ },
72
+ "products": {
73
+ "type": "array",
74
+ "items": {
75
+ "allOf": [
76
+ {
77
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/product.json"
78
+ },
79
+ {
80
+ "properties": {
81
+ "variants": {
82
+ "items": {
83
+ "$ref": "#/$defs/lookup_variant"
84
+ }
85
+ }
86
+ }
87
+ }
88
+ ]
89
+ },
90
+ "description": "Products matching the requested identifiers. May contain fewer items if some identifiers not found, or more if identifiers match multiple products."
91
+ },
92
+ "messages": {
93
+ "type": "array",
94
+ "items": {
95
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/message.json"
96
+ },
97
+ "description": "Errors, warnings, or informational messages about the requested items."
98
+ }
99
+ }
100
+ },
101
+ "get_product_request": {
102
+ "type": "object",
103
+ "description": "Request body for single-product retrieval. Supports interactive variant narrowing via selected and preferences.",
104
+ "required": [
105
+ "id"
106
+ ],
107
+ "properties": {
108
+ "id": {
109
+ "type": "string",
110
+ "description": "Product or variant identifier. Implementations MUST support product ID and variant ID."
111
+ },
112
+ "selected": {
113
+ "type": "array",
114
+ "items": {
115
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/selected_option.json"
116
+ },
117
+ "description": "Partial or full option selections for interactive variant narrowing. When provided, response option values include availability signals (available, exists) relative to these selections."
118
+ },
119
+ "preferences": {
120
+ "type": "array",
121
+ "items": {
122
+ "type": "string"
123
+ },
124
+ "description": "Option names in relaxation priority order. When no exact variant matches all selections, the server drops options from the end of this list first. E.g., ['Color', 'Size'] keeps Color and relaxes Size."
125
+ },
126
+ "filters": {
127
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/search_filters.json",
128
+ "description": "Filter criteria to narrow returned variants. All specified filters combine with AND logic."
129
+ },
130
+ "context": {
131
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/context.json"
132
+ },
133
+ "signals": {
134
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/signals.json"
135
+ },
136
+ "attribution": {
137
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/attribution.json"
138
+ }
139
+ }
140
+ },
141
+ "detail_product": {
142
+ "description": "A product in a get_product response, extended with effective selections and availability signals on option values.",
143
+ "type": "object",
144
+ "allOf": [
145
+ {
146
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/product.json"
147
+ }
148
+ ],
149
+ "properties": {
150
+ "selected": {
151
+ "type": "array",
152
+ "items": {
153
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/selected_option.json"
154
+ },
155
+ "description": "Effective option selections that anchor the featured variant and availability signals. Required when the product has configurable options; may be empty or omitted for products with no option axes."
156
+ },
157
+ "options": {
158
+ "type": "array",
159
+ "items": {
160
+ "type": "object",
161
+ "required": [
162
+ "name",
163
+ "values"
164
+ ],
165
+ "properties": {
166
+ "name": {
167
+ "type": "string"
168
+ },
169
+ "values": {
170
+ "type": "array",
171
+ "items": {
172
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/detail_option_value.json"
173
+ },
174
+ "minItems": 1
175
+ }
176
+ }
177
+ },
178
+ "description": "Product options with availability signals relative to the effective selections."
179
+ }
180
+ }
181
+ },
182
+ "get_product_response": {
183
+ "type": "object",
184
+ "required": [
185
+ "ucp",
186
+ "product"
187
+ ],
188
+ "properties": {
189
+ "ucp": {
190
+ "$ref": "https://ucp.dev/2026-04-08/schemas/ucp.json#/$defs/response_catalog_schema"
191
+ },
192
+ "product": {
193
+ "$ref": "#/$defs/detail_product",
194
+ "description": "The requested product with full detail. Singular — this is a single-resource operation."
195
+ },
196
+ "messages": {
197
+ "type": "array",
198
+ "items": {
199
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/message.json"
200
+ },
201
+ "description": "Warnings or informational messages about the product (e.g., price recently changed, limited availability)."
202
+ }
203
+ }
204
+ }
205
+ },
206
+ "version": "2026-04-08"
207
+ }
@@ -0,0 +1,64 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://ucp.dev/2026-04-08/schemas/shopping/catalog_search.json",
4
+ "name": "dev.ucp.shopping.catalog.search",
5
+ "title": "Catalog Search",
6
+ "description": "Product catalog search capability.",
7
+ "type": "object",
8
+ "$defs": {
9
+ "search_request": {
10
+ "type": "object",
11
+ "properties": {
12
+ "query": {
13
+ "type": "string",
14
+ "description": "Free-text search query."
15
+ },
16
+ "context": {
17
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/context.json"
18
+ },
19
+ "signals": {
20
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/signals.json"
21
+ },
22
+ "attribution": {
23
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/attribution.json"
24
+ },
25
+ "filters": {
26
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/search_filters.json"
27
+ },
28
+ "pagination": {
29
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/pagination.json#/$defs/request"
30
+ }
31
+ }
32
+ },
33
+ "search_response": {
34
+ "type": "object",
35
+ "required": [
36
+ "ucp",
37
+ "products"
38
+ ],
39
+ "properties": {
40
+ "ucp": {
41
+ "$ref": "https://ucp.dev/2026-04-08/schemas/ucp.json#/$defs/response_catalog_schema"
42
+ },
43
+ "products": {
44
+ "type": "array",
45
+ "items": {
46
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/product.json"
47
+ },
48
+ "description": "Products matching the search criteria."
49
+ },
50
+ "pagination": {
51
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/pagination.json#/$defs/response"
52
+ },
53
+ "messages": {
54
+ "type": "array",
55
+ "items": {
56
+ "$ref": "https://ucp.dev/2026-04-08/schemas/shopping/types/message.json"
57
+ },
58
+ "description": "Errors, warnings, or informational messages about the search results."
59
+ }
60
+ }
61
+ }
62
+ },
63
+ "version": "2026-04-08"
64
+ }