From 1c3b388f1a4597f65ed3926a8ec2646f5e0fc994 Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Sat, 5 Sep 2026 18:39:11 +0000 Subject: [PATCH 1/5] feat: Expose vault access in organization entitlements Stainless-Generated-From: 0553bf6048bcef35a58d4c3536f16301fa5ed99a --- .../types/organization/org_entitlements.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/kernel/types/organization/org_entitlements.py b/src/kernel/types/organization/org_entitlements.py index c940cbef..ed13dcc8 100644 --- a/src/kernel/types/organization/org_entitlements.py +++ b/src/kernel/types/organization/org_entitlements.py @@ -21,6 +21,7 @@ "FeaturesManagedProxies", "FeaturesProfiles", "FeaturesProxyBypassHosts", + "FeaturesVaults", "Limits", "Plan", ] @@ -114,6 +115,15 @@ class FeaturesProxyBypassHosts(BaseModel): """Whether the organization is entitled to use this feature.""" +class FeaturesVaults(BaseModel): + """ + Whether the organization can access vaults, using the same access check as vault API routes. + """ + + enabled: bool + """Whether the organization is entitled to use this feature.""" + + class Features(BaseModel): browser_extensions: FeaturesBrowserExtensions @@ -139,6 +149,12 @@ class Features(BaseModel): proxy_bypass_hosts: FeaturesProxyBypassHosts + vaults: FeaturesVaults + """ + Whether the organization can access vaults, using the same access check as vault + API routes. + """ + class Limits(BaseModel): default_max_concurrent_invocations_per_app: int From b0d5628acbe0a9d9d006a3349ba1338fdc3d4402 Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Sat, 5 Sep 2026 20:21:54 +0000 Subject: [PATCH 2/5] feat: Limit free organizations to three vaults Stainless-Generated-From: ba7e1af409ddd0c708f01417cc714eb89c3739f0 --- src/kernel/resources/organization/limits.py | 4 ++-- src/kernel/resources/vaults/vaults.py | 8 ++++++-- src/kernel/types/organization/org_entitlements.py | 6 ++++++ src/kernel/types/organization/org_limits.py | 9 +++++++++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/kernel/resources/organization/limits.py b/src/kernel/resources/organization/limits.py index d1bb6ecb..9dcd9dbb 100644 --- a/src/kernel/resources/organization/limits.py +++ b/src/kernel/resources/organization/limits.py @@ -55,7 +55,7 @@ def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OrgLimits: - """Get the organization's effective limits and managed auth usage.""" + """Get the organization's effective limits and managed auth and vault usage.""" return self._get( "/org/limits", options=make_request_options( @@ -138,7 +138,7 @@ async def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> OrgLimits: - """Get the organization's effective limits and managed auth usage.""" + """Get the organization's effective limits and managed auth and vault usage.""" return await self._get( "/org/limits", options=make_request_options( diff --git a/src/kernel/resources/vaults/vaults.py b/src/kernel/resources/vaults/vaults.py index ec33277c..f88ac5f1 100644 --- a/src/kernel/resources/vaults/vaults.py +++ b/src/kernel/resources/vaults/vaults.py @@ -176,7 +176,9 @@ def upsert( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Vault: """ - Create or retrieve a vault by immutable name + Free organizations can store up to 3 non-deleted vaults across all projects. + Paid plans and active trials have no vault cap. Retrieving an existing vault by + name succeeds even at the limit. Args: name: Immutable name used to create or retrieve the vault. @@ -345,7 +347,9 @@ async def upsert( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> Vault: """ - Create or retrieve a vault by immutable name + Free organizations can store up to 3 non-deleted vaults across all projects. + Paid plans and active trials have no vault cap. Retrieving an existing vault by + name succeeds even at the limit. Args: name: Immutable name used to create or retrieve the vault. diff --git a/src/kernel/types/organization/org_entitlements.py b/src/kernel/types/organization/org_entitlements.py index ed13dcc8..614ce2fa 100644 --- a/src/kernel/types/organization/org_entitlements.py +++ b/src/kernel/types/organization/org_entitlements.py @@ -172,6 +172,12 @@ class Limits(BaseModel): max_concurrent_invocations: int """Effective organization-wide concurrent app invocation ceiling.""" + max_vaults: Optional[int] = None + """Maximum non-deleted vaults allowed org-wide across all projects. + + Null means unlimited. The vaults feature flag still controls access. + """ + class Plan(BaseModel): id: Literal["FREE", "HOBBYIST", "START_UP", "ENTERPRISE"] diff --git a/src/kernel/types/organization/org_limits.py b/src/kernel/types/organization/org_limits.py index bdc3cb4a..4e24a5f0 100644 --- a/src/kernel/types/organization/org_limits.py +++ b/src/kernel/types/organization/org_limits.py @@ -22,6 +22,12 @@ class OrgLimits(BaseModel): projects. """ + max_vaults: Optional[int] = None + """Maximum non-deleted vaults allowed org-wide across all projects. + + Null means unlimited. + """ + min_health_check_interval_seconds: int """ Smallest health_check_interval the organization's plan accepts on a managed auth @@ -29,6 +35,9 @@ class OrgLimits(BaseModel): stored below the floor are grandfathered until edited. """ + vaults_used: int + """Current non-deleted vault count across all projects in the organization.""" + default_project_max_concurrent_sessions: Optional[int] = None """ Default maximum concurrent browsers applied to every project that has no From e0d9d715689585224cde848845ebaed90c404f64 Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2026 17:00:40 +0000 Subject: [PATCH 3/5] feat: Add config analysis lifecycle guarantees Stainless-Generated-From: 3a35e0b87b6364867c5a45f32039f9448f234afd --- src/kernel/types/analysis.py | 7 +++++-- src/kernel/types/recommendation_summary.py | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/kernel/types/analysis.py b/src/kernel/types/analysis.py index 9bce3019..34184ae4 100644 --- a/src/kernel/types/analysis.py +++ b/src/kernel/types/analysis.py @@ -17,8 +17,11 @@ class Analysis(BaseModel): created_at: datetime """Time the analysis was created.""" + expires_at: datetime + """Deadline after which a still-running analysis becomes expired.""" + failure: Optional[ErrorModel] = None - """Present for failed or canceled analyses. + """Present for failed, canceled, or expired analyses. Messages contain safe retry guidance rather than internal workflow errors. """ @@ -26,5 +29,5 @@ class Analysis(BaseModel): finished_at: Optional[datetime] = None """Time the analysis reached a terminal status. Null while it is running.""" - status: Literal["running", "completed", "failed", "canceled"] + status: Literal["running", "completed", "failed", "canceled", "expired"] """Lifecycle status of a background analysis.""" diff --git a/src/kernel/types/recommendation_summary.py b/src/kernel/types/recommendation_summary.py index 278ba9ef..5716ae60 100644 --- a/src/kernel/types/recommendation_summary.py +++ b/src/kernel/types/recommendation_summary.py @@ -14,7 +14,7 @@ class RecommendationSummary(BaseModel): analysis_id: str """ID of the most recently requested analysis for this exact target.""" - analysis_status: Literal["running", "completed", "failed", "canceled"] + analysis_status: Literal["running", "completed", "failed", "canceled", "expired"] """Lifecycle status of the most recently requested analysis for this exact target.""" last_requested_at: datetime From 78adb8a4ae929028497e30b0a5988050eee7c1f4 Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2026 23:53:58 +0000 Subject: [PATCH 4/5] feat: Support international ISP proxy countries Stainless-Generated-From: 3cb3f808b95f723b62071d2e57647368fd68baae --- src/kernel/types/proxy.py | 5 ++++- src/kernel/types/proxy_check_response.py | 5 ++++- src/kernel/types/proxy_create_params.py | 5 ++++- src/kernel/types/proxy_create_response.py | 5 ++++- src/kernel/types/proxy_list_response.py | 5 ++++- src/kernel/types/proxy_retrieve_response.py | 5 ++++- src/kernel/types/proxy_update_response.py | 5 ++++- 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/kernel/types/proxy.py b/src/kernel/types/proxy.py index d5238ad7..53ff0612 100644 --- a/src/kernel/types/proxy.py +++ b/src/kernel/types/proxy.py @@ -37,7 +37,10 @@ class ConfigRegistryManagedProxyCreateConfigIspProxyConfig(BaseModel): """Configuration for an ISP proxy.""" country: Optional[str] = None - """ISO 3166 country code. Defaults to US if not provided.""" + """ISO 3166 country code. + + Supported countries are US, GB, FR, DE, and SG. Defaults to US if not provided. + """ class ConfigRegistryManagedProxyCreateConfigResidentialProxyConfig(BaseModel): diff --git a/src/kernel/types/proxy_check_response.py b/src/kernel/types/proxy_check_response.py index 49833d66..3f3a0467 100644 --- a/src/kernel/types/proxy_check_response.py +++ b/src/kernel/types/proxy_check_response.py @@ -28,7 +28,10 @@ class ConfigIspProxyConfig(BaseModel): """Configuration for an ISP proxy.""" country: Optional[str] = None - """ISO 3166 country code. Defaults to US if not provided.""" + """ISO 3166 country code. + + Supported countries are US, GB, FR, DE, and SG. Defaults to US if not provided. + """ class ConfigResidentialProxyConfig(BaseModel): diff --git a/src/kernel/types/proxy_create_params.py b/src/kernel/types/proxy_create_params.py index 7069d9b1..ed7f413b 100644 --- a/src/kernel/types/proxy_create_params.py +++ b/src/kernel/types/proxy_create_params.py @@ -50,7 +50,10 @@ class ConfigIspProxyConfig(TypedDict, total=False): """Configuration for an ISP proxy.""" country: str - """ISO 3166 country code. Defaults to US if not provided.""" + """ISO 3166 country code. + + Supported countries are US, GB, FR, DE, and SG. Defaults to US if not provided. + """ class ConfigResidentialProxyConfig(TypedDict, total=False): diff --git a/src/kernel/types/proxy_create_response.py b/src/kernel/types/proxy_create_response.py index eeddcc3a..187168a3 100644 --- a/src/kernel/types/proxy_create_response.py +++ b/src/kernel/types/proxy_create_response.py @@ -28,7 +28,10 @@ class ConfigIspProxyConfig(BaseModel): """Configuration for an ISP proxy.""" country: Optional[str] = None - """ISO 3166 country code. Defaults to US if not provided.""" + """ISO 3166 country code. + + Supported countries are US, GB, FR, DE, and SG. Defaults to US if not provided. + """ class ConfigResidentialProxyConfig(BaseModel): diff --git a/src/kernel/types/proxy_list_response.py b/src/kernel/types/proxy_list_response.py index 878ad7f2..1cd6ca18 100644 --- a/src/kernel/types/proxy_list_response.py +++ b/src/kernel/types/proxy_list_response.py @@ -28,7 +28,10 @@ class ConfigIspProxyConfig(BaseModel): """Configuration for an ISP proxy.""" country: Optional[str] = None - """ISO 3166 country code. Defaults to US if not provided.""" + """ISO 3166 country code. + + Supported countries are US, GB, FR, DE, and SG. Defaults to US if not provided. + """ class ConfigResidentialProxyConfig(BaseModel): diff --git a/src/kernel/types/proxy_retrieve_response.py b/src/kernel/types/proxy_retrieve_response.py index f2eb1487..349ee91b 100644 --- a/src/kernel/types/proxy_retrieve_response.py +++ b/src/kernel/types/proxy_retrieve_response.py @@ -28,7 +28,10 @@ class ConfigIspProxyConfig(BaseModel): """Configuration for an ISP proxy.""" country: Optional[str] = None - """ISO 3166 country code. Defaults to US if not provided.""" + """ISO 3166 country code. + + Supported countries are US, GB, FR, DE, and SG. Defaults to US if not provided. + """ class ConfigResidentialProxyConfig(BaseModel): diff --git a/src/kernel/types/proxy_update_response.py b/src/kernel/types/proxy_update_response.py index bae95bba..7dcd14aa 100644 --- a/src/kernel/types/proxy_update_response.py +++ b/src/kernel/types/proxy_update_response.py @@ -28,7 +28,10 @@ class ConfigIspProxyConfig(BaseModel): """Configuration for an ISP proxy.""" country: Optional[str] = None - """ISO 3166 country code. Defaults to US if not provided.""" + """ISO 3166 country code. + + Supported countries are US, GB, FR, DE, and SG. Defaults to US if not provided. + """ class ConfigResidentialProxyConfig(BaseModel): From 3a72c2aeef98f9e62b2e38eb8ea2e94b86abdef8 Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2026 23:58:27 +0000 Subject: [PATCH 5/5] release: 0.101.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 10 ++++++++++ pyproject.toml | 2 +- src/kernel/_version.py | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 97d8dbba..aebbc8bc 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.100.0" + ".": "0.101.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a14e35a..fc247ce2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [0.101.0](https://github.com/kernel/kernel-python-sdk/compare/v0.100.0...v0.101.0) (2026-09-09) + + +### Features + +* Add config analysis lifecycle guarantees ([e0d9d71](https://github.com/kernel/kernel-python-sdk/commit/e0d9d715689585224cde848845ebaed90c404f64)) +* Expose vault access in organization entitlements ([1c3b388](https://github.com/kernel/kernel-python-sdk/commit/1c3b388f1a4597f65ed3926a8ec2646f5e0fc994)) +* Limit free organizations to three vaults ([b0d5628](https://github.com/kernel/kernel-python-sdk/commit/b0d5628acbe0a9d9d006a3349ba1338fdc3d4402)) +* Support international ISP proxy countries ([78adb8a](https://github.com/kernel/kernel-python-sdk/commit/78adb8a4ae929028497e30b0a5988050eee7c1f4)) + ## [0.100.0](https://github.com/kernel/kernel-python-sdk/compare/v0.99.0...v0.100.0) (2026-09-04) diff --git a/pyproject.toml b/pyproject.toml index 84718a85..ce24d358 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.100.0" +version = "0.101.0" description = "The official Python library for the kernel API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/kernel/_version.py b/src/kernel/_version.py index 2fba39cd..058933d0 100644 --- a/src/kernel/_version.py +++ b/src/kernel/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "kernel" -__version__ = "0.100.0" # x-release-please-version +__version__ = "0.101.0" # x-release-please-version