Skip to content

Commit de2fc59

Browse files
feat(managed-auth): add TS CUA worker contract (KERNEL-1456)
1 parent 2a288ca commit de2fc59

6 files changed

Lines changed: 158 additions & 3 deletions

File tree

.stats.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 127
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-0c99f133dc7e81a8e74e829299f4a7bfdd9f4fadc40e69a9a10c81ab28318f7a.yml
3-
openapi_spec_hash: 6e7e04300dc9554b2d1cf4284ee46504
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-5b9eb5cdadbc7a5f404f5c2cec40f726e5fece54bf8e2dd29ab5c7700eb44f0e.yml
3+
openapi_spec_hash: 63dd0798a4c0ed6477af50fff397f5dc
44
config_hash: 77ee715aa17061166f9a02b264a21b8d

src/kernel/resources/auth/connections.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,8 +505,10 @@ def submit(
505505
self,
506506
id: str,
507507
*,
508+
field_values: Dict[str, str] | Omit = omit,
508509
fields: Dict[str, str] | Omit = omit,
509510
mfa_option_id: str | Omit = omit,
511+
selected_choice_id: str | Omit = omit,
510512
sign_in_option_id: str | Omit = omit,
511513
sso_button_selector: str | Omit = omit,
512514
sso_provider: str | Omit = omit,
@@ -523,10 +525,14 @@ def submit(
523525
progress and get results.
524526
525527
Args:
528+
field_values: Canonical map of field ID to submitted value.
529+
526530
fields: Map of field name to value
527531
528532
mfa_option_id: The MFA method type to select (when mfa_options were returned)
529533
534+
selected_choice_id: Canonical choice ID selected by the user.
535+
530536
sign_in_option_id: The sign-in option ID to select (when sign_in_options were returned)
531537
532538
sso_button_selector: XPath selector for the SSO button to click (ODA). Use sso_provider instead for
@@ -549,8 +555,10 @@ def submit(
549555
path_template("/auth/connections/{id}/submit", id=id),
550556
body=maybe_transform(
551557
{
558+
"field_values": field_values,
552559
"fields": fields,
553560
"mfa_option_id": mfa_option_id,
561+
"selected_choice_id": selected_choice_id,
554562
"sign_in_option_id": sign_in_option_id,
555563
"sso_button_selector": sso_button_selector,
556564
"sso_provider": sso_provider,
@@ -1088,8 +1096,10 @@ async def submit(
10881096
self,
10891097
id: str,
10901098
*,
1099+
field_values: Dict[str, str] | Omit = omit,
10911100
fields: Dict[str, str] | Omit = omit,
10921101
mfa_option_id: str | Omit = omit,
1102+
selected_choice_id: str | Omit = omit,
10931103
sign_in_option_id: str | Omit = omit,
10941104
sso_button_selector: str | Omit = omit,
10951105
sso_provider: str | Omit = omit,
@@ -1106,10 +1116,14 @@ async def submit(
11061116
progress and get results.
11071117
11081118
Args:
1119+
field_values: Canonical map of field ID to submitted value.
1120+
11091121
fields: Map of field name to value
11101122
11111123
mfa_option_id: The MFA method type to select (when mfa_options were returned)
11121124
1125+
selected_choice_id: Canonical choice ID selected by the user.
1126+
11131127
sign_in_option_id: The sign-in option ID to select (when sign_in_options were returned)
11141128
11151129
sso_button_selector: XPath selector for the SSO button to click (ODA). Use sso_provider instead for
@@ -1132,8 +1146,10 @@ async def submit(
11321146
path_template("/auth/connections/{id}/submit", id=id),
11331147
body=await async_maybe_transform(
11341148
{
1149+
"field_values": field_values,
11351150
"fields": fields,
11361151
"mfa_option_id": mfa_option_id,
1152+
"selected_choice_id": selected_choice_id,
11371153
"sign_in_option_id": sign_in_option_id,
11381154
"sso_button_selector": sso_button_selector,
11391155
"sso_provider": sso_provider,

src/kernel/types/auth/connection_follow_response.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,36 @@
1212
__all__ = [
1313
"ConnectionFollowResponse",
1414
"ManagedAuthStateEvent",
15+
"ManagedAuthStateEventChoice",
1516
"ManagedAuthStateEventDiscoveredField",
17+
"ManagedAuthStateEventField",
1618
"ManagedAuthStateEventMfaOption",
1719
"ManagedAuthStateEventPendingSSOButton",
1820
"ManagedAuthStateEventSignInOption",
1921
]
2022

2123

24+
class ManagedAuthStateEventChoice(BaseModel):
25+
"""Canonical auth-flow choice awaiting user selection."""
26+
27+
id: str
28+
"""Stable choice identifier for canonical submit."""
29+
30+
label: str
31+
"""Human-readable choice label."""
32+
33+
type: Literal[
34+
"mfa_method", "sso_provider", "sign_in_method", "auth_method", "identifier_method", "account", "other"
35+
]
36+
"""Choice type."""
37+
38+
description: Optional[str] = None
39+
"""Additional context for the choice."""
40+
41+
observed_selector: Optional[str] = None
42+
"""Selector for the visible choice, when available."""
43+
44+
2245
class ManagedAuthStateEventDiscoveredField(BaseModel):
2346
"""A discovered form field"""
2447

@@ -53,6 +76,28 @@ class ManagedAuthStateEventDiscoveredField(BaseModel):
5376
"""Whether field is required"""
5477

5578

79+
class ManagedAuthStateEventField(BaseModel):
80+
"""Canonical field awaiting user input."""
81+
82+
id: str
83+
"""Stable field identifier for canonical submit."""
84+
85+
ref: str
86+
"""Credential reference name to store the submitted value under."""
87+
88+
type: Literal["identifier", "password", "code", "totp_code", "totp_secret", "text"]
89+
"""Managed-auth field type."""
90+
91+
label: Optional[str] = None
92+
"""Human-readable label shown to the user."""
93+
94+
observed_selector: Optional[str] = None
95+
"""Selector for the visible field, when available."""
96+
97+
required: Optional[bool] = None
98+
"""Whether this field is required."""
99+
100+
56101
class ManagedAuthStateEventMfaOption(BaseModel):
57102
"""An MFA method option for verification"""
58103

@@ -118,6 +163,13 @@ class ManagedAuthStateEvent(BaseModel):
118163
timestamp: datetime
119164
"""Time the state was reported."""
120165

166+
choices: Optional[List[ManagedAuthStateEventChoice]] = None
167+
"""Canonical choices awaiting selection.
168+
169+
Prefer this over pending_sso_buttons, mfa_options, and sign_in_options when
170+
present.
171+
"""
172+
121173
discovered_fields: Optional[List[ManagedAuthStateEventDiscoveredField]] = None
122174
"""
123175
Fields awaiting input (present when flow_step=AWAITING_INPUT; may also be
@@ -136,6 +188,12 @@ class ManagedAuthStateEvent(BaseModel):
136188
flow_step=AWAITING_EXTERNAL_ACTION).
137189
"""
138190

191+
fields: Optional[List[ManagedAuthStateEventField]] = None
192+
"""Canonical fields awaiting input.
193+
194+
Prefer this over discovered_fields when present.
195+
"""
196+
139197
flow_type: Optional[Literal["LOGIN", "REAUTH"]] = None
140198
"""Type of the current flow."""
141199

src/kernel/types/auth/connection_submit_params.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,18 @@
99

1010

1111
class ConnectionSubmitParams(TypedDict, total=False):
12+
field_values: Dict[str, str]
13+
"""Canonical map of field ID to submitted value."""
14+
1215
fields: Dict[str, str]
1316
"""Map of field name to value"""
1417

1518
mfa_option_id: str
1619
"""The MFA method type to select (when mfa_options were returned)"""
1720

21+
selected_choice_id: str
22+
"""Canonical choice ID selected by the user."""
23+
1824
sign_in_option_id: str
1925
"""The sign-in option ID to select (when sign_in_options were returned)"""
2026

src/kernel/types/auth/managed_auth.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,37 @@
66

77
from ..._models import BaseModel
88

9-
__all__ = ["ManagedAuth", "Credential", "DiscoveredField", "MfaOption", "PendingSSOButton", "SignInOption"]
9+
__all__ = [
10+
"ManagedAuth",
11+
"Choice",
12+
"Credential",
13+
"DiscoveredField",
14+
"Field",
15+
"MfaOption",
16+
"PendingSSOButton",
17+
"SignInOption",
18+
]
19+
20+
21+
class Choice(BaseModel):
22+
"""Canonical auth-flow choice awaiting user selection."""
23+
24+
id: str
25+
"""Stable choice identifier for canonical submit."""
26+
27+
label: str
28+
"""Human-readable choice label."""
29+
30+
type: Literal[
31+
"mfa_method", "sso_provider", "sign_in_method", "auth_method", "identifier_method", "account", "other"
32+
]
33+
"""Choice type."""
34+
35+
description: Optional[str] = None
36+
"""Additional context for the choice."""
37+
38+
observed_selector: Optional[str] = None
39+
"""Selector for the visible choice, when available."""
1040

1141

1242
class Credential(BaseModel):
@@ -65,6 +95,28 @@ class DiscoveredField(BaseModel):
6595
"""Whether field is required"""
6696

6797

98+
class Field(BaseModel):
99+
"""Canonical field awaiting user input."""
100+
101+
id: str
102+
"""Stable field identifier for canonical submit."""
103+
104+
ref: str
105+
"""Credential reference name to store the submitted value under."""
106+
107+
type: Literal["identifier", "password", "code", "totp_code", "totp_secret", "text"]
108+
"""Managed-auth field type."""
109+
110+
label: Optional[str] = None
111+
"""Human-readable label shown to the user."""
112+
113+
observed_selector: Optional[str] = None
114+
"""Selector for the visible field, when available."""
115+
116+
required: Optional[bool] = None
117+
"""Whether this field is required."""
118+
119+
68120
class MfaOption(BaseModel):
69121
"""An MFA method option for verification"""
70122

@@ -243,6 +295,13 @@ class ManagedAuth(BaseModel):
243295
automatically
244296
"""
245297

298+
choices: Optional[List[Choice]] = None
299+
"""Canonical choices awaiting selection.
300+
301+
Prefer this over pending_sso_buttons, mfa_options, and sign_in_options when
302+
present.
303+
"""
304+
246305
credential: Optional[Credential] = None
247306
"""Reference to credentials for the auth connection. Use one of:
248307
@@ -269,6 +328,12 @@ class ManagedAuth(BaseModel):
269328
flow_step=awaiting_external_action)
270329
"""
271330

331+
fields: Optional[List[Field]] = None
332+
"""Canonical fields awaiting input.
333+
334+
Prefer this over discovered_fields when present.
335+
"""
336+
272337
flow_expires_at: Optional[datetime] = None
273338
"""When the current flow expires (null when no flow in progress).
274339

tests/api_resources/auth/test_connections.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,11 +386,16 @@ def test_method_submit(self, client: Kernel) -> None:
386386
def test_method_submit_with_all_params(self, client: Kernel) -> None:
387387
connection = client.auth.connections.submit(
388388
id="id",
389+
field_values={
390+
"field_email": "user@example.com",
391+
"field_password": "secret",
392+
},
389393
fields={
390394
"email": "user@example.com",
391395
"password": "secret",
392396
},
393397
mfa_option_id="sms",
398+
selected_choice_id="google",
394399
sign_in_option_id="work-account",
395400
sso_button_selector="xpath=//button[contains(text(), 'Continue with Google')]",
396401
sso_provider="google",
@@ -853,11 +858,16 @@ async def test_method_submit(self, async_client: AsyncKernel) -> None:
853858
async def test_method_submit_with_all_params(self, async_client: AsyncKernel) -> None:
854859
connection = await async_client.auth.connections.submit(
855860
id="id",
861+
field_values={
862+
"field_email": "user@example.com",
863+
"field_password": "secret",
864+
},
856865
fields={
857866
"email": "user@example.com",
858867
"password": "secret",
859868
},
860869
mfa_option_id="sms",
870+
selected_choice_id="google",
861871
sign_in_option_id="work-account",
862872
sso_button_selector="xpath=//button[contains(text(), 'Continue with Google')]",
863873
sso_provider="google",

0 commit comments

Comments
 (0)