Skip to content

Commit 9c8e9ac

Browse files
feat: Expose audit logs in public SDK
1 parent a0c273b commit 9c8e9ac

10 files changed

Lines changed: 649 additions & 5 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: 122
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d9b82fc5346c9be1bf9c2b18792fdcdec6a80a86153ca765c9e93e597b46fa24.yml
3-
openapi_spec_hash: 9cbaab975acfa421b795d11aa635c57e
4-
config_hash: 99b2b2a25e8067ad9c9214e38e01d64c
1+
configured_endpoints: 123
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-784ee80ab17dd58e4b44292a4732d1669263d9928df5685e2683c59398e7a043.yml
3+
openapi_spec_hash: d34b07cf9549aef3469c82379f526f95
4+
config_hash: d52b040438a187c46050e0e8395b2f47

api.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,18 @@ Methods:
441441
- <code title="get /org/limits">client.organization.limits.<a href="./src/kernel/resources/organization/limits.py">retrieve</a>() -> <a href="./src/kernel/types/organization/org_limits.py">OrgLimits</a></code>
442442
- <code title="patch /org/limits">client.organization.limits.<a href="./src/kernel/resources/organization/limits.py">update</a>(\*\*<a href="src/kernel/types/organization/limit_update_params.py">params</a>) -> <a href="./src/kernel/types/organization/org_limits.py">OrgLimits</a></code>
443443

444+
# AuditLogs
445+
446+
Types:
447+
448+
```python
449+
from kernel.types import AuditLogEntry
450+
```
451+
452+
Methods:
453+
454+
- <code title="get /audit-logs">client.audit_logs.<a href="./src/kernel/resources/audit_logs.py">list</a>(\*\*<a href="src/kernel/types/audit_log_list_params.py">params</a>) -> <a href="./src/kernel/types/audit_log_entry.py">SyncPageTokenPagination[AuditLogEntry]</a></code>
455+
444456
# APIKeys
445457

446458
Types:

src/kernel/_client.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
browsers,
5555
profiles,
5656
projects,
57+
audit_logs,
5758
extensions,
5859
credentials,
5960
deployments,
@@ -67,6 +68,7 @@
6768
from .resources.api_keys import APIKeysResource, AsyncAPIKeysResource
6869
from .resources.profiles import ProfilesResource, AsyncProfilesResource
6970
from .resources.auth.auth import AuthResource, AsyncAuthResource
71+
from .resources.audit_logs import AuditLogsResource, AsyncAuditLogsResource
7072
from .resources.extensions import ExtensionsResource, AsyncExtensionsResource
7173
from .resources.credentials import CredentialsResource, AsyncCredentialsResource
7274
from .resources.deployments import DeploymentsResource, AsyncDeploymentsResource
@@ -275,6 +277,13 @@ def organization(self) -> OrganizationResource:
275277

276278
return OrganizationResource(self)
277279

280+
@cached_property
281+
def audit_logs(self) -> AuditLogsResource:
282+
"""Read audit log records for the authenticated organization."""
283+
from .resources.audit_logs import AuditLogsResource
284+
285+
return AuditLogsResource(self)
286+
278287
@cached_property
279288
def api_keys(self) -> APIKeysResource:
280289
"""Create and manage API keys for organization and project-scoped access."""
@@ -620,6 +629,13 @@ def organization(self) -> AsyncOrganizationResource:
620629

621630
return AsyncOrganizationResource(self)
622631

632+
@cached_property
633+
def audit_logs(self) -> AsyncAuditLogsResource:
634+
"""Read audit log records for the authenticated organization."""
635+
from .resources.audit_logs import AsyncAuditLogsResource
636+
637+
return AsyncAuditLogsResource(self)
638+
623639
@cached_property
624640
def api_keys(self) -> AsyncAPIKeysResource:
625641
"""Create and manage API keys for organization and project-scoped access."""
@@ -873,6 +889,13 @@ def organization(self) -> organization.OrganizationResourceWithRawResponse:
873889

874890
return OrganizationResourceWithRawResponse(self._client.organization)
875891

892+
@cached_property
893+
def audit_logs(self) -> audit_logs.AuditLogsResourceWithRawResponse:
894+
"""Read audit log records for the authenticated organization."""
895+
from .resources.audit_logs import AuditLogsResourceWithRawResponse
896+
897+
return AuditLogsResourceWithRawResponse(self._client.audit_logs)
898+
876899
@cached_property
877900
def api_keys(self) -> api_keys.APIKeysResourceWithRawResponse:
878901
"""Create and manage API keys for organization and project-scoped access."""
@@ -976,6 +999,13 @@ def organization(self) -> organization.AsyncOrganizationResourceWithRawResponse:
976999

9771000
return AsyncOrganizationResourceWithRawResponse(self._client.organization)
9781001

1002+
@cached_property
1003+
def audit_logs(self) -> audit_logs.AsyncAuditLogsResourceWithRawResponse:
1004+
"""Read audit log records for the authenticated organization."""
1005+
from .resources.audit_logs import AsyncAuditLogsResourceWithRawResponse
1006+
1007+
return AsyncAuditLogsResourceWithRawResponse(self._client.audit_logs)
1008+
9791009
@cached_property
9801010
def api_keys(self) -> api_keys.AsyncAPIKeysResourceWithRawResponse:
9811011
"""Create and manage API keys for organization and project-scoped access."""
@@ -1079,6 +1109,13 @@ def organization(self) -> organization.OrganizationResourceWithStreamingResponse
10791109

10801110
return OrganizationResourceWithStreamingResponse(self._client.organization)
10811111

1112+
@cached_property
1113+
def audit_logs(self) -> audit_logs.AuditLogsResourceWithStreamingResponse:
1114+
"""Read audit log records for the authenticated organization."""
1115+
from .resources.audit_logs import AuditLogsResourceWithStreamingResponse
1116+
1117+
return AuditLogsResourceWithStreamingResponse(self._client.audit_logs)
1118+
10821119
@cached_property
10831120
def api_keys(self) -> api_keys.APIKeysResourceWithStreamingResponse:
10841121
"""Create and manage API keys for organization and project-scoped access."""
@@ -1182,6 +1219,13 @@ def organization(self) -> organization.AsyncOrganizationResourceWithStreamingRes
11821219

11831220
return AsyncOrganizationResourceWithStreamingResponse(self._client.organization)
11841221

1222+
@cached_property
1223+
def audit_logs(self) -> audit_logs.AsyncAuditLogsResourceWithStreamingResponse:
1224+
"""Read audit log records for the authenticated organization."""
1225+
from .resources.audit_logs import AsyncAuditLogsResourceWithStreamingResponse
1226+
1227+
return AsyncAuditLogsResourceWithStreamingResponse(self._client.audit_logs)
1228+
11851229
@cached_property
11861230
def api_keys(self) -> api_keys.AsyncAPIKeysResourceWithStreamingResponse:
11871231
"""Create and manage API keys for organization and project-scoped access."""

src/kernel/pagination.py

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,93 @@
99
from ._models import BaseModel
1010
from ._base_client import BasePage, PageInfo, BaseSyncPage, BaseAsyncPage
1111

12-
__all__ = ["SyncOffsetPagination", "AsyncOffsetPagination"]
12+
__all__ = ["SyncPageTokenPagination", "AsyncPageTokenPagination", "SyncOffsetPagination", "AsyncOffsetPagination"]
1313

1414
_BaseModelT = TypeVar("_BaseModelT", bound=BaseModel)
1515

1616
_T = TypeVar("_T")
1717

1818

19+
class SyncPageTokenPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
20+
items: List[_T]
21+
next_page_token: Optional[str] = None
22+
has_more: Optional[bool] = None
23+
24+
@override
25+
def _get_page_items(self) -> List[_T]:
26+
items = self.items
27+
if not items:
28+
return []
29+
return items
30+
31+
@override
32+
def has_next_page(self) -> bool:
33+
has_more = self.has_more
34+
if has_more is not None and has_more is False:
35+
return False
36+
37+
return super().has_next_page()
38+
39+
@override
40+
def next_page_info(self) -> Optional[PageInfo]:
41+
next_page_token = self.next_page_token
42+
if not next_page_token:
43+
return None
44+
45+
return PageInfo(params={"page_token": next_page_token})
46+
47+
@classmethod
48+
def build(cls: Type[_BaseModelT], *, response: Response, data: object) -> _BaseModelT: # noqa: ARG003
49+
return cls.construct(
50+
None,
51+
**{
52+
**(cast(Mapping[str, Any], data) if is_mapping(data) else {"items": data}),
53+
"next_page_token": response.headers.get("X-Next-Page-Token"),
54+
"has_more": maybe_coerce_boolean(response.headers.get("X-Has-More")),
55+
},
56+
)
57+
58+
59+
class AsyncPageTokenPagination(BaseAsyncPage[_T], BasePage[_T], Generic[_T]):
60+
items: List[_T]
61+
next_page_token: Optional[str] = None
62+
has_more: Optional[bool] = None
63+
64+
@override
65+
def _get_page_items(self) -> List[_T]:
66+
items = self.items
67+
if not items:
68+
return []
69+
return items
70+
71+
@override
72+
def has_next_page(self) -> bool:
73+
has_more = self.has_more
74+
if has_more is not None and has_more is False:
75+
return False
76+
77+
return super().has_next_page()
78+
79+
@override
80+
def next_page_info(self) -> Optional[PageInfo]:
81+
next_page_token = self.next_page_token
82+
if not next_page_token:
83+
return None
84+
85+
return PageInfo(params={"page_token": next_page_token})
86+
87+
@classmethod
88+
def build(cls: Type[_BaseModelT], *, response: Response, data: object) -> _BaseModelT: # noqa: ARG003
89+
return cls.construct(
90+
None,
91+
**{
92+
**(cast(Mapping[str, Any], data) if is_mapping(data) else {"items": data}),
93+
"next_page_token": response.headers.get("X-Next-Page-Token"),
94+
"has_more": maybe_coerce_boolean(response.headers.get("X-Has-More")),
95+
},
96+
)
97+
98+
1999
class SyncOffsetPagination(BaseSyncPage[_T], BasePage[_T], Generic[_T]):
20100
items: List[_T]
21101
has_more: Optional[bool] = None

src/kernel/resources/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@
5656
ProjectsResourceWithStreamingResponse,
5757
AsyncProjectsResourceWithStreamingResponse,
5858
)
59+
from .audit_logs import (
60+
AuditLogsResource,
61+
AsyncAuditLogsResource,
62+
AuditLogsResourceWithRawResponse,
63+
AsyncAuditLogsResourceWithRawResponse,
64+
AuditLogsResourceWithStreamingResponse,
65+
AsyncAuditLogsResourceWithStreamingResponse,
66+
)
5967
from .extensions import (
6068
ExtensionsResource,
6169
AsyncExtensionsResource,
@@ -186,6 +194,12 @@
186194
"AsyncOrganizationResourceWithRawResponse",
187195
"OrganizationResourceWithStreamingResponse",
188196
"AsyncOrganizationResourceWithStreamingResponse",
197+
"AuditLogsResource",
198+
"AsyncAuditLogsResource",
199+
"AuditLogsResourceWithRawResponse",
200+
"AsyncAuditLogsResourceWithRawResponse",
201+
"AuditLogsResourceWithStreamingResponse",
202+
"AsyncAuditLogsResourceWithStreamingResponse",
189203
"APIKeysResource",
190204
"AsyncAPIKeysResource",
191205
"APIKeysResourceWithRawResponse",

0 commit comments

Comments
 (0)