Skip to content

Commit 871432f

Browse files
feat: Add auth connection event timeline endpoint
1 parent 4890ed3 commit 871432f

7 files changed

Lines changed: 337 additions & 4 deletions

File tree

.stats.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
configured_endpoints: 123
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ac06dd66a7a0da0dd6dd6cd98127652891b914e880dbaed90d7ab666b13af8a9.yml
3-
openapi_spec_hash: 1d35ae59d6570497f8b379ded59f0434
4-
config_hash: d52b040438a187c46050e0e8395b2f47
1+
configured_endpoints: 124
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-4fb45d71a99648425c84bdc8e5780920105cede4ee2d4eac67276d0609ac1e94.yml
3+
openapi_spec_hash: 1f04cb5b36e92db81dfa264c2a59c32a
4+
config_hash: fb167e754ebb3a14649463725891c9d0

api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ from kernel.types.auth import (
300300
LoginResponse,
301301
ManagedAuth,
302302
ManagedAuthCreateRequest,
303+
ManagedAuthTimelineEvent,
303304
ManagedAuthUpdateRequest,
304305
SubmitFieldsRequest,
305306
SubmitFieldsResponse,
@@ -317,6 +318,7 @@ Methods:
317318
- <code title="get /auth/connections/{id}/events">client.auth.connections.<a href="./src/kernel/resources/auth/connections.py">follow</a>(id) -> <a href="./src/kernel/types/auth/connection_follow_response.py">ConnectionFollowResponse</a></code>
318319
- <code title="post /auth/connections/{id}/login">client.auth.connections.<a href="./src/kernel/resources/auth/connections.py">login</a>(id, \*\*<a href="src/kernel/types/auth/connection_login_params.py">params</a>) -> <a href="./src/kernel/types/auth/login_response.py">LoginResponse</a></code>
319320
- <code title="post /auth/connections/{id}/submit">client.auth.connections.<a href="./src/kernel/resources/auth/connections.py">submit</a>(id, \*\*<a href="src/kernel/types/auth/connection_submit_params.py">params</a>) -> <a href="./src/kernel/types/auth/submit_fields_response.py">SubmitFieldsResponse</a></code>
321+
- <code title="get /auth/connections/{id}/timeline">client.auth.connections.<a href="./src/kernel/resources/auth/connections.py">timeline</a>(id, \*\*<a href="src/kernel/types/auth/connection_timeline_params.py">params</a>) -> <a href="./src/kernel/types/auth/managed_auth_timeline_event.py">SyncOffsetPagination[ManagedAuthTimelineEvent]</a></code>
320322

321323
# Proxies
322324

src/kernel/resources/auth/connections.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from __future__ import annotations
44

55
from typing import Any, Dict, cast
6+
from typing_extensions import Literal
67

78
import httpx
89

@@ -24,12 +25,14 @@
2425
connection_create_params,
2526
connection_submit_params,
2627
connection_update_params,
28+
connection_timeline_params,
2729
)
2830
from ..._base_client import AsyncPaginator, make_request_options
2931
from ...types.auth.managed_auth import ManagedAuth
3032
from ...types.auth.login_response import LoginResponse
3133
from ...types.auth.submit_fields_response import SubmitFieldsResponse
3234
from ...types.auth.connection_follow_response import ConnectionFollowResponse
35+
from ...types.auth.managed_auth_timeline_event import ManagedAuthTimelineEvent
3336

3437
__all__ = ["ConnectionsResource", "AsyncConnectionsResource"]
3538

@@ -554,6 +557,62 @@ def submit(
554557
cast_to=SubmitFieldsResponse,
555558
)
556559

560+
def timeline(
561+
self,
562+
id: str,
563+
*,
564+
limit: int | Omit = omit,
565+
offset: int | Omit = omit,
566+
type: Literal["login", "reauth", "health_check"] | Omit = omit,
567+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
568+
# The extra values given here take precedence over values defined on the client or passed to this method.
569+
extra_headers: Headers | None = None,
570+
extra_query: Query | None = None,
571+
extra_body: Body | None = None,
572+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
573+
) -> SyncOffsetPagination[ManagedAuthTimelineEvent]:
574+
"""
575+
Returns a chronological timeline of events for an auth connection — login
576+
attempts, automatic re-auth attempts, and health checks. Events are returned
577+
newest-first.
578+
579+
Args:
580+
limit: Maximum number of events to return
581+
582+
offset: Number of events to skip
583+
584+
type: Filter the timeline to a single event type.
585+
586+
extra_headers: Send extra headers
587+
588+
extra_query: Add additional query parameters to the request
589+
590+
extra_body: Add additional JSON properties to the request
591+
592+
timeout: Override the client-level default timeout for this request, in seconds
593+
"""
594+
if not id:
595+
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
596+
return self._get_api_list(
597+
path_template("/auth/connections/{id}/timeline", id=id),
598+
page=SyncOffsetPagination[ManagedAuthTimelineEvent],
599+
options=make_request_options(
600+
extra_headers=extra_headers,
601+
extra_query=extra_query,
602+
extra_body=extra_body,
603+
timeout=timeout,
604+
query=maybe_transform(
605+
{
606+
"limit": limit,
607+
"offset": offset,
608+
"type": type,
609+
},
610+
connection_timeline_params.ConnectionTimelineParams,
611+
),
612+
),
613+
model=ManagedAuthTimelineEvent,
614+
)
615+
557616

558617
class AsyncConnectionsResource(AsyncAPIResource):
559618
"""Create and manage auth connections for automated credential capture and login."""
@@ -1075,6 +1134,62 @@ async def submit(
10751134
cast_to=SubmitFieldsResponse,
10761135
)
10771136

1137+
def timeline(
1138+
self,
1139+
id: str,
1140+
*,
1141+
limit: int | Omit = omit,
1142+
offset: int | Omit = omit,
1143+
type: Literal["login", "reauth", "health_check"] | Omit = omit,
1144+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
1145+
# The extra values given here take precedence over values defined on the client or passed to this method.
1146+
extra_headers: Headers | None = None,
1147+
extra_query: Query | None = None,
1148+
extra_body: Body | None = None,
1149+
timeout: float | httpx.Timeout | None | NotGiven = not_given,
1150+
) -> AsyncPaginator[ManagedAuthTimelineEvent, AsyncOffsetPagination[ManagedAuthTimelineEvent]]:
1151+
"""
1152+
Returns a chronological timeline of events for an auth connection — login
1153+
attempts, automatic re-auth attempts, and health checks. Events are returned
1154+
newest-first.
1155+
1156+
Args:
1157+
limit: Maximum number of events to return
1158+
1159+
offset: Number of events to skip
1160+
1161+
type: Filter the timeline to a single event type.
1162+
1163+
extra_headers: Send extra headers
1164+
1165+
extra_query: Add additional query parameters to the request
1166+
1167+
extra_body: Add additional JSON properties to the request
1168+
1169+
timeout: Override the client-level default timeout for this request, in seconds
1170+
"""
1171+
if not id:
1172+
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
1173+
return self._get_api_list(
1174+
path_template("/auth/connections/{id}/timeline", id=id),
1175+
page=AsyncOffsetPagination[ManagedAuthTimelineEvent],
1176+
options=make_request_options(
1177+
extra_headers=extra_headers,
1178+
extra_query=extra_query,
1179+
extra_body=extra_body,
1180+
timeout=timeout,
1181+
query=maybe_transform(
1182+
{
1183+
"limit": limit,
1184+
"offset": offset,
1185+
"type": type,
1186+
},
1187+
connection_timeline_params.ConnectionTimelineParams,
1188+
),
1189+
),
1190+
model=ManagedAuthTimelineEvent,
1191+
)
1192+
10781193

10791194
class ConnectionsResourceWithRawResponse:
10801195
def __init__(self, connections: ConnectionsResource) -> None:
@@ -1104,6 +1219,9 @@ def __init__(self, connections: ConnectionsResource) -> None:
11041219
self.submit = to_raw_response_wrapper(
11051220
connections.submit,
11061221
)
1222+
self.timeline = to_raw_response_wrapper(
1223+
connections.timeline,
1224+
)
11071225

11081226

11091227
class AsyncConnectionsResourceWithRawResponse:
@@ -1134,6 +1252,9 @@ def __init__(self, connections: AsyncConnectionsResource) -> None:
11341252
self.submit = async_to_raw_response_wrapper(
11351253
connections.submit,
11361254
)
1255+
self.timeline = async_to_raw_response_wrapper(
1256+
connections.timeline,
1257+
)
11371258

11381259

11391260
class ConnectionsResourceWithStreamingResponse:
@@ -1164,6 +1285,9 @@ def __init__(self, connections: ConnectionsResource) -> None:
11641285
self.submit = to_streamed_response_wrapper(
11651286
connections.submit,
11661287
)
1288+
self.timeline = to_streamed_response_wrapper(
1289+
connections.timeline,
1290+
)
11671291

11681292

11691293
class AsyncConnectionsResourceWithStreamingResponse:
@@ -1194,3 +1318,6 @@ def __init__(self, connections: AsyncConnectionsResource) -> None:
11941318
self.submit = async_to_streamed_response_wrapper(
11951319
connections.submit,
11961320
)
1321+
self.timeline = async_to_streamed_response_wrapper(
1322+
connections.timeline,
1323+
)

src/kernel/types/auth/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@
1111
from .connection_submit_params import ConnectionSubmitParams as ConnectionSubmitParams
1212
from .connection_update_params import ConnectionUpdateParams as ConnectionUpdateParams
1313
from .connection_follow_response import ConnectionFollowResponse as ConnectionFollowResponse
14+
from .connection_timeline_params import ConnectionTimelineParams as ConnectionTimelineParams
15+
from .managed_auth_timeline_event import ManagedAuthTimelineEvent as ManagedAuthTimelineEvent
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from __future__ import annotations
4+
5+
from typing_extensions import Literal, TypedDict
6+
7+
__all__ = ["ConnectionTimelineParams"]
8+
9+
10+
class ConnectionTimelineParams(TypedDict, total=False):
11+
limit: int
12+
"""Maximum number of events to return"""
13+
14+
offset: int
15+
"""Number of events to skip"""
16+
17+
type: Literal["login", "reauth", "health_check"]
18+
"""Filter the timeline to a single event type."""
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
from typing import Optional
4+
from datetime import datetime
5+
from typing_extensions import Literal
6+
7+
from ..._models import BaseModel
8+
9+
__all__ = ["ManagedAuthTimelineEvent"]
10+
11+
12+
class ManagedAuthTimelineEvent(BaseModel):
13+
"""
14+
A single event in an auth connection's history — a login attempt, an automatic re-auth attempt, or a health check.
15+
"""
16+
17+
id: str
18+
"""Identifier of the underlying login/reauth session or health check."""
19+
20+
status: Literal["IN_PROGRESS", "SUCCESS", "EXPIRED", "CANCELED", "FAILED", "AUTHENTICATED", "NEEDS_AUTH"]
21+
"""Outcome of the event.
22+
23+
For login/reauth events this is the flow status (IN_PROGRESS, SUCCESS, EXPIRED,
24+
CANCELED, FAILED). For health_check events it is the observed session state
25+
(AUTHENTICATED, NEEDS_AUTH).
26+
"""
27+
28+
timestamp: datetime
29+
"""When the event occurred."""
30+
31+
type: Literal["login", "reauth", "health_check"]
32+
"""The kind of event.
33+
34+
"login" and "reauth" are authentication attempts; "health_check" is a periodic
35+
session-validity check.
36+
"""
37+
38+
error_code: Optional[str] = None
39+
"""Machine-readable error code. Present when a login/reauth event failed."""
40+
41+
error_message: Optional[str] = None
42+
"""Human-readable error message. Present when a login/reauth event failed."""
43+
44+
previous_status: Optional[Literal["AUTHENTICATED", "NEEDS_AUTH"]] = None
45+
"""The session state observed before this event.
46+
47+
Present for health_check events that recorded a prior state.
48+
"""
49+
50+
replay_id: Optional[str] = None
51+
"""
52+
Replay recording ID for the event's browser session, if session recording was
53+
enabled.
54+
"""
55+
56+
step: Optional[
57+
Literal[
58+
"INITIALIZED",
59+
"DISCOVERING",
60+
"AWAITING_INPUT",
61+
"AWAITING_EXTERNAL_ACTION",
62+
"AWAITING_HUMAN_INTERVENTION",
63+
"SUBMITTING",
64+
"COMPLETED",
65+
"EXPIRED",
66+
]
67+
] = None
68+
"""The step the flow reached. Present for login/reauth events."""
69+
70+
updated_at: Optional[datetime] = None
71+
"""When the event was last updated. Present for login/reauth events."""
72+
73+
website_error: Optional[str] = None
74+
"""Visible error message from the website (e.g., 'Incorrect password').
75+
76+
Present when the website displayed an error during the attempt.
77+
"""

0 commit comments

Comments
 (0)