Add web-bot-auth sign <url> command#106
Merged
Merged
Conversation
kreese-stripe
approved these changes
May 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
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 rawWebBotAuthBlockJSON, no interactive UI.Implementation notes
Capture pattern (not double-call):
onCompletecaptures the result into a local variable;getResultreturns it. Matches the pattern inmpp pay. The previoususer-info retrievepattern (passonComplete={() => {}}then call the resource a second time ingetResult) is avoided here because it makes two round-trips to the API.Explicit
exit():WebBotAuthSigncallsuseApp().exit()inside theonCompletecallback so Ink terminates deterministically instead of relying on event loop drain. This pairs with the capture pattern; thegetResultlambda is only called afterwaitUntilExit()resolves.Depends on CLI-1 (
nvp/link-cli-web-bot-auth), which addedWebBotAuthResourceandIWebBotAuthResourceto@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:
link-cli web-bot-auth sign <merchant-url>.SignatureandSignature-Inputheaders to the outgoing HTTP request to the merchant.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