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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions browsers/enable-payments-in-browser-agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ credential is created and when the user approves it:
| card source | provider-minted, one-use card for a specific purchase | user's enrolled card, represented by a reusable card item |
| approval timing | before the browser submits checkout | after the browser submits checkout and while the request is held |
| reuse | card item and aliases are consumed after the first native handoff | card item and aliases return to `ready`; every checkout requires approval |
| mode | live only | deployment credential; the vault api doesn't expose sandbox or live mode |
| mode | live only | credential-defined; customer-owned configs expose `test_mode` |

agentcard is backed by a card the user enrolls, but the agent and browser still
enter aliases rather than the underlying card details. those details remain
Expand Down Expand Up @@ -141,7 +141,11 @@ this guide starts after you have an existing browser agent. it changes how you p
- set `KERNEL_API_KEY` and `KERNEL_PROJECT_ID` in the trusted controller that creates your browser.
- use a low-value web checkout you control whose outgoing payment request matches a [native processor adapter](/integrations/payments/overview#checkout-and-processor-coverage). the merchant processor doesn't need to be stripe.
- link card creation is live-only. agentcard mode comes from the integration's configured credential.
- for agentcard, keep an application-owned `AGENTCARD_MODE` deployment setting and fail closed unless it explicitly matches the sandbox or live environment you intend to use. the vault api does not return this mode.
- for agentcard, keep an application-owned `AGENTCARD_MODE` setting and verify it against the credential's mode. customer-owned configs return `test_mode` (`true` means sandbox); for KERNEL-managed credentials, confirm the deployment's mode. fail closed if the mode is unknown or mismatched.

use KERNEL-managed credentials by default. optional client setup belongs in your
trusted backend, not the browser agent: see [link](/integrations/payments/stripe-link#bring-your-own-link-oauth-client)
or [agentcard](/integrations/payments/agentcard#bring-your-own-agentcard-oauth-client).

<Warning>
keep wallet collection and payment approval outside the agent. show hosted
Expand Down Expand Up @@ -634,6 +638,7 @@ use item state, item events, the checkout page, and the merchant's order record
| link `consumed`, `credential_submitted`, or `credential_tokenized` | confirm processor and merchant state; credential use alone does not prove purchase success |
| agentcard `ready` or authorization `approved` | inspect charge, replay, and merchant state; reusable item state does not prove purchase success |
| decline, expiry, rejection, failure, abandonment, or `payment_unknown` | stop and reconcile the existing attempt before deciding whether a new purchase is appropriate |
| `recovery_required` | stop; reconcile the unresolved provider outcome. do not retry or delete the item or its parent wallet/vault |

use the merchant order record as the authority for whether the expected order
was created and paid. require its merchant, amount, currency, and items to match
Expand Down
25 changes: 25 additions & 0 deletions integrations/payments/agentcard.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -528,3 +528,28 @@ merchant created the expected order. return `indeterminate` when the sources
disagree or the merchant record is unavailable, and don't retry automatically.

pass the aliases to the [browser agent payments guide](/browsers/enable-payments-in-browser-agent) and observe item events while the checkout runs.

# bring-your-own agentcard oauth client

the flow above uses KERNEL-managed credentials. to use your own oauth client,
register a [provider configuration](/vaults#provider-configurations) with
organization-scoped authentication. `agentcard-client.json` must contain
`client_id` and `client_secret`. keep it readable only by its owner (for example,
mode `0600`) and outside the agent's accessible files.

```bash CLI
kernel vault-provider-configs create --name checkout-agentcard --provider agentcard \
--credentials-file "$HOME/.config/kernel/agentcard-client.json"
```

unlike the KERNEL-managed wallet response, this config response exposes
`test_mode` (`true` means sandbox, `false` means live). verify that it matches
your expected mode, then reference the config when creating the wallet:

```bash CLI
kernel vaults wallets create user-12345 agentcard-wallet --provider agentcard \
--provider-config-name checkout-agentcard --spec '{}' --open
```

run `--open` only in a trusted, human-operated terminal. complete the returned
hosted enrollment action, then continue with card creation above.
34 changes: 34 additions & 0 deletions integrations/payments/stripe-link.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -342,3 +342,37 @@ substituted, not that the processor accepted the payment or the merchant created
an order.

don't repeat `authorize` or create a replacement item to retry an unknown purchase. inspect item events and the merchant's order state first.

# bring-your-own link oauth client

prefer KERNEL's oauth client for the flow above. with your own client, your
backend must construct the human-facing authorization url, manage state and
pkce, and handle the redirect. register your backend's callback with stripe,
validate the returned state, and exchange the code using the original pkce
verifier and client credentials. keep the client secret, verifier, and tokens
out of agent context, browser code, urls, and logs.

register a [provider configuration](/vaults#provider-configurations) with
organization-scoped authentication. `link-client.json` must contain `client_id`
and `client_secret`. keep credential and token files readable only by their
owner (for example, mode `0600`) and outside the agent's accessible files.

```bash CLI
kernel vault-provider-configs create --name checkout-link --provider link \
--credentials-file "$HOME/.config/kernel/link-client.json"
```

create the wallet using that config and the grant from your backend's token
exchange. `link-grant.json` must contain `access_token` and `refresh_token` from
the same grant, with a currently valid access token. run this from your trusted
backend or a human-operated terminal, not the agent:

```bash CLI
kernel vaults wallets create user-12345 link-wallet --provider link \
--provider-config-name checkout-link --spec '{}' \
--tokens-file "$HOME/.config/kernel/link-grant.json"
```

successful import returns a `connected` wallet; continue with payment-method
selection. KERNEL takes over refresh-token rotation, so your backend must stop
refreshing that grant.
36 changes: 32 additions & 4 deletions vaults.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,30 @@ read the [payments overview](/integrations/payments/overview) for the shared
lifecycle or use the [link by stripe](/integrations/payments/stripe-link) and
[agentcard](/integrations/payments/agentcard) provider guides.

## provider configurations

use KERNEL-managed credentials by default. if you need your own client, follow
the optional setup in [link](/integrations/payments/stripe-link#bring-your-own-link-oauth-client)
or [agentcard](/integrations/payments/agentcard#bring-your-own-agentcard-oauth-client). a named
provider configuration stores your application's `client_id` and `client_secret`,
not an end user's wallet grant. credentials are encrypted at rest; secrets are
never returned.

configurations are organization-scoped and shared across projects, unlike
project-scoped vaults. create, update, and delete require organization-scoped
authentication; project-scoped api keys receive `403`. names are unique within
the organization, and duplicate creates return `409` without replacing secrets.

- **selection:** choose exactly one config `id` or `name` when creating a wallet. the cli accepts `--provider-config-id` or `--provider-config-name`; responses resolve names to ids.
- **binding:** the wallet's configuration is immutable, and cards inherit it. renaming a config preserves bindings.
- **rotation:** updating `client_secret` affects all bound wallets. provider, client id, and agentcard mode cannot change; changing clients requires a new config and new wallets.
- **deletion:** returns `409` while any non-deleted item references the config, even if disconnected. it does not delete the external oauth client or revoke unrelated grants.
- **recovery:** `recovery_required` means a card's provider outcome is unresolved. it stops item wait loops and blocks new authorization, checkout, and deletion of the card or its parent wallet/vault.

for recovery, inspect existing evidence and contact the provider or support when
manual reconciliation is needed. there is no reset operation; deletion is not
payment recovery.

## Initial item specifications

the initial release accepts these `spec` fields. fields not listed here are rejected.
Expand All @@ -190,8 +214,12 @@ the initial release accepts these `spec` fields. fields not listed here are reje

| provider | required fields | optional fields |
| --------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| link | `provider: 'link'`, `authorization.method: 'oauth'`, `authorization.client.type: 'kernel_managed'` | none |
| agentcard | `provider: 'agentcard'` | `user_id` for a user already enrolled through a wallet in the organization |
| link | `provider: 'link'`, `authorization.method: 'oauth'`, `authorization.client` | write-only `authorization.tokens` is required only with a customer-managed client |
| agentcard | `provider: 'agentcard'` | `provider_config`; `user_id` for a user already enrolled in the organization under the same configuration |

the default link client is `{type: 'kernel_managed'}`. for your own client, set
`authorization.client` to `{type: 'customer_managed', provider_config: {name: 'checkout-link'}}`
and supply `authorization.tokens` with `access_token` and `refresh_token`.

for payment settings ui, enforce at most one wallet per provider in each vault.
the api currently enforces uniqueness by item key, not by wallet provider, so a
Expand Down Expand Up @@ -231,8 +259,8 @@ wallet status values are:

card status values are:

- link: `requested`, `pending_authorization`, `ready`, `consumed`, `expired`, `declined`
- agentcard: `requested`, `ready`, `pending_approval`, `degraded`
- link: `requested`, `pending_authorization`, `ready`, `consumed`, `expired`, `declined`, `recovery_required`
- agentcard: `requested`, `ready`, `pending_approval`, `degraded`, `recovery_required`

card state can include `masks.brand`, `masks.last4`, and read-only aliases: `number`, `cvc`, `exp_month`, and `exp_year`. aliases are non-sensitive stand-ins, not standalone credentials or permission to use the provider-backed value.

Expand Down
Loading