@mconroy-cf/tapkit-cli
v0.5.0-experimental.0
Published
EXPERIMENTAL — TAPKit command-line tool: sign, verify, and conformance-test Trusted Agent Protocol (TAP) integrations. Ships `tapkit sign`, `tapkit check`, and `tapkit verify` as a single binary. Companion to @mconroy-cf/tapkit-workers. Published to gathe
Maintainers
Readme
@mconroy-cf/tapkit-cli
⚠️ EXPERIMENTAL — partner-feedback release.
Published to a personal scope (
@mconroy-cf/) so external partners can install and try it without waiting on the formal Cloudflare release process. Expect breaking changes; not for production traffic. Companion to@mconroy-cf/tapkit-workers. Once an official@cloudflare/-scoped release ships, this package will deprecate and point at it.
The TAPKit command-line tool. Signs requests, verifies them, tests merchants, reports what the verifier saw.
This is the CLI package of the TAPKit monorepo. It's a Node.js tool that gives you both sides of a TAP interaction:
- A signing test agent (
tapkit sign) — simulates a trusted AI shopping agent end-to-end against a real merchant. - A conformance suite (
tapkit check) — runs 13 scenarios against a merchant URL and reports pass/fail per scenario. - A local verifier (
tapkit verify) — a mock TAP merchant in your terminal, useful for agent developers testing their signer without deploying a Worker.
Built to the Trusted Agent Protocol v1 spec. Signature format byte-identical to Visa's reference implementation.
Installation
Requires Node 20 or later (for native ed25519 in Web Crypto).
npx @mconroy-cf/tapkit-cli sign https://your-merchant.example.com
# or
npm install -g @mconroy-cf/tapkit-cli
tapkit sign https://your-merchant.example.comCommands
tapkit sign <merchant-url>
Run a full end-to-end signed flow against a merchant. Fetches /llms.txt,
picks a product, signs a browsing request and a checkout request, and
reports what the merchant verified.
tapkit sign <merchant-url> [options]
Options:
--product <slug> Pick a specific product (default: first in stock)
--qty <n> Quantity (default: 1)
--agent-id <id> Agent identity (default: tapkit-test-agent)
--key-id <id> Override signer keyId
--priv-key <b64> Override baked-in private key (PKCS8 base64)
--json Emit the full result as JSON
--verbose Show full stage detailstapkit check <merchant-url>
Run the TAP conformance test suite. Sends a curated set of signed and deliberately-malformed requests against the merchant and reports per-scenario pass/fail. This is the tool to run against your staging environment before you trust your TAP verification in production.
tapkit check <merchant-url> [options]
Options:
--only <names> Run specific scenarios (comma-separated)
--scenarios <names> Alias for --only
--stop-on-fail Halt at first failure
--json Emit the full result as JSON
--verbose Show full request/response detail per scenarioScenarios (run tapkit list-scenarios for the current list):
| Scenario | Merchant should |
|---|---|
| browsing-valid | Accept a valid agent-browser-auth signature on a product page |
| checkout-valid | Accept a valid agent-payer-auth signature on a checkout request |
| replay-rejected | Reject a second request with a nonce it has already seen |
| expired-rejected | Reject a signature whose expires is in the past |
| window-too-large | Reject a signature whose expires - created exceeds 8 minutes |
| wrong-tag-on-browsing | Reject an agent-payer-auth signature on a browsing endpoint |
| wrong-tag-on-checkout | Reject an agent-browser-auth signature on a checkout endpoint |
| missing-signature | Reject a request with no Signature/Signature-Input headers |
| unknown-keyid | Reject a signature whose keyId isn't in any trusted JWKS |
tapkit verify
Run a local mock TAP merchant on the port of your choice. Every incoming
request is passed through the same verifier that @mconroy-cf/tapkit-workers
ships — same code a merchant would deploy, just wrapped in a Node http
server instead of a Cloudflare Worker.
Useful for agent developers building a signer who want to test against a real TAP verifier without standing up a Cloudflare account.
tapkit verify [options]
Options:
--port <n> Listen on this port (default: 8787)
--tag <name> Tag to enforce: browser-auth | payer-auth | any (default: any)
--pub-key <b64> Trust this raw 32-byte Ed25519 public key (base64)
--pub-key-id <id> keyid to associate with --pub-key (default: tapkit-test-key-v0)
--json Emit NDJSON log lines instead of pretty-printed output
--verbose Include body preview + full verification detailExample flow:
# Terminal 1 — start the verifier
tapkit verify --port 8787
# Terminal 2 — sign against it
tapkit sign http://localhost:8787The verifier serves an unsigned GET /llms.txt with a tiny fake catalog
so tapkit sign can complete a full discovery → browsing → checkout
flow. Every other path runs verifyTap() against the incoming request.
Tag enforcement: --tag browser-auth makes the verifier only accept
agent-browser-auth-tagged signatures; --tag payer-auth only
agent-payer-auth; --tag any (default) accepts either. This lets
agent developers exercise both code paths against one running server.
tapkit list-scenarios
Print the conformance scenarios and their descriptions.
Exit codes
| Code | Meaning |
|---|---|
| 0 | All stages / scenarios passed |
| 1 | At least one stage / scenario failed (or, for check, produced a warning) |
| 2 | CLI usage error or internal crash |
Both --flag value and --flag=value forms are accepted.
Run against the deployed reference merchant
# End-to-end signed flow
npx @mconroy-cf/tapkit-cli sign https://tapkit-reference-merchant.agent-payments-testing.workers.dev
# Conformance suite (13 scenarios today)
npx @mconroy-cf/tapkit-cli check https://tapkit-reference-merchant.agent-payments-testing.workers.devExpected: all stages / scenarios PASS.
What TAPKit sends
Two signed requests per run:
Browsing (GET /product/:slug):
Signature-Input: sig2=("@authority" "@path"); created=…; expires=…; keyId="…"; alg="ed25519"; nonce="…"; tag="agent-browser-auth"
Signature: sig2=:<base64(ed25519-signature)>:Checkout (POST /checkout):
Content-Type: application/json
Signature-Input: sig2=("@authority" "@path"); created=…; expires=…; keyId="…"; alg="ed25519"; nonce="…"; tag="agent-payer-auth"
Signature: sig2=:<base64(ed25519-signature)>:The format is byte-identical to Visa's tap-agent reference implementation.
What your merchant endpoint needs to do
To pass TAPKit, your /checkout and /product/:slug endpoints must:
- Parse
Signature-Inputand extractcreated,expires,keyId,alg,nonce,tag - Validate the tag matches the endpoint (
agent-browser-authfor browsing,agent-payer-authfor checkout) - Check freshness:
expires - created ≤ 8 minutes, current time between them - Reject replays: if you've seen this nonce in the last 8 minutes, reject
- Look up the public key by
keyIdand verify the signature over the RFC 9421 signature base ("@authority": <host>\n"@path": <path>\n"@signature-params": <…>) - Respond with
{ "verified": true, … }on success or{ "verified": false, "reason": "…" }on failure
See packages/reference-merchant for a working ~300-line Cloudflare Worker implementation of all six steps.
Test keys
TAPKit ships with a baked-in ed25519 keypair so npx @mconroy-cf/tapkit-cli sign <url> works with zero setup. These keys are public and in every copy of TAPKit — anything signed with them proves nothing in production. They exist only so a merchant can hard-code the matching public key in their verifier and see the full flow succeed.
Override with --priv-key <pkcs8-base64> for your own keys.
Architecture
src/
├── core/ Protocol-neutral primitives
│ ├── signer-base.ts Abstract signer interface (ProtocolSigner)
│ ├── types.ts Shared result/product types
│ ├── discover.ts /llms.txt fetch + parse
│ └── reporter.ts Pretty-printed stage report
├── protocols/
│ └── tap/ TAP adapter
│ ├── signer.ts TAP-compliant ed25519 signer
│ ├── spec.ts TAP constants (tags, algorithms, windows)
│ └── keys.ts Baked-in test keypair
├── modes/
│ ├── sign.ts The "sign" mode — end-to-end browsing + checkout
│ ├── check.ts The "check" mode — TAP conformance test scenarios
│ └── verify.ts The "verify" mode — local mock TAP merchant
└── cli.ts Entry pointThe core/ layer is protocol-agnostic. Adding AP2 or Mastercard Agent Pay later means adding a protocols/<name>/ adapter and registering it in the CLI — no core changes.
Status
v0.5-experimental — ships full TAP layers 1, 2, and 3 (Agent Recognition Signature, Consumer Recognition Object, Agentic Payment Container) with full sign + check + verify coverage. The check command runs 13 conformance scenarios.
See ../../TODO.md for the full roadmap.
Licence
MIT.
