Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.124.0"
".": "0.125.0"
}
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## [0.125.0](https://github.com/kernel/kernel-python-sdk/compare/v0.124.0...v0.125.0) (2026-10-13)


### Features

* chore(stlc): seal custom-code tracking files ([a77f648](https://github.com/kernel/kernel-python-sdk/commit/a77f648fb68c7b4e6f93826238e9ac21ab39a4dd))

## [0.124.0](https://github.com/kernel/kernel-python-sdk/compare/v0.123.0...v0.124.0) (2026-10-13)


Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "kernel"
version = "0.124.0"
version = "0.125.0"
description = "The official Python library for the kernel API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion src/kernel/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "kernel"
__version__ = "0.124.0" # x-release-please-version
__version__ = "0.125.0" # x-release-please-version
41 changes: 34 additions & 7 deletions src/kernel/resources/api_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

from __future__ import annotations

from typing import Optional
from typing import Union, Optional
from datetime import datetime
from typing_extensions import Literal

import httpx
Expand Down Expand Up @@ -59,6 +60,8 @@ def create(
*,
name: str,
days_to_expire: Optional[int] | Omit = omit,
expires_at: Union[str, datetime, None] | Omit = omit,
policy: api_key_create_params.Policy | Omit = omit,
project_id: Optional[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
Expand All @@ -67,13 +70,22 @@ def create(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> CreatedAPIKey:
"""
Create a new API key within the authenticated organization.
"""Create a new API key.

API keys may be scoped by project and may include a
policy.

Args:
name: Label for the API key (1-255 characters). API keys are not addressable by name.

days_to_expire: Number of days until expiry, up to 3650. Use null for never.
days_to_expire: Number of days until expiry, up to 3650. Use null for never. Cannot be combined
with expires_at.

expires_at: Exact expiry time. Must be in the future and no later than the issuing
credential's own expiry. Cannot be combined with days_to_expire.

policy: Issue a scoped key that may only perform the listed actions on the listed
resources.

project_id: Unique project identifier

Expand All @@ -91,6 +103,8 @@ def create(
{
"name": name,
"days_to_expire": days_to_expire,
"expires_at": expires_at,
"policy": policy,
"project_id": project_id,
},
api_key_create_params.APIKeyCreateParams,
Expand Down Expand Up @@ -377,6 +391,8 @@ async def create(
*,
name: str,
days_to_expire: Optional[int] | Omit = omit,
expires_at: Union[str, datetime, None] | Omit = omit,
policy: api_key_create_params.Policy | Omit = omit,
project_id: Optional[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
Expand All @@ -385,13 +401,22 @@ async def create(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> CreatedAPIKey:
"""
Create a new API key within the authenticated organization.
"""Create a new API key.

API keys may be scoped by project and may include a
policy.

Args:
name: Label for the API key (1-255 characters). API keys are not addressable by name.

days_to_expire: Number of days until expiry, up to 3650. Use null for never.
days_to_expire: Number of days until expiry, up to 3650. Use null for never. Cannot be combined
with expires_at.

expires_at: Exact expiry time. Must be in the future and no later than the issuing
credential's own expiry. Cannot be combined with days_to_expire.

policy: Issue a scoped key that may only perform the listed actions on the listed
resources.

project_id: Unique project identifier

Expand All @@ -409,6 +434,8 @@ async def create(
{
"name": name,
"days_to_expire": days_to_expire,
"expires_at": expires_at,
"policy": policy,
"project_id": project_id,
},
api_key_create_params.APIKeyCreateParams,
Expand Down
32 changes: 30 additions & 2 deletions src/kernel/types/api_key.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from typing import Optional
from typing import List, Optional
from datetime import datetime

from .._models import BaseModel

__all__ = ["APIKey", "CreatedBy"]
__all__ = ["APIKey", "CreatedBy", "Policy", "PolicyStatement"]


class CreatedBy(BaseModel):
Expand All @@ -19,6 +19,27 @@ class CreatedBy(BaseModel):
"""Display name of the creator, if available."""


class PolicyStatement(BaseModel):
action: str
"""Permitted action, such as browsers:use or vaults:read."""

resource: str
"""Resource the action applies to, in the format projects/{project_id}/{kind}/{id}.

Wildcards are supported.
"""


class Policy(BaseModel):
"""Permissions granted to a scoped API key.

Absent for an ordinary key, which keeps unrestricted access within its organization or project.
"""

statements: List[PolicyStatement]
"""Allow statements. Every action and resource not listed is denied."""


class APIKey(BaseModel):
id: str
"""Unique API key identifier"""
Expand Down Expand Up @@ -55,3 +76,10 @@ class APIKey(BaseModel):

Null means the key is org-wide or the project name is unavailable.
"""

policy: Optional[Policy] = None
"""Permissions granted to a scoped API key.

Absent for an ordinary key, which keeps unrestricted access within its
organization or project.
"""
47 changes: 43 additions & 4 deletions src/kernel/types/api_key_create_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,57 @@

from __future__ import annotations

from typing import Optional
from typing_extensions import Required, TypedDict
from typing import Union, Iterable, Optional
from datetime import datetime
from typing_extensions import Required, Annotated, TypedDict

__all__ = ["APIKeyCreateParams"]
from .._utils import PropertyInfo

__all__ = ["APIKeyCreateParams", "Policy", "PolicyStatement"]


class APIKeyCreateParams(TypedDict, total=False):
name: Required[str]
"""Label for the API key (1-255 characters). API keys are not addressable by name."""

days_to_expire: Optional[int]
"""Number of days until expiry, up to 3650. Use null for never."""
"""Number of days until expiry, up to 3650.

Use null for never. Cannot be combined with expires_at.
"""

expires_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
"""Exact expiry time.

Must be in the future and no later than the issuing credential's own expiry.
Cannot be combined with days_to_expire.
"""

policy: Policy
"""
Issue a scoped key that may only perform the listed actions on the listed
resources.
"""

project_id: Optional[str]
"""Unique project identifier"""


class PolicyStatement(TypedDict, total=False):
action: Required[str]
"""Permitted action, such as browsers:use or vaults:read."""

resource: Required[str]
"""Resource the action applies to, in the format projects/{project_id}/{kind}/{id}.

Wildcards are supported.
"""


class Policy(TypedDict, total=False):
"""
Issue a scoped key that may only perform the listed actions on the listed resources.
"""

statements: Required[Iterable[PolicyStatement]]
"""Allow statements. Every action and resource not listed is denied."""
19 changes: 19 additions & 0 deletions tests/api_resources/test_api_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
APIKey,
CreatedAPIKey,
)
from kernel._utils import parse_datetime
from kernel.pagination import SyncOffsetPagination, AsyncOffsetPagination

base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
Expand All @@ -35,6 +36,15 @@ def test_method_create_with_all_params(self, client: Kernel) -> None:
api_key = client.api_keys.create(
name="staging",
days_to_expire=30,
expires_at=parse_datetime("2025-01-15T09:00:00Z"),
policy={
"statements": [
{
"action": "browsers:use",
"resource": "projects/proj_abc123/browsers/br_abc123",
}
]
},
project_id="proj_abc123",
)
assert_matches_type(CreatedAPIKey, api_key, path=["response"])
Expand Down Expand Up @@ -319,6 +329,15 @@ async def test_method_create_with_all_params(self, async_client: AsyncKernel) ->
api_key = await async_client.api_keys.create(
name="staging",
days_to_expire=30,
expires_at=parse_datetime("2025-01-15T09:00:00Z"),
policy={
"statements": [
{
"action": "browsers:use",
"resource": "projects/proj_abc123/browsers/br_abc123",
}
]
},
project_id="proj_abc123",
)
assert_matches_type(CreatedAPIKey, api_key, path=["response"])
Expand Down
Loading