From a665adcb96641db34148f14e15c891458a30fa59 Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Mon, 2 Nov 2026 23:26:50 +0000 Subject: [PATCH 1/5] feat: Pass through tool_page_unloaded and disable SDK retries for WebMCP invoke failures Stainless-Generated-From: 99d2df34644636e2590f1f9c6c3affcb165ed489 --- browserwebmcp.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/browserwebmcp.go b/browserwebmcp.go index 5cbdad12..7435348c 100644 --- a/browserwebmcp.go +++ b/browserwebmcp.go @@ -49,9 +49,13 @@ func NewBrowserWebmcpService(opts ...option.RequestOption) (r BrowserWebmcpServi // across navigation. Inspect a populated form, obtain any required confirmation, // then submit through Playwright or computer interaction without invoking the tool // again. If the tab or embedded frame disappears, or the request times out after -// invocation begins, the response reports outcome_unknown and the tool is not -// retried. CDP-backed custom tool outputs above 240 KiB return an error rather -// than a truncated result. +// invocation begins, the response reports outcome_unknown. If the tool's page is +// reloaded or replaced by a navigation the tool did not start, and the tool never +// responds, the response reports tool_page_unloaded once the replacement page +// loads, or right away if the tool's tab crashes. Neither failure is retried, and +// both set X-Should-Retry to false because the tool may have had side effects. +// CDP-backed custom tool outputs above 240 KiB return an error rather than a +// truncated result. func (r *BrowserWebmcpService) InvokeTool(ctx context.Context, idOrName string, body BrowserWebmcpInvokeToolParams, opts ...option.RequestOption) (res *InvocationResult, err error) { opts = slices.Concat(r.Options, opts) if idOrName == "" { @@ -143,7 +147,7 @@ const ( // The properties Input, ToolRef are required. type InvokeRequestParam struct { - // Tool input, limited to 1 MiB after JSON serialization. + // Tool input, limited to 4 MiB after JSON serialization. Input map[string]any `json:"input,omitzero" api:"required"` ToolRef string `json:"tool_ref" api:"required"` TimeoutSec param.Opt[int64] `json:"timeout_sec,omitzero"` From df833447061474b8abc81d1b663d272f8862d7ee Mon Sep 17 00:00:00 2001 From: Rafael Date: Tue, 3 Nov 2026 10:00:48 -0500 Subject: [PATCH 2/5] Run the CLI updater on release and report on the whole evergreen PR (#14) * Run the CLI updater on release and report on the whole evergreen PR * Fetch full SDK history so the CLI updater can diff from older tags --------- Co-authored-by: rgarcia <72655+rgarcia@users.noreply.github.com> --- .github/workflows/update-cli-coverage.yml | 46 +++++++++++------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/update-cli-coverage.yml b/.github/workflows/update-cli-coverage.yml index 1b486bf5..6b710e70 100644 --- a/.github/workflows/update-cli-coverage.yml +++ b/.github/workflows/update-cli-coverage.yml @@ -1,17 +1,15 @@ name: Update CLI Coverage on: - push: - branches: [main] + # A push to main can run before release-please tags the release. + release: + types: [published] workflow_dispatch: inputs: pr_number: description: 'PR number to use for context (leave empty to use most recent merged PR)' required: false type: string - # Or trigger on releases: - # release: - # types: [published] permissions: contents: read @@ -84,8 +82,8 @@ jobs: uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: persist-credentials: false - fetch-depth: 2 - fetch-tags: true + # The SDK diff starts at CLI main's version, which can be several tags back. + fetch-depth: 0 # For manual dispatch with a specific PR, checkout the merge commit ref: ${{ steps.pr-info.outputs.merge_sha || github.sha }} @@ -153,9 +151,11 @@ jobs: - name: Get SDK version info id: sdk-version + env: + RELEASE_TAG: ${{ github.event.release.tag_name }} run: | - # Get the latest tag if available, otherwise use commit SHA - LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + # Use the published release, else the latest tag, else the commit SHA + LATEST_TAG=${RELEASE_TAG:-$(git describe --tags --abbrev=0 2>/dev/null || echo "")} if [ -n "$LATEST_TAG" ]; then echo "version=$LATEST_TAG" >> $GITHUB_OUTPUT echo "SDK version: $LATEST_TAG" @@ -177,18 +177,15 @@ jobs: echo "author=${{ github.event.head_commit.author.username || github.actor }}" >> $GITHUB_OUTPUT fi - - name: Compute SDK diff since CLI's current version + - name: Compute SDK diff since CLI main's version id: sdk-diff run: | - # Extract the SDK version currently used by the CLI - # Prefer go list (parses go.mod properly); fall back to grep, taking the - # first non-conflict-marker match so a merge conflict can't yield a - # multi-line value that breaks $GITHUB_OUTPUT. - OLD_SDK_VERSION=$(cd /tmp/kernel-cli && go list -m github.com/kernel/kernel-go-sdk 2>/dev/null | awk '{print $2}') - if [ -z "$OLD_SDK_VERSION" ]; then - OLD_SDK_VERSION=$(grep 'kernel/kernel-go-sdk' /tmp/kernel-cli/go.mod | grep -v '^[<>=]' | head -1 | awk '{print $2}') - fi - echo "CLI currently uses SDK version: $OLD_SDK_VERSION" + # The report replaces the PR description, so audit every release since + # the SDK version on CLI main, not only the ones since the last run. + git -C /tmp/kernel-cli show origin/main:go.mod > "$RUNNER_TEMP/cli-main-go.mod" + OLD_SDK_VERSION=$(go mod edit -json "$RUNNER_TEMP/cli-main-go.mod" \ + | jq -er '.Require[] | select(.Path == "github.com/kernel/kernel-go-sdk") | .Version') + echo "CLI main uses SDK version: $OLD_SDK_VERSION" echo "old_version=$OLD_SDK_VERSION" >> $GITHUB_OUTPUT NEW_SDK_VERSION="${{ steps.sdk-version.outputs.version }}" @@ -278,15 +275,16 @@ jobs: # Background The Go SDK (this repo) was just updated by Stainless, and may contain new API methods. The CLI (kernel/cli) needs to be updated to expose these new methods as CLI commands. - The CLI was previously on SDK version ${{ steps.sdk-diff.outputs.old_version }}, and we are updating it to ${{ steps.sdk-version.outputs.version }}. + The CLI main branch is on SDK version ${{ steps.sdk-diff.outputs.old_version }}, and we are updating it to ${{ steps.sdk-version.outputs.version }}. + The update branch may already hold coverage from earlier runs for releases in between; keep it and build on it. # Source Files - SDK api.md: Current directory - READ THIS FILE FIRST. This is the authoritative list of all SDK methods and their signatures. - SDK *.go files: Current directory - Contains param structs (e.g., BrowserNewParams, DeploymentListParams) with all available options/fields. - - SDK diff: /tmp/sdk-diff.patch - IMPORTANT: This is the diff of api.md and Go source files between the CLI's current SDK version (${{ steps.sdk-diff.outputs.old_version }}) and the new version (${{ steps.sdk-version.outputs.version }}). Read this file to see exactly what methods, params, and fields were added or changed. Any additions here MUST be reflected in the CLI. + - SDK diff: /tmp/sdk-diff.patch - IMPORTANT: This is the diff of api.md and Go source files between the SDK version on CLI main (${{ steps.sdk-diff.outputs.old_version }}) and the new version (${{ steps.sdk-version.outputs.version }}). Read this file to see exactly what methods, params, and fields were added or changed. Any additions here MUST be reflected in the CLI. - API Spec: /tmp/kernel-api/packages/api/stainless.yaml - SDK configuration with resources and methods - API Spec: /tmp/kernel-api/packages/api/openapi.yaml - Full OpenAPI specification. CHECK for x-cli-skip: true on endpoints - skip those from CLI coverage. - - API Spec diff: /tmp/openapi-diff.patch - Spec changes between the CLI's current SDK version and the new one, including endpoint, parameter, and field description changes. + - API Spec diff: /tmp/openapi-diff.patch - Spec changes between the SDK version on CLI main and the new one, including endpoint, parameter, and field description changes. - CLI: /tmp/kernel-cli - Existing CLI commands # Task @@ -299,7 +297,7 @@ jobs: - This ensures the CLI always uses the latest SDK, even if no new commands are added ## Step 2: Review SDK Diff (CRITICAL - DO THIS BEFORE THE FULL ENUMERATION) - Read /tmp/sdk-diff.patch to see exactly what changed in the SDK between the CLI's current version and the new version. + Read /tmp/sdk-diff.patch to see exactly what changed in the SDK between the version on CLI main and the new version. This diff shows new methods, new param fields, and changed signatures — these are the changes most likely to need CLI coverage. Treat every addition in this diff as a checklist item: each new method needs a CLI command, each new param field needs a CLI flag. After verifying these are covered, proceed to the full enumeration below to catch anything else. @@ -394,6 +392,7 @@ jobs: ## Step 8: Review and Report - Read the full diff against origin/main and remove unrelated changes or unnecessary wrappers/casts. - Write $RUNNER_TEMP/cli-coverage-report.md with the new commands/flags, help text updated to match spec changes (with the spec operation or field each follows), intentional exclusions, and test results or limitations. + - The report replaces the PR description, so it must describe every change in the diff against origin/main, including changes earlier runs left on this branch, not only this run's. - The report becomes part of a public PR. Include no credentials, customer information, private discussions, or internal URLs. - Do not commit, push, change git authentication, or open PRs. Leave the changes for the workflow to validate and publish. - Only go.mod, go.sum, and .go files under cmd/ and pkg/ are published. The workflow discards every other change before validation. @@ -471,6 +470,7 @@ jobs: - ALWAYS perform the full enumeration (Steps 2-4) - this is critical for finding gaps - ALL SDK methods in api.md MUST have corresponding CLI commands, EXCEPT those marked with x-cli-skip in openapi.yaml - SKIP endpoints marked with x-cli-skip: true in openapi.yaml - these are internal endpoints (e.g., hosted UI auth flows) not suitable for CLI + - The API spec is taken from the API's main branch at release time and can be ahead of the released SDK. The SDK defines what exists: never add commands or flags for operations or fields this SDK version does not have. Use the spec only for the meaning of things the SDK has. - Streaming methods may have different CLI implementations (e.g., follow flags) - Even if no coverage gaps are found, still leave the SDK version bump and write the coverage report - Ensure code compiles before finishing From 34a9b40c4f814388551374fbd6b5df259e57113a Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Tue, 3 Nov 2026 17:04:22 +0000 Subject: [PATCH 3/5] feat: Drop Kernel's origin gate from 1Password fill Stainless-Generated-From: 3cdabb505d7b51988f5b58555d76d629f85fab8c --- vaultitem.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/vaultitem.go b/vaultitem.go index 93f5d488..03904dc7 100644 --- a/vaultitem.go +++ b/vaultitem.go @@ -4640,10 +4640,12 @@ func (r *OnePasswordCredentialVaultItemStateAccessRequestResolved) UnmarshalJSON } // Fill and submit an approved 1Password login in the selected browser page. The -// page must share the selected entry's login origin. Supply entry_id when more -// than one approved entry matches the page origin, and target_id when more than -// one open page has page_url. The extension selects fields; callers cannot supply -// selectors or secret values. Submission does not confirm website authentication. +// 1Password extension decides whether the approved login matches the page and +// refuses pages that don't. Supply entry_id when several entries are approved and +// the page origin does not identify exactly one of them, and target_id when more +// than one open page has page_url. The extension selects fields; callers cannot +// supply selectors or secret values. Submission does not confirm website +// authentication. // // The properties BrowserID, PageURL, Type are required. type OnePasswordFillVaultItemOperationRequestParam struct { @@ -4654,8 +4656,8 @@ type OnePasswordFillVaultItemOperationRequestParam struct { PageURL string `json:"page_url" api:"required" format:"uri"` // Any of "1pw_fill". Type OnePasswordFillVaultItemOperationRequestType `json:"type,omitzero" api:"required"` - // ID of an approved request entry. Required when several approved entries have the - // page's origin. + // ID of an approved request entry. Required when several entries are approved and + // the page's origin does not match exactly one of them. EntryID param.Opt[string] `json:"entry_id,omitzero"` // CDP target ID of the page to fill, such as tab.target_id from // playwright.execute. Use it when several open pages have page_url. The page's @@ -9450,11 +9452,13 @@ type VaultItemPerformOperationParams struct { // references in state.access_request.resolved. Of1pwAccessRequestStatus *VaultItemPerformOperationParamsBody1pwAccessRequestStatus `json:",inline"` // This field is a request body variant, only one variant field can be set. Fill - // and submit an approved 1Password login in the selected browser page. The page - // must share the selected entry's login origin. Supply entry_id when more than one - // approved entry matches the page origin, and target_id when more than one open - // page has page_url. The extension selects fields; callers cannot supply selectors - // or secret values. Submission does not confirm website authentication. + // and submit an approved 1Password login in the selected browser page. The + // 1Password extension decides whether the approved login matches the page and + // refuses pages that don't. Supply entry_id when several entries are approved and + // the page origin does not identify exactly one of them, and target_id when more + // than one open page has page_url. The extension selects fields; callers cannot + // supply selectors or secret values. Submission does not confirm website + // authentication. Of1pwFill *OnePasswordFillVaultItemOperationRequestParam `json:",inline"` // This field is a request body variant, only one variant field can be set. Kernel // encountered a recoverable error while linking this 1Password account. Use this From f1dab109b5d4dc03674d56394f866a87b81ad60d Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Wed, 4 Nov 2026 04:07:44 +0000 Subject: [PATCH 4/5] feat: Add single-use Kernel cards to vaults Stainless-Generated-From: 85a90444d4c2b58975648a936a000f4272c28668 --- api.md | 4 + vaultitem.go | 302 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 285 insertions(+), 21 deletions(-) diff --git a/api.md b/api.md index 7c6d8058..fdd440db 100644 --- a/api.md +++ b/api.md @@ -568,6 +568,7 @@ Params Types: - kernel.KernelCardVaultItemSpecParam - kernel.KernelCredentialVaultItemSpecInputParam - kernel.KernelPaymentRequestVaultItemSpecParam +- kernel.KernelSingleUseCardParam - kernel.KernelWalletVaultItemSpecParam - kernel.ManagedAuthCredentialVaultItemSpecInputParam - kernel.OnePasswordCredentialAccountSpecParam @@ -582,6 +583,7 @@ Params Types: - kernel.RestartVerificationVaultItemOperationRequestParam - kernel.ShopPayCardVaultItemSpecParam - kernel.ShopPayWalletVaultItemSpecParam +- kernel.SingleUseCardBillingAddressParam - kernel.VaultCheckoutContextParam - kernel.VaultFillFieldParam - kernel.VaultWebmcpBindingParam @@ -609,6 +611,7 @@ Response Types: - kernel.KernelCredentialVaultItemSpec - kernel.KernelCredentialVaultItemState - kernel.KernelPaymentRequestVaultItemSpec +- kernel.KernelSingleUseCard - kernel.KernelWalletState - kernel.KernelWalletVaultItemSpec - kernel.LinkShippingAddress @@ -631,6 +634,7 @@ Response Types: - kernel.ShopPayCardVaultItemSpec - kernel.ShopPayWalletState - kernel.ShopPayWalletVaultItemSpec +- kernel.SingleUseCardBillingAddress - kernel.VaultCardAliases - kernel.VaultFillFieldResult - kernel.VaultItemUnion diff --git a/vaultitem.go b/vaultitem.go index 03904dc7..04c945dc 100644 --- a/vaultitem.go +++ b/vaultitem.go @@ -572,11 +572,15 @@ type CardVaultItemSpecUnion struct { // This field is from variant [CardVaultItemSpecAgentcard]. CheckoutOrigin string `json:"checkout_origin"` // This field is from variant [KernelCardVaultItemSpec]. + ExpiresAt time.Time `json:"expires_at"` + // This field is from variant [KernelCardVaultItemSpec]. MerchantCategory string `json:"merchant_category"` // This field is from variant [KernelCardVaultItemSpec]. MerchantCategoryCode string `json:"merchant_category_code"` MerchantCountry string `json:"merchant_country"` - JSON struct { + // This field is from variant [KernelCardVaultItemSpec]. + SingleUseCard KernelSingleUseCard `json:"single_use_card"` + JSON struct { Amount respjson.Field Context respjson.Field Currency respjson.Field @@ -592,9 +596,11 @@ type CardVaultItemSpecUnion struct { Merchant respjson.Field CardID respjson.Field CheckoutOrigin respjson.Field + ExpiresAt respjson.Field MerchantCategory respjson.Field MerchantCategoryCode respjson.Field MerchantCountry respjson.Field + SingleUseCard respjson.Field raw string } `json:"-"` } @@ -1005,6 +1011,14 @@ func (u CardVaultItemSpecUnionParam) GetCheckoutOrigin() *string { return nil } +// Returns a pointer to the underlying variant's property, if present. +func (u CardVaultItemSpecUnionParam) GetExpiresAt() *time.Time { + if vt := u.OfKernel; vt != nil && vt.ExpiresAt.Valid() { + return &vt.ExpiresAt.Value + } + return nil +} + // Returns a pointer to the underlying variant's property, if present. func (u CardVaultItemSpecUnionParam) GetMerchantCategory() *string { if vt := u.OfKernel; vt != nil && vt.MerchantCategory.Valid() { @@ -1021,6 +1035,14 @@ func (u CardVaultItemSpecUnionParam) GetMerchantCategoryCode() *string { return nil } +// Returns a pointer to the underlying variant's property, if present. +func (u CardVaultItemSpecUnionParam) GetSingleUseCard() *KernelSingleUseCardParam { + if vt := u.OfKernel; vt != nil { + return &vt.SingleUseCard + } + return nil +} + // Returns a pointer to the underlying variant's property, if present. func (u CardVaultItemSpecUnionParam) GetAmount() *int64 { if vt := u.OfLink; vt != nil { @@ -1398,6 +1420,8 @@ type CardVaultItemStateUnion struct { // This field is from variant [CardVaultItemStateAgentcard]. Preparation AgentcardCheckoutPreparation `json:"preparation"` // This field is from variant [KernelCardState]. + Source KernelCardStateSource `json:"source"` + // This field is from variant [KernelCardState]. FundingStatus KernelCardStateFundingStatus `json:"funding_status"` // This field is from variant [KernelCardState]. PaymentMethodID string `json:"payment_method_id"` @@ -1410,6 +1434,7 @@ type CardVaultItemStateUnion struct { Aliases respjson.Field Authorization respjson.Field Preparation respjson.Field + Source respjson.Field FundingStatus respjson.Field PaymentMethodID respjson.Field raw string @@ -2959,16 +2984,24 @@ const ( FillVaultItemOperationResultTypeFill FillVaultItemOperationResultType = "fill" ) -// 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. +// A ready Kernel card funded by a payment method supports authorize, fill, then +// submit checkout. A single-use card (source single_use_card) is ready on +// creation, supports only fill, and is expired from expires_at; Kernel deletes its +// stored details shortly after expires_at. It has no payment_method_id or +// funding_status. 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. type KernelCardState struct { // Any of "kernel". Provider KernelCardStateProvider `json:"provider" api:"required"` + // payment_method for a purchase funded by a wallet payment method; single_use_card + // for a card whose details were supplied with single_use_card. + // + // Any of "payment_method", "single_use_card". + Source KernelCardStateSource `json:"source" api:"required"` // pending_authorization waits for cardholder approval on Visa purchases or fresh // security-code collection on alias-mode purchases through the spend_approval // action; an unused link expires after 30 minutes. Alias-mode cards become ready @@ -2990,7 +3023,9 @@ type KernelCardState struct { // Any of "requested", "pending_authorization", "ready", "consumed", "expired", // "declined", "recovery_required". Status KernelCardStateStatus `json:"status" api:"required"` - // Informational registrable domain. Fill is locked to merchant_url's exact origin. + // Informational registrable domain. Fill is locked to merchant_url's exact origin, + // except that a single-use card fills on any https page of this registrable + // domain. Domains []string `json:"domains"` // Whether payment_method_id can still fund this purchase. unavailable means the // method is being removed or awaits recovery, so authorization, fill and @@ -3010,6 +3045,7 @@ type KernelCardState struct { // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { Provider respjson.Field + Source respjson.Field Status respjson.Field Domains respjson.Field FundingStatus respjson.Field @@ -3033,6 +3069,15 @@ const ( KernelCardStateProviderKernel KernelCardStateProvider = "kernel" ) +// payment_method for a purchase funded by a wallet payment method; single_use_card +// for a card whose details were supplied with single_use_card. +type KernelCardStateSource string + +const ( + KernelCardStateSourcePaymentMethod KernelCardStateSource = "payment_method" + KernelCardStateSourceSingleUseCard KernelCardStateSource = "single_use_card" +) + // pending_authorization waits for cardholder approval on Visa purchases or fresh // security-code collection on alias-mode purchases through the spend_approval // action; an unused link expires after 30 minutes. Alias-mode cards become ready @@ -3113,7 +3158,18 @@ func (r *KernelCardStateMasks) UnmarshalJSON(data []byte) error { // after collection. An expired card requires a new purchase. 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. +// updates are not supported; delete and create a new item instead. With +// single_use_card the item is instead a single-use card whose details the caller +// supplies, such as a virtual card from its issuer. It is not funded by a payment +// method, is ready on creation, and supports only fill: Kernel stores the details +// encrypted, never returns them, and fills them on any https page whose +// registrable domain (state.domains) is merchant_url's, including its subdomains. +// Fill does not consume it. From expires_at it is expired and can no longer be +// filled; Kernel deletes its stored details shortly after expires_at. Deleting the +// card, its wallet or its vault deletes them immediately. amount, currency and the +// merchant fields are recorded but not enforced. Repeating the identical request +// returns the existing card; any other request with the same key returns 409, as +// does repeating it once the expired card's details have been deleted. type KernelCardVaultItemSpec struct { // Integer amount in minor currency units (at most 1000000), bound to the one-time // code. @@ -3128,6 +3184,13 @@ type KernelCardVaultItemSpec struct { Provider KernelCardVaultItemSpecProvider `json:"provider" api:"required"` // Key of the Kernel wallet item whose enrolled card pays. Wallet string `json:"wallet" api:"required"` + // Single-use cards only. From this time the card is expired and can no longer be + // filled; Kernel deletes its stored details shortly after. Deleting the card, its + // wallet or its vault deletes them immediately. Defaults to 2 hours after + // creation, capped at the end of the card's expiry month; a requested time must be + // in the future, at most 24 hours after creation, and not after the end of the + // card's expiry month. Returned in UTC. + ExpiresAt time.Time `json:"expires_at" format:"date-time"` // Actual merchant category when known. Omit rather than invent a category. MerchantCategory string `json:"merchant_category"` // Actual merchant MCC when known. Omit rather than invent a code. 0000 is not @@ -3140,8 +3203,16 @@ type KernelCardVaultItemSpec struct { // Omission selects the wallet's default card, ID card, for compatibility with // existing requests; it never falls back to another method, and a wallet without a // default card requires the ID. The purchase is bound to the method's enrolled - // card and network token, so later operations cannot switch funding. + // card and network token, so later operations cannot switch funding. Not allowed + // with single_use_card. PaymentMethodID string `json:"payment_method_id"` + // Details of a card the caller supplies, such as a single-use virtual card from + // its issuer. Mutually exclusive with payment_method_id. The card details are + // stored encrypted for fill and never returned; reads return only reference. + // Kernel deletes them shortly after the card's expires_at; deleting the card, its + // wallet or its vault deletes them immediately. A card whose expiry month has + // ended is rejected. + SingleUseCard KernelSingleUseCard `json:"single_use_card"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { Amount respjson.Field @@ -3150,10 +3221,12 @@ type KernelCardVaultItemSpec struct { MerchantURL respjson.Field Provider respjson.Field Wallet respjson.Field + ExpiresAt respjson.Field MerchantCategory respjson.Field MerchantCategoryCode respjson.Field MerchantCountry respjson.Field PaymentMethodID respjson.Field + SingleUseCard respjson.Field ExtraFields map[string]respjson.Field raw string } `json:"-"` @@ -3195,7 +3268,18 @@ const ( // after collection. An expired card requires a new purchase. 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. +// updates are not supported; delete and create a new item instead. With +// single_use_card the item is instead a single-use card whose details the caller +// supplies, such as a virtual card from its issuer. It is not funded by a payment +// method, is ready on creation, and supports only fill: Kernel stores the details +// encrypted, never returns them, and fills them on any https page whose +// registrable domain (state.domains) is merchant_url's, including its subdomains. +// Fill does not consume it. From expires_at it is expired and can no longer be +// filled; Kernel deletes its stored details shortly after expires_at. Deleting the +// card, its wallet or its vault deletes them immediately. amount, currency and the +// merchant fields are recorded but not enforced. Repeating the identical request +// returns the existing card; any other request with the same key returns 409, as +// does repeating it once the expired card's details have been deleted. // // The properties Amount, Currency, MerchantName, MerchantURL, Provider, Wallet are // required. @@ -3213,6 +3297,13 @@ type KernelCardVaultItemSpecParam struct { Provider KernelCardVaultItemSpecProvider `json:"provider,omitzero" api:"required"` // Key of the Kernel wallet item whose enrolled card pays. Wallet string `json:"wallet" api:"required"` + // Single-use cards only. From this time the card is expired and can no longer be + // filled; Kernel deletes its stored details shortly after. Deleting the card, its + // wallet or its vault deletes them immediately. Defaults to 2 hours after + // creation, capped at the end of the card's expiry month; a requested time must be + // in the future, at most 24 hours after creation, and not after the end of the + // card's expiry month. Returned in UTC. + ExpiresAt param.Opt[time.Time] `json:"expires_at,omitzero" format:"date-time"` // Actual merchant category when known. Omit rather than invent a category. MerchantCategory param.Opt[string] `json:"merchant_category,omitzero"` // Actual merchant MCC when known. Omit rather than invent a code. 0000 is not @@ -3225,8 +3316,16 @@ type KernelCardVaultItemSpecParam struct { // Omission selects the wallet's default card, ID card, for compatibility with // existing requests; it never falls back to another method, and a wallet without a // default card requires the ID. The purchase is bound to the method's enrolled - // card and network token, so later operations cannot switch funding. + // card and network token, so later operations cannot switch funding. Not allowed + // with single_use_card. PaymentMethodID param.Opt[string] `json:"payment_method_id,omitzero"` + // Details of a card the caller supplies, such as a single-use virtual card from + // its issuer. Mutually exclusive with payment_method_id. The card details are + // stored encrypted for fill and never returned; reads return only reference. + // Kernel deletes them shortly after the card's expires_at; deleting the card, its + // wallet or its vault deletes them immediately. A card whose expiry month has + // ended is rejected. + SingleUseCard KernelSingleUseCardParam `json:"single_use_card,omitzero"` paramObj } @@ -3458,6 +3557,86 @@ func (r *KernelPaymentRequestVaultItemSpecParam) UnmarshalJSON(data []byte) erro return apijson.UnmarshalRoot(data, r) } +// Details of a card the caller supplies, such as a single-use virtual card from +// its issuer. Mutually exclusive with payment_method_id. The card details are +// stored encrypted for fill and never returned; reads return only reference. +// Kernel deletes them shortly after the card's expires_at; deleting the card, its +// wallet or its vault deletes them immediately. A card whose expiry month has +// ended is rejected. +type KernelSingleUseCard struct { + Cvc string `json:"cvc" api:"required"` + ExpMonth string `json:"exp_month" api:"required"` + ExpYear string `json:"exp_year" api:"required"` + // Card number; must pass the Luhn check. + Number string `json:"number" api:"required"` + // Billing address filled with the billing\_\* fill fields. Never returned. + BillingAddress SingleUseCardBillingAddress `json:"billing_address"` + // Cardholder name, filled as billing_name. + Name string `json:"name"` + // The caller's identifier for the card, such as the issuer's card ID. Returned + // unchanged on reads. + Reference string `json:"reference"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Cvc respjson.Field + ExpMonth respjson.Field + ExpYear respjson.Field + Number respjson.Field + BillingAddress respjson.Field + Name respjson.Field + Reference respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r KernelSingleUseCard) RawJSON() string { return r.JSON.raw } +func (r *KernelSingleUseCard) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// ToParam converts this KernelSingleUseCard to a KernelSingleUseCardParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// KernelSingleUseCardParam.Overrides() +func (r KernelSingleUseCard) ToParam() KernelSingleUseCardParam { + return param.Override[KernelSingleUseCardParam](json.RawMessage(r.RawJSON())) +} + +// Details of a card the caller supplies, such as a single-use virtual card from +// its issuer. Mutually exclusive with payment_method_id. The card details are +// stored encrypted for fill and never returned; reads return only reference. +// Kernel deletes them shortly after the card's expires_at; deleting the card, its +// wallet or its vault deletes them immediately. A card whose expiry month has +// ended is rejected. +// +// The properties Cvc, ExpMonth, ExpYear, Number are required. +type KernelSingleUseCardParam struct { + Cvc string `json:"cvc" api:"required"` + ExpMonth string `json:"exp_month" api:"required"` + ExpYear string `json:"exp_year" api:"required"` + // Card number; must pass the Luhn check. + Number string `json:"number" api:"required"` + // Cardholder name, filled as billing_name. + Name param.Opt[string] `json:"name,omitzero"` + // The caller's identifier for the card, such as the issuer's card ID. Returned + // unchanged on reads. + Reference param.Opt[string] `json:"reference,omitzero"` + // Billing address filled with the billing\_\* fill fields. Never returned. + BillingAddress SingleUseCardBillingAddressParam `json:"billing_address,omitzero"` + paramObj +} + +func (r KernelSingleUseCardParam) MarshalJSON() (data []byte, err error) { + type shadow KernelSingleUseCardParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *KernelSingleUseCardParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + type KernelWalletState struct { // Any of "kernel". Provider KernelWalletStateProvider `json:"provider" api:"required"` @@ -5571,6 +5750,8 @@ type PaymentRequestVaultItemStateUnion struct { Masks PaymentRequestVaultItemStateUnionMasks `json:"masks"` StatusReason string `json:"status_reason"` // This field is from variant [KernelCardState]. + Source KernelCardStateSource `json:"source"` + // This field is from variant [KernelCardState]. FundingStatus KernelCardStateFundingStatus `json:"funding_status"` // This field is from variant [KernelCardState]. PaymentMethodID string `json:"payment_method_id"` @@ -5580,6 +5761,7 @@ type PaymentRequestVaultItemStateUnion struct { Domains respjson.Field Masks respjson.Field StatusReason respjson.Field + Source respjson.Field FundingStatus respjson.Field PaymentMethodID respjson.Field raw string @@ -6335,6 +6517,64 @@ func init() { ) } +// Billing address filled with the billing\_\* fill fields. Never returned. +type SingleUseCardBillingAddress struct { + City string `json:"city"` + // ISO 3166-1 alpha-2 code. + Country string `json:"country"` + Line1 string `json:"line1"` + Line2 string `json:"line2"` + PostalCode string `json:"postal_code"` + State string `json:"state"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + City respjson.Field + Country respjson.Field + Line1 respjson.Field + Line2 respjson.Field + PostalCode respjson.Field + State respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r SingleUseCardBillingAddress) RawJSON() string { return r.JSON.raw } +func (r *SingleUseCardBillingAddress) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// ToParam converts this SingleUseCardBillingAddress to a +// SingleUseCardBillingAddressParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// SingleUseCardBillingAddressParam.Overrides() +func (r SingleUseCardBillingAddress) ToParam() SingleUseCardBillingAddressParam { + return param.Override[SingleUseCardBillingAddressParam](json.RawMessage(r.RawJSON())) +} + +// Billing address filled with the billing\_\* fill fields. Never returned. +type SingleUseCardBillingAddressParam struct { + City param.Opt[string] `json:"city,omitzero"` + // ISO 3166-1 alpha-2 code. + Country param.Opt[string] `json:"country,omitzero"` + Line1 param.Opt[string] `json:"line1,omitzero"` + Line2 param.Opt[string] `json:"line2,omitzero"` + PostalCode param.Opt[string] `json:"postal_code,omitzero"` + State param.Opt[string] `json:"state,omitzero"` + paramObj +} + +func (r SingleUseCardBillingAddressParam) MarshalJSON() (data []byte, err error) { + type shadow SingleUseCardBillingAddressParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *SingleUseCardBillingAddressParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + type VaultCardAliases struct { Cvc string `json:"cvc" api:"required"` ExpMonth string `json:"exp_month" api:"required"` @@ -6752,10 +6992,14 @@ type VaultItemUnionSpec struct { // This field is from variant [CardVaultItemSpecUnion]. CardID string `json:"card_id"` // This field is from variant [CardVaultItemSpecUnion]. - CheckoutOrigin string `json:"checkout_origin"` - MerchantCategory string `json:"merchant_category"` - MerchantCategoryCode string `json:"merchant_category_code"` - MerchantCountry string `json:"merchant_country"` + CheckoutOrigin string `json:"checkout_origin"` + // This field is from variant [CardVaultItemSpecUnion]. + ExpiresAt time.Time `json:"expires_at"` + MerchantCategory string `json:"merchant_category"` + MerchantCategoryCode string `json:"merchant_category_code"` + MerchantCountry string `json:"merchant_country"` + // This field is from variant [CardVaultItemSpecUnion]. + SingleUseCard KernelSingleUseCard `json:"single_use_card"` // This field is from variant [CredentialVaultItemSpecUnion]. Fields []CredentialVaultFieldDefinition `json:"fields"` Description string `json:"description"` @@ -6786,9 +7030,11 @@ type VaultItemUnionSpec struct { Merchant respjson.Field CardID respjson.Field CheckoutOrigin respjson.Field + ExpiresAt respjson.Field MerchantCategory respjson.Field MerchantCategoryCode respjson.Field MerchantCountry respjson.Field + SingleUseCard respjson.Field Fields respjson.Field Description respjson.Field Requests respjson.Field @@ -6956,6 +7202,9 @@ type VaultItemUnionState struct { Preparation AgentcardCheckoutPreparation `json:"preparation"` // This field is from variant [CardVaultItemStateUnion], // [PaymentRequestVaultItemStateUnion]. + Source KernelCardStateSource `json:"source"` + // This field is from variant [CardVaultItemStateUnion], + // [PaymentRequestVaultItemStateUnion]. FundingStatus KernelCardStateFundingStatus `json:"funding_status"` // This field is from variant [CardVaultItemStateUnion], // [PaymentRequestVaultItemStateUnion]. @@ -6977,6 +7226,7 @@ type VaultItemUnionState struct { Aliases respjson.Field Authorization respjson.Field Preparation respjson.Field + Source respjson.Field FundingStatus respjson.Field PaymentMethodID respjson.Field Fields respjson.Field @@ -7872,10 +8122,14 @@ type VaultItemOperationResponseUnionSpec struct { // This field is from variant [CardVaultItemSpecUnion]. CardID string `json:"card_id"` // This field is from variant [CardVaultItemSpecUnion]. - CheckoutOrigin string `json:"checkout_origin"` - MerchantCategory string `json:"merchant_category"` - MerchantCategoryCode string `json:"merchant_category_code"` - MerchantCountry string `json:"merchant_country"` + CheckoutOrigin string `json:"checkout_origin"` + // This field is from variant [CardVaultItemSpecUnion]. + ExpiresAt time.Time `json:"expires_at"` + MerchantCategory string `json:"merchant_category"` + MerchantCategoryCode string `json:"merchant_category_code"` + MerchantCountry string `json:"merchant_country"` + // This field is from variant [CardVaultItemSpecUnion]. + SingleUseCard KernelSingleUseCard `json:"single_use_card"` // This field is from variant [CredentialVaultItemSpecUnion]. Fields []CredentialVaultFieldDefinition `json:"fields"` Description string `json:"description"` @@ -7906,9 +8160,11 @@ type VaultItemOperationResponseUnionSpec struct { Merchant respjson.Field CardID respjson.Field CheckoutOrigin respjson.Field + ExpiresAt respjson.Field MerchantCategory respjson.Field MerchantCategoryCode respjson.Field MerchantCountry respjson.Field + SingleUseCard respjson.Field Fields respjson.Field Description respjson.Field Requests respjson.Field @@ -8078,6 +8334,9 @@ type VaultItemOperationResponseUnionState struct { Preparation AgentcardCheckoutPreparation `json:"preparation"` // This field is from variant [CardVaultItemStateUnion], // [PaymentRequestVaultItemStateUnion]. + Source KernelCardStateSource `json:"source"` + // This field is from variant [CardVaultItemStateUnion], + // [PaymentRequestVaultItemStateUnion]. FundingStatus KernelCardStateFundingStatus `json:"funding_status"` // This field is from variant [CardVaultItemStateUnion], // [PaymentRequestVaultItemStateUnion]. @@ -8099,6 +8358,7 @@ type VaultItemOperationResponseUnionState struct { Aliases respjson.Field Authorization respjson.Field Preparation respjson.Field + Source respjson.Field FundingStatus respjson.Field PaymentMethodID respjson.Field Fields respjson.Field From 6953408a9703d397966f2f71cea66e330c89dc2f Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Wed, 4 Nov 2026 04:13:08 +0000 Subject: [PATCH 5/5] release: 0.139.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 9 +++++++++ README.md | 2 +- internal/version.go | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1aec2271..b84fc160 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.138.0" + ".": "0.139.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6997517c..d8834d96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [0.139.0](https://github.com/kernel/kernel-go-sdk/compare/v0.138.0...v0.139.0) (2026-11-04) + + +### Features + +* Add single-use Kernel cards to vaults ([f1dab10](https://github.com/kernel/kernel-go-sdk/commit/f1dab109b5d4dc03674d56394f866a87b81ad60d)) +* Drop Kernel's origin gate from 1Password fill ([34a9b40](https://github.com/kernel/kernel-go-sdk/commit/34a9b40c4f814388551374fbd6b5df259e57113a)) +* Pass through tool_page_unloaded and disable SDK retries for WebMCP invoke failures ([a665adc](https://github.com/kernel/kernel-go-sdk/commit/a665adcb96641db34148f14e15c891458a30fa59)) + ## [0.138.0](https://github.com/kernel/kernel-go-sdk/compare/v0.137.0...v0.138.0) (2026-10-30) diff --git a/README.md b/README.md index e1080669..31583c8d 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Or to pin the version: ```sh -go get -u 'github.com/kernel/kernel-go-sdk@v0.138.0' +go get -u 'github.com/kernel/kernel-go-sdk@v0.139.0' ``` diff --git a/internal/version.go b/internal/version.go index 984961b4..024b2579 100644 --- a/internal/version.go +++ b/internal/version.go @@ -2,4 +2,4 @@ package internal -const PackageVersion = "0.138.0" // x-release-please-version +const PackageVersion = "0.139.0" // x-release-please-version