Repository navigation
Authorize Link cards at checkout and steer the Link Pay Token flow - #251
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
bmsaadat
left a comment
There was a problem hiding this comment.
Verdict: Request changes for item 1 (small fix). Item 2 is a test ask; the rest is optional.
The authorize body, the both-or-neither rule, the seven checkout error codes, the optional fields on fill and the PATCH 409 wording all match the API on main. bun test 1055 pass, tsc clean, prettier clean, CI green.
-
Link virtual cards are told not to use
webmcp_invoke, but the API still advertises it (vault-responses.ts:511,webmcp.ts:30,linkCardGuidance, themanage_vault_itemsdescription). When Kernel issues a virtual card,renderVaultItemadvertiseswebmcp_invokenext tofill(only Pay Token cards drop it). The PR now says "for link cards, use the advertised fill operation instead; KERNEL invokes the checkout's webmcp tools itself". That's only true for a Pay Token: a virtual card means the checkout had no usable Link tools (or authorize ran without checkout context), so Kernel has nothing to invoke. Meanwhilehints.invocationstill listswebmcp_invokefor the same item, andwebmcpInvokeItemGuidance(may submit, untrusted output, never retry unknown) is no longer attached. Could we scope the "don't invoke WebMCP yourself" text to authorize and Pay Token fills, and keepwebmcpInvokeItemGuidancewheneverwebmcp_invokeis advertised? If the intent is to retirewebmcp_invokefor Link, it would need to go from the API first. The "Link cards are not told to drive checkout webmcp tools" test would need updating either way. -
No test covers a lost response after a Link authorize was sent. I swapped
authorizationSubmitted(vault-cards.ts) andoperationSubmitted(vault-items.ts) forfalsein the Link authorize error path, and the full suite still passed (1055/1055). That flag is what produces "…after the operation was submitted", the hint that a Link spend request may exist. Could we add one connection-error-on-POST test per tool?
Optional
vault-items.ts:271: after a Pay Token fill, "completed means the fields were written" isn't accurate; no fields are written (the result hasfields: []). The docs already say "the credential was supplied to the page".linkCardGuidance: the API's decline step also says "read the item's status_reason" first.vault-schemas.ts:97:z.url({ protocol: /^https$/ })acceptsHTTPS://…, userinfo, spaces and*, which the API'spage_urlpattern rejects. The API rejects these with a 400 ("invalid Link card checkout") before any provider call, so this is harmless; using^https://[^/?#@*\s]+(?:[/?#][^\s]*)?$would make it a true mirror.- The seven codes are typed out twice in code (
linkCheckoutErrorCodesandlinkCardGuidance), and the "exactly one tab at page_url" recovery step is written out five times across the tools, guidance and docs. Deriving the list from the Set would at least keep the codes in sync.
API side (not this PR): authorizing with a browser that isn't attached to the vault (or is deleted, an unleased pool instance, or in another project) returns 500 provider_error "failed to perform item operation". fillUnavailableError only implements Is(conflict), so linkCardCheckoutError's errors.As misses it. That's probably the most likely agent mistake on this path, and it gets no recovery step from either the API or the MCP. I raised the same thing on cli#298.
|
Thanks. All addressed in 0ea97c4.
Optional items:
API side: agreed. A browser that isn't attached to the vault falls through
|
Brings the vault tools in line with the final Link card API: Link cards are authorized at the final checkout page with
browser_idandpage_url. Kernel inspects the checkout and delivers either a Link Pay Token or a virtual card. Card updates still work until a card is authorized at a checkout.Builds on #247, which is already on
main: API errors still pass through unchanged. The only addition is a recovery step for the seven Link checkout-inspection error codes.Behavior
manage_vault_cardsauthorizeaccepts Link cards. It takes optional top-levelbrowser_idandpage_url, which must be passed together or not at all. They are forwarded as{"type":"authorize","browser_id":…,"page_url":…}. Re-checking a pending card omits them. A KERNEL card that getsbrowser_id/page_urlis rejected after the item read, and an AgentCard authorize is rejected before any request.manage_vault_itemsinvoke authorizevalidatesinputsagainst a strict schema:{}or{ browser_id, page_url }, with an httpspage_url. Unknown keys such asmerchant_account_idare named and rejected before any request.fillcan omitfields. The schema now matchesFillVaultItemOperationRequest, so a Link Pay Token fill sends{type, browser_id, page_url}.browser_not_found,browser_unavailable,destination_denied,page_not_found,ambiguous_page,timeout, andbrowser_error, the API's status, message, and code pass through, followed by: "no payment request was made. make sure the checkout is open in exactly one tab at page_url, then authorize again. if checkout inspection keeps failing, authorize without browser_id and page_url to issue a virtual card for the merchant_url origin." Other errors, including a 409 from updating an authorized card and the virtual-card amount limit, pass through unchanged as in Validate vault fill inputs and pass API errors through #247. Link authorize no longer goes through the KERNEL-card error path, which added KERNEL-specific advice and removed URLs from messages.description. It is now included in item projections, so agents see the API's Link wallet guidance.authorizehint carriesrequired_inputs: ["browser_id", "page_url"]. Without it, an agent replaying the hint unchanged would take the fallback virtual-card path by accident.Agent-facing text
manage_vault_cards,manage_vault_items,manage_vault_wallets,manage_vaults, the Link card item guidance, and theamountandinputsparameter descriptions now describe one order. Reach checkout, create the card, authorize withbrowser_idandpage_url, share the approval URL, wait forfill, fill, then submit yourself. The text points agents at the item'savailable_operationsdescriptions and the walletdescriptionand doesn't restate them. It says "link pay token" and "virtual card" in the repo's lowercase brand casing. It never asks for or shows a merchant account and never names how the credential is delivered. Every failure has a recovery step. The generic "do not retry … payments" guidance line is no longer added to Link card items. "Do not inspect or invoke the checkout's WebMCP tools yourself" is scoped to authorize and Link Pay Token fills. When the API advertiseswebmcp_invokeon a Link virtual card, the item keeps the genericwebmcp_invokeguidance, and thewebmcptool description is unchanged frommain.docs/vault-payments.md: the Link flow is rewritten in the same order, with authorize and fill examples. The intro, the error bullet, and the update bullet are updated. The fill examples now use the realinputsparameter instead of a nonexistent nestedfillkey. The README line formanage_vault_cardsis updated.SDK
Updates
@onkernel/sdkto 0.126.0, which addsbrowser_id/page_urltoAuthorizeVaultItemOperationRequestand makesfieldsoptional on fill. The authorize request inmanage_vault_cardsis now typed directly with no cast.The bump also picks up the 0.124.0 change that types
browserPools.acquireasBrowserPoolAcquireResponse | null(204 on long-poll timeout).manage_browser_poolsalready returns an error for a null acquire; only its response type alias changes, toNonNullable<…>.Testing
bun test: 1064 pass, 0 fail (1013 onmain), against@onkernel/sdk0.126.0.bunx tsc --noEmit --incremental false: clean.bun run check:managed-auth-app: clean.bunx prettier --check "src/**/*.ts" docs README.md: clean.bun run format:checkflags onlyAGENTS.md, which is pre-existing onmain.bun run lintis broken onmain(next lintwas removed in Next 16).New tests:
vault-items.test.ts: authorize forwards checkout context,{}, or no inputs. One-of,http, and unknown-key inputs are rejected before any request. Each checkout error code passes through with its recovery step. Other errors pass through unchanged. A Link Pay Token fill withoutfieldsis forwarded, and its result guidance doesn't claim fields were written. A lost response after the authorize POST reports "after the operation was submitted"; a lost response before it doesn't.page_urlvalues that the API's pattern rejects (uppercase scheme, userinfo, spaces,*) are rejected locally.vaults.test.ts: tool descriptions name the flow in order and contain no internal terms.manage_vault_cardsauthorizes with checkout context and re-checks without it. The rejection cases, the KERNEL-card guard, error pass-through, update 409 pass-through, the walletdescriptionprojection, and lost responses before and after the authorize POST are covered.vault-hints.test.ts: hints for Link authorize through both tools.vault-operation-errors.test.ts:throwLinkAuthorizeErrorfor each code, unchanged pass-through for other codes, and transport loss.vault-payment-guidance.test.ts: Link guidance order, recovery steps (includingstatus_reasonon decline), WebMCP steering scoped to authorize and Pay Token fills,webmcp_invokeguidance kept for virtual cards, andrequired_inputsonly on requested cards.