diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c37434e9..2969a756 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.110.0" + ".": "0.111.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 67530bf8..d3456d14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [0.111.0](https://github.com/kernel/kernel-python-sdk/compare/v0.110.0...v0.111.0) (2026-09-21) + + +### Features + +* Allow managed auth logins to disable learned skills ([e230ce3](https://github.com/kernel/kernel-python-sdk/commit/e230ce3a684ce7723256170443ba0b84b08310a4)) +* Distinguish optimistic managed auth reauth ([41059ae](https://github.com/kernel/kernel-python-sdk/commit/41059ae6d345b924d7e508e43a8b1d0842c58556)) +* Persist stable managed auth completion timestamps ([17a7960](https://github.com/kernel/kernel-python-sdk/commit/17a7960d9304fdceb54d59b09277651b6166fdb1)) +* Publish restricted_route_unavailable and unknown proxy_error codes ([64805ae](https://github.com/kernel/kernel-python-sdk/commit/64805ae68f0978264fb77801e8e94a470a039e94)) +* Support native prepared Adyen Sessions checkout ([5f2df0a](https://github.com/kernel/kernel-python-sdk/commit/5f2df0a4170aa146eabb23f576195d1a06621925)) + ## [0.110.0](https://github.com/kernel/kernel-python-sdk/compare/v0.109.0...v0.110.0) (2026-09-18) diff --git a/pyproject.toml b/pyproject.toml index ef25af35..c8bc1630 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.110.0" +version = "0.111.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 78e78477..bd2462d5 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.110.0" # x-release-please-version +__version__ = "0.111.0" # x-release-please-version diff --git a/src/kernel/resources/auth/connections.py b/src/kernel/resources/auth/connections.py index 62858fdd..fae767b7 100644 --- a/src/kernel/resources/auth/connections.py +++ b/src/kernel/resources/auth/connections.py @@ -477,6 +477,7 @@ def login( browser_telemetry: Optional[connection_login_params.BrowserTelemetry] | Omit = omit, proxy: connection_login_params.Proxy | Omit = omit, record_session: bool | Omit = omit, + skill_mode: Literal["enabled", "disabled"] | 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. extra_headers: Headers | None = None, @@ -502,6 +503,10 @@ def login( record_session: Override the connection's default for recording this login's browser session. When omitted, the connection's record_session default is used. + skill_mode: Controls whether this login reads and writes learned domain skills. Automatic + reauths inherit the selected mode until a later accepted login sets enabled or + omits this field. Defaults to enabled when omitted. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -520,6 +525,7 @@ def login( "browser_telemetry": browser_telemetry, "proxy": proxy, "record_session": record_session, + "skill_mode": skill_mode, }, connection_login_params.ConnectionLoginParams, ), @@ -1100,6 +1106,7 @@ async def login( browser_telemetry: Optional[connection_login_params.BrowserTelemetry] | Omit = omit, proxy: connection_login_params.Proxy | Omit = omit, record_session: bool | Omit = omit, + skill_mode: Literal["enabled", "disabled"] | 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. extra_headers: Headers | None = None, @@ -1125,6 +1132,10 @@ async def login( record_session: Override the connection's default for recording this login's browser session. When omitted, the connection's record_session default is used. + skill_mode: Controls whether this login reads and writes learned domain skills. Automatic + reauths inherit the selected mode until a later accepted login sets enabled or + omits this field. Defaults to enabled when omitted. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1143,6 +1154,7 @@ async def login( "browser_telemetry": browser_telemetry, "proxy": proxy, "record_session": record_session, + "skill_mode": skill_mode, }, connection_login_params.ConnectionLoginParams, ), diff --git a/src/kernel/resources/vaults/items.py b/src/kernel/resources/vaults/items.py index a9058c09..acaf0315 100644 --- a/src/kernel/resources/vaults/items.py +++ b/src/kernel/resources/vaults/items.py @@ -517,7 +517,7 @@ def perform_operation( leave the outcome unknown; do not automatically retry. Args: - checkout: Required when preparing an unused AgentCard card for a supported tokenization + checkout: Required when preparing an unused AgentCard card for a supported checkout processor. Consent is bound to this browser and declared merchant origin, not a tab. Wait for the item's ready_to_submit status before native Pay and submit within its readiness deadline. Unused preparations expire automatically; every @@ -1290,7 +1290,7 @@ async def perform_operation( leave the outcome unknown; do not automatically retry. Args: - checkout: Required when preparing an unused AgentCard card for a supported tokenization + checkout: Required when preparing an unused AgentCard card for a supported checkout processor. Consent is bound to this browser and declared merchant origin, not a tab. Wait for the item's ready_to_submit status before native Pay and submit within its readiness deadline. Unused preparations expire automatically; every diff --git a/src/kernel/types/auth/connection_login_params.py b/src/kernel/types/auth/connection_login_params.py index cbe2bf3b..0d62506d 100644 --- a/src/kernel/types/auth/connection_login_params.py +++ b/src/kernel/types/auth/connection_login_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Optional -from typing_extensions import TypedDict +from typing_extensions import Literal, TypedDict from .managed_auth_browser_config_param import ManagedAuthBrowserConfigParam from ..browsers.browser_telemetry_categories_config_param import BrowserTelemetryCategoriesConfigParam @@ -40,6 +40,13 @@ class ConnectionLoginParams(TypedDict, total=False): When omitted, the connection's record_session default is used. """ + skill_mode: Literal["enabled", "disabled"] + """Controls whether this login reads and writes learned domain skills. + + Automatic reauths inherit the selected mode until a later accepted login sets + enabled or omits this field. Defaults to enabled when omitted. + """ + class BrowserTelemetryExportOtlpDestination(TypedDict, total=False): """OTLP destination to export this session's captured telemetry to. diff --git a/src/kernel/types/auth/managed_auth.py b/src/kernel/types/auth/managed_auth.py index 62fa7852..be202e61 100644 --- a/src/kernel/types/auth/managed_auth.py +++ b/src/kernel/types/auth/managed_auth.py @@ -367,10 +367,12 @@ class ManagedAuth(BaseModel): can_reauth: Optional[bool] = None """ - Whether Kernel can automatically re-authenticate this connection when the - session expires. Requires a prior successful login plus either a Kernel - credential or an external credential reference. See `can_reauth_reason` for the - specific outcome. + Whether this connection's stored requirements are eligible for unattended + re-authentication. A true value can represent either fully satisfiable + requirements or a best-effort attempt. It does not account for whether automatic + re-authentication is enabled or parent workflow state such as an active flow or + circuit-breaker cooldown, so it does not guarantee an attempt on the next health + check. See `can_reauth_reason` for the specific outcome. """ can_reauth_reason: Optional[ @@ -381,6 +383,7 @@ class ManagedAuth(BaseModel): "viable_plans_found", "no_requirements_recorded", "totp_reauth_allowed", + "optimistic_totp_attempt", "requirements_satisfiable", "no_prior_successful_login", "no_credential", @@ -395,7 +398,7 @@ class ManagedAuth(BaseModel): ] = None """ Machine-readable reason for the current value of `can_reauth`. Affirmative - values (re-auth is possible): + values (requirements are eligible for unattended re-authentication): - `external_credential` — an external credential provider is attached - `cua_has_credential` — CUA flow with a stored credential @@ -404,8 +407,12 @@ class ManagedAuth(BaseModel): - `viable_plans_found` — at least one stored login plan can be replayed - `no_requirements_recorded` — no recorded credential requirements to fail against - - `totp_reauth_allowed` — TOTP is the only recorded requirement and is safe to - attempt automatically + - `totp_reauth_allowed` — TOTP is the only recorded requirement and a stored + secret can generate the code + - `optimistic_totp_attempt` — TOTP was previously required but no reusable + secret is stored; the connection remains eligible for a + circuit-breaker-bounded attempt because the site may not challenge returning + sessions - `requirements_satisfiable` — recorded requirements contain no recognized blocker diff --git a/src/kernel/types/auth/managed_auth_timeline_event.py b/src/kernel/types/auth/managed_auth_timeline_event.py index b2e0213b..79eee70c 100644 --- a/src/kernel/types/auth/managed_auth_timeline_event.py +++ b/src/kernel/types/auth/managed_auth_timeline_event.py @@ -38,6 +38,14 @@ class ManagedAuthTimelineEvent(BaseModel): browser_session_id: Optional[str] = None """Browser session that produced the event, if one was created.""" + completed_at: Optional[datetime] = None + """When the login/reauth attempt first reached a terminal status. + + Stable across retries and subsequent cleanup writes. Absent for in-progress + attempts, health checks, and historical attempts without a recorded completion + time. + """ + error_code: Optional[str] = None """Machine-readable error code. Present when a login/reauth event failed.""" diff --git a/src/kernel/types/browsers/browser_proxy_error_event.py b/src/kernel/types/browsers/browser_proxy_error_event.py index d8c9dd93..5d40f9ed 100644 --- a/src/kernel/types/browsers/browser_proxy_error_event.py +++ b/src/kernel/types/browsers/browser_proxy_error_event.py @@ -22,18 +22,23 @@ class Data(BrowserEventContext): "provider_unreachable", "provider_rejected", "origin_tls_timeout", + "origin_response_incomplete", "proxy_unavailable", + "restricted_route_unavailable", "upstream_timeout", "upstream_dns_failure", "upstream_connect_failed", + "unknown", ] """ Proxy-layer error code: the X-Kernel-Proxy-Error response header value from a branded 5xx error page served by the metro egress host-proxy. Values mirror what the proxy emits: destination_blocked, provider_blacklisted, - provider_unreachable, provider_rejected, origin_tls_timeout, proxy_unavailable, - upstream_timeout, upstream_dns_failure, upstream_connect_failed. Unknown header - values are dropped. + provider_unreachable, provider_rejected, origin_tls_timeout, + origin_response_incomplete, proxy_unavailable, restricted_route_unavailable, + upstream_timeout, upstream_dns_failure, upstream_connect_failed. A header value + the browser image does not recognize is reported as unknown, with the header + value in raw_code. """ request_id: str @@ -45,6 +50,14 @@ class Data(BrowserEventContext): method: Optional[str] = None """HTTP method of the failed request, when known.""" + raw_code: Optional[str] = None + """Sanitized X-Kernel-Proxy-Error header value, present only when code is unknown. + + Surrounding whitespace is removed, the value is lowercased, characters outside + [a-z0-9_] are replaced with \\__, and the result is truncated to at most 64 + characters. + """ + resource_type: Optional[str] = None """CDP Network.ResourceType for the request, when known.""" diff --git a/src/kernel/types/vaults/agentcard_checkout_preparation.py b/src/kernel/types/vaults/agentcard_checkout_preparation.py index 7f9da71f..419f3fdd 100644 --- a/src/kernel/types/vaults/agentcard_checkout_preparation.py +++ b/src/kernel/types/vaults/agentcard_checkout_preparation.py @@ -13,7 +13,7 @@ class AgentcardCheckoutPreparation(BaseModel): """One-use processor-bound checkout preparation. - Keep the approval page open through token handoff. The amount is display-only and does not constrain the merchant's eventual charge. + Keep the approval page open through device handoff, including Adyen encryption. The amount is declared by the caller and does not constrain the merchant's eventual charge. Adyen device approval and browser Authorised responses are not capture or fulfillment evidence. """ browser_id: str diff --git a/src/kernel/types/vaults/agentcard_prepared_processor.py b/src/kernel/types/vaults/agentcard_prepared_processor.py index ebf94c86..41c3c7c2 100644 --- a/src/kernel/types/vaults/agentcard_prepared_processor.py +++ b/src/kernel/types/vaults/agentcard_prepared_processor.py @@ -4,4 +4,4 @@ __all__ = ["AgentcardPreparedProcessor"] -AgentcardPreparedProcessor: TypeAlias = Literal["square", "braintree", "worldpay", "bambora", "mercado_pago"] +AgentcardPreparedProcessor: TypeAlias = Literal["square", "braintree", "worldpay", "bambora", "mercado_pago", "adyen"] diff --git a/src/kernel/types/vaults/card_vault_item_state.py b/src/kernel/types/vaults/card_vault_item_state.py index a1cb0b68..df7a4306 100644 --- a/src/kernel/types/vaults/card_vault_item_state.py +++ b/src/kernel/types/vaults/card_vault_item_state.py @@ -117,8 +117,10 @@ class AgentCardCardState(BaseModel): preparation: Optional[AgentcardCheckoutPreparation] = None """One-use processor-bound checkout preparation. - Keep the approval page open through token handoff. The amount is display-only - and does not constrain the merchant's eventual charge. + Keep the approval page open through device handoff, including Adyen encryption. + The amount is declared by the caller and does not constrain the merchant's + eventual charge. Adyen device approval and browser Authorised responses are not + capture or fulfillment evidence. """ status_reason: Optional[str] = None diff --git a/src/kernel/types/vaults/item_perform_operation_params.py b/src/kernel/types/vaults/item_perform_operation_params.py index c1fb80c9..7e866ff3 100644 --- a/src/kernel/types/vaults/item_perform_operation_params.py +++ b/src/kernel/types/vaults/item_perform_operation_params.py @@ -34,7 +34,7 @@ class PrepareCheckoutVaultItemOperationRequest(TypedDict, total=False): checkout: Required[VaultCheckoutContextParam] """ - Required when preparing an unused AgentCard card for a supported tokenization + Required when preparing an unused AgentCard card for a supported checkout processor. Consent is bound to this browser and declared merchant origin, not a tab. Wait for the item's ready_to_submit status before native Pay and submit within its readiness deadline. Unused preparations expire automatically; every diff --git a/src/kernel/types/vaults/prepare_checkout_vault_item_operation_request_param.py b/src/kernel/types/vaults/prepare_checkout_vault_item_operation_request_param.py index 72fdb4d2..73d92e08 100644 --- a/src/kernel/types/vaults/prepare_checkout_vault_item_operation_request_param.py +++ b/src/kernel/types/vaults/prepare_checkout_vault_item_operation_request_param.py @@ -10,14 +10,14 @@ class PrepareCheckoutVaultItemOperationRequestParam(TypedDict, total=False): - """Prepare an unused AgentCard card for a supported tokenization checkout. + """Prepare an unused AgentCard card for a supported checkout. Deliver the returned approval URL and keep the approval page open. Poll the item until ready_to_submit, then submit native Pay before preparation.expires_at. Readiness lasts at most 30 seconds. Unused preparations expire automatically. Preparations are single-use even after failure or expiry; do not automatically retry and reconcile uncertain outcomes with the merchant. """ checkout: Required[VaultCheckoutContextParam] """ - Required when preparing an unused AgentCard card for a supported tokenization + Required when preparing an unused AgentCard card for a supported checkout processor. Consent is bound to this browser and declared merchant origin, not a tab. Wait for the item's ready_to_submit status before native Pay and submit within its readiness deadline. Unused preparations expire automatically; every diff --git a/src/kernel/types/vaults/vault_checkout_context_param.py b/src/kernel/types/vaults/vault_checkout_context_param.py index f5fda5db..545f2dff 100644 --- a/src/kernel/types/vaults/vault_checkout_context_param.py +++ b/src/kernel/types/vaults/vault_checkout_context_param.py @@ -11,7 +11,7 @@ class VaultCheckoutContextParam(TypedDict, total=False): """ - Required when preparing an unused AgentCard card for a supported tokenization processor. Consent is bound to this browser and declared merchant origin, not a tab. Wait for the item's ready_to_submit status before native Pay and submit within its readiness deadline. Unused preparations expire automatically; every preparation is single-use, including after failure or expiry. + Required when preparing an unused AgentCard card for a supported checkout processor. Consent is bound to this browser and declared merchant origin, not a tab. Wait for the item's ready_to_submit status before native Pay and submit within its readiness deadline. Unused preparations expire automatically; every preparation is single-use, including after failure or expiry. """ browser_id: Required[str] @@ -19,8 +19,8 @@ class VaultCheckoutContextParam(TypedDict, total=False): environment: Required[Literal["production", "sandbox", "shared"]] """ - Use production or sandbox for Square, Braintree and Worldpay; shared for Bambora - and Mercado Pago. Shared endpoints do not establish test mode. Merchant + Use production or sandbox for Square, Braintree, Worldpay and Adyen; shared for + Bambora and Mercado Pago. Shared endpoints do not establish test mode. Merchant credentials/configuration determine processor test mode, independently of the AgentCard credential mode. """ @@ -32,8 +32,10 @@ class VaultCheckoutContextParam(TypedDict, total=False): """ psp: AgentcardPreparedProcessor - """Tokenization processor. + """Checkout processor. - Omit for Square compatibility. Non-Square processors require multi-processor - preparation enablement. + Omit for Square compatibility. Adyen supports fresh-card Sessions requests on + Adyen hosts only. Use public dummy card fields, not vault aliases. The unique + armed preparation is associated with the subsequent eligible request from this + browser and declared merchant origin; competing preparations are rejected. """ diff --git a/tests/api_resources/auth/test_connections.py b/tests/api_resources/auth/test_connections.py index 53a55fa7..311b9971 100644 --- a/tests/api_resources/auth/test_connections.py +++ b/tests/api_resources/auth/test_connections.py @@ -525,6 +525,7 @@ def test_method_login_with_all_params(self, client: Kernel) -> None: "name": "name", }, record_session=True, + skill_mode="enabled", ) assert_matches_type(LoginResponse, connection, path=["response"]) @@ -1187,6 +1188,7 @@ async def test_method_login_with_all_params(self, async_client: AsyncKernel) -> "name": "name", }, record_session=True, + skill_mode="enabled", ) assert_matches_type(LoginResponse, connection, path=["response"])