@dupecom/botcha-cloudflare 0.15.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dashboard/landing.d.ts.map +1 -1
- package/dist/dashboard/landing.js +2 -9
- package/dist/dashboard/layout.d.ts.map +1 -1
- package/dist/dashboard/layout.js +4 -4
- package/dist/dashboard/showcase.d.ts +1 -0
- package/dist/dashboard/showcase.d.ts.map +1 -1
- package/dist/dashboard/showcase.js +2 -2
- package/dist/dashboard/whitepaper.d.ts +14 -0
- package/dist/dashboard/whitepaper.d.ts.map +1 -0
- package/dist/dashboard/whitepaper.js +418 -0
- package/dist/email.d.ts.map +1 -1
- package/dist/email.js +5 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +105 -18
- package/dist/og-image.d.ts +2 -0
- package/dist/og-image.d.ts.map +1 -0
- package/dist/og-image.js +2 -0
- package/dist/static.d.ts +331 -2
- package/dist/static.d.ts.map +1 -1
- package/dist/static.js +462 -4
- package/dist/tap-agents.d.ts +3 -2
- package/dist/tap-agents.d.ts.map +1 -1
- package/dist/tap-agents.js +19 -6
- package/dist/tap-consumer.d.ts +151 -0
- package/dist/tap-consumer.d.ts.map +1 -0
- package/dist/tap-consumer.js +346 -0
- package/dist/tap-edge.d.ts +106 -0
- package/dist/tap-edge.d.ts.map +1 -0
- package/dist/tap-edge.js +487 -0
- package/dist/tap-federation.d.ts +89 -0
- package/dist/tap-federation.d.ts.map +1 -0
- package/dist/tap-federation.js +237 -0
- package/dist/tap-jwks.d.ts +64 -0
- package/dist/tap-jwks.d.ts.map +1 -0
- package/dist/tap-jwks.js +279 -0
- package/dist/tap-payment.d.ts +172 -0
- package/dist/tap-payment.d.ts.map +1 -0
- package/dist/tap-payment.js +425 -0
- package/dist/tap-routes.d.ts +239 -2
- package/dist/tap-routes.d.ts.map +1 -1
- package/dist/tap-routes.js +279 -4
- package/dist/tap-verify.d.ts +43 -1
- package/dist/tap-verify.d.ts.map +1 -1
- package/dist/tap-verify.js +215 -30
- package/package.json +1 -1
package/dist/static.js
CHANGED
|
@@ -87,6 +87,30 @@ curl https://botcha.ai/agent-only -H "Authorization: Bearer <token>"
|
|
|
87
87
|
| \`POST\` | \`/v1/sessions/tap\` | Create TAP session with intent validation |
|
|
88
88
|
| \`GET\` | \`/v1/sessions/:id/tap\` | Get TAP session info |
|
|
89
89
|
|
|
90
|
+
### TAP Full Spec — JWKS & Keys (v0.16.0)
|
|
91
|
+
|
|
92
|
+
| Method | Path | Description |
|
|
93
|
+
|--------|------|-------------|
|
|
94
|
+
| \`GET\` | \`/.well-known/jwks\` | JWK Set for app's TAP agents (Visa spec standard) |
|
|
95
|
+
| \`GET\` | \`/v1/keys\` | List keys (supports ?keyID= for Visa compat) |
|
|
96
|
+
| \`GET\` | \`/v1/keys/:keyId\` | Get specific key by ID |
|
|
97
|
+
| \`POST\` | \`/v1/agents/:id/tap/rotate-key\` | Rotate agent's key pair |
|
|
98
|
+
|
|
99
|
+
### TAP Full Spec — 402 Micropayments (v0.16.0)
|
|
100
|
+
|
|
101
|
+
| Method | Path | Description |
|
|
102
|
+
|--------|------|-------------|
|
|
103
|
+
| \`POST\` | \`/v1/invoices\` | Create invoice for gated content |
|
|
104
|
+
| \`GET\` | \`/v1/invoices/:id\` | Get invoice details |
|
|
105
|
+
| \`POST\` | \`/v1/invoices/:id/verify-iou\` | Verify Browsing IOU |
|
|
106
|
+
|
|
107
|
+
### TAP Full Spec — Verification (v0.16.0)
|
|
108
|
+
|
|
109
|
+
| Method | Path | Description |
|
|
110
|
+
|--------|------|-------------|
|
|
111
|
+
| \`POST\` | \`/v1/verify/consumer\` | Verify Agentic Consumer (Layer 2) |
|
|
112
|
+
| \`POST\` | \`/v1/verify/payment\` | Verify Agentic Payment Container (Layer 3) |
|
|
113
|
+
|
|
90
114
|
### Challenges
|
|
91
115
|
|
|
92
116
|
| Method | Path | Description |
|
|
@@ -262,8 +286,10 @@ API-Format: OpenAPI 3.1.0
|
|
|
262
286
|
|
|
263
287
|
# Documentation
|
|
264
288
|
Docs: https://botcha.ai
|
|
289
|
+
Docs: https://botcha.ai/whitepaper
|
|
265
290
|
Docs: https://github.com/dupe-com/botcha#readme
|
|
266
291
|
Docs: https://www.npmjs.com/package/@dupecom/botcha
|
|
292
|
+
Whitepaper: https://botcha.ai/whitepaper
|
|
267
293
|
|
|
268
294
|
# Verification Methods
|
|
269
295
|
Feature: Web Bot Auth (cryptographic signatures)
|
|
@@ -287,6 +313,7 @@ Feature: Trusted Agent Protocol (TAP) — cryptographic agent auth with HTTP Mes
|
|
|
287
313
|
Feature: TAP Capabilities (action + resource scoping for agent sessions)
|
|
288
314
|
Feature: TAP Trust Levels (basic, verified, enterprise)
|
|
289
315
|
Feature: TAP Showcase Homepage (botcha.ai — one of the first services to implement Visa's Trusted Agent Protocol)
|
|
316
|
+
Feature: TAP Full Spec v0.16.0 — Ed25519, RFC 9421 full compliance, JWKS infrastructure, Layer 2 Consumer Recognition, Layer 3 Payment Container, 402 micropayments, CDN edge verification, Visa key federation
|
|
290
317
|
|
|
291
318
|
# Endpoints
|
|
292
319
|
# Challenge Endpoints
|
|
@@ -341,6 +368,21 @@ Endpoint: GET https://botcha.ai/v1/agents/tap - List TAP-enabled agents for app
|
|
|
341
368
|
Endpoint: POST https://botcha.ai/v1/sessions/tap - Create TAP session with intent validation
|
|
342
369
|
Endpoint: GET https://botcha.ai/v1/sessions/:id/tap - Get TAP session info
|
|
343
370
|
|
|
371
|
+
# TAP Full Spec — JWKS & Key Management (v0.16.0)
|
|
372
|
+
Endpoint: GET https://botcha.ai/.well-known/jwks - JWK Set for app's TAP agents (Visa spec standard)
|
|
373
|
+
Endpoint: GET https://botcha.ai/v1/keys - List keys (supports ?keyID= query for Visa compatibility)
|
|
374
|
+
Endpoint: GET https://botcha.ai/v1/keys/:keyId - Get specific key by ID
|
|
375
|
+
Endpoint: POST https://botcha.ai/v1/agents/:id/tap/rotate-key - Rotate agent's key pair
|
|
376
|
+
|
|
377
|
+
# TAP Full Spec — 402 Micropayments (v0.16.0)
|
|
378
|
+
Endpoint: POST https://botcha.ai/v1/invoices - Create invoice for gated content (402 flow)
|
|
379
|
+
Endpoint: GET https://botcha.ai/v1/invoices/:id - Get invoice details
|
|
380
|
+
Endpoint: POST https://botcha.ai/v1/invoices/:id/verify-iou - Verify Browsing IOU against invoice
|
|
381
|
+
|
|
382
|
+
# TAP Full Spec — Consumer & Payment Verification (v0.16.0)
|
|
383
|
+
Endpoint: POST https://botcha.ai/v1/verify/consumer - Verify Agentic Consumer object (Layer 2)
|
|
384
|
+
Endpoint: POST https://botcha.ai/v1/verify/payment - Verify Agentic Payment Container (Layer 3)
|
|
385
|
+
|
|
344
386
|
# Legacy Endpoints
|
|
345
387
|
Endpoint: GET https://botcha.ai/api/challenge - Generate standard challenge
|
|
346
388
|
Endpoint: POST https://botcha.ai/api/challenge - Verify standard challenge
|
|
@@ -411,7 +453,7 @@ Multi-Tenant-Token-Claim: Tokens include app_id claim when app_id provided
|
|
|
411
453
|
# TRUSTED AGENT PROTOCOL (TAP)
|
|
412
454
|
TAP-Description: Enterprise-grade cryptographic agent auth using HTTP Message Signatures (RFC 9421)
|
|
413
455
|
TAP-Register: POST /v1/agents/register/tap with {name, public_key, signature_algorithm, capabilities, trust_level}
|
|
414
|
-
TAP-Algorithms: ecdsa-p256-sha256, rsa-pss-sha256
|
|
456
|
+
TAP-Algorithms: ed25519 (Visa recommended), ecdsa-p256-sha256, rsa-pss-sha256
|
|
415
457
|
TAP-Trust-Levels: basic, verified, enterprise
|
|
416
458
|
TAP-Capabilities: Array of {action, resource, constraints} — scoped access control
|
|
417
459
|
TAP-Session-Create: POST /v1/sessions/tap with {agent_id, user_context, intent}
|
|
@@ -419,10 +461,22 @@ TAP-Session-Get: GET /v1/sessions/:id/tap — includes time_remaining
|
|
|
419
461
|
TAP-Get-Agent: GET /v1/agents/:id/tap — includes public_key for verification
|
|
420
462
|
TAP-List-Agents: GET /v1/agents/tap?app_id=...&tap_only=true
|
|
421
463
|
TAP-Middleware-Modes: tap, signature-only, challenge-only, flexible
|
|
422
|
-
TAP-SDK-TS: registerTAPAgent(options), getTAPAgent(agentId), listTAPAgents(tapOnly?), createTAPSession(options), getTAPSession(sessionId)
|
|
423
|
-
TAP-SDK-Python: register_tap_agent(name, ...), get_tap_agent(agent_id), list_tap_agents(tap_only?), create_tap_session(agent_id, user_context, intent), get_tap_session(session_id)
|
|
464
|
+
TAP-SDK-TS: registerTAPAgent(options), getTAPAgent(agentId), listTAPAgents(tapOnly?), createTAPSession(options), getTAPSession(sessionId), getJWKS(), getKeyById(keyId), rotateAgentKey(agentId), createInvoice(data), getInvoice(id), verifyBrowsingIOU(invoiceId, token)
|
|
465
|
+
TAP-SDK-Python: register_tap_agent(name, ...), get_tap_agent(agent_id), list_tap_agents(tap_only?), create_tap_session(agent_id, user_context, intent), get_tap_session(session_id), get_jwks(), get_key_by_id(key_id), rotate_agent_key(agent_id), create_invoice(data), get_invoice(id), verify_browsing_iou(invoice_id, token)
|
|
424
466
|
TAP-Middleware-Import: import { createTAPVerifyMiddleware } from '@dupecom/botcha/middleware'
|
|
425
467
|
|
|
468
|
+
# TAP FULL SPEC v0.16.0
|
|
469
|
+
TAP-RFC-9421: Full compliance — @authority, @path, expires, nonce, tag params
|
|
470
|
+
TAP-Nonce-Replay: 8-minute TTL nonce-based replay protection
|
|
471
|
+
TAP-Tags: agent-browser-auth (browsing), agent-payer-auth (payment)
|
|
472
|
+
TAP-Layer-2: Agentic Consumer Recognition — OIDC ID tokens, obfuscated identity, contextual data
|
|
473
|
+
TAP-Layer-3: Agentic Payment Container — card metadata, credential hash, encrypted payload, Browsing IOU
|
|
474
|
+
TAP-JWKS: GET /.well-known/jwks — JWK Set endpoint for key discovery
|
|
475
|
+
TAP-Key-Rotation: POST /v1/agents/:id/tap/rotate-key — rotate keys, invalidate old
|
|
476
|
+
TAP-402-Flow: POST /v1/invoices → GET /v1/invoices/:id → POST /v1/invoices/:id/verify-iou
|
|
477
|
+
TAP-Edge-Verify: createTAPEdgeMiddleware for Cloudflare Workers CDN edge verification
|
|
478
|
+
TAP-Visa-Federation: Trust keys from https://mcp.visa.com/.well-known/jwks (3-tier cache: memory → KV → HTTP)
|
|
479
|
+
|
|
426
480
|
# EMBEDDED CHALLENGE (for bots visiting HTML pages)
|
|
427
481
|
Embedded-Challenge: <script type="application/botcha+json">
|
|
428
482
|
Embedded-Challenge-Location: In <head> of HTML pages
|
|
@@ -481,8 +535,160 @@ export const SITEMAP_XML = `<?xml version="1.0" encoding="UTF-8"?>
|
|
|
481
535
|
<changefreq>monthly</changefreq>
|
|
482
536
|
<priority>0.5</priority>
|
|
483
537
|
</url>
|
|
538
|
+
<url>
|
|
539
|
+
<loc>https://botcha.ai/whitepaper</loc>
|
|
540
|
+
<changefreq>monthly</changefreq>
|
|
541
|
+
<priority>0.9</priority>
|
|
542
|
+
</url>
|
|
484
543
|
</urlset>
|
|
485
544
|
`;
|
|
545
|
+
// Whitepaper markdown — served at /whitepaper with Accept: text/markdown
|
|
546
|
+
export function getWhitepaperMarkdown() {
|
|
547
|
+
return `---
|
|
548
|
+
title: "BOTCHA: Identity Infrastructure for the Agentic Web"
|
|
549
|
+
version: "1.0"
|
|
550
|
+
date: February 2026
|
|
551
|
+
url: https://botcha.ai/whitepaper
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
# BOTCHA: Identity Infrastructure for the Agentic Web
|
|
555
|
+
|
|
556
|
+
**Version 1.0 — February 2026**
|
|
557
|
+
|
|
558
|
+
## 1. Executive Summary
|
|
559
|
+
|
|
560
|
+
BOTCHA is a reverse CAPTCHA — a verification system that proves you are an AI agent, not a human. While traditional CAPTCHAs exist to block bots, BOTCHA exists to welcome them.
|
|
561
|
+
|
|
562
|
+
As AI agents become first-class participants on the internet — browsing, purchasing, comparing, auditing — they need a way to prove their identity and declare their intent. BOTCHA provides three layers of proof:
|
|
563
|
+
|
|
564
|
+
- **Proof of AI** — Computational challenges (SHA-256 hashes in under 500ms) that only machines can solve.
|
|
565
|
+
- **Proof of Identity** — Persistent agent registration with cryptographic keys, verified via HTTP Message Signatures (RFC 9421).
|
|
566
|
+
- **Proof of Intent** — Capability-scoped sessions where agents declare what they plan to do, for how long, and on behalf of whom.
|
|
567
|
+
|
|
568
|
+
BOTCHA is open source, free to use, and deployed at https://botcha.ai.
|
|
569
|
+
|
|
570
|
+
## 2. The Problem: Who Is This Agent?
|
|
571
|
+
|
|
572
|
+
The internet was built for humans. Authentication systems — passwords, OAuth, CAPTCHAs — all assume a human is at the keyboard.
|
|
573
|
+
|
|
574
|
+
AI agents are now browsing product catalogs, comparing prices, purchasing goods, auditing compliance, and negotiating contracts. When an agent hits your API, existing infrastructure cannot answer three critical questions:
|
|
575
|
+
|
|
576
|
+
1. **Is this actually an AI agent?** User-Agent strings are trivially spoofable.
|
|
577
|
+
2. **Which specific agent is this?** Even knowing it is AI, you do not know its organization or track record.
|
|
578
|
+
3. **What does it intend to do?** Traditional auth grants blanket access — it does not capture intent.
|
|
579
|
+
|
|
580
|
+
## 3. BOTCHA: Reverse CAPTCHA for AI Agents
|
|
581
|
+
|
|
582
|
+
A CAPTCHA asks: *Can you identify traffic lights?* A human can; a bot struggles.
|
|
583
|
+
BOTCHA asks: *Can you compute 5 SHA-256 hashes in 500ms?* A machine can; a human cannot.
|
|
584
|
+
|
|
585
|
+
### Design Principles
|
|
586
|
+
|
|
587
|
+
- **Agent-first, always.** Every flow requires an AI agent as participant. No human-only login paths.
|
|
588
|
+
- **Fail-open on infrastructure errors.** Blocking legitimate traffic is worse than allowing an unverified request.
|
|
589
|
+
- **Zero configuration to start.** Solve one challenge, get a token. No registration required.
|
|
590
|
+
|
|
591
|
+
## 4. The Challenge System
|
|
592
|
+
|
|
593
|
+
| Challenge | Tests | Time Limit | Best For |
|
|
594
|
+
|-----------|-------|------------|----------|
|
|
595
|
+
| Speed | SHA-256 computation | 500ms | Quick verification |
|
|
596
|
+
| Reasoning | Language understanding (6 categories, parameterized generators) | 30s | Proving AI comprehension |
|
|
597
|
+
| Hybrid | Speed + Reasoning combined | 35s | Default — strongest proof |
|
|
598
|
+
| Compute | Prime generation + hashing | 3-10s | High-value operations |
|
|
599
|
+
|
|
600
|
+
**RTT-aware fairness:** Time limits adjust for network latency (max 5s cap).
|
|
601
|
+
**Anti-replay:** Challenges deleted from storage on first verification attempt.
|
|
602
|
+
**Anti-gaming:** Parameterized question generators; no static question bank.
|
|
603
|
+
|
|
604
|
+
## 5. The Trusted Agent Protocol (TAP)
|
|
605
|
+
|
|
606
|
+
Solving a challenge proves you are *a bot*. TAP proves you are *a specific, trusted bot*.
|
|
607
|
+
|
|
608
|
+
Inspired by Visa's Trusted Agent Protocol (https://developer.visa.com/capabilities/trusted-agent-protocol/overview), BOTCHA's TAP provides:
|
|
609
|
+
|
|
610
|
+
- **Persistent agent identity** — unique ID, name, operator metadata
|
|
611
|
+
- **Cryptographic verification** — ECDSA P-256 / RSA-PSS public keys; HTTP Message Signatures (RFC 9421)
|
|
612
|
+
- **Capability-based access control** — browse, search, compare, purchase, audit
|
|
613
|
+
- **Intent-scoped sessions** — time-limited, validated against capabilities
|
|
614
|
+
- **Trust levels** — basic, verified, enterprise
|
|
615
|
+
|
|
616
|
+
### Verification Hierarchy
|
|
617
|
+
|
|
618
|
+
| Layer | Proves | Mechanism |
|
|
619
|
+
|-------|--------|-----------|
|
|
620
|
+
| Anonymous | "I am a bot" | Speed challenge <500ms |
|
|
621
|
+
| App-scoped | "I belong to this org" | Challenge + app_id |
|
|
622
|
+
| Agent identity | "I am this specific bot" | Registered ID + capabilities |
|
|
623
|
+
| Cryptographic | "I can prove it" | RFC 9421 signatures |
|
|
624
|
+
| Dual auth | "Verified + proven" | Challenge + signature |
|
|
625
|
+
| Intent-scoped | "I intend to do this now" | Validated session |
|
|
626
|
+
|
|
627
|
+
## 6. Architecture
|
|
628
|
+
|
|
629
|
+
- **Runtime:** Cloudflare Workers (300+ edge locations)
|
|
630
|
+
- **Storage:** Workers KV with TTLs
|
|
631
|
+
- **Tokens:** HMAC-SHA256 JWTs (5-min access, 1-hr refresh)
|
|
632
|
+
- **TAP Signatures:** ECDSA P-256 or RSA-PSS SHA-256
|
|
633
|
+
- **Rate Limits:** 100 challenges/hour/app (fail-open)
|
|
634
|
+
|
|
635
|
+
## 7. Integration
|
|
636
|
+
|
|
637
|
+
### Client SDKs
|
|
638
|
+
|
|
639
|
+
\`\`\`typescript
|
|
640
|
+
import { BotchaClient } from '@dupecom/botcha';
|
|
641
|
+
const client = new BotchaClient();
|
|
642
|
+
const response = await client.fetch('https://api.example.com/products');
|
|
643
|
+
\`\`\`
|
|
644
|
+
|
|
645
|
+
\`\`\`python
|
|
646
|
+
from botcha import BotchaClient
|
|
647
|
+
async with BotchaClient() as client:
|
|
648
|
+
response = await client.fetch("https://api.example.com/products")
|
|
649
|
+
\`\`\`
|
|
650
|
+
|
|
651
|
+
### Server-side Verification
|
|
652
|
+
|
|
653
|
+
Express: \`@botcha/verify\` · FastAPI/Django: \`botcha-verify\` · Hono middleware included.
|
|
654
|
+
|
|
655
|
+
### CLI
|
|
656
|
+
|
|
657
|
+
\`\`\`bash
|
|
658
|
+
npm install -g @dupecom/botcha-cli
|
|
659
|
+
botcha init --email you@company.com
|
|
660
|
+
botcha tap register --name "my-agent" --capabilities browse,search
|
|
661
|
+
botcha tap session --action browse --resource products --duration 1h
|
|
662
|
+
\`\`\`
|
|
663
|
+
|
|
664
|
+
## 8. The Agent Infrastructure Stack
|
|
665
|
+
|
|
666
|
+
\`\`\`
|
|
667
|
+
Layer 3: Identity TAP (BOTCHA) Who agents are
|
|
668
|
+
Layer 2: Communication A2A (Google) How agents talk
|
|
669
|
+
Layer 1: Tools MCP (Anthropic) What agents access
|
|
670
|
+
\`\`\`
|
|
671
|
+
|
|
672
|
+
MCP gives agents tools. A2A lets agents communicate. TAP proves identity and scopes authorization.
|
|
673
|
+
|
|
674
|
+
## 9. Use Cases
|
|
675
|
+
|
|
676
|
+
- **E-commerce:** Agents register capabilities, create scoped purchase sessions, full audit trail.
|
|
677
|
+
- **API access control:** Speed challenge gates endpoints; no API keys needed.
|
|
678
|
+
- **Multi-agent systems:** Coordinator delegates to capability-scoped sub-agents.
|
|
679
|
+
- **Compliance:** TAP audit logging records every agent interaction with intent and context.
|
|
680
|
+
|
|
681
|
+
## 10. Roadmap
|
|
682
|
+
|
|
683
|
+
**Shipped:** Challenge types, JWT tokens, multi-tenant apps, agent registry, TAP, dashboard, SDKs (TS/Python), CLI, LangChain, discovery standards.
|
|
684
|
+
|
|
685
|
+
**Planned:** Delegation chains, capability attestation, agent reputation scoring, Agent SSO (cross-service verification), IETF RFC contribution.
|
|
686
|
+
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
Website: https://botcha.ai · GitHub: https://github.com/dupe-com/botcha · npm: @dupecom/botcha · PyPI: botcha
|
|
690
|
+
`;
|
|
691
|
+
}
|
|
486
692
|
// OpenAPI spec - keeping this as a function to allow dynamic version
|
|
487
693
|
export function getOpenApiSpec(version) {
|
|
488
694
|
return {
|
|
@@ -1167,7 +1373,7 @@ export function getOpenApiSpec(version) {
|
|
|
1167
1373
|
"operator": { type: "string", description: "Operator/organization name" },
|
|
1168
1374
|
"version": { type: "string", description: "Agent version" },
|
|
1169
1375
|
"public_key": { type: "string", description: "PEM-encoded public key" },
|
|
1170
|
-
"signature_algorithm": { type: "string", enum: ["ecdsa-p256-sha256", "rsa-pss-sha256"], description: "Signature algorithm (required if public_key provided)" },
|
|
1376
|
+
"signature_algorithm": { type: "string", enum: ["ed25519", "ecdsa-p256-sha256", "rsa-pss-sha256"], description: "Signature algorithm (required if public_key provided)" },
|
|
1171
1377
|
"trust_level": { type: "string", enum: ["basic", "verified", "enterprise"], description: "Agent trust level (default: basic)" },
|
|
1172
1378
|
"capabilities": {
|
|
1173
1379
|
type: "array",
|
|
@@ -1294,6 +1500,258 @@ export function getOpenApiSpec(version) {
|
|
|
1294
1500
|
"404": { description: "Session not found or expired" }
|
|
1295
1501
|
}
|
|
1296
1502
|
}
|
|
1503
|
+
},
|
|
1504
|
+
"/.well-known/jwks": {
|
|
1505
|
+
get: {
|
|
1506
|
+
summary: "Get JWK Set (Visa TAP spec standard)",
|
|
1507
|
+
description: "Retrieve the JWK Set containing public keys for all TAP agents registered in your app. Follows Visa TAP specification standard.",
|
|
1508
|
+
operationId: "getJWKS",
|
|
1509
|
+
responses: {
|
|
1510
|
+
"200": {
|
|
1511
|
+
description: "JWK Set with array of keys",
|
|
1512
|
+
content: {
|
|
1513
|
+
"application/json": {
|
|
1514
|
+
schema: {
|
|
1515
|
+
type: "object",
|
|
1516
|
+
properties: {
|
|
1517
|
+
"keys": {
|
|
1518
|
+
type: "array",
|
|
1519
|
+
items: {
|
|
1520
|
+
type: "object",
|
|
1521
|
+
properties: {
|
|
1522
|
+
"kty": { type: "string", description: "Key type (EC, RSA, OKP)" },
|
|
1523
|
+
"kid": { type: "string", description: "Key ID" },
|
|
1524
|
+
"use": { type: "string", description: "Public key use (sig)" },
|
|
1525
|
+
"alg": { type: "string", description: "Algorithm (ES256, RS256, EdDSA)" }
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
},
|
|
1537
|
+
"/v1/keys": {
|
|
1538
|
+
get: {
|
|
1539
|
+
summary: "List keys or get key by ID",
|
|
1540
|
+
description: "List all keys or get a specific key using ?keyID= query parameter (Visa compatibility).",
|
|
1541
|
+
operationId: "getKeys",
|
|
1542
|
+
parameters: [
|
|
1543
|
+
{
|
|
1544
|
+
name: "keyID",
|
|
1545
|
+
in: "query",
|
|
1546
|
+
schema: { type: "string" },
|
|
1547
|
+
description: "Optional key ID for Visa TAP compatibility"
|
|
1548
|
+
}
|
|
1549
|
+
],
|
|
1550
|
+
responses: {
|
|
1551
|
+
"200": { description: "Key list or specific key" }
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
},
|
|
1555
|
+
"/v1/keys/{keyId}": {
|
|
1556
|
+
get: {
|
|
1557
|
+
summary: "Get key by ID",
|
|
1558
|
+
description: "Retrieve a specific public key by key ID.",
|
|
1559
|
+
operationId: "getKeyById",
|
|
1560
|
+
parameters: [
|
|
1561
|
+
{
|
|
1562
|
+
name: "keyId",
|
|
1563
|
+
in: "path",
|
|
1564
|
+
required: true,
|
|
1565
|
+
schema: { type: "string" }
|
|
1566
|
+
}
|
|
1567
|
+
],
|
|
1568
|
+
responses: {
|
|
1569
|
+
"200": { description: "Public key details" },
|
|
1570
|
+
"404": { description: "Key not found" }
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
},
|
|
1574
|
+
"/v1/agents/{id}/tap/rotate-key": {
|
|
1575
|
+
post: {
|
|
1576
|
+
summary: "Rotate agent key pair",
|
|
1577
|
+
description: "Generate a new key pair for the agent and invalidate the old one.",
|
|
1578
|
+
operationId: "rotateAgentKey",
|
|
1579
|
+
parameters: [
|
|
1580
|
+
{
|
|
1581
|
+
name: "id",
|
|
1582
|
+
in: "path",
|
|
1583
|
+
required: true,
|
|
1584
|
+
schema: { type: "string" }
|
|
1585
|
+
}
|
|
1586
|
+
],
|
|
1587
|
+
requestBody: {
|
|
1588
|
+
content: {
|
|
1589
|
+
"application/json": {
|
|
1590
|
+
schema: {
|
|
1591
|
+
type: "object",
|
|
1592
|
+
properties: {
|
|
1593
|
+
"algorithm": {
|
|
1594
|
+
type: "string",
|
|
1595
|
+
enum: ["ed25519", "ecdsa-p256-sha256", "rsa-pss-sha256"],
|
|
1596
|
+
description: "Algorithm for new key (default: ed25519)"
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
},
|
|
1603
|
+
responses: {
|
|
1604
|
+
"200": { description: "Key rotated successfully" }
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
},
|
|
1608
|
+
"/v1/invoices": {
|
|
1609
|
+
post: {
|
|
1610
|
+
summary: "Create invoice for 402 micropayment",
|
|
1611
|
+
description: "Create an invoice for gated content. Used with Browsing IOU flow.",
|
|
1612
|
+
operationId: "createInvoice",
|
|
1613
|
+
requestBody: {
|
|
1614
|
+
required: true,
|
|
1615
|
+
content: {
|
|
1616
|
+
"application/json": {
|
|
1617
|
+
schema: {
|
|
1618
|
+
type: "object",
|
|
1619
|
+
required: ["amount", "currency", "description"],
|
|
1620
|
+
properties: {
|
|
1621
|
+
"amount": { type: "integer", description: "Amount in cents" },
|
|
1622
|
+
"currency": { type: "string", description: "Currency code (USD, EUR, etc.)" },
|
|
1623
|
+
"description": { type: "string" },
|
|
1624
|
+
"metadata": { type: "object" }
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
},
|
|
1630
|
+
responses: {
|
|
1631
|
+
"201": { description: "Invoice created" }
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
},
|
|
1635
|
+
"/v1/invoices/{id}": {
|
|
1636
|
+
get: {
|
|
1637
|
+
summary: "Get invoice details",
|
|
1638
|
+
operationId: "getInvoice",
|
|
1639
|
+
parameters: [
|
|
1640
|
+
{
|
|
1641
|
+
name: "id",
|
|
1642
|
+
in: "path",
|
|
1643
|
+
required: true,
|
|
1644
|
+
schema: { type: "string" }
|
|
1645
|
+
}
|
|
1646
|
+
],
|
|
1647
|
+
responses: {
|
|
1648
|
+
"200": { description: "Invoice details" },
|
|
1649
|
+
"404": { description: "Invoice not found" }
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
},
|
|
1653
|
+
"/v1/invoices/{id}/verify-iou": {
|
|
1654
|
+
post: {
|
|
1655
|
+
summary: "Verify Browsing IOU",
|
|
1656
|
+
description: "Verify a Browsing IOU (payment intent token) against an invoice.",
|
|
1657
|
+
operationId: "verifyBrowsingIOU",
|
|
1658
|
+
parameters: [
|
|
1659
|
+
{
|
|
1660
|
+
name: "id",
|
|
1661
|
+
in: "path",
|
|
1662
|
+
required: true,
|
|
1663
|
+
schema: { type: "string" }
|
|
1664
|
+
}
|
|
1665
|
+
],
|
|
1666
|
+
requestBody: {
|
|
1667
|
+
required: true,
|
|
1668
|
+
content: {
|
|
1669
|
+
"application/json": {
|
|
1670
|
+
schema: {
|
|
1671
|
+
type: "object",
|
|
1672
|
+
required: ["iou_token"],
|
|
1673
|
+
properties: {
|
|
1674
|
+
"iou_token": { type: "string" }
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
},
|
|
1680
|
+
responses: {
|
|
1681
|
+
"200": { description: "IOU verified" },
|
|
1682
|
+
"400": { description: "Invalid IOU" }
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
},
|
|
1686
|
+
"/v1/verify/consumer": {
|
|
1687
|
+
post: {
|
|
1688
|
+
summary: "Verify Agentic Consumer object (Layer 2)",
|
|
1689
|
+
description: "Verify an agenticConsumer object including ID token, contextual data, and signature chain.",
|
|
1690
|
+
operationId: "verifyConsumer",
|
|
1691
|
+
requestBody: {
|
|
1692
|
+
required: true,
|
|
1693
|
+
content: {
|
|
1694
|
+
"application/json": {
|
|
1695
|
+
schema: {
|
|
1696
|
+
type: "object",
|
|
1697
|
+
required: ["agenticConsumer", "signature"],
|
|
1698
|
+
properties: {
|
|
1699
|
+
"agenticConsumer": {
|
|
1700
|
+
type: "object",
|
|
1701
|
+
properties: {
|
|
1702
|
+
"idToken": { type: "string", description: "OIDC ID token" },
|
|
1703
|
+
"country": { type: "string" },
|
|
1704
|
+
"postalCode": { type: "string" },
|
|
1705
|
+
"ipAddress": { type: "string" },
|
|
1706
|
+
"nonce": { type: "string" }
|
|
1707
|
+
}
|
|
1708
|
+
},
|
|
1709
|
+
"signature": { type: "string" }
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
},
|
|
1715
|
+
responses: {
|
|
1716
|
+
"200": { description: "Consumer verified" },
|
|
1717
|
+
"400": { description: "Invalid consumer object" }
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
},
|
|
1721
|
+
"/v1/verify/payment": {
|
|
1722
|
+
post: {
|
|
1723
|
+
summary: "Verify Agentic Payment Container (Layer 3)",
|
|
1724
|
+
description: "Verify an agenticPaymentContainer object including card metadata, credential hash, and encrypted payload.",
|
|
1725
|
+
operationId: "verifyPayment",
|
|
1726
|
+
requestBody: {
|
|
1727
|
+
required: true,
|
|
1728
|
+
content: {
|
|
1729
|
+
"application/json": {
|
|
1730
|
+
schema: {
|
|
1731
|
+
type: "object",
|
|
1732
|
+
required: ["agenticPaymentContainer", "signature"],
|
|
1733
|
+
properties: {
|
|
1734
|
+
"agenticPaymentContainer": {
|
|
1735
|
+
type: "object",
|
|
1736
|
+
properties: {
|
|
1737
|
+
"lastFour": { type: "string" },
|
|
1738
|
+
"par": { type: "string", description: "Payment Account Reference" },
|
|
1739
|
+
"credentialHash": { type: "string" },
|
|
1740
|
+
"encryptedPayload": { type: "string" },
|
|
1741
|
+
"nonce": { type: "string" }
|
|
1742
|
+
}
|
|
1743
|
+
},
|
|
1744
|
+
"signature": { type: "string" }
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
},
|
|
1750
|
+
responses: {
|
|
1751
|
+
"200": { description: "Payment verified" },
|
|
1752
|
+
"400": { description: "Invalid payment container" }
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1297
1755
|
}
|
|
1298
1756
|
},
|
|
1299
1757
|
components: {
|
package/dist/tap-agents.d.ts
CHANGED
|
@@ -14,8 +14,9 @@ import { Agent, KVNamespace } from './agents.js';
|
|
|
14
14
|
*/
|
|
15
15
|
export interface TAPAgent extends Agent {
|
|
16
16
|
public_key?: string;
|
|
17
|
-
signature_algorithm?: 'ecdsa-p256-sha256' | 'rsa-pss-sha256';
|
|
17
|
+
signature_algorithm?: 'ecdsa-p256-sha256' | 'rsa-pss-sha256' | 'ed25519';
|
|
18
18
|
key_created_at?: number;
|
|
19
|
+
key_expires_at?: number;
|
|
19
20
|
capabilities?: TAPCapability[];
|
|
20
21
|
trust_level?: 'basic' | 'verified' | 'enterprise';
|
|
21
22
|
issuer?: string;
|
|
@@ -58,7 +59,7 @@ export declare function registerTAPAgent(agents: KVNamespace, appId: string, reg
|
|
|
58
59
|
operator?: string;
|
|
59
60
|
version?: string;
|
|
60
61
|
public_key?: string;
|
|
61
|
-
signature_algorithm?: 'ecdsa-p256-sha256' | 'rsa-pss-sha256';
|
|
62
|
+
signature_algorithm?: 'ecdsa-p256-sha256' | 'rsa-pss-sha256' | 'ed25519';
|
|
62
63
|
capabilities?: TAPCapability[];
|
|
63
64
|
trust_level?: 'basic' | 'verified' | 'enterprise';
|
|
64
65
|
issuer?: string;
|
package/dist/tap-agents.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tap-agents.d.ts","sourceRoot":"","sources":["../src/tap-agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,KAAK,EAAE,WAAW,EAAmB,MAAM,aAAa,CAAC;AAIlE;;GAEG;AACH,MAAM,WAAW,QAAS,SAAQ,KAAK;IAErC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB,CAAC,EAAE,mBAAmB,GAAG,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"tap-agents.d.ts","sourceRoot":"","sources":["../src/tap-agents.ts"],"names":[],"mappings":"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"}
|
package/dist/tap-agents.js
CHANGED
|
@@ -42,8 +42,8 @@ export async function registerTAPAgent(agents, appId, registration) {
|
|
|
42
42
|
return { success: false, error: 'signature_algorithm required when public_key provided' };
|
|
43
43
|
}
|
|
44
44
|
// Validate public key format
|
|
45
|
-
if (!
|
|
46
|
-
return { success: false, error: 'Invalid
|
|
45
|
+
if (!isValidPublicKey(agent.public_key, agent.signature_algorithm)) {
|
|
46
|
+
return { success: false, error: 'Invalid public key format' };
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
// Store agent
|
|
@@ -175,10 +175,23 @@ function generateSessionId() {
|
|
|
175
175
|
.map(b => b.toString(16).padStart(2, '0'))
|
|
176
176
|
.join('');
|
|
177
177
|
}
|
|
178
|
-
function
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
178
|
+
function isValidPublicKey(key, algorithm) {
|
|
179
|
+
// PEM format
|
|
180
|
+
if (key.includes('BEGIN PUBLIC KEY') && key.includes('END PUBLIC KEY') && key.length > 100) {
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
// Raw Ed25519 key (32 bytes = ~44 base64 chars)
|
|
184
|
+
if (algorithm === 'ed25519') {
|
|
185
|
+
const stripped = key.replace(/[\s]/g, '');
|
|
186
|
+
try {
|
|
187
|
+
const decoded = atob(stripped.replace(/-/g, '+').replace(/_/g, '/'));
|
|
188
|
+
return decoded.length === 32;
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return false;
|
|
182
195
|
}
|
|
183
196
|
async function updateAppAgentIndex(agents, appId, agentId, operation) {
|
|
184
197
|
try {
|