Skip to content

Commit f6ead45

Browse files
committed
chore(models): regenerate from ucp@c5c6139
./generate_models.sh --ref c5c61396ebf9a5afb9c4169bfa3af1409daa6fd6 against Universal-Commerce-Protocol/ucp — the identity-linking OAuth 2.0 foundation merge (PR #354) plus everything from the v2026-04-08 release. The capability-$defs lift in this PR's preprocessor change collapses common/identity_linking/dev/ucp/common.py (which used to contain only `IdentityLinking = RootModel[Any]`) into a flat common/identity_linking.py exposing typed ScopePolicy, ScopeToken, Config, IdentityLinkingPlatformSchema, IdentityLinkingBusinessSchema, and a discriminating IdentityLinking union — i.e. real typed access to config.scopes / scope_policy. Same lift applies to fulfillment's dev.ucp.shopping.fulfillment dotted key. Other additions vs the previous snapshot: Cart (cart.py + create/ update request variants), Catalog Search and Lookup (with GetProductRequest / GetProductResponse / DetailProduct as nested defs), the standalone info_code / warning_code / error_response models, signed_amount with no ge=0 (discounts and refunds carry negative values), and a wider shopping/types tree covering adjustment, attribution, available payment instruments, category, description, media, option / detail option values, pagination, price, signing keys, signals, and the embedded transport schemas. Context grew language, currency, and eligibility alongside intent. Total.type relaxed from a closed Literal to a plain string, matching the spec's open vocabulary. AP2 mandate, buyer consent, and discount became package directories instead of single modules due to nested $defs. Provenance recorded at src/ucp_sdk/_schema_ref.py.
1 parent a07f862 commit f6ead45

99 files changed

Lines changed: 4923 additions & 225 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/ucp_sdk/models/schemas/capability.py

Lines changed: 116 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,114 @@ class UcpCapability(RootModel[Any]):
3333
"""
3434

3535

36+
class Extends(RootModel[str]):
37+
model_config = ConfigDict(
38+
frozen=True,
39+
)
40+
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
41+
"""
42+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
43+
"""
44+
45+
46+
class Extends1Item(RootModel[str]):
47+
model_config = ConfigDict(
48+
frozen=True,
49+
)
50+
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
51+
52+
53+
class Extends1(RootModel[list[Extends1Item]]):
54+
model_config = ConfigDict(
55+
frozen=True,
56+
)
57+
root: list[Extends1Item] = Field(..., min_length=1)
58+
"""
59+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
60+
"""
61+
62+
63+
class Extends2(RootModel[str]):
64+
model_config = ConfigDict(
65+
frozen=True,
66+
)
67+
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
68+
"""
69+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
70+
"""
71+
72+
73+
class Extends3Item(RootModel[str]):
74+
model_config = ConfigDict(
75+
frozen=True,
76+
)
77+
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
78+
79+
80+
class Extends3(RootModel[list[Extends3Item]]):
81+
model_config = ConfigDict(
82+
frozen=True,
83+
)
84+
root: list[Extends3Item] = Field(..., min_length=1)
85+
"""
86+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
87+
"""
88+
89+
90+
class Extends4(RootModel[str]):
91+
model_config = ConfigDict(
92+
frozen=True,
93+
)
94+
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
95+
"""
96+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
97+
"""
98+
99+
100+
class Extends5Item(RootModel[str]):
101+
model_config = ConfigDict(
102+
frozen=True,
103+
)
104+
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
105+
106+
107+
class Extends5(RootModel[list[Extends5Item]]):
108+
model_config = ConfigDict(
109+
frozen=True,
110+
)
111+
root: list[Extends5Item] = Field(..., min_length=1)
112+
"""
113+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
114+
"""
115+
116+
117+
class Extends6(RootModel[str]):
118+
model_config = ConfigDict(
119+
frozen=True,
120+
)
121+
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
122+
"""
123+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
124+
"""
125+
126+
127+
class Extends7Item(RootModel[str]):
128+
model_config = ConfigDict(
129+
frozen=True,
130+
)
131+
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
132+
133+
134+
class Extends7(RootModel[list[Extends7Item]]):
135+
model_config = ConfigDict(
136+
frozen=True,
137+
)
138+
root: list[Extends7Item] = Field(..., min_length=1)
139+
"""
140+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
141+
"""
142+
143+
36144
class Version(RootModel[Any]):
37145
model_config = ConfigDict(
38146
frozen=True,
@@ -64,11 +172,9 @@ class Base(BaseModel):
64172
"""
65173
Entity-specific configuration. Structure defined by each entity's schema.
66174
"""
67-
extends: str | None = Field(
68-
None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$"
69-
)
175+
extends: Extends | Extends1 | None = None
70176
"""
71-
Parent capability this extends. Present for extensions, absent for root capabilities.
177+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
72178
"""
73179

74180

@@ -100,11 +206,9 @@ class PlatformSchema(BaseModel):
100206
"""
101207
Entity-specific configuration. Structure defined by each entity's schema.
102208
"""
103-
extends: str | None = Field(
104-
None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$"
105-
)
209+
extends: Extends2 | Extends3 | None = None
106210
"""
107-
Parent capability this extends. Present for extensions, absent for root capabilities.
211+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
108212
"""
109213

110214

@@ -136,11 +240,9 @@ class BusinessSchema(BaseModel):
136240
"""
137241
Entity-specific configuration. Structure defined by each entity's schema.
138242
"""
139-
extends: str | None = Field(
140-
None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$"
141-
)
243+
extends: Extends4 | Extends5 | None = None
142244
"""
143-
Parent capability this extends. Present for extensions, absent for root capabilities.
245+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
144246
"""
145247

146248

@@ -172,9 +274,7 @@ class ResponseSchema(BaseModel):
172274
"""
173275
Entity-specific configuration. Structure defined by each entity's schema.
174276
"""
175-
extends: str | None = Field(
176-
None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$"
177-
)
277+
extends: Extends6 | Extends7 | None = None
178278
"""
179-
Parent capability this extends. Present for extensions, absent for root capabilities.
279+
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
180280
"""
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copyright 2026 UCP Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# generated by datamodel-codegen
16+
# pylint: disable=all
17+
# pyformat: disable
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Copyright 2026 UCP Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# generated by datamodel-codegen
16+
# pylint: disable=all
17+
# pyformat: disable
18+
19+
from __future__ import annotations
20+
21+
from pydantic import BaseModel, ConfigDict, Field, RootModel
22+
23+
from ..capability import BusinessSchema, PlatformSchema
24+
from ..shopping.types import description as description_1
25+
26+
27+
class ScopePolicy(BaseModel):
28+
"""
29+
Per-scope policy and metadata — auth constraints (e.g. min_acr, max_token_age), declarative metadata (e.g. claims produced, consent descriptions), or any other scope-specific configuration. An empty object means user authentication is required with no additional policy. Open for non-breaking extension.
30+
"""
31+
32+
model_config = ConfigDict(
33+
extra="allow",
34+
)
35+
description: description_1.Description | None = None
36+
"""
37+
Optional human-readable description of the scope that platforms can use to present and explain context (requirement and value) to the user.
38+
"""
39+
40+
41+
class ScopeToken(RootModel[str]):
42+
model_config = ConfigDict(
43+
frozen=True,
44+
)
45+
root: str = Field(
46+
..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+:[a-z][a-z0-9_]*$"
47+
)
48+
"""
49+
OAuth scope string formed by joining a capability name and a scope name with a colon: '{capability}:{scope}', e.g. 'dev.ucp.shopping.order:read'. Capability names use reverse-DNS naming; scope names denote the permission granted, defined by each capability's spec (e.g. 'read', 'manage', 'create'). Platforms request these strings verbatim in OAuth 'scope' parameters; issued tokens carry them in the 'scope' claim.
50+
"""
51+
52+
53+
class Config(BaseModel):
54+
model_config = ConfigDict(
55+
extra="allow",
56+
)
57+
scopes: dict[ScopeToken, ScopePolicy]
58+
"""
59+
Map of user-authenticated scopes offered by this business. Each key is an OAuth scope string formed as '{capability}:{scope}' (e.g. 'dev.ucp.shopping.order:read'). Scope presence in this map declares that the corresponding operations require a user identity token. Operations not gated by any listed scope operate at whatever access level the business permits; UCP does not prescribe a default. Each value is a per-scope policy object (empty object means user auth required with no additional policy).
60+
"""
61+
62+
63+
class IdentityLinkingPlatformSchema(PlatformSchema):
64+
"""
65+
Platform-level identity linking capability declaration. Platforms advertise support for identity linking; no auth-specific config is required.
66+
"""
67+
68+
model_config = ConfigDict(
69+
extra="allow",
70+
)
71+
72+
73+
class IdentityLinkingBusinessSchema(BusinessSchema):
74+
"""
75+
Business-level identity linking configuration. Businesses declare the user-authenticated scopes they offer in 'config.scopes'.
76+
"""
77+
78+
model_config = ConfigDict(
79+
extra="allow",
80+
)
81+
config: Config
82+
83+
84+
class IdentityLinking(
85+
RootModel[IdentityLinkingPlatformSchema | IdentityLinkingBusinessSchema]
86+
):
87+
model_config = ConfigDict(
88+
frozen=True,
89+
)
90+
root: IdentityLinkingPlatformSchema | IdentityLinkingBusinessSchema = Field(
91+
..., title="Identity Linking"
92+
)
93+
"""
94+
Capability schema for identity linking. Businesses declare the user-authenticated scopes they offer in a flat 'scopes' map. Each key is the OAuth scope string as it appears on the wire ('{capability}:{scope}', e.g. 'dev.ucp.shopping.order:read'). Scope presence implies that the corresponding operations require user authentication. Operations not gated by any listed scope operate at whatever access level the business permits; UCP does not prescribe a default.
95+
"""

src/ucp_sdk/models/schemas/payment_handler.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
from pydantic import AnyUrl, BaseModel, ConfigDict, Field, RootModel
2424

25+
from .shopping.types import available_payment_instrument
26+
2527

2628
class PaymentHandler(RootModel[Any]):
2729
model_config = ConfigDict(
@@ -64,6 +66,12 @@ class Base(BaseModel):
6466
"""
6567
Entity-specific configuration. Structure defined by each entity's schema.
6668
"""
69+
available_instruments: (
70+
list[available_payment_instrument.AvailablePaymentInstrument] | None
71+
) = Field(None, min_length=1)
72+
"""
73+
Instrument types this handler supports, with optional constraints. When absent, every instrument should be considered available.
74+
"""
6775

6876

6977
class PlatformSchema(BaseModel):
@@ -94,6 +102,12 @@ class PlatformSchema(BaseModel):
94102
"""
95103
Entity-specific configuration. Structure defined by each entity's schema.
96104
"""
105+
available_instruments: (
106+
list[available_payment_instrument.AvailablePaymentInstrument] | None
107+
) = Field(None, min_length=1)
108+
"""
109+
Instrument types this handler supports, with optional constraints. When absent, every instrument should be considered available.
110+
"""
97111

98112

99113
class BusinessSchema(BaseModel):
@@ -124,6 +138,12 @@ class BusinessSchema(BaseModel):
124138
"""
125139
Entity-specific configuration. Structure defined by each entity's schema.
126140
"""
141+
available_instruments: (
142+
list[available_payment_instrument.AvailablePaymentInstrument] | None
143+
) = Field(None, min_length=1)
144+
"""
145+
Instrument types this handler supports, with optional constraints. When absent, every instrument should be considered available.
146+
"""
127147

128148

129149
class ResponseSchema(BaseModel):
@@ -154,3 +174,9 @@ class ResponseSchema(BaseModel):
154174
"""
155175
Entity-specific configuration. Structure defined by each entity's schema.
156176
"""
177+
available_instruments: (
178+
list[available_payment_instrument.AvailablePaymentInstrument] | None
179+
) = Field(None, min_length=1)
180+
"""
181+
Instrument types this handler supports, with optional constraints. When absent, every instrument should be considered available.
182+
"""

0 commit comments

Comments
 (0)