@dupecom/botcha-cloudflare 0.20.2 → 0.23.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.
Files changed (88) hide show
  1. package/README.md +74 -9
  2. package/dist/agent-auth.d.ts +129 -0
  3. package/dist/agent-auth.d.ts.map +1 -0
  4. package/dist/agent-auth.js +210 -0
  5. package/dist/agents.d.ts +10 -0
  6. package/dist/agents.d.ts.map +1 -1
  7. package/dist/agents.js +51 -1
  8. package/dist/app-gate.d.ts +6 -0
  9. package/dist/app-gate.d.ts.map +1 -0
  10. package/dist/app-gate.js +69 -0
  11. package/dist/apps.d.ts +13 -4
  12. package/dist/apps.d.ts.map +1 -1
  13. package/dist/apps.js +30 -4
  14. package/dist/dashboard/account.d.ts +63 -0
  15. package/dist/dashboard/account.d.ts.map +1 -0
  16. package/dist/dashboard/account.js +488 -0
  17. package/dist/dashboard/api.js +15 -68
  18. package/dist/dashboard/auth.d.ts.map +1 -1
  19. package/dist/dashboard/auth.js +14 -14
  20. package/dist/dashboard/docs.d.ts.map +1 -1
  21. package/dist/dashboard/docs.js +146 -3
  22. package/dist/dashboard/layout.d.ts.map +1 -1
  23. package/dist/dashboard/layout.js +2 -2
  24. package/dist/dashboard/mcp-setup.d.ts +15 -0
  25. package/dist/dashboard/mcp-setup.d.ts.map +1 -0
  26. package/dist/dashboard/mcp-setup.js +391 -0
  27. package/dist/dashboard/showcase.d.ts +6 -10
  28. package/dist/dashboard/showcase.d.ts.map +1 -1
  29. package/dist/dashboard/showcase.js +67 -991
  30. package/dist/dashboard/whitepaper.d.ts.map +1 -1
  31. package/dist/dashboard/whitepaper.js +42 -4
  32. package/dist/index.d.ts +5 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +660 -83
  35. package/dist/mcp.d.ts +20 -0
  36. package/dist/mcp.d.ts.map +1 -0
  37. package/dist/mcp.js +1290 -0
  38. package/dist/oauth-agent.d.ts +130 -0
  39. package/dist/oauth-agent.d.ts.map +1 -0
  40. package/dist/oauth-agent.js +194 -0
  41. package/dist/static.d.ts +781 -5
  42. package/dist/static.d.ts.map +1 -1
  43. package/dist/static.js +790 -111
  44. package/dist/tap-a2a-routes.d.ts +355 -0
  45. package/dist/tap-a2a-routes.d.ts.map +1 -0
  46. package/dist/tap-a2a-routes.js +475 -0
  47. package/dist/tap-a2a.d.ts +199 -0
  48. package/dist/tap-a2a.d.ts.map +1 -0
  49. package/dist/tap-a2a.js +502 -0
  50. package/dist/tap-agents.d.ts +15 -0
  51. package/dist/tap-agents.d.ts.map +1 -1
  52. package/dist/tap-agents.js +31 -1
  53. package/dist/tap-ans-routes.d.ts +302 -0
  54. package/dist/tap-ans-routes.d.ts.map +1 -0
  55. package/dist/tap-ans-routes.js +535 -0
  56. package/dist/tap-ans.d.ts +241 -0
  57. package/dist/tap-ans.d.ts.map +1 -0
  58. package/dist/tap-ans.js +481 -0
  59. package/dist/tap-delegation-routes.d.ts.map +1 -1
  60. package/dist/tap-delegation-routes.js +11 -0
  61. package/dist/tap-did.d.ts +140 -0
  62. package/dist/tap-did.d.ts.map +1 -0
  63. package/dist/tap-did.js +262 -0
  64. package/dist/tap-oidca-routes.d.ts +383 -0
  65. package/dist/tap-oidca-routes.d.ts.map +1 -0
  66. package/dist/tap-oidca-routes.js +597 -0
  67. package/dist/tap-oidca.d.ts +288 -0
  68. package/dist/tap-oidca.d.ts.map +1 -0
  69. package/dist/tap-oidca.js +461 -0
  70. package/dist/tap-routes.d.ts +24 -8
  71. package/dist/tap-routes.d.ts.map +1 -1
  72. package/dist/tap-routes.js +169 -23
  73. package/dist/tap-vc-routes.d.ts +358 -0
  74. package/dist/tap-vc-routes.d.ts.map +1 -0
  75. package/dist/tap-vc-routes.js +367 -0
  76. package/dist/tap-vc.d.ts +125 -0
  77. package/dist/tap-vc.d.ts.map +1 -0
  78. package/dist/tap-vc.js +245 -0
  79. package/dist/tap-x402-routes.d.ts +89 -0
  80. package/dist/tap-x402-routes.d.ts.map +1 -0
  81. package/dist/tap-x402-routes.js +579 -0
  82. package/dist/tap-x402.d.ts +222 -0
  83. package/dist/tap-x402.d.ts.map +1 -0
  84. package/dist/tap-x402.js +546 -0
  85. package/dist/webhooks.d.ts +99 -0
  86. package/dist/webhooks.d.ts.map +1 -0
  87. package/dist/webhooks.js +642 -0
  88. package/package.json +3 -1
package/dist/tap-vc.js ADDED
@@ -0,0 +1,245 @@
1
+ /**
2
+ * BOTCHA Verifiable Credentials — W3C VC Data Model 2.0
3
+ *
4
+ * Implements:
5
+ * - VC issuance: sign a BotchaVerification credential as a JWT
6
+ * - VC verification: validate signature, expiry, and issuer
7
+ * - Credential schema aligned with the VC Data Model 2.0 spec
8
+ *
9
+ * Encoding:
10
+ * VCs are encoded as JWT-VCs per the VC Data Model 2.0 spec.
11
+ * The JWT payload contains a "vc" claim with the JSON-LD credential,
12
+ * plus standard JWT claims (iss, sub, jti, iat, nbf, exp).
13
+ *
14
+ * Signing:
15
+ * - Preferred: ES256 with the BOTCHA JWT_SIGNING_KEY (verifiable offline)
16
+ * - Fallback: HS256 with JWT_SECRET (verifiable only by botcha.ai)
17
+ *
18
+ * Standards:
19
+ * - W3C VC Data Model 2.0: https://www.w3.org/TR/vc-data-model-2.0/
20
+ * - VC-JWT: https://www.w3.org/TR/vc-data-model-2.0/#json-web-token
21
+ * - DID Core 1.0: https://www.w3.org/TR/did-core/
22
+ */
23
+ import { SignJWT, jwtVerify, importJWK, decodeProtectedHeader } from 'jose';
24
+ import { getSigningPublicKeyJWK } from './auth.js';
25
+ // ============ CONSTANTS ============
26
+ const VC_ISSUER_DID = 'did:web:botcha.ai';
27
+ const VC_CONTEXT_V2 = 'https://www.w3.org/ns/credentials/v2';
28
+ const DEFAULT_VC_DURATION = 86_400; // 24 hours (seconds)
29
+ const MAX_VC_DURATION = 86_400 * 30; // 30 days (seconds)
30
+ // ============ ISSUANCE ============
31
+ /**
32
+ * Issue a W3C Verifiable Credential for a successful BOTCHA verification.
33
+ *
34
+ * The VC is encoded as a JWT-VC signed with BOTCHA's ES256 key.
35
+ * If no ES256 key is available, falls back to HS256.
36
+ *
37
+ * The JWT payload includes:
38
+ * iss = did:web:botcha.ai
39
+ * sub = agent DID or agent_id
40
+ * jti = credential ID (urn:botcha:vc:<uuid>)
41
+ * vc = the full JSON-LD credential object
42
+ * type = "botcha-vc" (BOTCHA-specific claim for quick type-checking)
43
+ */
44
+ export async function issueVC(options, signingKey, secret) {
45
+ try {
46
+ if (!signingKey && !secret) {
47
+ return { success: false, error: 'No signing key or secret provided' };
48
+ }
49
+ const durationSeconds = Math.min(options.duration_seconds ?? DEFAULT_VC_DURATION, MAX_VC_DURATION);
50
+ const now = new Date();
51
+ const expiresAt = new Date(now.getTime() + durationSeconds * 1_000);
52
+ const credentialId = `urn:botcha:vc:${crypto.randomUUID()}`;
53
+ // Build credentialSubject
54
+ const credentialSubject = {
55
+ agent_id: options.agent_id || 'anonymous',
56
+ app_id: options.app_id,
57
+ challenge_type: options.challenge_type || 'speed',
58
+ solve_time_ms: options.solve_time_ms,
59
+ trust_level: options.trust_level || 'basic',
60
+ };
61
+ if (options.capabilities && options.capabilities.length > 0) {
62
+ credentialSubject.capabilities = options.capabilities;
63
+ }
64
+ // Set subject DID if agent has one
65
+ if (options.agent_did) {
66
+ credentialSubject.id = options.agent_did;
67
+ }
68
+ // Build the JSON-LD VC object
69
+ const vc = {
70
+ '@context': [VC_CONTEXT_V2],
71
+ type: ['VerifiableCredential', 'BotchaVerification'],
72
+ id: credentialId,
73
+ issuer: VC_ISSUER_DID,
74
+ validFrom: now.toISOString(),
75
+ validUntil: expiresAt.toISOString(),
76
+ credentialSubject,
77
+ };
78
+ // Determine signing key + algorithm
79
+ let signKey;
80
+ let protectedHeader;
81
+ if (signingKey) {
82
+ signKey = (await importJWK(signingKey, 'ES256'));
83
+ protectedHeader = {
84
+ alg: 'ES256',
85
+ kid: signingKey.kid || 'botcha-signing-1',
86
+ typ: 'JWT',
87
+ };
88
+ }
89
+ else {
90
+ // HS256 fallback — valid JWT but not verifiable offline
91
+ signKey = new TextEncoder().encode(secret);
92
+ protectedHeader = { alg: 'HS256', typ: 'JWT' };
93
+ }
94
+ // JWT-VC claim mapping (VC Data Model 2.0 §6.3.1):
95
+ // iss → issuer
96
+ // sub → credentialSubject.id (or agent_id)
97
+ // jti → id (credential identifier)
98
+ // nbf → validFrom
99
+ // exp → validUntil
100
+ // vc → the JSON-LD credential object
101
+ const jwtPayload = {
102
+ vc,
103
+ type: 'botcha-vc', // BOTCHA-specific type claim for fast filtering
104
+ };
105
+ const subjectId = credentialSubject.id || options.agent_id || 'anonymous';
106
+ const vcJwt = await new SignJWT(jwtPayload)
107
+ .setProtectedHeader(protectedHeader)
108
+ .setIssuer(VC_ISSUER_DID)
109
+ .setSubject(subjectId)
110
+ .setJti(credentialId)
111
+ .setIssuedAt()
112
+ .setNotBefore(Math.floor(now.getTime() / 1_000))
113
+ .setExpirationTime(Math.floor(expiresAt.getTime() / 1_000))
114
+ .sign(signKey);
115
+ return {
116
+ success: true,
117
+ vc,
118
+ vc_jwt: vcJwt,
119
+ credential_id: credentialId,
120
+ issued_at: now.toISOString(),
121
+ expires_at: expiresAt.toISOString(),
122
+ };
123
+ }
124
+ catch (error) {
125
+ console.error('VC issuance failed:', error);
126
+ return {
127
+ success: false,
128
+ error: error instanceof Error ? error.message : 'VC issuance failed',
129
+ };
130
+ }
131
+ }
132
+ // ============ VERIFICATION ============
133
+ /**
134
+ * Verify a BOTCHA VC JWT.
135
+ *
136
+ * Checks (in order):
137
+ * 1. JWT signature (ES256 or HS256)
138
+ * 2. JWT expiration (exp claim)
139
+ * 3. Token type claim = "botcha-vc"
140
+ * 4. Issuer claim = "did:web:botcha.ai"
141
+ * 5. Presence of `vc` claim with credentialSubject
142
+ *
143
+ * Returns the decoded VC and credential subject if valid.
144
+ */
145
+ export async function verifyVC(vcJwt, signingKey, secret) {
146
+ try {
147
+ if (!signingKey && !secret) {
148
+ return { valid: false, error: 'No verification key or secret provided' };
149
+ }
150
+ // Detect algorithm from token header
151
+ const header = decodeProtectedHeader(vcJwt);
152
+ let verifyKey;
153
+ let algorithms;
154
+ if (header.alg === 'ES256' && signingKey) {
155
+ const publicKeyJwk = getSigningPublicKeyJWK(signingKey);
156
+ verifyKey = (await importJWK(publicKeyJwk, 'ES256'));
157
+ algorithms = ['ES256'];
158
+ }
159
+ else if (secret) {
160
+ verifyKey = new TextEncoder().encode(secret);
161
+ algorithms = ['HS256'];
162
+ }
163
+ else {
164
+ return {
165
+ valid: false,
166
+ error: `Token signed with ${header.alg} but no compatible key provided`,
167
+ };
168
+ }
169
+ const { payload } = await jwtVerify(vcJwt, verifyKey, { algorithms });
170
+ // Check BOTCHA-specific type claim
171
+ if (payload.type !== 'botcha-vc') {
172
+ return {
173
+ valid: false,
174
+ error: `Invalid token type "${payload.type}". Expected "botcha-vc".`,
175
+ };
176
+ }
177
+ // Check issuer
178
+ if (payload.iss !== VC_ISSUER_DID) {
179
+ return {
180
+ valid: false,
181
+ error: `Invalid issuer "${payload.iss}". Expected "${VC_ISSUER_DID}".`,
182
+ };
183
+ }
184
+ // Extract VC object
185
+ const vc = payload.vc;
186
+ if (!vc || !vc.credentialSubject) {
187
+ return {
188
+ valid: false,
189
+ error: 'VC payload is missing or malformed (no credentialSubject)',
190
+ };
191
+ }
192
+ return {
193
+ valid: true,
194
+ vc,
195
+ credential_subject: vc.credentialSubject,
196
+ issuer: payload.iss,
197
+ credential_id: payload.jti,
198
+ issued_at: payload.iat
199
+ ? new Date(payload.iat * 1_000).toISOString()
200
+ : undefined,
201
+ expires_at: payload.exp
202
+ ? new Date(payload.exp * 1_000).toISOString()
203
+ : undefined,
204
+ };
205
+ }
206
+ catch (error) {
207
+ return {
208
+ valid: false,
209
+ error: error instanceof Error ? error.message : 'VC verification failed',
210
+ };
211
+ }
212
+ }
213
+ // ============ UTILITIES ============
214
+ /**
215
+ * Extract the BOTCHA access_token payload from the Authorization header.
216
+ * Returns null if the token is missing or cannot be decoded (does NOT verify).
217
+ */
218
+ export function extractVCPayloadClaims(vcJwt) {
219
+ try {
220
+ const parts = vcJwt.split('.');
221
+ if (parts.length !== 3)
222
+ return null;
223
+ const padded = parts[1] + '='.repeat((4 - (parts[1].length % 4)) % 4);
224
+ const decoded = JSON.parse(atob(padded.replace(/-/g, '+').replace(/_/g, '/')));
225
+ const vc = decoded?.vc;
226
+ if (!vc?.credentialSubject)
227
+ return null;
228
+ const cs = vc.credentialSubject;
229
+ return {
230
+ agent_id: cs.agent_id,
231
+ app_id: cs.app_id,
232
+ solve_time_ms: cs.solve_time_ms,
233
+ challenge_type: cs.challenge_type,
234
+ trust_level: cs.trust_level,
235
+ };
236
+ }
237
+ catch {
238
+ return null;
239
+ }
240
+ }
241
+ export default {
242
+ issueVC,
243
+ verifyVC,
244
+ extractVCPayloadClaims,
245
+ };
@@ -0,0 +1,89 @@
1
+ /**
2
+ * x402 Payment Gating — Route Handlers
3
+ *
4
+ * Exposes BOTCHA's x402-compliant API endpoints:
5
+ *
6
+ * POST /v1/x402/verify-payment — Facilitator: verify a payment proof
7
+ * GET /v1/x402/challenge — Pay-for-verification (402 → X-Payment → token)
8
+ * GET /agent-only/x402 — Demo: requires BOTCHA token + x402 payment
9
+ * POST /v1/x402/webhook — Settlement notifications from facilitators
10
+ *
11
+ * All endpoints are built for Cloudflare Workers (Hono framework, no Node APIs).
12
+ */
13
+ import type { Context } from 'hono';
14
+ /**
15
+ * POST /v1/x402/verify-payment
16
+ *
17
+ * Acts as a lightweight x402-compatible facilitator.
18
+ * Accepts a payment proof (base64-encoded X-Payment payload) and
19
+ * verifies: structure, recipient, amount, deadline, nonce, signature.
20
+ *
21
+ * Request body:
22
+ * { payment: "<base64-encoded X402PaymentProof>" }
23
+ * OR submit the raw X-Payment header value directly in the body field.
24
+ *
25
+ * Response:
26
+ * 200 { verified: true, txHash, payer, amount, network }
27
+ * 400 { verified: false, error, errorCode }
28
+ */
29
+ export declare function verifyPaymentRoute(c: Context): Promise<Response>;
30
+ /**
31
+ * GET /v1/x402/challenge
32
+ *
33
+ * The flagship pay-for-verification endpoint.
34
+ *
35
+ * Without X-Payment header → 402 Payment Required
36
+ * With valid X-Payment header → 200 with BOTCHA access_token
37
+ *
38
+ * This allows agents to get a BOTCHA verification token by paying
39
+ * $0.001 USDC instead of solving a challenge.
40
+ *
41
+ * x402 standard flow:
42
+ * 1. Agent: GET /v1/x402/challenge
43
+ * 2. Server: 402 + X-Payment-Required: { amount, payTo, asset, ... }
44
+ * 3. Agent: signs ERC-3009 transferWithAuthorization
45
+ * 4. Agent: GET /v1/x402/challenge + X-Payment: <base64-proof>
46
+ * 5. Server: 200 + { access_token, ... } + X-Payment-Response: { success, txHash }
47
+ */
48
+ export declare function x402ChallengeRoute(c: Context): Promise<Response>;
49
+ /**
50
+ * GET /agent-only/x402
51
+ *
52
+ * Demo endpoint: requires BOTH BOTCHA Bearer token + x402 micropayment.
53
+ * Reference implementation for "verified + paid" double-gated resources.
54
+ *
55
+ * Without token → 401 (get BOTCHA verified first)
56
+ * Without payment → 402 (pay $0.001 USDC)
57
+ * With both → 200 (access granted)
58
+ */
59
+ export declare function agentOnlyX402Route(c: Context): Promise<Response>;
60
+ /**
61
+ * POST /v1/x402/webhook
62
+ *
63
+ * Receive x402 settlement notifications from facilitators (Coinbase CDP, etc.)
64
+ *
65
+ * This endpoint:
66
+ * - Validates the webhook signature (HMAC-SHA256 of payload with BOTCHA_WEBHOOK_SECRET)
67
+ * - Updates payment records
68
+ * - Credits agent reputation on successful payment
69
+ * - Returns 200 to acknowledge receipt
70
+ *
71
+ * Expected payload: X402WebhookEvent
72
+ */
73
+ export declare function x402WebhookRoute(c: Context): Promise<Response>;
74
+ /**
75
+ * GET /v1/x402/info
76
+ *
77
+ * Public endpoint: returns x402 payment configuration for this BOTCHA instance.
78
+ * Agents can discover pricing, wallet, and supported networks.
79
+ */
80
+ export declare function x402InfoRoute(c: Context): Promise<Response>;
81
+ declare const _default: {
82
+ verifyPaymentRoute: typeof verifyPaymentRoute;
83
+ x402ChallengeRoute: typeof x402ChallengeRoute;
84
+ agentOnlyX402Route: typeof agentOnlyX402Route;
85
+ x402WebhookRoute: typeof x402WebhookRoute;
86
+ x402InfoRoute: typeof x402InfoRoute;
87
+ };
88
+ export default _default;
89
+ //# sourceMappingURL=tap-x402-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tap-x402-routes.d.ts","sourceRoot":"","sources":["../src/tap-x402-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAqEpC;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAmFtE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CA6ItE;AAED;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAsJtE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAsEpE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAiDjE;;;;;;;;AAgDD,wBAME"}