diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f61d46c..78b4fb3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.70.0" + ".": "0.71.0" } diff --git a/.stats.yml b/.stats.yml index 2018924..397b820 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 122 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-d9b82fc5346c9be1bf9c2b18792fdcdec6a80a86153ca765c9e93e597b46fa24.yml -openapi_spec_hash: 9cbaab975acfa421b795d11aa635c57e -config_hash: 99b2b2a25e8067ad9c9214e38e01d64c +configured_endpoints: 123 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-ac06dd66a7a0da0dd6dd6cd98127652891b914e880dbaed90d7ab666b13af8a9.yml +openapi_spec_hash: 1d35ae59d6570497f8b379ded59f0434 +config_hash: d52b040438a187c46050e0e8395b2f47 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0847704..d4a8ed2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.71.0 (2026-06-25) + +Full Changelog: [v0.70.0...v0.71.0](https://github.com/kernel/kernel-node-sdk/compare/v0.70.0...v0.71.0) + +### Features + +* Expose audit logs in public SDK ([e08b560](https://github.com/kernel/kernel-node-sdk/commit/e08b560f83fd5532f2e45940dd2b92bdbbe27951)) + ## 0.70.0 (2026-06-24) Full Changelog: [v0.69.0...v0.70.0](https://github.com/kernel/kernel-node-sdk/compare/v0.69.0...v0.70.0) diff --git a/api.md b/api.md index 45d6969..d9a2d96 100644 --- a/api.md +++ b/api.md @@ -393,6 +393,16 @@ Methods: - client.organization.limits.retrieve() -> OrgLimits - client.organization.limits.update({ ...params }) -> OrgLimits +# AuditLogs + +Types: + +- AuditLogEntry + +Methods: + +- client.auditLogs.list({ ...params }) -> AuditLogEntriesPageTokenPagination + # APIKeys Types: diff --git a/package.json b/package.json index ed4c30b..ebf6056 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.70.0", + "version": "0.71.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/client.ts b/src/client.ts index 947e3da..427df47 100644 --- a/src/client.ts +++ b/src/client.ts @@ -15,7 +15,13 @@ import { stringifyQuery } from './internal/utils/query'; import { VERSION } from './version'; import * as Errors from './core/error'; import * as Pagination from './core/pagination'; -import { AbstractPage, type OffsetPaginationParams, OffsetPaginationResponse } from './core/pagination'; +import { + AbstractPage, + type OffsetPaginationParams, + OffsetPaginationResponse, + type PageTokenPaginationParams, + PageTokenPaginationResponse, +} from './core/pagination'; import * as Uploads from './core/uploads'; import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; @@ -36,6 +42,12 @@ import { browserRoutingSubresourcesFromEnv, createRoutingFetch, } from './lib/browser-routing'; +import { + AuditLogEntriesPageTokenPagination, + AuditLogEntry, + AuditLogListParams, + AuditLogs, +} from './resources/audit-logs'; import { BrowserPool, BrowserPoolAcquireParams, @@ -1005,6 +1017,10 @@ export class Kernel { */ projects: API.Projects = new API.Projects(this); organization: API.Organization = new API.Organization(this); + /** + * Read audit log records for the authenticated organization. + */ + auditLogs: API.AuditLogs = new API.AuditLogs(this); /** * Create and manage API keys for organization and project-scoped access. */ @@ -1027,12 +1043,19 @@ Kernel.BrowserPools = BrowserPools; Kernel.Credentials = Credentials; Kernel.Projects = Projects; Kernel.Organization = Organization; +Kernel.AuditLogs = AuditLogs; Kernel.APIKeys = APIKeys; Kernel.CredentialProviders = CredentialProviders; export declare namespace Kernel { export type RequestOptions = Opts.RequestOptions; + export import PageTokenPagination = Pagination.PageTokenPagination; + export { + type PageTokenPaginationParams as PageTokenPaginationParams, + type PageTokenPaginationResponse as PageTokenPaginationResponse, + }; + export import OffsetPagination = Pagination.OffsetPagination; export { type OffsetPaginationParams as OffsetPaginationParams, @@ -1164,6 +1187,13 @@ export declare namespace Kernel { export { Organization as Organization }; + export { + AuditLogs as AuditLogs, + type AuditLogEntry as AuditLogEntry, + type AuditLogEntriesPageTokenPagination as AuditLogEntriesPageTokenPagination, + type AuditLogListParams as AuditLogListParams, + }; + export { APIKeys as APIKeys, type APIKey as APIKey, diff --git a/src/core/pagination.ts b/src/core/pagination.ts index 91bb203..85e1d84 100644 --- a/src/core/pagination.ts +++ b/src/core/pagination.ts @@ -107,6 +107,62 @@ export class PagePromise< } } +export type PageTokenPaginationResponse = Item[]; + +export interface PageTokenPaginationParams { + page_token?: string; + + limit?: number; +} + +export class PageTokenPagination extends AbstractPage { + items: Array; + + next_page_token: string | null; + + has_more: boolean | null; + + constructor( + client: Kernel, + response: Response, + body: PageTokenPaginationResponse, + options: FinalRequestOptions, + ) { + super(client, response, body, options); + + this.items = body || []; + this.next_page_token = this.response.headers.get('x-next-page-token') ?? null; + this.has_more = maybeCoerceBoolean(this.response.headers.get('x-has-more')) ?? null; + } + + getPaginatedItems(): Item[] { + return this.items ?? []; + } + + override hasNextPage(): boolean { + if (this.has_more === false) { + return false; + } + + return super.hasNextPage(); + } + + nextPageRequestOptions(): PageRequestOptions | null { + const cursor = this.next_page_token; + if (!cursor) { + return null; + } + + return { + ...this.options, + query: { + ...maybeObj(this.options.query), + page_token: cursor, + }, + }; + } +} + export type OffsetPaginationResponse = Item[]; export interface OffsetPaginationParams { diff --git a/src/resources/audit-logs.ts b/src/resources/audit-logs.ts new file mode 100644 index 0000000..69366c5 --- /dev/null +++ b/src/resources/audit-logs.ts @@ -0,0 +1,135 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import { PagePromise, PageTokenPagination, type PageTokenPaginationParams } from '../core/pagination'; +import { RequestOptions } from '../internal/request-options'; + +/** + * Read audit log records for the authenticated organization. + */ +export class AuditLogs extends APIResource { + /** + * API for searching audit logs. Limited to at most 30 day search, returns up to + * 100 records per page. Not recommended for bulk export. + */ + list( + query: AuditLogListParams, + options?: RequestOptions, + ): PagePromise { + return this._client.getAPIList('/audit-logs', PageTokenPagination, { query, ...options }); + } +} + +export type AuditLogEntriesPageTokenPagination = PageTokenPagination; + +export interface AuditLogEntry { + /** + * Authentication strategy used for the request. + */ + auth_strategy: string; + + /** + * Client IP address. + */ + client_ip: string; + + /** + * Request host. + */ + domain: string; + + /** + * Request duration in milliseconds. + */ + duration_ms: number; + + /** + * Email of the authenticated user at request time, if any. + */ + email: string; + + /** + * HTTP method. + */ + method: string; + + /** + * Request path. + */ + path: string; + + /** + * Matched API route pattern, if available. + */ + route: string; + + /** + * HTTP response status code. + */ + status: number; + + /** + * UTC time when the request was received. + */ + timestamp: string; + + /** + * User agent header. + */ + user_agent: string; + + /** + * ID of the authenticated user, if any. + */ + user_id: string; +} + +export interface AuditLogListParams extends PageTokenPaginationParams { + /** + * Upper bound (exclusive) for the audit record timestamp. + */ + end: string; + + /** + * Lower bound (inclusive) for the audit record timestamp. + */ + start: string; + + /** + * Filter by authentication strategy. + */ + auth_strategy?: string; + + /** + * Filter out results by HTTP method. + */ + exclude_method?: string; + + /** + * Filter by HTTP method. + */ + method?: string; + + /** + * Free-text search over path, user ID, email, client IP, and status. + */ + search?: string; + + /** + * Additional user IDs to OR into free-text search. + */ + search_user_id?: Array; + + /** + * Filter by service name. + */ + service?: string; +} + +export declare namespace AuditLogs { + export { + type AuditLogEntry as AuditLogEntry, + type AuditLogEntriesPageTokenPagination as AuditLogEntriesPageTokenPagination, + type AuditLogListParams as AuditLogListParams, + }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index edbee05..4704f6a 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -18,6 +18,12 @@ export { type AppListParams, type AppListResponsesOffsetPagination, } from './apps'; +export { + AuditLogs, + type AuditLogEntry, + type AuditLogListParams, + type AuditLogEntriesPageTokenPagination, +} from './audit-logs'; export { Auth } from './auth/auth'; export { BrowserPools, diff --git a/src/version.ts b/src/version.ts index 9d083b8..5f6b920 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.70.0'; // x-release-please-version +export const VERSION = '0.71.0'; // x-release-please-version diff --git a/tests/api-resources/audit-logs.test.ts b/tests/api-resources/audit-logs.test.ts new file mode 100644 index 0000000..833cbe1 --- /dev/null +++ b/tests/api-resources/audit-logs.test.ts @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import Kernel from '@onkernel/sdk'; + +const client = new Kernel({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource auditLogs', () => { + // Mock server tests are disabled + test.skip('list: only required params', async () => { + const responsePromise = client.auditLogs.list({ + end: '2026-01-02T00:00:00Z', + start: '2026-01-01T00:00:00Z', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Mock server tests are disabled + test.skip('list: required and optional params', async () => { + const response = await client.auditLogs.list({ + end: '2026-01-02T00:00:00Z', + start: '2026-01-01T00:00:00Z', + auth_strategy: 'auth_strategy', + exclude_method: 'exclude_method', + limit: 1, + method: 'method', + page_token: 'page_token', + search: 'search', + search_user_id: ['string'], + service: 'service', + }); + }); +});