@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
@@ -0,0 +1,475 @@
1
+ /**
2
+ * A2A Agent Card Attestation — Route Handlers
3
+ *
4
+ * Routes:
5
+ * GET /.well-known/agent.json — BOTCHA's own A2A Agent Card
6
+ * POST /v1/a2a/attest — Attest an A2A Agent Card
7
+ * POST /v1/a2a/verify-card — Verify an attested A2A Agent Card
8
+ * GET /v1/a2a/cards — List BOTCHA-verified Agent Cards
9
+ * GET /v1/a2a/cards/:id — Get a specific A2A attestation record
10
+ */
11
+ import { extractBearerToken, verifyToken, getSigningPublicKeyJWK } from './auth.js';
12
+ import { getBotchaAgentCard, attestCard, verifyCard, getCardAttestation, listVerifiedCards, } from './tap-a2a.js';
13
+ // ============ HELPERS ============
14
+ function getVerificationPublicKey(env) {
15
+ const rawSigningKey = env?.JWT_SIGNING_KEY;
16
+ if (!rawSigningKey)
17
+ return undefined;
18
+ try {
19
+ const signingKey = JSON.parse(rawSigningKey);
20
+ return getSigningPublicKeyJWK(signingKey);
21
+ }
22
+ catch {
23
+ console.error('Failed to parse JWT_SIGNING_KEY for A2A route verification');
24
+ return undefined;
25
+ }
26
+ }
27
+ async function validateAppAccess(c, requireAuth = true) {
28
+ const queryAppId = c.req.query('app_id');
29
+ const authHeader = c.req.header('authorization');
30
+ const token = extractBearerToken(authHeader);
31
+ if (!token) {
32
+ if (!requireAuth)
33
+ return { valid: true, appId: queryAppId };
34
+ return { valid: false, error: 'UNAUTHORIZED', status: 401 };
35
+ }
36
+ const publicKey = getVerificationPublicKey(c.env);
37
+ const result = await verifyToken(token, c.env.JWT_SECRET, c.env, undefined, publicKey);
38
+ if (!result.valid || !result.payload) {
39
+ return { valid: false, error: 'INVALID_TOKEN', status: 401 };
40
+ }
41
+ const jwtAppId = result.payload.app_id;
42
+ if (!jwtAppId) {
43
+ return { valid: false, error: 'MISSING_APP_ID', status: 403 };
44
+ }
45
+ if (queryAppId && queryAppId !== jwtAppId) {
46
+ return { valid: false, error: 'APP_ID_MISMATCH', status: 403 };
47
+ }
48
+ return { valid: true, appId: jwtAppId };
49
+ }
50
+ // ============ ROUTE HANDLERS ============
51
+ /**
52
+ * GET /.well-known/agent.json
53
+ *
54
+ * BOTCHA's own A2A Agent Card. Serves the standard A2A discovery document
55
+ * so any A2A-compatible agent can discover BOTCHA's skills and auth requirements.
56
+ *
57
+ * No auth required — this is a public discovery endpoint.
58
+ */
59
+ export async function agentCardRoute(c) {
60
+ const version = c.env?.BOTCHA_VERSION;
61
+ const card = getBotchaAgentCard(version);
62
+ return c.json(card, 200, {
63
+ 'Cache-Control': 'public, max-age=3600',
64
+ 'Content-Type': 'application/json',
65
+ 'X-A2A-Version': '0.2.2',
66
+ });
67
+ }
68
+ /**
69
+ * POST /v1/a2a/attest
70
+ *
71
+ * Attest an A2A Agent Card. BOTCHA verifies the card structure, hashes its
72
+ * content, signs a JWT attestation, and embeds it in extensions.botcha_attestation.
73
+ *
74
+ * Request body:
75
+ * card — A2A Agent Card JSON (required)
76
+ * duration_seconds — TTL for attestation (default 86400, max 2592000)
77
+ * trust_level — 'basic' | 'verified' | 'enterprise' (default 'verified')
78
+ *
79
+ * Auth: BOTCHA Bearer token (app_id required)
80
+ */
81
+ export async function attestCardRoute(c) {
82
+ try {
83
+ const appAccess = await validateAppAccess(c, true);
84
+ if (!appAccess.valid) {
85
+ return c.json({
86
+ success: false,
87
+ error: appAccess.error,
88
+ message: 'Authentication required. Solve a BOTCHA challenge to get a Bearer token.',
89
+ hint: 'GET /v1/token?app_id=<your_app_id> → solve SHA256 → POST /v1/token/verify',
90
+ }, (appAccess.status || 401));
91
+ }
92
+ const body = await c.req.json().catch(() => ({}));
93
+ if (!body.card || typeof body.card !== 'object') {
94
+ return c.json({
95
+ success: false,
96
+ error: 'MISSING_CARD',
97
+ message: 'Request body must include a "card" field containing an A2A Agent Card JSON object.',
98
+ example: {
99
+ card: {
100
+ name: 'My Commerce Agent',
101
+ description: 'An A2A-compatible commerce agent',
102
+ url: 'https://myagent.example.com',
103
+ version: '1.0.0',
104
+ capabilities: { streaming: false },
105
+ skills: [{ id: 'browse', name: 'Browse', description: 'Browse products' }],
106
+ },
107
+ duration_seconds: 86400,
108
+ },
109
+ }, 400);
110
+ }
111
+ const card = body.card;
112
+ const result = await attestCard(c.env.SESSIONS, c.env.JWT_SECRET, {
113
+ card,
114
+ app_id: appAccess.appId,
115
+ duration_seconds: typeof body.duration_seconds === 'number' ? body.duration_seconds : undefined,
116
+ trust_level: typeof body.trust_level === 'string' ? body.trust_level : undefined,
117
+ });
118
+ if (!result.success) {
119
+ const status = result.error?.includes('must have') ? 400
120
+ : result.error?.includes('Invalid') ? 400
121
+ : 500;
122
+ return c.json({
123
+ success: false,
124
+ error: 'ATTESTATION_FAILED',
125
+ message: result.error,
126
+ }, status);
127
+ }
128
+ const att = result.attestation;
129
+ return c.json({
130
+ success: true,
131
+ message: 'Agent Card attested successfully. BOTCHA is now the trust oracle for this card.',
132
+ attestation: {
133
+ attestation_id: att.attestation_id,
134
+ agent_url: att.agent_url,
135
+ agent_name: att.agent_name,
136
+ app_id: att.app_id,
137
+ card_hash: att.card_hash,
138
+ trust_level: att.trust_level,
139
+ token: att.token,
140
+ created_at: new Date(att.created_at).toISOString(),
141
+ expires_at: new Date(att.expires_at).toISOString(),
142
+ },
143
+ attested_card: result.attested_card,
144
+ usage: {
145
+ note: 'Embed the attested_card in your A2A discovery endpoint (/.well-known/agent.json)',
146
+ verify: 'Other agents can verify this card via POST /v1/a2a/verify-card',
147
+ registry: 'This card is now listed in GET /v1/a2a/cards?verified=true',
148
+ },
149
+ }, 201);
150
+ }
151
+ catch (error) {
152
+ console.error('A2A attest route error:', error);
153
+ return c.json({
154
+ success: false,
155
+ error: 'INTERNAL_ERROR',
156
+ message: 'Internal server error',
157
+ }, 500);
158
+ }
159
+ }
160
+ /**
161
+ * POST /v1/a2a/verify-card
162
+ *
163
+ * Verify a BOTCHA-attested A2A Agent Card. Any agent can call this endpoint
164
+ * to check whether a card's attestation is valid. No auth required.
165
+ *
166
+ * Request body:
167
+ * card — A2A Agent Card JSON including extensions.botcha_attestation (required)
168
+ *
169
+ * Returns:
170
+ * valid: true → card is verified, claims decoded
171
+ * valid: false → reason for failure (expired, tampered, revoked, missing)
172
+ */
173
+ export async function verifyCardRoute(c) {
174
+ try {
175
+ const body = await c.req.json().catch(() => ({}));
176
+ if (!body.card || typeof body.card !== 'object') {
177
+ return c.json({
178
+ success: false,
179
+ error: 'MISSING_CARD',
180
+ message: 'Request body must include a "card" field containing an A2A Agent Card JSON with extensions.botcha_attestation.',
181
+ }, 400);
182
+ }
183
+ const card = body.card;
184
+ const result = await verifyCard(c.env.SESSIONS, c.env.JWT_SECRET, card);
185
+ if (!result.success) {
186
+ return c.json({
187
+ success: false,
188
+ error: 'VERIFICATION_ERROR',
189
+ message: result.error,
190
+ }, 500);
191
+ }
192
+ if (!result.valid) {
193
+ return c.json({
194
+ success: true,
195
+ valid: false,
196
+ verified: false,
197
+ error: result.error,
198
+ reason: result.reason,
199
+ attestation_id: result.attestation_id || null,
200
+ card_hash: result.card_hash || null,
201
+ }, 200);
202
+ }
203
+ return c.json({
204
+ success: true,
205
+ valid: true,
206
+ verified: true,
207
+ attestation_id: result.attestation_id,
208
+ agent_url: result.agent_url,
209
+ agent_name: result.agent_name,
210
+ card_hash: result.card_hash,
211
+ trust_level: result.trust_level,
212
+ app_id: result.app_id,
213
+ issued_at: result.issued_at,
214
+ expires_at: result.expires_at,
215
+ issuer: 'https://botcha.ai',
216
+ message: '✅ Agent Card verified. BOTCHA attests this agent is who it claims to be.',
217
+ }, 200);
218
+ }
219
+ catch (error) {
220
+ console.error('A2A verify-card route error:', error);
221
+ return c.json({
222
+ success: false,
223
+ error: 'INTERNAL_ERROR',
224
+ message: 'Internal server error',
225
+ }, 500);
226
+ }
227
+ }
228
+ /**
229
+ * GET /v1/a2a/cards
230
+ *
231
+ * List BOTCHA-verified A2A Agent Cards from the public registry.
232
+ *
233
+ * Query params:
234
+ * verified=true — only non-revoked (default true)
235
+ * agent_url= — filter by agent URL
236
+ * limit= — max results (default 50, max 200)
237
+ *
238
+ * No auth required — this is a public discovery endpoint.
239
+ */
240
+ export async function listCardsRoute(c) {
241
+ try {
242
+ const verifiedParam = c.req.query('verified');
243
+ const agentUrl = c.req.query('agent_url');
244
+ const limitParam = c.req.query('limit');
245
+ const verifiedOnly = verifiedParam !== 'false';
246
+ const limit = limitParam ? Math.min(parseInt(limitParam, 10) || 50, 200) : 50;
247
+ const result = await listVerifiedCards(c.env.SESSIONS, {
248
+ verified_only: verifiedOnly,
249
+ agent_url: agentUrl || undefined,
250
+ limit,
251
+ });
252
+ if (!result.success) {
253
+ return c.json({
254
+ success: false,
255
+ error: 'REGISTRY_ERROR',
256
+ message: result.error,
257
+ }, 500);
258
+ }
259
+ const attestations = result.attestations;
260
+ return c.json({
261
+ success: true,
262
+ count: attestations.length,
263
+ verified_only: verifiedOnly,
264
+ agent_url_filter: agentUrl || null,
265
+ cards: attestations.map(att => ({
266
+ attestation_id: att.attestation_id,
267
+ agent_url: att.agent_url,
268
+ agent_name: att.agent_name,
269
+ app_id: att.app_id,
270
+ card_hash: att.card_hash,
271
+ trust_level: att.trust_level,
272
+ created_at: new Date(att.created_at).toISOString(),
273
+ expires_at: new Date(att.expires_at).toISOString(),
274
+ revoked: att.revoked,
275
+ })),
276
+ meta: {
277
+ note: 'BOTCHA-verified A2A Agent Card registry. Each entry is a cryptographically attested agent.',
278
+ verify: 'Verify any listed card: POST /v1/a2a/verify-card with the card JSON',
279
+ attest: 'Add your agent: POST /v1/a2a/attest (requires BOTCHA Bearer token)',
280
+ },
281
+ }, 200, {
282
+ 'Cache-Control': 'public, max-age=60',
283
+ });
284
+ }
285
+ catch (error) {
286
+ console.error('A2A list cards route error:', error);
287
+ return c.json({
288
+ success: false,
289
+ error: 'INTERNAL_ERROR',
290
+ message: 'Internal server error',
291
+ }, 500);
292
+ }
293
+ }
294
+ /**
295
+ * GET /v1/a2a/cards/:id
296
+ *
297
+ * Get a specific A2A attestation record by attestation ID.
298
+ * No auth required — public registry lookup.
299
+ */
300
+ export async function getCardAttestationRoute(c) {
301
+ try {
302
+ const attestationId = c.req.param('id');
303
+ if (!attestationId) {
304
+ return c.json({
305
+ success: false,
306
+ error: 'MISSING_ID',
307
+ message: 'Attestation ID is required',
308
+ }, 400);
309
+ }
310
+ const result = await getCardAttestation(c.env.SESSIONS, attestationId);
311
+ if (!result.success || !result.attestation) {
312
+ return c.json({
313
+ success: false,
314
+ error: 'NOT_FOUND',
315
+ message: result.error || 'Attestation not found or expired',
316
+ }, 404);
317
+ }
318
+ const att = result.attestation;
319
+ return c.json({
320
+ success: true,
321
+ attestation_id: att.attestation_id,
322
+ agent_url: att.agent_url,
323
+ agent_name: att.agent_name,
324
+ app_id: att.app_id,
325
+ card_hash: att.card_hash,
326
+ trust_level: att.trust_level,
327
+ created_at: new Date(att.created_at).toISOString(),
328
+ expires_at: new Date(att.expires_at).toISOString(),
329
+ revoked: att.revoked,
330
+ revoked_at: att.revoked_at ? new Date(att.revoked_at).toISOString() : null,
331
+ }, 200);
332
+ }
333
+ catch (error) {
334
+ console.error('A2A get card attestation route error:', error);
335
+ return c.json({
336
+ success: false,
337
+ error: 'INTERNAL_ERROR',
338
+ message: 'Internal server error',
339
+ }, 500);
340
+ }
341
+ }
342
+ /**
343
+ * POST /v1/a2a/verify-agent
344
+ *
345
+ * Verify an agent by agent_card (with embedded attestation) or by agent_url.
346
+ * Convenience wrapper: accepts the same payload as /v1/a2a/verify-card
347
+ * plus an `agent_url` shorthand to look up the latest active attestation.
348
+ */
349
+ export async function verifyAgentRoute(c) {
350
+ try {
351
+ const body = await c.req
352
+ .json()
353
+ .catch(() => ({}));
354
+ const sessions = c.env.SESSIONS;
355
+ // Shorthand: agent_url lookup
356
+ if (body.agent_url && !body.agent_card) {
357
+ const cards = await listVerifiedCards(sessions, {
358
+ agent_url: body.agent_url,
359
+ verified_only: true,
360
+ limit: 1,
361
+ });
362
+ if (!cards.success || !cards.attestations?.length) {
363
+ return c.json({
364
+ success: false,
365
+ verified: false,
366
+ error: 'NOT_FOUND',
367
+ message: `No active attestation found for agent_url: ${body.agent_url}`,
368
+ }, 404);
369
+ }
370
+ const att = cards.attestations[0];
371
+ return c.json({
372
+ success: true,
373
+ verified: true,
374
+ agent_url: att.agent_url,
375
+ agent_name: att.agent_name,
376
+ attestation_id: att.attestation_id,
377
+ trust_level: att.trust_level,
378
+ issued_at: new Date(att.created_at).toISOString(),
379
+ expires_at: new Date(att.expires_at).toISOString(),
380
+ issuer: 'https://botcha.ai',
381
+ });
382
+ }
383
+ // Full card verification path (same as verify-card)
384
+ if (!body.agent_card) {
385
+ return c.json({
386
+ success: false,
387
+ verified: false,
388
+ error: 'MISSING_CARD',
389
+ message: 'Provide { agent_card: {...} } (Agent Card with embedded attestation) or { agent_url: "..." }',
390
+ example: { agent_card: { name: 'My Agent', url: 'https://example.com', extensions: { botcha_attestation: '...' } } },
391
+ }, 400);
392
+ }
393
+ const result = await verifyCard(sessions, c.env.JWT_SECRET, body.agent_card);
394
+ if (!result.success) {
395
+ return c.json({
396
+ success: false,
397
+ verified: false,
398
+ error: result.error || 'VERIFICATION_FAILED',
399
+ valid: false,
400
+ }, result.error === 'MISSING_CARD' ? 400 : 200);
401
+ }
402
+ return c.json({
403
+ success: true,
404
+ verified: result.valid,
405
+ valid: result.valid,
406
+ attestation_id: result.attestation_id,
407
+ trust_level: result.trust_level,
408
+ card_hash: result.card_hash,
409
+ issued_at: result.issued_at,
410
+ expires_at: result.expires_at,
411
+ issuer: 'https://botcha.ai',
412
+ });
413
+ }
414
+ catch (error) {
415
+ console.error('A2A verify-agent route error:', error);
416
+ return c.json({ success: false, error: 'INTERNAL_ERROR', message: 'Internal server error' }, 500);
417
+ }
418
+ }
419
+ /**
420
+ * GET /v1/a2a/trust-level/:agent_url
421
+ *
422
+ * Returns the current trust level for an agent identified by URL.
423
+ * The :agent_url path param should be URL-encoded.
424
+ */
425
+ export async function agentTrustLevelRoute(c) {
426
+ try {
427
+ const agentUrl = decodeURIComponent(c.req.param('agent_url') || '');
428
+ const sessions = c.env.SESSIONS;
429
+ if (!agentUrl) {
430
+ return c.json({
431
+ success: false,
432
+ error: 'MISSING_AGENT_URL',
433
+ message: 'Provide the agent URL as a URL-encoded path parameter: /v1/a2a/trust-level/:agent_url',
434
+ }, 400);
435
+ }
436
+ const cards = await listVerifiedCards(sessions, {
437
+ agent_url: agentUrl,
438
+ verified_only: true,
439
+ limit: 1,
440
+ });
441
+ if (!cards.success || !cards.attestations?.length) {
442
+ return c.json({
443
+ success: true,
444
+ agent_url: agentUrl,
445
+ trust_level: 'unverified',
446
+ attestation_count: 0,
447
+ message: 'No active BOTCHA attestation found for this agent.',
448
+ });
449
+ }
450
+ const att = cards.attestations[0];
451
+ return c.json({
452
+ success: true,
453
+ agent_url: att.agent_url,
454
+ agent_name: att.agent_name,
455
+ trust_level: att.trust_level,
456
+ attestation_id: att.attestation_id,
457
+ issued_at: new Date(att.created_at).toISOString(),
458
+ expires_at: new Date(att.expires_at).toISOString(),
459
+ verified: !att.revoked,
460
+ });
461
+ }
462
+ catch (error) {
463
+ console.error('A2A trust-level route error:', error);
464
+ return c.json({ success: false, error: 'INTERNAL_ERROR', message: 'Internal server error' }, 500);
465
+ }
466
+ }
467
+ export default {
468
+ agentCardRoute,
469
+ attestCardRoute,
470
+ verifyCardRoute,
471
+ listCardsRoute,
472
+ getCardAttestationRoute,
473
+ verifyAgentRoute,
474
+ agentTrustLevelRoute,
475
+ };
@@ -0,0 +1,199 @@
1
+ /**
2
+ * A2A Agent Card Attestation — BOTCHA as A2A Trust Oracle
3
+ *
4
+ * Implements Google's A2A (Agent-to-Agent) protocol trust layer:
5
+ * 1. BOTCHA's own Agent Card (/.well-known/agent.json)
6
+ * 2. Agent Card attestation issuance (POST /v1/a2a/attest)
7
+ * 3. Agent Card attestation verification (POST /v1/a2a/verify-card)
8
+ * 4. Verified card registry (GET /v1/a2a/cards)
9
+ *
10
+ * Attestation model:
11
+ * - Input: any A2A Agent Card JSON
12
+ * - Output: a signed JWT embedding SHA-256(canonicalized card)
13
+ * - The JWT is embedded into card.extensions.botcha_attestation
14
+ * - Verification checks: signature, hash match, expiration, revocation
15
+ *
16
+ * References:
17
+ * https://google.github.io/A2A/
18
+ * https://github.com/google-a2a/A2A
19
+ */
20
+ import type { KVNamespace } from './agents.js';
21
+ export interface A2AAgentCardAuthentication {
22
+ schemes: string[];
23
+ description?: string;
24
+ credentials?: Record<string, string>;
25
+ }
26
+ export interface A2AAgentCardSkill {
27
+ id: string;
28
+ name: string;
29
+ description?: string;
30
+ tags?: string[];
31
+ examples?: string[];
32
+ inputModes?: string[];
33
+ outputModes?: string[];
34
+ }
35
+ export interface A2AAgentCardCapabilities {
36
+ streaming?: boolean;
37
+ pushNotifications?: boolean;
38
+ stateTransitionHistory?: boolean;
39
+ }
40
+ export interface BotchaAttestationExtension {
41
+ token: string;
42
+ verified_at: string;
43
+ trust_level: string;
44
+ issuer: string;
45
+ card_hash: string;
46
+ expires_at: string;
47
+ }
48
+ export interface A2AAgentCard {
49
+ name: string;
50
+ description?: string;
51
+ url: string;
52
+ version?: string;
53
+ documentationUrl?: string;
54
+ capabilities?: A2AAgentCardCapabilities;
55
+ authentication?: A2AAgentCardAuthentication[];
56
+ defaultInputModes?: string[];
57
+ defaultOutputModes?: string[];
58
+ skills?: A2AAgentCardSkill[];
59
+ extensions?: {
60
+ botcha_attestation?: BotchaAttestationExtension;
61
+ [key: string]: unknown;
62
+ };
63
+ [key: string]: unknown;
64
+ }
65
+ export interface A2AAttestationPayload {
66
+ sub: string;
67
+ iss: string;
68
+ type: 'botcha-a2a-attestation';
69
+ jti: string;
70
+ iat: number;
71
+ exp: number;
72
+ card_hash: string;
73
+ agent_name: string;
74
+ agent_url: string;
75
+ app_id: string;
76
+ trust_level: string;
77
+ }
78
+ export interface A2AAttestation {
79
+ attestation_id: string;
80
+ agent_url: string;
81
+ agent_name: string;
82
+ app_id: string;
83
+ card_hash: string;
84
+ token: string;
85
+ trust_level: string;
86
+ created_at: number;
87
+ expires_at: number;
88
+ revoked: boolean;
89
+ revoked_at?: number;
90
+ card_snapshot?: A2AAgentCard;
91
+ }
92
+ export interface AttestCardOptions {
93
+ card: A2AAgentCard;
94
+ app_id: string;
95
+ duration_seconds?: number;
96
+ trust_level?: string;
97
+ }
98
+ export interface AttestCardResult {
99
+ success: boolean;
100
+ attestation?: A2AAttestation;
101
+ attested_card?: A2AAgentCard;
102
+ error?: string;
103
+ }
104
+ export interface VerifyCardResult {
105
+ success: boolean;
106
+ valid?: boolean;
107
+ attestation_id?: string;
108
+ agent_url?: string;
109
+ agent_name?: string;
110
+ card_hash?: string;
111
+ trust_level?: string;
112
+ issued_at?: string;
113
+ expires_at?: string;
114
+ app_id?: string;
115
+ error?: string;
116
+ reason?: string;
117
+ }
118
+ export declare const BOTCHA_VERSION = "0.21.2";
119
+ export declare const BOTCHA_URL = "https://botcha.ai";
120
+ /**
121
+ * BOTCHA's A2A Agent Card.
122
+ * Served at /.well-known/agent.json
123
+ */
124
+ export declare function getBotchaAgentCard(version?: string): A2AAgentCard;
125
+ /**
126
+ * Canonicalize an A2A Agent Card for hashing.
127
+ *
128
+ * We remove the extensions.botcha_attestation field before hashing
129
+ * so that the attestation can be embedded in the card without
130
+ * invalidating its own hash. All other fields are included.
131
+ *
132
+ * Canonicalization: JSON.stringify with sorted keys (deterministic).
133
+ */
134
+ export declare function canonicalizeCard(card: A2AAgentCard): string;
135
+ /**
136
+ * Compute SHA-256 of a canonicalized card string.
137
+ * Returns lowercase hex string.
138
+ */
139
+ export declare function hashCard(card: A2AAgentCard): Promise<string>;
140
+ /**
141
+ * Issue a BOTCHA attestation for an A2A Agent Card.
142
+ *
143
+ * Steps:
144
+ * 1. Validate card (name + url required)
145
+ * 2. Canonicalize and hash the card (without extensions)
146
+ * 3. Sign a JWT with card_hash + agent identity
147
+ * 4. Embed attestation in card.extensions.botcha_attestation
148
+ * 5. Store attestation in KV for lookup and revocation
149
+ */
150
+ export declare function attestCard(sessions: KVNamespace, secret: string, options: AttestCardOptions): Promise<AttestCardResult>;
151
+ /**
152
+ * Verify a BOTCHA-attested A2A Agent Card.
153
+ *
154
+ * Checks:
155
+ * 1. Card has extensions.botcha_attestation.token
156
+ * 2. JWT signature and expiration (cryptographic)
157
+ * 3. JWT type is 'botcha-a2a-attestation'
158
+ * 4. card_hash matches the current card content (tamper detection)
159
+ * 5. Revocation status (KV lookup, fail-open)
160
+ *
161
+ * Returns verified/invalid + decoded claims.
162
+ */
163
+ export declare function verifyCard(sessions: KVNamespace, secret: string, card: A2AAgentCard): Promise<VerifyCardResult>;
164
+ /**
165
+ * Get a specific A2A attestation record by ID.
166
+ */
167
+ export declare function getCardAttestation(sessions: KVNamespace, attestationId: string): Promise<{
168
+ success: boolean;
169
+ attestation?: A2AAttestation;
170
+ error?: string;
171
+ }>;
172
+ /**
173
+ * List BOTCHA-verified A2A cards from the registry.
174
+ *
175
+ * Query options:
176
+ * verified_only: boolean — only return non-revoked attestations (default: true)
177
+ * agent_url: string — filter by agent URL
178
+ * limit: number — max results (default 50, max 200)
179
+ */
180
+ export declare function listVerifiedCards(sessions: KVNamespace, opts?: {
181
+ verified_only?: boolean;
182
+ agent_url?: string;
183
+ limit?: number;
184
+ }): Promise<{
185
+ success: boolean;
186
+ attestations?: A2AAttestation[];
187
+ error?: string;
188
+ }>;
189
+ declare const _default: {
190
+ getBotchaAgentCard: typeof getBotchaAgentCard;
191
+ canonicalizeCard: typeof canonicalizeCard;
192
+ hashCard: typeof hashCard;
193
+ attestCard: typeof attestCard;
194
+ verifyCard: typeof verifyCard;
195
+ getCardAttestation: typeof getCardAttestation;
196
+ listVerifiedCards: typeof listVerifiedCards;
197
+ };
198
+ export default _default;
199
+ //# sourceMappingURL=tap-a2a.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tap-a2a.d.ts","sourceRoot":"","sources":["../src/tap-a2a.ts"],"names":[],"mappings":"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"}