diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f38100a4..47775e91 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.126.0" + ".": "0.127.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d69a64ae..dcd39316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [0.127.0](https://github.com/kernel/kernel-python-sdk/compare/v0.126.0...v0.127.0) (2026-10-16) + + +### Features + +* Add atomic preconditions to pool network updates ([9869c91](https://github.com/kernel/kernel-python-sdk/commit/9869c911414a8be186a1a64682487fd38423fb92)) +* Add passkey credential fields and PATCH field add/remove ([84a69ad](https://github.com/kernel/kernel-python-sdk/commit/84a69ad74c46ddcdd87acd88a23dd5330adf555b)) +* Allow replacing vault cards whose provider outcome is unknown ([30f88e1](https://github.com/kernel/kernel-python-sdk/commit/30f88e18b045f3fedbe1bd79d3125db105dd725f)) +* chore(stlc): seal custom-code tracking files ([5a62113](https://github.com/kernel/kernel-python-sdk/commit/5a621135bad2661c79068027773ff32b4e14e0c9)) +* Classify text captchas as token tasks and Binance as a provider ([84f71b8](https://github.com/kernel/kernel-python-sdk/commit/84f71b89f84dea25464cbc22ed92786d73083419)) +* Deliver Kernel card details through fill ([eed3e7b](https://github.com/kernel/kernel-python-sdk/commit/eed3e7ba06c46d3cfa6048d9f02c3d8fff6046e6)) +* Raise Kernel card amount cap to $10,000 ([483f331](https://github.com/kernel/kernel-python-sdk/commit/483f3312824d07e5f315afe0ce5058d4fc4a6e99)) +* Remove Link expires_at, return 400 for missing credential values, and log fill failures ([766dd6e](https://github.com/kernel/kernel-python-sdk/commit/766dd6e961fd36f580540a535cad76e659ecafee)) + ## [0.126.0](https://github.com/kernel/kernel-python-sdk/compare/v0.125.0...v0.126.0) (2026-10-14) diff --git a/api.md b/api.md index f5243e5a..33b17d60 100644 --- a/api.md +++ b/api.md @@ -576,6 +576,7 @@ from kernel.types.vaults import ( CredentialAccountVaultItemRequest, CredentialCollectionAction, CredentialVaultFieldDefinition, + CredentialVaultFieldDefinitionInput, CredentialVaultFieldInput, CredentialVaultFieldState, CredentialVaultFieldType, diff --git a/pyproject.toml b/pyproject.toml index e13b78ea..d2de2e3b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.126.0" +version = "0.127.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 20748255..d351e0a2 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.126.0" # x-release-please-version +__version__ = "0.127.0" # x-release-please-version diff --git a/src/kernel/resources/browser_pools.py b/src/kernel/resources/browser_pools.py index 645c0d27..61ad0977 100644 --- a/src/kernel/resources/browser_pools.py +++ b/src/kernel/resources/browser_pools.py @@ -119,7 +119,8 @@ def create( kiosk_mode: If true, launches the browser in kiosk mode to hide address bar and tabs in live view. Defaults to false. - memory: Memory requested for headful browsers in this pool. + memory: Memory for browsers in this pool. Headless: 1GiB (default), 2GiB, or 4GiB. + Headful: 8GiB (default) or 16GiB. name: Optional name for the browser pool. Must be unique within the project. @@ -254,11 +255,12 @@ def update( *, chrome_policy: Dict[str, object] | Omit = omit, discard_all_idle: bool | Omit = omit, + expected_network: BrowserNetworkConfigParam | Omit = omit, extensions: Iterable[BrowserExtension] | Omit = omit, fill_rate_per_minute: int | Omit = omit, headless: bool | Omit = omit, kiosk_mode: bool | Omit = omit, - memory: Literal["8GiB", "16GiB"] | Omit = omit, + memory: Literal["1GiB", "2GiB", "4GiB", "8GiB", "16GiB"] | Omit = omit, name: str | Omit = omit, network: BrowserNetworkConfigParam | Omit = omit, profile: browser_pool_update_params.Profile | Omit = omit, @@ -302,6 +304,13 @@ def update( configuration until it is discarded (by this flag on a later update, or by flushing the pool). + expected_network: Optional optimistic concurrency precondition. Send the network configuration + from the last pool response, or {} when it has no network configuration. The + entire update is rejected with 409 stale_network if the saved network differs, + checked atomically with the write. Omit for unconditional updates. Explicit + empty lists differ from omitted lists; route targets must match the saved + references (resolved IDs, not equivalent proxy names). + extensions: If provided, replaces the extension list. Empty array clears all previously-selected extensions. Omit this field to leave extensions unchanged. @@ -313,9 +322,9 @@ def update( kiosk_mode: If provided, replaces whether browsers launch in kiosk mode. - memory: Memory requested for newly-warmed headful browsers in this pool. Existing - browsers retain their original allocation. Use discard_all_idle to replace idle - browsers. + memory: Memory requested for newly-warmed browsers in this pool: 1GiB, 2GiB, or 4GiB for + headless, 8GiB or 16GiB for headful. Existing browsers retain their original + allocation. Use discard_all_idle to replace idle browsers. name: If provided, replaces the pool name. Empty string is a no-op; the pool name cannot be cleared or reset to empty once assigned. @@ -397,6 +406,7 @@ def update( { "chrome_policy": chrome_policy, "discard_all_idle": discard_all_idle, + "expected_network": expected_network, "extensions": extensions, "fill_rate_per_minute": fill_rate_per_minute, "headless": headless, @@ -776,7 +786,8 @@ async def create( kiosk_mode: If true, launches the browser in kiosk mode to hide address bar and tabs in live view. Defaults to false. - memory: Memory requested for headful browsers in this pool. + memory: Memory for browsers in this pool. Headless: 1GiB (default), 2GiB, or 4GiB. + Headful: 8GiB (default) or 16GiB. name: Optional name for the browser pool. Must be unique within the project. @@ -911,11 +922,12 @@ async def update( *, chrome_policy: Dict[str, object] | Omit = omit, discard_all_idle: bool | Omit = omit, + expected_network: BrowserNetworkConfigParam | Omit = omit, extensions: Iterable[BrowserExtension] | Omit = omit, fill_rate_per_minute: int | Omit = omit, headless: bool | Omit = omit, kiosk_mode: bool | Omit = omit, - memory: Literal["8GiB", "16GiB"] | Omit = omit, + memory: Literal["1GiB", "2GiB", "4GiB", "8GiB", "16GiB"] | Omit = omit, name: str | Omit = omit, network: BrowserNetworkConfigParam | Omit = omit, profile: browser_pool_update_params.Profile | Omit = omit, @@ -959,6 +971,13 @@ async def update( configuration until it is discarded (by this flag on a later update, or by flushing the pool). + expected_network: Optional optimistic concurrency precondition. Send the network configuration + from the last pool response, or {} when it has no network configuration. The + entire update is rejected with 409 stale_network if the saved network differs, + checked atomically with the write. Omit for unconditional updates. Explicit + empty lists differ from omitted lists; route targets must match the saved + references (resolved IDs, not equivalent proxy names). + extensions: If provided, replaces the extension list. Empty array clears all previously-selected extensions. Omit this field to leave extensions unchanged. @@ -970,9 +989,9 @@ async def update( kiosk_mode: If provided, replaces whether browsers launch in kiosk mode. - memory: Memory requested for newly-warmed headful browsers in this pool. Existing - browsers retain their original allocation. Use discard_all_idle to replace idle - browsers. + memory: Memory requested for newly-warmed browsers in this pool: 1GiB, 2GiB, or 4GiB for + headless, 8GiB or 16GiB for headful. Existing browsers retain their original + allocation. Use discard_all_idle to replace idle browsers. name: If provided, replaces the pool name. Empty string is a no-op; the pool name cannot be cleared or reset to empty once assigned. @@ -1054,6 +1073,7 @@ async def update( { "chrome_policy": chrome_policy, "discard_all_idle": discard_all_idle, + "expected_network": expected_network, "extensions": extensions, "fill_rate_per_minute": fill_rate_per_minute, "headless": headless, diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py index ec5f0f42..0333bfdd 100644 --- a/src/kernel/resources/browsers/browsers.py +++ b/src/kernel/resources/browsers/browsers.py @@ -239,7 +239,9 @@ def create( kiosk_mode: If true, launches the browser in kiosk mode to hide address bar and tabs in live view. - memory: Memory for a headful, non-GPU browser session. Defaults to 8GiB. + memory: + Memory for a non-GPU browser. Headless: 1GiB (default), 2GiB, or 4GiB. Headful: + 8GiB (default) or 16GiB. name: Optional human-readable name for the browser session, used to find it later in the dashboard. Must be unique among active sessions within the project. Can be @@ -954,7 +956,9 @@ async def create( kiosk_mode: If true, launches the browser in kiosk mode to hide address bar and tabs in live view. - memory: Memory for a headful, non-GPU browser session. Defaults to 8GiB. + memory: + Memory for a non-GPU browser. Headless: 1GiB (default), 2GiB, or 4GiB. Headful: + 8GiB (default) or 16GiB. name: Optional human-readable name for the browser session, used to find it later in the dashboard. Must be unique among active sessions within the project. Can be diff --git a/src/kernel/resources/vaults/items.py b/src/kernel/resources/vaults/items.py index 0cdc5164..209c9e86 100644 --- a/src/kernel/resources/vaults/items.py +++ b/src/kernel/resources/vaults/items.py @@ -154,10 +154,10 @@ def update( request, subject to atomic provider approval checks; omitted optional fields remain unchanged and explicit empty lists clear them. Wallet/provider binding and unsupported fields cannot change after authorization starts. An uncertain - update enters recovery_required and must not be retried. Checkout cards may be - edited between authorizations. A Link card authorized with browser_id and - page_url cannot be changed; delete it and create a new card with the updated - details. + update enters recovery_required; delete the card and create a new one rather + than retrying the update. Checkout cards may be edited between authorizations. A + Link card authorized with browser_id and page_url cannot be changed; delete it + and create a new card with the updated details. Args: spec: Live Link card request. Test-mode card creation is not supported. The spec can @@ -205,10 +205,10 @@ def update( request, subject to atomic provider approval checks; omitted optional fields remain unchanged and explicit empty lists clear them. Wallet/provider binding and unsupported fields cannot change after authorization starts. An uncertain - update enters recovery_required and must not be retried. Checkout cards may be - edited between authorizations. A Link card authorized with browser_id and - page_url cannot be changed; delete it and create a new card with the updated - details. + update enters recovery_required; delete the card and create a new one rather + than retrying the update. Checkout cards may be edited between authorizations. A + Link card authorized with browser_id and page_url cannot be changed; delete it + and create a new card with the updated details. Args: version: Expected current item version from the latest read. @@ -321,11 +321,12 @@ def delete( Unresolved payment operations normally block deletion, including operations on child cards of a wallet. Deleting a connected Kernel wallet first blocks new payments on it, then removes its enrolled card. If that fails, the wallet is - kept and keeps refusing payments; retry the deletion. An AgentCard card in - recovery_required whose checkout create response returned no authorization ID - may be explicitly abandoned by deleting that card directly; deleting its wallet - or vault remains blocked. Deleting or recreating an item is not proof that a - payment did not occur. Deleting a managed auth credential item leaves the + kept and keeps refusing payments; retry the deletion. A Link or Kernel card in + recovery_required for issuance, or an AgentCard card in recovery_required whose + checkout create response returned no authorization ID, may be explicitly + abandoned by deleting that card directly; deleting its wallet or vault remains + blocked until the card is deleted. Deleting or recreating an item is not proof + that a payment did not occur. Deleting a managed auth credential item leaves the connection and its saved credential unchanged. Args: @@ -434,6 +435,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -487,6 +491,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -542,6 +549,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -596,6 +606,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -645,6 +658,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -703,6 +719,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -772,6 +791,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -821,6 +843,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -873,6 +898,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -929,6 +957,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -979,6 +1010,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -1035,6 +1069,9 @@ def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -1490,10 +1527,10 @@ async def update( request, subject to atomic provider approval checks; omitted optional fields remain unchanged and explicit empty lists clear them. Wallet/provider binding and unsupported fields cannot change after authorization starts. An uncertain - update enters recovery_required and must not be retried. Checkout cards may be - edited between authorizations. A Link card authorized with browser_id and - page_url cannot be changed; delete it and create a new card with the updated - details. + update enters recovery_required; delete the card and create a new one rather + than retrying the update. Checkout cards may be edited between authorizations. A + Link card authorized with browser_id and page_url cannot be changed; delete it + and create a new card with the updated details. Args: spec: Live Link card request. Test-mode card creation is not supported. The spec can @@ -1541,10 +1578,10 @@ async def update( request, subject to atomic provider approval checks; omitted optional fields remain unchanged and explicit empty lists clear them. Wallet/provider binding and unsupported fields cannot change after authorization starts. An uncertain - update enters recovery_required and must not be retried. Checkout cards may be - edited between authorizations. A Link card authorized with browser_id and - page_url cannot be changed; delete it and create a new card with the updated - details. + update enters recovery_required; delete the card and create a new one rather + than retrying the update. Checkout cards may be edited between authorizations. A + Link card authorized with browser_id and page_url cannot be changed; delete it + and create a new card with the updated details. Args: version: Expected current item version from the latest read. @@ -1657,11 +1694,12 @@ async def delete( Unresolved payment operations normally block deletion, including operations on child cards of a wallet. Deleting a connected Kernel wallet first blocks new payments on it, then removes its enrolled card. If that fails, the wallet is - kept and keeps refusing payments; retry the deletion. An AgentCard card in - recovery_required whose checkout create response returned no authorization ID - may be explicitly abandoned by deleting that card directly; deleting its wallet - or vault remains blocked. Deleting or recreating an item is not proof that a - payment did not occur. Deleting a managed auth credential item leaves the + kept and keeps refusing payments; retry the deletion. A Link or Kernel card in + recovery_required for issuance, or an AgentCard card in recovery_required whose + checkout create response returned no authorization ID, may be explicitly + abandoned by deleting that card directly; deleting its wallet or vault remains + blocked until the card is deleted. Deleting or recreating an item is not proof + that a payment did not occur. Deleting a managed auth credential item leaves the connection and its saved credential unchanged. Args: @@ -1770,6 +1808,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -1823,6 +1864,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -1878,6 +1922,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -1932,6 +1979,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -1981,6 +2031,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -2039,6 +2092,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -2108,6 +2164,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -2157,6 +2216,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -2209,6 +2271,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -2265,6 +2330,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -2315,6 +2383,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, @@ -2371,6 +2442,9 @@ async def perform_operation( return HTTP 429 and retain the card item; stop, back off, and retry the same authorize operation. + Ready Kernel cards advertise fill. Fill delivers card details for a few minutes; + submit checkout promptly after filling. A repeated fill is safe. + Fill returns a value-free execution result. Validation failures before writing return 400 (invalid request or targets), 403 (access or destination denied), 404 (resource not found), or 409 (item or browser not ready). Once writing starts, diff --git a/src/kernel/types/browser_create_params.py b/src/kernel/types/browser_create_params.py index 3fe435d5..d773f8cc 100644 --- a/src/kernel/types/browser_create_params.py +++ b/src/kernel/types/browser_create_params.py @@ -63,7 +63,10 @@ class BrowserCreateParams(TypedDict, total=False): """ memory: BrowserMemoryRequest - """Memory for a headful, non-GPU browser session. Defaults to 8GiB.""" + """Memory for a non-GPU browser. + + Headless: 1GiB (default), 2GiB, or 4GiB. Headful: 8GiB (default) or 16GiB. + """ name: str """ diff --git a/src/kernel/types/browser_memory.py b/src/kernel/types/browser_memory.py index 31f362ee..ccdb8fd4 100644 --- a/src/kernel/types/browser_memory.py +++ b/src/kernel/types/browser_memory.py @@ -4,4 +4,4 @@ __all__ = ["BrowserMemory"] -BrowserMemory: TypeAlias = Literal["1GiB", "2GiB", "6GiB", "8GiB", "12GiB", "16GiB"] +BrowserMemory: TypeAlias = Literal["1GiB", "2GiB", "4GiB", "6GiB", "8GiB", "12GiB", "16GiB"] diff --git a/src/kernel/types/browser_memory_request.py b/src/kernel/types/browser_memory_request.py index f2363b71..8f853631 100644 --- a/src/kernel/types/browser_memory_request.py +++ b/src/kernel/types/browser_memory_request.py @@ -4,4 +4,4 @@ __all__ = ["BrowserMemoryRequest"] -BrowserMemoryRequest: TypeAlias = Literal["8GiB", "16GiB"] +BrowserMemoryRequest: TypeAlias = Literal["1GiB", "2GiB", "4GiB", "8GiB", "16GiB"] diff --git a/src/kernel/types/browser_pool_create_params.py b/src/kernel/types/browser_pool_create_params.py index 6850502a..bf05dd92 100644 --- a/src/kernel/types/browser_pool_create_params.py +++ b/src/kernel/types/browser_pool_create_params.py @@ -62,7 +62,10 @@ class BrowserPoolCreateParams(TypedDict, total=False): """ memory: BrowserMemoryRequest - """Memory requested for headful browsers in this pool.""" + """Memory for browsers in this pool. + + Headless: 1GiB (default), 2GiB, or 4GiB. Headful: 8GiB (default) or 16GiB. + """ name: str """Optional name for the browser pool. Must be unique within the project.""" diff --git a/src/kernel/types/browser_pool_update_params.py b/src/kernel/types/browser_pool_update_params.py index 8374568e..4b5c6a0f 100644 --- a/src/kernel/types/browser_pool_update_params.py +++ b/src/kernel/types/browser_pool_update_params.py @@ -44,6 +44,17 @@ class BrowserPoolUpdateParams(TypedDict, total=False): flushing the pool). """ + expected_network: BrowserNetworkConfigParam + """Optional optimistic concurrency precondition. + + Send the network configuration from the last pool response, or {} when it has no + network configuration. The entire update is rejected with 409 stale_network if + the saved network differs, checked atomically with the write. Omit for + unconditional updates. Explicit empty lists differ from omitted lists; route + targets must match the saved references (resolved IDs, not equivalent proxy + names). + """ + extensions: Iterable[BrowserExtension] """If provided, replaces the extension list. @@ -64,11 +75,11 @@ class BrowserPoolUpdateParams(TypedDict, total=False): kiosk_mode: bool """If provided, replaces whether browsers launch in kiosk mode.""" - memory: Literal["8GiB", "16GiB"] - """Memory requested for newly-warmed headful browsers in this pool. - - Existing browsers retain their original allocation. Use discard_all_idle to - replace idle browsers. + memory: Literal["1GiB", "2GiB", "4GiB", "8GiB", "16GiB"] + """ + Memory requested for newly-warmed browsers in this pool: 1GiB, 2GiB, or 4GiB for + headless, 8GiB or 16GiB for headful. Existing browsers retain their original + allocation. Use discard_all_idle to replace idle browsers. """ name: str diff --git a/src/kernel/types/browsers/browser_captcha_challenge_result_event.py b/src/kernel/types/browsers/browser_captcha_challenge_result_event.py index bed8fa7c..00580a46 100644 --- a/src/kernel/types/browsers/browser_captcha_challenge_result_event.py +++ b/src/kernel/types/browsers/browser_captcha_challenge_result_event.py @@ -43,14 +43,16 @@ class Data(BaseModel): """ captcha_provider: Optional[ - Literal["hcaptcha", "recaptcha_v2", "recaptcha_v3", "turnstile", "geetest", "arkose", "human", "other"] + Literal[ + "hcaptcha", "recaptcha_v2", "recaptcha_v3", "turnstile", "geetest", "arkose", "human", "binance", "other" + ] ] = None """Captcha product the challenge belongs to, not the service that solved it. Enterprise reCAPTCHA variants are grouped into their version bucket (recaptcha_v2 or recaptcha_v3), FunCaptcha uses arkose, press-and-hold challenges served by HUMAN (formerly PerimeterX) use human, and unlisted - products use other. + products, including text captchas a site draws itself, use other. """ challenge_id: Optional[str] = None diff --git a/src/kernel/types/browsers/browser_captcha_solve_result_event.py b/src/kernel/types/browsers/browser_captcha_solve_result_event.py index 1feb5d77..5d7a7360 100644 --- a/src/kernel/types/browsers/browser_captcha_solve_result_event.py +++ b/src/kernel/types/browsers/browser_captcha_solve_result_event.py @@ -29,14 +29,16 @@ class Data(BaseModel): """ captcha_provider: Optional[ - Literal["hcaptcha", "recaptcha_v2", "recaptcha_v3", "turnstile", "geetest", "arkose", "human", "other"] + Literal[ + "hcaptcha", "recaptcha_v2", "recaptcha_v3", "turnstile", "geetest", "arkose", "human", "binance", "other" + ] ] = None """Captcha product the challenge belongs to, not the service that solved it. Enterprise reCAPTCHA variants are grouped into their version bucket (recaptcha_v2 or recaptcha_v3), FunCaptcha uses arkose, press-and-hold challenges served by HUMAN (formerly PerimeterX) use human, and unlisted - products use other. + products, including text captchas a site draws itself, use other. """ challenge_id: Optional[str] = None @@ -53,6 +55,9 @@ class Data(BaseModel): ERROR_CAPTCHA_UNSOLVABLE). Absent on success. """ + media: Optional[Literal["image", "video"]] = None + """Captured hCaptcha recognition media, when known.""" + task_id: Optional[str] = None """Opaque identifier shared with the matching captcha_solve_started.""" diff --git a/src/kernel/types/browsers/browser_captcha_solve_started_event.py b/src/kernel/types/browsers/browser_captcha_solve_started_event.py index 12dd56e6..c17b9097 100644 --- a/src/kernel/types/browsers/browser_captcha_solve_started_event.py +++ b/src/kernel/types/browsers/browser_captcha_solve_started_event.py @@ -19,14 +19,16 @@ class Data(BaseModel): """Deprecated: use captcha_provider and task_kind.""" captcha_provider: Optional[ - Literal["hcaptcha", "recaptcha_v2", "recaptcha_v3", "turnstile", "geetest", "arkose", "human", "other"] + Literal[ + "hcaptcha", "recaptcha_v2", "recaptcha_v3", "turnstile", "geetest", "arkose", "human", "binance", "other" + ] ] = None """Captcha product the challenge belongs to, not the service that solved it. Enterprise reCAPTCHA variants are grouped into their version bucket (recaptcha_v2 or recaptcha_v3), FunCaptcha uses arkose, press-and-hold challenges served by HUMAN (formerly PerimeterX) use human, and unlisted - products use other. + products, including text captchas a site draws itself, use other. """ challenge_id: Optional[str] = None @@ -37,6 +39,9 @@ class Data(BaseModel): continues. It does not indicate task ordering or challenge completion. """ + media: Optional[Literal["image", "video"]] = None + """Captured hCaptcha recognition media, when known.""" + task_id: Optional[str] = None """Opaque identifier shared with the matching captcha_solve_result.""" diff --git a/src/kernel/types/vaults/__init__.py b/src/kernel/types/vaults/__init__.py index ff4183c4..d72d730c 100644 --- a/src/kernel/types/vaults/__init__.py +++ b/src/kernel/types/vaults/__init__.py @@ -92,6 +92,9 @@ from .authorize_vault_item_operation_request_param import ( AuthorizeVaultItemOperationRequestParam as AuthorizeVaultItemOperationRequestParam, ) +from .credential_vault_field_definition_input_param import ( + CredentialVaultFieldDefinitionInputParam as CredentialVaultFieldDefinitionInputParam, +) from .kernel_credential_vault_item_spec_input_param import ( KernelCredentialVaultItemSpecInputParam as KernelCredentialVaultItemSpecInputParam, ) diff --git a/src/kernel/types/vaults/card_vault_item_spec.py b/src/kernel/types/vaults/card_vault_item_spec.py index 9224fe34..f6b471f8 100644 --- a/src/kernel/types/vaults/card_vault_item_spec.py +++ b/src/kernel/types/vaults/card_vault_item_spec.py @@ -90,8 +90,6 @@ class LinkCardVaultItemSpec(BaseModel): wallet: str """Connected Link wallet item key.""" - expires_at: Optional[int] = None - line_items: Optional[List[LinkCardVaultItemSpecLineItem]] = None metadata: Optional[Dict[str, str]] = None diff --git a/src/kernel/types/vaults/card_vault_item_spec_param.py b/src/kernel/types/vaults/card_vault_item_spec_param.py index 08cd8545..6e3ad521 100644 --- a/src/kernel/types/vaults/card_vault_item_spec_param.py +++ b/src/kernel/types/vaults/card_vault_item_spec_param.py @@ -90,8 +90,6 @@ class LinkCardVaultItemSpec(TypedDict, total=False): wallet: Required[str] """Connected Link wallet item key.""" - expires_at: int - line_items: Iterable[LinkCardVaultItemSpecLineItem] metadata: Dict[str, str] diff --git a/src/kernel/types/vaults/card_vault_item_state.py b/src/kernel/types/vaults/card_vault_item_state.py index cead6d53..37dbdecd 100644 --- a/src/kernel/types/vaults/card_vault_item_state.py +++ b/src/kernel/types/vaults/card_vault_item_state.py @@ -47,13 +47,13 @@ class LinkCardState(BaseModel): status: Literal[ "requested", "pending_authorization", "ready", "consumed", "expired", "declined", "recovery_required" ] - """recovery_required means an original provider operation has an unresolved - outcome. - - Do not retry, delete, or replace it. Known references may be observed safely, - but unknown creation without an ID and uncertain card-material retrieval require - manual reconciliation with the provider or support. There is no reset or - caller-asserted reconciliation operation. + """ + recovery_required means an original provider operation has an unresolved outcome + and the card cannot be used. Reads keep observing a known provider request and + may clear the recovery. To continue, delete this card and create a new one; + deleting cancels the original request when its ID is known and keeps the + recovery evidence. The user may see an approval request for the original card + and should approve only the new one. """ domains: Optional[List[str]] = None diff --git a/src/kernel/types/vaults/collect_vault_item_operation_request_param.py b/src/kernel/types/vaults/collect_vault_item_operation_request_param.py index 2ce3031c..4038b90e 100644 --- a/src/kernel/types/vaults/collect_vault_item_operation_request_param.py +++ b/src/kernel/types/vaults/collect_vault_item_operation_request_param.py @@ -12,7 +12,7 @@ class CollectVaultItemOperationRequestParam(TypedDict, total=False): Supported for ready and pending_collection credential items. Always render the same form from - every form-supported field; totp fields have no form input and are omitted. + every form-supported field; totp and passkey fields have no form input and are omitted. No caller-selected field subsets or form overrides are accepted. Reuse an active Kernel-hosted session or renew an expired session atomically. Customer-hosted forms use their own backend and ordinary item GET/PATCH. Opening diff --git a/src/kernel/types/vaults/credential_collection_action.py b/src/kernel/types/vaults/credential_collection_action.py index 331e255c..2f1cd48c 100644 --- a/src/kernel/types/vaults/credential_collection_action.py +++ b/src/kernel/types/vaults/credential_collection_action.py @@ -11,14 +11,14 @@ class CredentialCollectionAction(BaseModel): """ One schema-derived form for the item, available in ready or pending_collection - state. Render every form-supported field as editable; omit totp fields and - preserve their stored seeds. Prefill non-sensitive values, + state. Render every form-supported field as editable; omit totp and passkey + fields and preserve their stored values. Prefill non-sensitive values, and allow existing sensitive values to be preserved or replaced without ever revealing them. No field subsets or per-request form configuration exist. Validate required fields against the resulting values, including preserved secrets. Submit changed values only, using the version used to render the form. - Scoped hosted submission rejects totp edits; seed writes require the ordinary - authenticated item API. Customer forms likewise omit totp from their payloads. + Scoped hosted submission rejects totp and passkey edits; those writes require the ordinary + authenticated item API. Customer forms likewise omit them from their payloads. Save edits atomically. A successful hosted submission increments the version, marks ready, and consumes the session; an empty edit may complete collection while preserving values. A customer form uses PATCH for changed values and diff --git a/src/kernel/types/vaults/credential_vault_field_definition.py b/src/kernel/types/vaults/credential_vault_field_definition.py index 8c60748d..c8317687 100644 --- a/src/kernel/types/vaults/credential_vault_field_definition.py +++ b/src/kernel/types/vaults/credential_vault_field_definition.py @@ -25,14 +25,19 @@ class CredentialVaultFieldDefinition(BaseModel): type: CredentialVaultFieldType """ - Text, email, and password have form inputs; totp does not and is omitted from - both Kernel-hosted and customer React forms. Password and totp must be - sensitive. A totp value is an RFC 4648 Base32 generator seed (case-insensitive, - optional trailing padding), not an otpauth URI or current code. Reject invalid - or empty decoded seeds. Browser fill generates an RFC 6238 code at execution - time using HMAC-SHA1, 6 digits, and a 30-second period. Preserve leading zeros; - never fill the seed. Custom algorithms, digits, periods, and form enrollment are - unsupported. + Text, email, and password have form inputs; totp and passkey do not and are + omitted from both Kernel-hosted and customer React forms. Password, totp, and + passkey must be sensitive. A totp value is an RFC 4648 Base32 generator seed + (case-insensitive, optional trailing padding), not an otpauth URI or current + code. Reject invalid or empty decoded seeds. Browser fill generates an RFC 6238 + code at execution time using HMAC-SHA1, 6 digits, and a 30-second period. + Preserve leading zeros; never fill the seed. Custom algorithms, digits, periods, + and form enrollment are unsupported. A passkey value is a JSON-encoded FIDO + Credential Exchange Format passkey object with unpadded base64url + `credentialId`, `userHandle` (at most 64 bytes), and `key` (a PKCS#8 ECDSA P-256 + private key), a lowercase `rpId` domain, and optional `username` and + `userDisplayName`. Other CXF members are ignored. Passkeys are never filled into + pages. """ label: Optional[str] = None diff --git a/src/kernel/types/vaults/credential_vault_field_definition_input_param.py b/src/kernel/types/vaults/credential_vault_field_definition_input_param.py new file mode 100644 index 00000000..f97cf911 --- /dev/null +++ b/src/kernel/types/vaults/credential_vault_field_definition_input_param.py @@ -0,0 +1,55 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +from .credential_vault_field_type import CredentialVaultFieldType + +__all__ = ["CredentialVaultFieldDefinitionInputParam"] + + +class CredentialVaultFieldDefinitionInputParam(TypedDict, total=False): + """A field definition without a value. + + Field updates add fields with this shape and set their values in `fields`. + """ + + name: Required[str] + """Unique stable field name used to key values, updates, and browser fills.""" + + type: Required[CredentialVaultFieldType] + """ + Text, email, and password have form inputs; totp and passkey do not and are + omitted from both Kernel-hosted and customer React forms. Password, totp, and + passkey must be sensitive. A totp value is an RFC 4648 Base32 generator seed + (case-insensitive, optional trailing padding), not an otpauth URI or current + code. Reject invalid or empty decoded seeds. Browser fill generates an RFC 6238 + code at execution time using HMAC-SHA1, 6 digits, and a 30-second period. + Preserve leading zeros; never fill the seed. Custom algorithms, digits, periods, + and form enrollment are unsupported. A passkey value is a JSON-encoded FIDO + Credential Exchange Format passkey object with unpadded base64url + `credentialId`, `userHandle` (at most 64 bytes), and `key` (a PKCS#8 ECDSA P-256 + private key), a lowercase `rpId` domain, and optional `username` and + `userDisplayName`. Other CXF members are ignored. Passkeys are never filled into + pages. + """ + + label: str + """Optional human-readable display label. + + It is returned as non-secret metadata and never affects value keys, updates, or + browser fills. Use single-line, trimmed display text without control or + formatting characters. The server enforces a 128-byte UTF-8 limit. + """ + + required: bool + + sensitive: bool + """ + Set false explicitly for ordinary usernames, email addresses, and other + non-secret identifiers. Reserve true for secrets such as passwords, API tokens, + and TOTP seeds. Password, totp, and passkey fields must be true. Omission + defaults to true for safety; do not rely on that default for every field. False + permits API reads and form prefilling. + """ diff --git a/src/kernel/types/vaults/credential_vault_field_input_param.py b/src/kernel/types/vaults/credential_vault_field_input_param.py index 2f481706..5e26bb8d 100644 --- a/src/kernel/types/vaults/credential_vault_field_input_param.py +++ b/src/kernel/types/vaults/credential_vault_field_input_param.py @@ -15,14 +15,19 @@ class CredentialVaultFieldInputParam(TypedDict, total=False): type: Required[CredentialVaultFieldType] """ - Text, email, and password have form inputs; totp does not and is omitted from - both Kernel-hosted and customer React forms. Password and totp must be - sensitive. A totp value is an RFC 4648 Base32 generator seed (case-insensitive, - optional trailing padding), not an otpauth URI or current code. Reject invalid - or empty decoded seeds. Browser fill generates an RFC 6238 code at execution - time using HMAC-SHA1, 6 digits, and a 30-second period. Preserve leading zeros; - never fill the seed. Custom algorithms, digits, periods, and form enrollment are - unsupported. + Text, email, and password have form inputs; totp and passkey do not and are + omitted from both Kernel-hosted and customer React forms. Password, totp, and + passkey must be sensitive. A totp value is an RFC 4648 Base32 generator seed + (case-insensitive, optional trailing padding), not an otpauth URI or current + code. Reject invalid or empty decoded seeds. Browser fill generates an RFC 6238 + code at execution time using HMAC-SHA1, 6 digits, and a 30-second period. + Preserve leading zeros; never fill the seed. Custom algorithms, digits, periods, + and form enrollment are unsupported. A passkey value is a JSON-encoded FIDO + Credential Exchange Format passkey object with unpadded base64url + `credentialId`, `userHandle` (at most 64 bytes), and `key` (a PKCS#8 ECDSA P-256 + private key), a lowercase `rpId` domain, and optional `username` and + `userDisplayName`. Other CXF members are ignored. Passkeys are never filled into + pages. """ encrypted_value: str @@ -55,9 +60,9 @@ class CredentialVaultFieldInputParam(TypedDict, total=False): """ Set false explicitly for ordinary usernames, email addresses, and other non-secret identifiers. Reserve true for secrets such as passwords, API tokens, - and TOTP seeds. Password and totp fields must be true. Omission defaults to true - for safety; do not rely on that default for every field. False permits API reads - and form prefilling. + and TOTP seeds. Password, totp, and passkey fields must be true. Omission + defaults to true for safety; do not rely on that default for every field. False + permits API reads and form prefilling. """ value: str diff --git a/src/kernel/types/vaults/credential_vault_field_type.py b/src/kernel/types/vaults/credential_vault_field_type.py index cb400e9c..67e5368e 100644 --- a/src/kernel/types/vaults/credential_vault_field_type.py +++ b/src/kernel/types/vaults/credential_vault_field_type.py @@ -4,4 +4,4 @@ __all__ = ["CredentialVaultFieldType"] -CredentialVaultFieldType: TypeAlias = Literal["text", "email", "password", "totp"] +CredentialVaultFieldType: TypeAlias = Literal["text", "email", "password", "totp", "passkey"] diff --git a/src/kernel/types/vaults/credential_vault_field_update_param.py b/src/kernel/types/vaults/credential_vault_field_update_param.py index 823b21aa..b33079bf 100644 --- a/src/kernel/types/vaults/credential_vault_field_update_param.py +++ b/src/kernel/types/vaults/credential_vault_field_update_param.py @@ -36,6 +36,7 @@ class CredentialVaultFieldUpdateParam(TypedDict, total=False): immediately clear the stored value. Clearing a required form-supported field reopens collection; clearing an optional field does not prevent readiness. Values must satisfy the declared field type. For totp, value is the generator - seed, never a current code. Clearing a required totp field returns 400 because - it cannot be collected in a form. + seed, never a current code. For passkey, value is the JSON-encoded CXF passkey + object. Clearing a required totp or passkey field returns 400 because it cannot + be collected in a form. """ diff --git a/src/kernel/types/vaults/credential_vault_item.py b/src/kernel/types/vaults/credential_vault_item.py index f9bd1158..91f6d8e1 100644 --- a/src/kernel/types/vaults/credential_vault_item.py +++ b/src/kernel/types/vaults/credential_vault_item.py @@ -116,28 +116,29 @@ class CredentialVaultItem(BaseModel): action: Optional[Action] = None """ One schema-derived form for the item, available in ready or pending_collection - state. Render every form-supported field as editable; omit totp fields and - preserve their stored seeds. Prefill non-sensitive values, and allow existing - sensitive values to be preserved or replaced without ever revealing them. No - field subsets or per-request form configuration exist. Validate required fields - against the resulting values, including preserved secrets. Submit changed values - only, using the version used to render the form. Scoped hosted submission - rejects totp edits; seed writes require the ordinary authenticated item API. - Customer forms likewise omit totp from their payloads. Save edits atomically. A - successful hosted submission increments the version, marks ready, and consumes - the session; an empty edit may complete collection while preserving values. A - customer form uses PATCH for changed values and does not send an empty PATCH - when nothing changed. Kernel-hosted bearer sessions require no Kernel account - and are bound to the item version. Expired, superseded, consumed, or - deleted-item sessions cannot submit. Authenticated item GET renews expired - active sessions for ready or pending items; pending items always receive an - action. A ready item with no active session omits the action until collect is - invoked. Concurrent renewals return the same link. Renewal changes neither - values nor item version. An expired link cannot renew itself. The hosted form - handles its collection protocol; callers only open the returned URL and do not - extract or submit its token through the public API. For customer-hosted forms, - use @onkernel/vault-react and an authenticated customer backend calling the - ordinary item GET/PATCH API. Kernel does not store customer collection URLs or - authenticate the customer's end users. Treat URLs and submitted values as - secrets and exclude them from logs, traces, and errors. + state. Render every form-supported field as editable; omit totp and passkey + fields and preserve their stored values. Prefill non-sensitive values, and allow + existing sensitive values to be preserved or replaced without ever revealing + them. No field subsets or per-request form configuration exist. Validate + required fields against the resulting values, including preserved secrets. + Submit changed values only, using the version used to render the form. Scoped + hosted submission rejects totp and passkey edits; those writes require the + ordinary authenticated item API. Customer forms likewise omit them from their + payloads. Save edits atomically. A successful hosted submission increments the + version, marks ready, and consumes the session; an empty edit may complete + collection while preserving values. A customer form uses PATCH for changed + values and does not send an empty PATCH when nothing changed. Kernel-hosted + bearer sessions require no Kernel account and are bound to the item version. + Expired, superseded, consumed, or deleted-item sessions cannot submit. + Authenticated item GET renews expired active sessions for ready or pending + items; pending items always receive an action. A ready item with no active + session omits the action until collect is invoked. Concurrent renewals return + the same link. Renewal changes neither values nor item version. An expired link + cannot renew itself. The hosted form handles its collection protocol; callers + only open the returned URL and do not extract or submit its token through the + public API. For customer-hosted forms, use @onkernel/vault-react and an + authenticated customer backend calling the ordinary item GET/PATCH API. Kernel + does not store customer collection URLs or authenticate the customer's end + users. Treat URLs and submitted values as secrets and exclude them from logs, + traces, and errors. """ diff --git a/src/kernel/types/vaults/credential_vault_item_spec_update_param.py b/src/kernel/types/vaults/credential_vault_item_spec_update_param.py index d7933b9b..06dde966 100644 --- a/src/kernel/types/vaults/credential_vault_item_spec_update_param.py +++ b/src/kernel/types/vaults/credential_vault_item_spec_update_param.py @@ -2,15 +2,25 @@ from __future__ import annotations -from typing import Dict +from typing import Dict, Iterable from typing_extensions import TypedDict +from ..._types import SequenceNotStr from .credential_vault_field_update_param import CredentialVaultFieldUpdateParam +from .credential_vault_field_definition_input_param import CredentialVaultFieldDefinitionInputParam __all__ = ["CredentialVaultItemSpecUpdateParam"] class CredentialVaultItemSpecUpdateParam(TypedDict, total=False): + add_fields: Iterable[CredentialVaultFieldDefinitionInputParam] + """Field definitions to append, with the same defaults as creation. + + Set their values in `fields` in the same update. Names must be unique after + removals; at most 32 fields may result. A required totp or passkey field needs a + value in `fields`. + """ + description: str """ Recognizable site or service name used as the form title, without suffixes such @@ -19,3 +29,9 @@ class CredentialVaultItemSpecUpdateParam(TypedDict, total=False): """ fields: Dict[str, CredentialVaultFieldUpdateParam] + + remove_fields: SequenceNotStr[str] + """Names of fields to delete with their values. + + Unknown names return 400. At least one field must remain. + """ diff --git a/src/kernel/types/vaults/credential_vault_item_update_request_param.py b/src/kernel/types/vaults/credential_vault_item_update_request_param.py index ca34cbc9..5c45f9df 100644 --- a/src/kernel/types/vaults/credential_vault_item_update_request_param.py +++ b/src/kernel/types/vaults/credential_vault_item_update_request_param.py @@ -10,10 +10,13 @@ class CredentialVaultItemUpdateRequestParam(TypedDict, total=False): - """Atomically update description and selected values. - - Omitted properties are - preserved. Field names, types, required flags, and sensitivity cannot change. + """ + Atomically update description, field definitions, and selected values. + Omitted properties are preserved. `remove_fields` deletes definitions and + their values, then `add_fields` appends definitions, then `fields` sets + values, including for added fields. An existing field's definition cannot + be edited in place; to change it, remove the field and add it again, in + the same update or a later one. The old value is deleted with it. Unknown field names return 400; stale versions or mismatched item types return 409 without changing the item. A successful update increments version and invalidates outstanding Kernel-hosted collection sessions. If required diff --git a/src/kernel/types/vaults/kernel_card_state.py b/src/kernel/types/vaults/kernel_card_state.py index 047b5f9e..b2daa14f 100644 --- a/src/kernel/types/vaults/kernel_card_state.py +++ b/src/kernel/types/vaults/kernel_card_state.py @@ -32,8 +32,9 @@ def __getattr__(self, attr: str) -> str: ... class KernelCardState(BaseModel): - """ - A ready Kernel card retains its encrypted network token and one-time code for the fill operation until the item's expires_at. Fill and submit checkout before then. Visa purchases require a spend_approval action before the code is issued; Mastercard purchases need no hosted approval. masks.last4 is the enrolled card's last four digits; masks.token_last4 is the network token's last four digits shown to the merchant. Kernel cards do not expose aliases or support egress substitution. Kernel does not observe whether the merchant charged the card. + """A ready Kernel card supports authorize, fill, then submit checkout. + + Card details are delivered for a few minutes after fill; submit promptly. Repeated fill is safe and never submits checkout. Visa purchases require a spend_approval action before details are issued; Mastercard purchases need no hosted approval. masks.last4 is the enrolled card's last four digits; masks.token_last4, when present, is the token's last four digits shown to the merchant. Kernel does not observe whether the merchant charged the card. """ provider: Literal["kernel"] @@ -50,10 +51,12 @@ class KernelCardState(BaseModel): fresh local verification link; this does not approve spending or replay any provider request. Unclassified legacy recovery and uncertain intent creation cannot restart. Kernel never approves again or issues another code for the item - automatically, and the item cannot be deleted or replaced until the original - attempt is reconciled with support. When status_reason says the provider refused - retrieval before acceptance, no code was issued and a later read retries. - declined means the card network refused to issue a code. + automatically. To continue, delete this card and create a new purchase; the + cardholder approves the new purchase separately. Recovery while reporting a + merchant transaction cannot be deleted and must be reconciled with support. When + status_reason says the provider refused retrieval before acceptance, no code was + issued and a later read retries. declined means the card network refused to + issue a code. """ domains: Optional[List[str]] = None diff --git a/src/kernel/types/vaults/kernel_card_vault_item_spec.py b/src/kernel/types/vaults/kernel_card_vault_item_spec.py index 1581c68c..77912828 100644 --- a/src/kernel/types/vaults/kernel_card_vault_item_spec.py +++ b/src/kernel/types/vaults/kernel_card_vault_item_spec.py @@ -11,12 +11,12 @@ class KernelCardVaultItemSpec(BaseModel): """One live purchase with a Kernel-enrolled card. - Authorization obtains an agentic network token number, expiry and one-time 3-digit code. They are stored encrypted for the fill operation, which types them only on merchant_url's origin; the merchant's own checkout submits the payment. The one-time code is valid until the item's expires_at; fill and submit checkout before then. Mastercard purchases need no cardholder approval. A Visa purchase returns a spend_approval action: the cardholder approves it with a Visa passkey, and Kernel registers a Visa intent for one transaction up to the amount before issuing the code. Card updates are not supported; delete and create a new item instead. + Authorization obtains an agentic network token number, expiry and one-time 3-digit code. They are stored encrypted for the fill operation, which types them only on merchant_url's origin; the merchant's own checkout submits the payment. The one-time code is valid until the item's expires_at; fill and submit checkout before then. Mastercard purchases need no cardholder approval. A Visa purchase returns a spend_approval action: the cardholder approves it with a Visa passkey, and Kernel registers a Visa intent for one transaction up to the amount before issuing the code. For supported cards whose network cannot be enrolled for agentic tokens, authorize prepares checkout details without issuing a one-time code. The card can be filled into one checkout before its expires_at, one hour after authorization. Fill types those details on merchant_url's origin. The amount, merchant_url and merchant_country are recorded but do not restrict payment requests sent by the browser. Card updates are not supported; delete and create a new item instead. """ amount: int """ - Integer amount in minor currency units (at most 50000), bound to the one-time + Integer amount in minor currency units (at most 1000000), bound to the one-time code. """ diff --git a/src/kernel/types/vaults/kernel_card_vault_item_spec_param.py b/src/kernel/types/vaults/kernel_card_vault_item_spec_param.py index 72d6dae8..77d3084d 100644 --- a/src/kernel/types/vaults/kernel_card_vault_item_spec_param.py +++ b/src/kernel/types/vaults/kernel_card_vault_item_spec_param.py @@ -10,12 +10,12 @@ class KernelCardVaultItemSpecParam(TypedDict, total=False): """One live purchase with a Kernel-enrolled card. - Authorization obtains an agentic network token number, expiry and one-time 3-digit code. They are stored encrypted for the fill operation, which types them only on merchant_url's origin; the merchant's own checkout submits the payment. The one-time code is valid until the item's expires_at; fill and submit checkout before then. Mastercard purchases need no cardholder approval. A Visa purchase returns a spend_approval action: the cardholder approves it with a Visa passkey, and Kernel registers a Visa intent for one transaction up to the amount before issuing the code. Card updates are not supported; delete and create a new item instead. + Authorization obtains an agentic network token number, expiry and one-time 3-digit code. They are stored encrypted for the fill operation, which types them only on merchant_url's origin; the merchant's own checkout submits the payment. The one-time code is valid until the item's expires_at; fill and submit checkout before then. Mastercard purchases need no cardholder approval. A Visa purchase returns a spend_approval action: the cardholder approves it with a Visa passkey, and Kernel registers a Visa intent for one transaction up to the amount before issuing the code. For supported cards whose network cannot be enrolled for agentic tokens, authorize prepares checkout details without issuing a one-time code. The card can be filled into one checkout before its expires_at, one hour after authorization. Fill types those details on merchant_url's origin. The amount, merchant_url and merchant_country are recorded but do not restrict payment requests sent by the browser. Card updates are not supported; delete and create a new item instead. """ amount: Required[int] """ - Integer amount in minor currency units (at most 50000), bound to the one-time + Integer amount in minor currency units (at most 1000000), bound to the one-time code. """ diff --git a/src/kernel/types/vaults/kernel_wallet_vault_item_spec.py b/src/kernel/types/vaults/kernel_wallet_vault_item_spec.py index 728d54f2..fb2f039e 100644 --- a/src/kernel/types/vaults/kernel_wallet_vault_item_spec.py +++ b/src/kernel/types/vaults/kernel_wallet_vault_item_spec.py @@ -10,7 +10,7 @@ class KernelWalletVaultItemSpec(BaseModel): """One card stored with Kernel-managed credentials. - Creation returns a card_enrollment action: the cardholder enters the card and their email on a Kernel-hosted page, and the wallet connects once the card is stored. Kernel then enrolls it for an agentic network token when the issuer supports it. The card number never reaches Kernel. The connected wallet's payment_methods expansion lists the card; capabilities.single_use_card.eligible is false, with a network_token_* reason, until the card has a network token, and authorize returns 400 for such a card. Visa purchases require the cardholder to complete a spend_approval action before Kernel issues a one-time code; Mastercard purchases need no hosted approval. + Creation returns a card_enrollment action: the cardholder enters the card and their email on a Kernel-hosted page, and the wallet connects once the card is stored. Kernel then enrolls it for an agentic network token when the issuer supports it. The card number never reaches Kernel. The connected wallet's payment_methods expansion lists the card; capabilities.single_use_card.eligible is false, with a network_token_* reason, until the card has a network token, and authorize returns 400 for such a card unless Kernel supports checkout delivery without a network token for that card. In that case, fill types the checkout details. Visa purchases require the cardholder to complete a spend_approval action before Kernel issues a one-time code; Mastercard purchases need no hosted approval. """ provider: Literal["kernel"] diff --git a/src/kernel/types/vaults/kernel_wallet_vault_item_spec_param.py b/src/kernel/types/vaults/kernel_wallet_vault_item_spec_param.py index c29066ce..b0e87117 100644 --- a/src/kernel/types/vaults/kernel_wallet_vault_item_spec_param.py +++ b/src/kernel/types/vaults/kernel_wallet_vault_item_spec_param.py @@ -10,7 +10,7 @@ class KernelWalletVaultItemSpecParam(TypedDict, total=False): """One card stored with Kernel-managed credentials. - Creation returns a card_enrollment action: the cardholder enters the card and their email on a Kernel-hosted page, and the wallet connects once the card is stored. Kernel then enrolls it for an agentic network token when the issuer supports it. The card number never reaches Kernel. The connected wallet's payment_methods expansion lists the card; capabilities.single_use_card.eligible is false, with a network_token_* reason, until the card has a network token, and authorize returns 400 for such a card. Visa purchases require the cardholder to complete a spend_approval action before Kernel issues a one-time code; Mastercard purchases need no hosted approval. + Creation returns a card_enrollment action: the cardholder enters the card and their email on a Kernel-hosted page, and the wallet connects once the card is stored. Kernel then enrolls it for an agentic network token when the issuer supports it. The card number never reaches Kernel. The connected wallet's payment_methods expansion lists the card; capabilities.single_use_card.eligible is false, with a network_token_* reason, until the card has a network token, and authorize returns 400 for such a card unless Kernel supports checkout delivery without a network token for that card. In that case, fill types the checkout details. Visa purchases require the cardholder to complete a spend_approval action before Kernel issues a one-time code; Mastercard purchases need no hosted approval. """ provider: Required[Literal["kernel"]] diff --git a/src/kernel/types/vaults/managed_auth_credential_vault_field.py b/src/kernel/types/vaults/managed_auth_credential_vault_field.py index 5554832b..e13171c5 100644 --- a/src/kernel/types/vaults/managed_auth_credential_vault_field.py +++ b/src/kernel/types/vaults/managed_auth_credential_vault_field.py @@ -9,12 +9,17 @@ class ManagedAuthCredentialVaultField(BaseModel): type: CredentialVaultFieldType """ - Text, email, and password have form inputs; totp does not and is omitted from - both Kernel-hosted and customer React forms. Password and totp must be - sensitive. A totp value is an RFC 4648 Base32 generator seed (case-insensitive, - optional trailing padding), not an otpauth URI or current code. Reject invalid - or empty decoded seeds. Browser fill generates an RFC 6238 code at execution - time using HMAC-SHA1, 6 digits, and a 30-second period. Preserve leading zeros; - never fill the seed. Custom algorithms, digits, periods, and form enrollment are - unsupported. + Text, email, and password have form inputs; totp and passkey do not and are + omitted from both Kernel-hosted and customer React forms. Password, totp, and + passkey must be sensitive. A totp value is an RFC 4648 Base32 generator seed + (case-insensitive, optional trailing padding), not an otpauth URI or current + code. Reject invalid or empty decoded seeds. Browser fill generates an RFC 6238 + code at execution time using HMAC-SHA1, 6 digits, and a 30-second period. + Preserve leading zeros; never fill the seed. Custom algorithms, digits, periods, + and form enrollment are unsupported. A passkey value is a JSON-encoded FIDO + Credential Exchange Format passkey object with unpadded base64url + `credentialId`, `userHandle` (at most 64 bytes), and `key` (a PKCS#8 ECDSA P-256 + private key), a lowercase `rpId` domain, and optional `username` and + `userDisplayName`. Other CXF members are ignored. Passkeys are never filled into + pages. """ diff --git a/src/kernel/types/vaults/vault_webmcp_binding_param.py b/src/kernel/types/vaults/vault_webmcp_binding_param.py index b7a18292..cdb94f49 100644 --- a/src/kernel/types/vaults/vault_webmcp_binding_param.py +++ b/src/kernel/types/vaults/vault_webmcp_binding_param.py @@ -11,7 +11,8 @@ class VaultWebmcpBindingParam(TypedDict, total=False): field: Required[str] """A declared, populated credential field or supported card field. - A TOTP field supplies a fresh code, never its seed. + A TOTP field supplies a fresh code, never its seed. Passkey fields cannot be + filled. """ input_path: Required[str] diff --git a/tests/api_resources/test_browser_pools.py b/tests/api_resources/test_browser_pools.py index 863c39c2..04734119 100644 --- a/tests/api_resources/test_browser_pools.py +++ b/tests/api_resources/test_browser_pools.py @@ -188,6 +188,19 @@ def test_method_update_with_all_params(self, client: Kernel) -> None: id_or_name="id_or_name", chrome_policy={"foo": "bar"}, discard_all_idle=False, + expected_network={ + "allowed_hosts": ["example.com", "*.example.com"], + "private_hosts": ["*.example.ts.net", "100.64.0.0/10"], + "proxy_routes": [ + { + "hosts": ["string"], + "proxy": { + "id": "x", + "name": "x", + }, + } + ], + }, extensions=[ { "id": "id", @@ -197,7 +210,7 @@ def test_method_update_with_all_params(self, client: Kernel) -> None: fill_rate_per_minute=0, headless=False, kiosk_mode=True, - memory="8GiB", + memory="1GiB", name="my-pool", network={ "allowed_hosts": ["example.com", "*.example.com"], @@ -744,6 +757,19 @@ async def test_method_update_with_all_params(self, async_client: AsyncKernel) -> id_or_name="id_or_name", chrome_policy={"foo": "bar"}, discard_all_idle=False, + expected_network={ + "allowed_hosts": ["example.com", "*.example.com"], + "private_hosts": ["*.example.ts.net", "100.64.0.0/10"], + "proxy_routes": [ + { + "hosts": ["string"], + "proxy": { + "id": "x", + "name": "x", + }, + } + ], + }, extensions=[ { "id": "id", @@ -753,7 +779,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncKernel) -> fill_rate_per_minute=0, headless=False, kiosk_mode=True, - memory="8GiB", + memory="1GiB", name="my-pool", network={ "allowed_hosts": ["example.com", "*.example.com"], diff --git a/tests/api_resources/vaults/test_items.py b/tests/api_resources/vaults/test_items.py index 8e565e2e..96363302 100644 --- a/tests/api_resources/vaults/test_items.py +++ b/tests/api_resources/vaults/test_items.py @@ -120,7 +120,6 @@ def test_method_update_with_all_params_overload_1(self, client: Kernel) -> None: "payment_method_id": "x", "provider": "link", "wallet": "wallet", - "expires_at": 0, "line_items": [ { "name": "name", @@ -255,6 +254,15 @@ def test_method_update_with_all_params_overload_2(self, client: Kernel) -> None: key="x", id_or_name="id_or_name", spec={ + "add_fields": [ + { + "name": "name", + "type": "text", + "label": "label", + "required": True, + "sensitive": True, + } + ], "description": "description", "fields": { "foo": { @@ -262,6 +270,7 @@ def test_method_update_with_all_params_overload_2(self, client: Kernel) -> None: "value": "value", } }, + "remove_fields": ["x"], }, type="credential", version=1, @@ -1607,7 +1616,6 @@ def test_method_upsert_with_all_params_overload_2(self, client: Kernel) -> None: "payment_method_id": "x", "provider": "link", "wallet": "wallet", - "expires_at": 0, "line_items": [ { "name": "name", @@ -2049,7 +2057,6 @@ async def test_method_update_with_all_params_overload_1(self, async_client: Asyn "payment_method_id": "x", "provider": "link", "wallet": "wallet", - "expires_at": 0, "line_items": [ { "name": "name", @@ -2184,6 +2191,15 @@ async def test_method_update_with_all_params_overload_2(self, async_client: Asyn key="x", id_or_name="id_or_name", spec={ + "add_fields": [ + { + "name": "name", + "type": "text", + "label": "label", + "required": True, + "sensitive": True, + } + ], "description": "description", "fields": { "foo": { @@ -2191,6 +2207,7 @@ async def test_method_update_with_all_params_overload_2(self, async_client: Asyn "value": "value", } }, + "remove_fields": ["x"], }, type="credential", version=1, @@ -3536,7 +3553,6 @@ async def test_method_upsert_with_all_params_overload_2(self, async_client: Asyn "payment_method_id": "x", "provider": "link", "wallet": "wallet", - "expires_at": 0, "line_items": [ { "name": "name",