@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
@@ -5,7 +5,9 @@
5
5
  * Provides backward-compatible endpoints with optional TAP functionality
6
6
  */
7
7
  import { extractBearerToken, verifyToken, getSigningPublicKeyJWK } from './auth.js';
8
- import { registerTAPAgent, getTAPAgent, listTAPAgents, createTAPSession, getTAPSession, validateCapability, TAP_VALID_ACTIONS } from './tap-agents.js';
8
+ import { validateAppSecret } from './apps.js';
9
+ import { triggerWebhook } from './webhooks.js';
10
+ import { registerTAPAgent, getTAPAgent, listTAPAgents, createTAPSession, getTAPSession, updateAgentVerification, validateCapability, isValidJWK, TAP_VALID_ACTIONS } from './tap-agents.js';
9
11
  import { parseTAPIntent } from './tap-verify.js';
10
12
  import { createInvoice, getInvoice, verifyPaymentContainer, verifyBrowsingIOU, fulfillInvoice, parsePaymentContainer } from './tap-payment.js';
11
13
  import { parseAgenticConsumer, verifyAgenticConsumer } from './tap-consumer.js';
@@ -67,8 +69,13 @@ function validateTAPRegistration(body) {
67
69
  if (!body.name || typeof body.name !== 'string') {
68
70
  return { valid: false, error: 'Agent name is required' };
69
71
  }
72
+ // Normalize public_key: accept JWK objects by serializing them to JSON strings
73
+ let publicKey = body.public_key;
74
+ if (publicKey && typeof publicKey === 'object') {
75
+ publicKey = JSON.stringify(publicKey);
76
+ }
70
77
  // Validate public key if provided
71
- if (body.public_key) {
78
+ if (publicKey) {
72
79
  if (!body.signature_algorithm) {
73
80
  return { valid: false, error: 'signature_algorithm required when public_key provided' };
74
81
  }
@@ -76,11 +83,12 @@ function validateTAPRegistration(body) {
76
83
  if (!validAlgorithms.includes(body.signature_algorithm)) {
77
84
  return { valid: false, error: `Unsupported algorithm. Supported: ${validAlgorithms.join(', ')}` };
78
85
  }
79
- // PEM format or raw Ed25519 key (32-byte base64)
80
- const isPEM = body.public_key.includes('BEGIN PUBLIC KEY');
81
- const isRawEd25519 = body.signature_algorithm === 'ed25519' && !isPEM;
82
- if (!isPEM && !isRawEd25519) {
83
- return { valid: false, error: 'Invalid public key format. Provide PEM or raw Ed25519 base64 key.' };
86
+ // Accept: PEM, JWK JSON string, or raw Ed25519 base64 key
87
+ const isPEM = typeof publicKey === 'string' && publicKey.includes('BEGIN PUBLIC KEY');
88
+ const isJWK = isValidJWK(publicKey);
89
+ const isRawEd25519 = body.signature_algorithm === 'ed25519' && !isPEM && !isJWK;
90
+ if (!isPEM && !isJWK && !isRawEd25519) {
91
+ return { valid: false, error: 'Invalid public key format. Provide a PEM key, JWK object/JSON, or raw Ed25519 base64 key.' };
84
92
  }
85
93
  }
86
94
  // Validate capabilities if provided
@@ -94,17 +102,48 @@ function validateTAPRegistration(body) {
94
102
  }
95
103
  }
96
104
  }
105
+ // Validate ANS name format if provided
106
+ if (body.ans_name !== undefined && body.ans_name !== null) {
107
+ if (typeof body.ans_name !== 'string') {
108
+ return { valid: false, error: 'ans_name must be a string (e.g. "ans://v1.0.myagent.example.com")' };
109
+ }
110
+ // Basic format check — full validation happens in tap-ans module
111
+ const clean = body.ans_name.trim().replace(/^ans:\/\//, '');
112
+ if (clean.split('.').length < 2) {
113
+ return { valid: false, error: 'ans_name must include at least a label and domain (e.g. "myagent.example.com")' };
114
+ }
115
+ }
116
+ // Validate optional DID field
117
+ if (body.did !== undefined) {
118
+ if (typeof body.did !== 'string' || !body.did.startsWith('did:')) {
119
+ return { valid: false, error: 'Invalid did field: must be a valid DID string (e.g. did:web:example.com)' };
120
+ }
121
+ }
122
+ // Validate provider if provided
123
+ const SUPPORTED_PROVIDERS = ['anthropic', 'openai', 'google', 'mistral', 'cohere', 'other'];
124
+ if (body.provider !== undefined) {
125
+ if (!SUPPORTED_PROVIDERS.includes(body.provider)) {
126
+ return { valid: false, error: `Unsupported provider. Use one of: ${SUPPORTED_PROVIDERS.join(', ')}` };
127
+ }
128
+ if (!body.api_key || typeof body.api_key !== 'string') {
129
+ return { valid: false, error: 'api_key is required when provider is specified' };
130
+ }
131
+ }
97
132
  return {
98
133
  valid: true,
99
134
  data: {
100
135
  name: body.name,
101
136
  operator: body.operator,
102
137
  version: body.version,
103
- public_key: body.public_key,
138
+ public_key: publicKey,
104
139
  signature_algorithm: body.signature_algorithm,
105
140
  capabilities: body.capabilities,
106
141
  trust_level: body.trust_level || 'basic',
107
- issuer: body.issuer
142
+ issuer: body.issuer,
143
+ ans_name: body.ans_name,
144
+ did: body.did,
145
+ provider: body.provider,
146
+ api_key: body.api_key, // plaintext — hashed in route handler, never persisted
108
147
  }
109
148
  };
110
149
  }
@@ -134,16 +173,64 @@ export async function registerTAPAgentRoute(c) {
134
173
  message: validation.error
135
174
  }, 400);
136
175
  }
137
- // Register TAP-enhanced agent
138
- const result = await registerTAPAgent(c.env.AGENTS, appAccess.appId, validation.data);
139
- if (!result.success) {
140
- return c.json({
141
- success: false,
142
- error: 'AGENT_CREATION_FAILED',
143
- message: result.error || 'Failed to create agent'
144
- }, 500);
176
+ // If agent_id provided, update existing agent with TAP fields instead of creating a new one
177
+ let agent;
178
+ if (body.agent_id) {
179
+ const existing = await getTAPAgent(c.env.AGENTS, body.agent_id);
180
+ if (!existing.success || !existing.agent) {
181
+ return c.json({
182
+ success: false,
183
+ error: 'AGENT_NOT_FOUND',
184
+ message: `Agent '${body.agent_id}' not found`
185
+ }, 404);
186
+ }
187
+ if (existing.agent.app_id !== appAccess.appId) {
188
+ return c.json({
189
+ success: false,
190
+ error: 'UNAUTHORIZED',
191
+ message: 'Agent does not belong to this app'
192
+ }, 403);
193
+ }
194
+ const now = Date.now();
195
+ // Hash provider API key if provided — never store plaintext
196
+ let providerKeyHash = existing.agent.provider_key_hash;
197
+ if (validation.data.api_key) {
198
+ const hashBuf = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(validation.data.api_key.trim()));
199
+ providerKeyHash = Array.from(new Uint8Array(hashBuf)).map(b => b.toString(16).padStart(2, '0')).join('');
200
+ }
201
+ agent = {
202
+ ...existing.agent,
203
+ public_key: validation.data.public_key ?? existing.agent.public_key,
204
+ signature_algorithm: validation.data.signature_algorithm ?? existing.agent.signature_algorithm,
205
+ capabilities: validation.data.capabilities ?? existing.agent.capabilities,
206
+ trust_level: validation.data.trust_level ?? existing.agent.trust_level ?? 'basic',
207
+ tap_enabled: Boolean(validation.data.public_key ?? existing.agent.public_key),
208
+ key_created_at: validation.data.public_key ? now : existing.agent.key_created_at,
209
+ ans_name: validation.data.ans_name ?? existing.agent.ans_name,
210
+ did: validation.data.did ?? existing.agent.did,
211
+ provider: validation.data.provider ?? existing.agent.provider,
212
+ provider_key_hash: providerKeyHash,
213
+ };
214
+ await c.env.AGENTS.put(`agent:${agent.agent_id}`, JSON.stringify(agent));
215
+ }
216
+ else {
217
+ // Create new agent
218
+ const result = await registerTAPAgent(c.env.AGENTS, appAccess.appId, validation.data);
219
+ if (!result.success) {
220
+ return c.json({
221
+ success: false,
222
+ error: 'AGENT_CREATION_FAILED',
223
+ message: result.error || 'Failed to create agent'
224
+ }, 500);
225
+ }
226
+ agent = result.agent;
227
+ }
228
+ ;
229
+ // Webhook: agent.tap.registered
230
+ const tapRegCtx = c.executionCtx;
231
+ if (tapRegCtx?.waitUntil) {
232
+ tapRegCtx.waitUntil(triggerWebhook(c.env.AGENTS, appAccess.appId, 'agent.tap.registered', { agent_id: agent.agent_id, name: agent.name, trust_level: agent.trust_level }));
145
233
  }
146
- const agent = result.agent;
147
234
  // Return enhanced agent info
148
235
  return c.json({
149
236
  success: true,
@@ -159,6 +246,12 @@ export async function registerTAPAgentRoute(c) {
159
246
  capabilities: agent.capabilities,
160
247
  signature_algorithm: agent.signature_algorithm,
161
248
  issuer: agent.issuer,
249
+ // W3C DID (optional)
250
+ did: agent.did || null,
251
+ // ANS fields
252
+ ans_name: agent.ans_name || null,
253
+ ans_badge_id: agent.ans_badge_id || null,
254
+ ans_trust_level: agent.ans_trust_level || null,
162
255
  // Security info (don't expose full public key)
163
256
  has_public_key: Boolean(agent.public_key),
164
257
  key_fingerprint: agent.public_key ?
@@ -213,6 +306,12 @@ export async function getTAPAgentRoute(c) {
213
306
  issuer: agent.issuer,
214
307
  last_verified_at: agent.last_verified_at ?
215
308
  new Date(agent.last_verified_at).toISOString() : null,
309
+ // ANS identity
310
+ ans_name: agent.ans_name || null,
311
+ ans_badge_id: agent.ans_badge_id || null,
312
+ ans_trust_level: agent.ans_trust_level || null,
313
+ ans_verified_at: agent.ans_verified_at
314
+ ? new Date(agent.ans_verified_at).toISOString() : null,
216
315
  // Public key info (secure)
217
316
  has_public_key: Boolean(agent.public_key),
218
317
  key_fingerprint: agent.public_key ?
@@ -305,6 +404,18 @@ export async function createTAPSessionRoute(c) {
305
404
  }, 404);
306
405
  }
307
406
  const agent = agentResult.agent;
407
+ // Gate: agent must have TAP enabled (i.e. a registered public key).
408
+ // tap_enabled is set to true only when a public key is registered, so this
409
+ // check is the canonical guard. Without cryptographic identity, a TAP
410
+ // session has no trust anchor and would silently bypass the entire
411
+ // verification model.
412
+ if (!agent.tap_enabled) {
413
+ return c.json({
414
+ success: false,
415
+ error: 'TAP_NOT_ENABLED',
416
+ message: 'Agent does not have TAP enabled. Register a public key via POST /v1/agents/register/tap (with public_key field) or POST /v1/agents/:id/tap/rotate-key to enable TAP sessions.'
417
+ }, 403);
418
+ }
308
419
  // Parse intent
309
420
  const intentResult = parseTAPIntent(JSON.stringify(body.intent));
310
421
  if (!intentResult.valid) {
@@ -333,6 +444,16 @@ export async function createTAPSessionRoute(c) {
333
444
  }, 500);
334
445
  }
335
446
  const session = sessionResult.session;
447
+ // Update last_verified_at — session creation is a successful TAP verification event.
448
+ // updateAgentVerification catches and logs internally; void signals intentional fire-and-forget.
449
+ // Note: this does a read-modify-write on the full agent KV record. A concurrent key rotation
450
+ // could clobber that write. Future work: store last_verified_at in a separate KV key.
451
+ void updateAgentVerification(c.env.AGENTS, agent.agent_id, true);
452
+ // Webhook: tap.session.created
453
+ const tapSessCtx = c.executionCtx;
454
+ if (tapSessCtx?.waitUntil) {
455
+ tapSessCtx.waitUntil(triggerWebhook(c.env.AGENTS, agent.app_id, 'tap.session.created', { session_id: session.session_id, agent_id: agent.agent_id, intent: session.intent }));
456
+ }
336
457
  return c.json({
337
458
  success: true,
338
459
  session_id: session.session_id,
@@ -406,19 +527,44 @@ export async function rotateKeyRoute(c) {
406
527
  if (!agentId) {
407
528
  return c.json({ success: false, error: 'MISSING_AGENT_ID', message: 'Agent ID is required' }, 400);
408
529
  }
409
- const appAccess = await validateAppAccess(c, true);
410
- if (!appAccess.valid) {
411
- return c.json({ success: false, error: appAccess.error, message: 'Authentication required' }, (appAccess.status || 401));
530
+ // Accept either a Bearer JWT (normal flow) or x-app-secret header (recovery flow)
531
+ const queryAppId = c.req.query('app_id');
532
+ const appSecretHeader = c.req.header('x-app-secret');
533
+ let resolvedAppId;
534
+ if (appSecretHeader && queryAppId) {
535
+ const valid = await validateAppSecret(c.env.APPS, queryAppId, appSecretHeader);
536
+ if (!valid) {
537
+ return c.json({ success: false, error: 'UNAUTHORIZED', message: 'Invalid app_secret' }, 401);
538
+ }
539
+ resolvedAppId = queryAppId;
540
+ }
541
+ else {
542
+ const appAccess = await validateAppAccess(c, true);
543
+ if (!appAccess.valid) {
544
+ return c.json({ success: false, error: appAccess.error, message: 'Authentication required. Provide a Bearer token or x-app-secret + app_id.' }, (appAccess.status || 401));
545
+ }
546
+ resolvedAppId = appAccess.appId;
412
547
  }
413
548
  const body = await c.req.json().catch(() => ({}));
414
549
  if (!body.public_key || !body.signature_algorithm) {
415
550
  return c.json({ success: false, error: 'MISSING_FIELDS', message: 'public_key and signature_algorithm are required' }, 400);
416
551
  }
552
+ // Normalize public_key: accept JWK objects by serializing to JSON
553
+ const newPublicKey = typeof body.public_key === 'object'
554
+ ? JSON.stringify(body.public_key)
555
+ : body.public_key;
417
556
  // Validate algorithm
418
557
  const validAlgorithms = ['ecdsa-p256-sha256', 'rsa-pss-sha256', 'ed25519'];
419
558
  if (!validAlgorithms.includes(body.signature_algorithm)) {
420
559
  return c.json({ success: false, error: 'INVALID_ALGORITHM', message: `Unsupported algorithm. Supported: ${validAlgorithms.join(', ')}` }, 400);
421
560
  }
561
+ // Validate key format (PEM, JWK, or raw Ed25519)
562
+ const isPEM = typeof newPublicKey === 'string' && newPublicKey.includes('BEGIN PUBLIC KEY');
563
+ const isJWK = isValidJWK(newPublicKey);
564
+ const isRawEd25519 = body.signature_algorithm === 'ed25519' && !isPEM && !isJWK;
565
+ if (!isPEM && !isJWK && !isRawEd25519) {
566
+ return c.json({ success: false, error: 'INVALID_KEY_FORMAT', message: 'Invalid public key format. Provide a PEM key, JWK object/JSON, or raw Ed25519 base64 key.' }, 400);
567
+ }
422
568
  // Get existing agent
423
569
  const agentResult = await getTAPAgent(c.env.AGENTS, agentId);
424
570
  if (!agentResult.success || !agentResult.agent) {
@@ -426,11 +572,11 @@ export async function rotateKeyRoute(c) {
426
572
  }
427
573
  const agent = agentResult.agent;
428
574
  // Verify agent belongs to this app
429
- if (agent.app_id !== appAccess.appId) {
575
+ if (agent.app_id !== resolvedAppId) {
430
576
  return c.json({ success: false, error: 'UNAUTHORIZED', message: 'Agent does not belong to this app' }, 403);
431
577
  }
432
578
  // Update agent with new key
433
- agent.public_key = body.public_key;
579
+ agent.public_key = newPublicKey;
434
580
  agent.signature_algorithm = body.signature_algorithm;
435
581
  agent.key_created_at = Date.now();
436
582
  agent.key_expires_at = body.key_expires_at ? new Date(body.key_expires_at).getTime() : undefined;
@@ -0,0 +1,358 @@
1
+ /**
2
+ * DID/VC API Routes
3
+ *
4
+ * Endpoints:
5
+ * GET /.well-known/did.json — BOTCHA DID Document (did:web:botcha.ai)
6
+ * POST /v1/credentials/issue — Issue VC from a valid BOTCHA access_token
7
+ * POST /v1/credentials/verify — Verify a VC JWT
8
+ * GET /v1/dids/:did/resolve — Resolve a did:web DID Document
9
+ *
10
+ * All credential issuance requires a valid BOTCHA access_token in the
11
+ * Authorization header (Bearer <token>). The token is the result of a
12
+ * successful BOTCHA challenge solve (/v1/token/verify).
13
+ */
14
+ import type { Context } from 'hono';
15
+ /**
16
+ * GET /.well-known/did.json
17
+ *
18
+ * Returns the BOTCHA DID Document for did:web:botcha.ai.
19
+ * This is a public endpoint — no auth required.
20
+ * Resolvers use this to discover BOTCHA's public keys for VC verification.
21
+ */
22
+ export declare function didDocumentRoute(c: Context): Promise<Response>;
23
+ /**
24
+ * POST /v1/credentials/issue
25
+ *
26
+ * Exchange a valid BOTCHA access_token for a W3C Verifiable Credential.
27
+ *
28
+ * Request (body, all optional):
29
+ * {
30
+ * "agent_id": "agent_xxx", // Override agent identity in VC
31
+ * "duration_seconds": 86400, // VC validity period (default: 24h, max: 30d)
32
+ * }
33
+ *
34
+ * Headers:
35
+ * Authorization: Bearer <access_token> (required — from /v1/token/verify)
36
+ *
37
+ * Response:
38
+ * {
39
+ * "success": true,
40
+ * "credential_id": "urn:botcha:vc:...",
41
+ * "vc": { ...W3C JSON-LD credential... },
42
+ * "vc_jwt": "eyJ...",
43
+ * "issued_at": "2026-...",
44
+ * "expires_at": "2026-...",
45
+ * }
46
+ */
47
+ export declare function issueVCRoute(c: Context): Promise<(Response & import("hono").TypedResponse<{
48
+ success: false;
49
+ error: string;
50
+ message: string;
51
+ }, 401, "json">) | (Response & import("hono").TypedResponse<{
52
+ success: false;
53
+ error: string;
54
+ message: string;
55
+ }, 403, "json">) | (Response & import("hono").TypedResponse<{
56
+ success: false;
57
+ error: string;
58
+ message: string;
59
+ }, 404, "json">) | (Response & import("hono").TypedResponse<{
60
+ success: false;
61
+ error: string;
62
+ message: string;
63
+ }, 500, "json">) | (Response & import("hono").TypedResponse<{
64
+ success: true;
65
+ credential_id: string | undefined;
66
+ vc: {
67
+ '@context': string[];
68
+ type: string[];
69
+ id: string;
70
+ issuer: string;
71
+ credentialSubject: {
72
+ id?: string | undefined;
73
+ agent_id: string;
74
+ app_id: string;
75
+ challenge_type: string;
76
+ solve_time_ms: number;
77
+ trust_level: "basic" | "verified" | "enterprise";
78
+ capabilities?: string[] | undefined;
79
+ };
80
+ validFrom: string;
81
+ validUntil: string;
82
+ } | undefined;
83
+ vc_jwt: string | undefined;
84
+ issued_at: string | undefined;
85
+ expires_at: string | undefined;
86
+ issuer: string;
87
+ usage: {
88
+ note: string;
89
+ verify_endpoint: string;
90
+ offline_verify: string;
91
+ did_document: string;
92
+ };
93
+ }, 201, "json">)>;
94
+ /**
95
+ * POST /v1/credentials/verify
96
+ *
97
+ * Verify a BOTCHA VC JWT. No auth required — the VC is the credential.
98
+ *
99
+ * Request body:
100
+ * { "vc_jwt": "eyJ..." }
101
+ *
102
+ * Response (valid):
103
+ * {
104
+ * "valid": true,
105
+ * "issuer": "did:web:botcha.ai",
106
+ * "credential_id": "urn:botcha:vc:...",
107
+ * "credential_subject": { ... },
108
+ * "issued_at": "...",
109
+ * "expires_at": "...",
110
+ * }
111
+ *
112
+ * Response (invalid):
113
+ * { "valid": false, "error": "..." }
114
+ */
115
+ export declare function verifyVCRoute(c: Context): Promise<(Response & import("hono").TypedResponse<{
116
+ valid: false;
117
+ error: string;
118
+ message: string;
119
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
120
+ valid: false;
121
+ error: string;
122
+ message: string;
123
+ }, 503, "json">) | (Response & import("hono").TypedResponse<{
124
+ valid: false;
125
+ error: string;
126
+ }, 200, "json">) | (Response & import("hono").TypedResponse<{
127
+ valid: true;
128
+ issuer: string | undefined;
129
+ credential_id: string | undefined;
130
+ credential_subject: {
131
+ id?: string | undefined;
132
+ agent_id: string;
133
+ app_id: string;
134
+ challenge_type: string;
135
+ solve_time_ms: number;
136
+ trust_level: "basic" | "verified" | "enterprise";
137
+ capabilities?: string[] | undefined;
138
+ } | undefined;
139
+ vc: {
140
+ '@context': string[];
141
+ type: string[];
142
+ id: string;
143
+ issuer: string;
144
+ credentialSubject: {
145
+ id?: string | undefined;
146
+ agent_id: string;
147
+ app_id: string;
148
+ challenge_type: string;
149
+ solve_time_ms: number;
150
+ trust_level: "basic" | "verified" | "enterprise";
151
+ capabilities?: string[] | undefined;
152
+ };
153
+ validFrom: string;
154
+ validUntil: string;
155
+ } | undefined;
156
+ issued_at: string | undefined;
157
+ expires_at: string | undefined;
158
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
159
+ valid: false;
160
+ error: string;
161
+ message: string;
162
+ }, 500, "json">)>;
163
+ /**
164
+ * GET /v1/dids/:did/resolve
165
+ *
166
+ * Resolve a did:web DID Document.
167
+ * This is a public endpoint — no auth required.
168
+ *
169
+ * Supports: did:web:* only (other methods return methodNotSupported)
170
+ *
171
+ * Special case: did:web:botcha.ai is resolved locally (no outbound fetch).
172
+ *
173
+ * Query params:
174
+ * (none currently)
175
+ *
176
+ * Response:
177
+ * W3C DID Resolution Result object
178
+ */
179
+ export declare function resolveDIDRoute(c: Context): Promise<(Response & import("hono").TypedResponse<{
180
+ '@context': string;
181
+ didDocument: null;
182
+ didResolutionMetadata: {
183
+ error: string;
184
+ };
185
+ didDocumentMetadata: {};
186
+ }, 400, "json">) | (Response & import("hono").TypedResponse<{
187
+ '@context': string;
188
+ didDocument: {
189
+ [x: string]: import("hono/utils/types").JSONValue;
190
+ '@context': string | string[];
191
+ id: string;
192
+ controller?: string | string[] | undefined;
193
+ verificationMethod?: {
194
+ id: string;
195
+ type: string;
196
+ controller: string;
197
+ publicKeyJwk?: {
198
+ [x: string]: string | undefined;
199
+ } | undefined;
200
+ publicKeyMultibase?: string | undefined;
201
+ }[] | undefined;
202
+ authentication?: (string | {
203
+ id: string;
204
+ type: string;
205
+ controller: string;
206
+ publicKeyJwk?: {
207
+ [x: string]: string | undefined;
208
+ } | undefined;
209
+ publicKeyMultibase?: string | undefined;
210
+ })[] | undefined;
211
+ assertionMethod?: (string | {
212
+ id: string;
213
+ type: string;
214
+ controller: string;
215
+ publicKeyJwk?: {
216
+ [x: string]: string | undefined;
217
+ } | undefined;
218
+ publicKeyMultibase?: string | undefined;
219
+ })[] | undefined;
220
+ keyAgreement?: (string | {
221
+ id: string;
222
+ type: string;
223
+ controller: string;
224
+ publicKeyJwk?: {
225
+ [x: string]: string | undefined;
226
+ } | undefined;
227
+ publicKeyMultibase?: string | undefined;
228
+ })[] | undefined;
229
+ capabilityInvocation?: (string | {
230
+ id: string;
231
+ type: string;
232
+ controller: string;
233
+ publicKeyJwk?: {
234
+ [x: string]: string | undefined;
235
+ } | undefined;
236
+ publicKeyMultibase?: string | undefined;
237
+ })[] | undefined;
238
+ capabilityDelegation?: (string | {
239
+ id: string;
240
+ type: string;
241
+ controller: string;
242
+ publicKeyJwk?: {
243
+ [x: string]: string | undefined;
244
+ } | undefined;
245
+ publicKeyMultibase?: string | undefined;
246
+ })[] | undefined;
247
+ service?: {
248
+ id: string;
249
+ type: string;
250
+ serviceEndpoint: string | string[] | {
251
+ [x: string]: string;
252
+ };
253
+ description?: string | undefined;
254
+ }[] | undefined;
255
+ };
256
+ didResolutionMetadata: {
257
+ contentType: string;
258
+ retrieved: string;
259
+ duration: number;
260
+ };
261
+ didDocumentMetadata: {};
262
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | (Response & import("hono").TypedResponse<{
263
+ '@context': string;
264
+ didDocument: {
265
+ [x: string]: import("hono/utils/types").JSONValue;
266
+ '@context': string | string[];
267
+ id: string;
268
+ controller?: string | string[] | undefined;
269
+ verificationMethod?: {
270
+ id: string;
271
+ type: string;
272
+ controller: string;
273
+ publicKeyJwk?: {
274
+ [x: string]: string | undefined;
275
+ } | undefined;
276
+ publicKeyMultibase?: string | undefined;
277
+ }[] | undefined;
278
+ authentication?: (string | {
279
+ id: string;
280
+ type: string;
281
+ controller: string;
282
+ publicKeyJwk?: {
283
+ [x: string]: string | undefined;
284
+ } | undefined;
285
+ publicKeyMultibase?: string | undefined;
286
+ })[] | undefined;
287
+ assertionMethod?: (string | {
288
+ id: string;
289
+ type: string;
290
+ controller: string;
291
+ publicKeyJwk?: {
292
+ [x: string]: string | undefined;
293
+ } | undefined;
294
+ publicKeyMultibase?: string | undefined;
295
+ })[] | undefined;
296
+ keyAgreement?: (string | {
297
+ id: string;
298
+ type: string;
299
+ controller: string;
300
+ publicKeyJwk?: {
301
+ [x: string]: string | undefined;
302
+ } | undefined;
303
+ publicKeyMultibase?: string | undefined;
304
+ })[] | undefined;
305
+ capabilityInvocation?: (string | {
306
+ id: string;
307
+ type: string;
308
+ controller: string;
309
+ publicKeyJwk?: {
310
+ [x: string]: string | undefined;
311
+ } | undefined;
312
+ publicKeyMultibase?: string | undefined;
313
+ })[] | undefined;
314
+ capabilityDelegation?: (string | {
315
+ id: string;
316
+ type: string;
317
+ controller: string;
318
+ publicKeyJwk?: {
319
+ [x: string]: string | undefined;
320
+ } | undefined;
321
+ publicKeyMultibase?: string | undefined;
322
+ })[] | undefined;
323
+ service?: {
324
+ id: string;
325
+ type: string;
326
+ serviceEndpoint: string | string[] | {
327
+ [x: string]: string;
328
+ };
329
+ description?: string | undefined;
330
+ }[] | undefined;
331
+ } | null;
332
+ didResolutionMetadata: {
333
+ contentType?: string | undefined;
334
+ error?: string | undefined;
335
+ retrieved?: string | undefined;
336
+ duration?: number | undefined;
337
+ };
338
+ didDocumentMetadata: {
339
+ created?: string | undefined;
340
+ updated?: string | undefined;
341
+ deactivated?: boolean | undefined;
342
+ };
343
+ }, 200 | 404, "json">) | (Response & import("hono").TypedResponse<{
344
+ '@context': string;
345
+ didDocument: null;
346
+ didResolutionMetadata: {
347
+ error: string;
348
+ };
349
+ didDocumentMetadata: {};
350
+ }, 500, "json">)>;
351
+ declare const _default: {
352
+ didDocumentRoute: typeof didDocumentRoute;
353
+ issueVCRoute: typeof issueVCRoute;
354
+ verifyVCRoute: typeof verifyVCRoute;
355
+ resolveDIDRoute: typeof resolveDIDRoute;
356
+ };
357
+ export default _default;
358
+ //# sourceMappingURL=tap-vc-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tap-vc-routes.d.ts","sourceRoot":"","sources":["../src/tap-vc-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAoCpC;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,OAAO,qBAkBhD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA8I5C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,aAAa,CAAC,CAAC,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAwD7C;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAsE/C;;;;;;;AAED,wBAKE"}