Skip to content

Add web-bot-auth sign <url> command#106

Merged
nvp-stripe merged 2 commits into
mainfrom
nvp/link-cli-web-bot-auth-sign-command
May 21, 2026
Merged

Add web-bot-auth sign <url> command#106
nvp-stripe merged 2 commits into
mainfrom
nvp/link-cli-web-bot-auth-sign-command

Conversation

@nvp-stripe
Copy link
Copy Markdown
Contributor

Summary

Adds the link-cli web-bot-auth sign <url> command, which fetches Web Bot Auth signature headers for a given merchant URL and returns them for injection into outbound HTTP requests.

New command:

link-cli web-bot-auth sign <url>

What it returns (WebBotAuthBlock):

{
  "signature": "sig1=:...",
  "signature_input": "sig1=(\"@authority\" \"signature-agent\");created=...;keyid=...;alg=\"ed25519\";expires=...;tag=\"web-bot-auth\"",
  "signature_agent": "https://api.link.com/.well-known/http-message-signatures-directory",
  "authority": "merchant.com",
  "expires_at": "2026-05-19T00:10:00Z"
}

Interactive mode (human-facing): renders a spinner while fetching, then displays a success view with all fields labeled.

Agent / format mode (--format json, --mcp): returns the raw WebBotAuthBlock JSON, no interactive UI.

Implementation notes

  • Capture pattern (not double-call): onComplete captures the result into a local variable; getResult returns it. Matches the pattern in mpp pay. The previous user-info retrieve pattern (pass onComplete={() => {}} then call the resource a second time in getResult) is avoided here because it makes two round-trips to the API.

  • Explicit exit(): WebBotAuthSign calls useApp().exit() inside the onComplete callback so Ink terminates deterministically instead of relying on event loop drain. This pairs with the capture pattern; the getResult lambda is only called after waitUntilExit() resolves.

  • Depends on CLI-1 (nvp/link-cli-web-bot-auth), which added WebBotAuthResource and IWebBotAuthResource to @stripe/link-sdk. That PR has been merged; this branch is based on its merge commit.

Motivation

AI agents making purchases on behalf of users send HTTP requests to merchant sites. Many merchants run Cloudflare or Vercel in front of their checkout flows, and those platforms flag non-browser traffic as bots and return 403 responses before the agent can complete the transaction.

Web Bot Auth (an extension of RFC 9421 HTTP Message Signatures) solves this: an authenticated Link user can prove that their agent is authorized. The Link backend signs requests with an Ed25519 key tied to the user's identity. The merchant site verifies the signature against a published JWKS directory (/.well-known/http-message-signatures-directory).

This command is the agent-facing surface for that flow:

  1. Agent calls link-cli web-bot-auth sign <merchant-url>.
  2. CLI fetches pre-signed headers
  3. Agent attaches Signature and Signature-Input headers to the outgoing HTTP request to the merchant.
  4. Cloudflare/Vercel verifies the signature and allows the request through.

Without this command, agents must either implement the signing protocol themselves (requiring direct API access and key management) or fall back to browser automation (slower, brittle, higher compute cost).

Testing

Unit tests

  • packages/cli/src/commands/web-bot-auth/__tests__/web-bot-auth.test.tsx

@nvp-stripe nvp-stripe merged commit bed025f into main May 21, 2026
5 checks passed
@nvp-stripe nvp-stripe deleted the nvp/link-cli-web-bot-auth-sign-command branch May 21, 2026 00:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants