@dupecom/botcha-cloudflare 0.15.0 → 0.18.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 +12 -0
- package/dist/dashboard/layout.d.ts.map +1 -1
- package/dist/dashboard/layout.js +12 -5
- package/dist/dashboard/showcase.d.ts +1 -0
- package/dist/dashboard/showcase.d.ts.map +1 -1
- package/dist/dashboard/showcase.js +3 -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 +148 -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 +871 -2
- package/dist/static.d.ts.map +1 -1
- package/dist/static.js +812 -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-attestation-routes.d.ts +204 -0
- package/dist/tap-attestation-routes.d.ts.map +1 -0
- package/dist/tap-attestation-routes.js +396 -0
- package/dist/tap-attestation.d.ts +178 -0
- package/dist/tap-attestation.d.ts.map +1 -0
- package/dist/tap-attestation.js +416 -0
- 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-delegation-routes.d.ts +236 -0
- package/dist/tap-delegation-routes.d.ts.map +1 -0
- package/dist/tap-delegation-routes.js +378 -0
- package/dist/tap-delegation.d.ts +127 -0
- package/dist/tap-delegation.d.ts.map +1 -0
- package/dist/tap-delegation.js +490 -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-reputation-routes.d.ts +154 -0
- package/dist/tap-reputation-routes.d.ts.map +1 -0
- package/dist/tap-reputation-routes.js +341 -0
- package/dist/tap-reputation.d.ts +136 -0
- package/dist/tap-reputation.d.ts.map +1 -0
- package/dist/tap-reputation.js +346 -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/tap-routes.js
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
import { extractBearerToken, verifyToken } from './auth.js';
|
|
8
8
|
import { registerTAPAgent, getTAPAgent, listTAPAgents, createTAPSession, getTAPSession, validateCapability, TAP_VALID_ACTIONS } from './tap-agents.js';
|
|
9
9
|
import { parseTAPIntent } from './tap-verify.js';
|
|
10
|
+
import { createInvoice, getInvoice, verifyPaymentContainer, verifyBrowsingIOU, fulfillInvoice, parsePaymentContainer } from './tap-payment.js';
|
|
11
|
+
import { parseAgenticConsumer, verifyAgenticConsumer } from './tap-consumer.js';
|
|
10
12
|
// ============ VALIDATION HELPERS ============
|
|
11
13
|
async function validateAppAccess(c, requireAuth = true) {
|
|
12
14
|
// Extract app_id from query param or JWT
|
|
@@ -41,12 +43,15 @@ function validateTAPRegistration(body) {
|
|
|
41
43
|
if (!body.signature_algorithm) {
|
|
42
44
|
return { valid: false, error: 'signature_algorithm required when public_key provided' };
|
|
43
45
|
}
|
|
44
|
-
const validAlgorithms = ['ecdsa-p256-sha256', 'rsa-pss-sha256'];
|
|
46
|
+
const validAlgorithms = ['ecdsa-p256-sha256', 'rsa-pss-sha256', 'ed25519'];
|
|
45
47
|
if (!validAlgorithms.includes(body.signature_algorithm)) {
|
|
46
48
|
return { valid: false, error: `Unsupported algorithm. Supported: ${validAlgorithms.join(', ')}` };
|
|
47
49
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
// PEM format or raw Ed25519 key (32-byte base64)
|
|
51
|
+
const isPEM = body.public_key.includes('BEGIN PUBLIC KEY');
|
|
52
|
+
const isRawEd25519 = body.signature_algorithm === 'ed25519' && !isPEM;
|
|
53
|
+
if (!isPEM && !isRawEd25519) {
|
|
54
|
+
return { valid: false, error: 'Invalid public key format. Provide PEM or raw Ed25519 base64 key.' };
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
// Validate capabilities if provided
|
|
@@ -361,6 +366,270 @@ export async function getTAPSessionRoute(c) {
|
|
|
361
366
|
}, 500);
|
|
362
367
|
}
|
|
363
368
|
}
|
|
369
|
+
// ============ TAP KEY ROTATION ============
|
|
370
|
+
/**
|
|
371
|
+
* POST /v1/agents/:id/tap/rotate-key
|
|
372
|
+
* Rotate an agent's public key
|
|
373
|
+
*/
|
|
374
|
+
export async function rotateKeyRoute(c) {
|
|
375
|
+
try {
|
|
376
|
+
const agentId = c.req.param('id');
|
|
377
|
+
if (!agentId) {
|
|
378
|
+
return c.json({ success: false, error: 'MISSING_AGENT_ID', message: 'Agent ID is required' }, 400);
|
|
379
|
+
}
|
|
380
|
+
const appAccess = await validateAppAccess(c, true);
|
|
381
|
+
if (!appAccess.valid) {
|
|
382
|
+
return c.json({ success: false, error: appAccess.error, message: 'Authentication required' }, (appAccess.status || 401));
|
|
383
|
+
}
|
|
384
|
+
const body = await c.req.json().catch(() => ({}));
|
|
385
|
+
if (!body.public_key || !body.signature_algorithm) {
|
|
386
|
+
return c.json({ success: false, error: 'MISSING_FIELDS', message: 'public_key and signature_algorithm are required' }, 400);
|
|
387
|
+
}
|
|
388
|
+
// Validate algorithm
|
|
389
|
+
const validAlgorithms = ['ecdsa-p256-sha256', 'rsa-pss-sha256', 'ed25519'];
|
|
390
|
+
if (!validAlgorithms.includes(body.signature_algorithm)) {
|
|
391
|
+
return c.json({ success: false, error: 'INVALID_ALGORITHM', message: `Unsupported algorithm. Supported: ${validAlgorithms.join(', ')}` }, 400);
|
|
392
|
+
}
|
|
393
|
+
// Get existing agent
|
|
394
|
+
const agentResult = await getTAPAgent(c.env.AGENTS, agentId);
|
|
395
|
+
if (!agentResult.success || !agentResult.agent) {
|
|
396
|
+
return c.json({ success: false, error: 'AGENT_NOT_FOUND', message: 'Agent not found' }, 404);
|
|
397
|
+
}
|
|
398
|
+
const agent = agentResult.agent;
|
|
399
|
+
// Verify agent belongs to this app
|
|
400
|
+
if (agent.app_id !== appAccess.appId) {
|
|
401
|
+
return c.json({ success: false, error: 'UNAUTHORIZED', message: 'Agent does not belong to this app' }, 403);
|
|
402
|
+
}
|
|
403
|
+
// Update agent with new key
|
|
404
|
+
agent.public_key = body.public_key;
|
|
405
|
+
agent.signature_algorithm = body.signature_algorithm;
|
|
406
|
+
agent.key_created_at = Date.now();
|
|
407
|
+
agent.key_expires_at = body.key_expires_at ? new Date(body.key_expires_at).getTime() : undefined;
|
|
408
|
+
agent.tap_enabled = true;
|
|
409
|
+
await c.env.AGENTS.put(`agent:${agentId}`, JSON.stringify(agent));
|
|
410
|
+
return c.json({
|
|
411
|
+
success: true,
|
|
412
|
+
agent_id: agent.agent_id,
|
|
413
|
+
message: 'Key rotated successfully',
|
|
414
|
+
has_public_key: true,
|
|
415
|
+
signature_algorithm: agent.signature_algorithm,
|
|
416
|
+
key_created_at: new Date(agent.key_created_at).toISOString(),
|
|
417
|
+
key_expires_at: agent.key_expires_at ? new Date(agent.key_expires_at).toISOString() : null,
|
|
418
|
+
key_fingerprint: agent.public_key ? await generateKeyFingerprint(agent.public_key) : undefined
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
console.error('Key rotation error:', error);
|
|
423
|
+
return c.json({ success: false, error: 'INTERNAL_ERROR', message: 'Internal server error' }, 500);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
// ============ TAP INVOICE ROUTES (402 FLOW) ============
|
|
427
|
+
/**
|
|
428
|
+
* POST /v1/invoices
|
|
429
|
+
* Create an invoice for gated content
|
|
430
|
+
*/
|
|
431
|
+
export async function createInvoiceRoute(c) {
|
|
432
|
+
try {
|
|
433
|
+
const appAccess = await validateAppAccess(c, true);
|
|
434
|
+
if (!appAccess.valid) {
|
|
435
|
+
return c.json({ success: false, error: appAccess.error, message: 'Authentication required' }, (appAccess.status || 401));
|
|
436
|
+
}
|
|
437
|
+
const body = await c.req.json().catch(() => ({}));
|
|
438
|
+
if (!body.resource_uri || !body.amount || !body.currency || !body.card_acceptor_id) {
|
|
439
|
+
return c.json({
|
|
440
|
+
success: false,
|
|
441
|
+
error: 'MISSING_FIELDS',
|
|
442
|
+
message: 'resource_uri, amount, currency, and card_acceptor_id are required'
|
|
443
|
+
}, 400);
|
|
444
|
+
}
|
|
445
|
+
const result = await createInvoice(c.env.INVOICES, appAccess.appId, {
|
|
446
|
+
resource_uri: body.resource_uri,
|
|
447
|
+
amount: body.amount,
|
|
448
|
+
currency: body.currency,
|
|
449
|
+
card_acceptor_id: body.card_acceptor_id,
|
|
450
|
+
description: body.description,
|
|
451
|
+
ttl_seconds: body.ttl_seconds,
|
|
452
|
+
});
|
|
453
|
+
if (!result.success) {
|
|
454
|
+
return c.json({ success: false, error: 'INVOICE_CREATION_FAILED', message: result.error }, 500);
|
|
455
|
+
}
|
|
456
|
+
return c.json({
|
|
457
|
+
success: true,
|
|
458
|
+
...result.invoice,
|
|
459
|
+
created_at: new Date(result.invoice.created_at).toISOString(),
|
|
460
|
+
expires_at: new Date(result.invoice.expires_at).toISOString(),
|
|
461
|
+
}, 201);
|
|
462
|
+
}
|
|
463
|
+
catch (error) {
|
|
464
|
+
console.error('Invoice creation error:', error);
|
|
465
|
+
return c.json({ success: false, error: 'INTERNAL_ERROR', message: 'Internal server error' }, 500);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* GET /v1/invoices/:id
|
|
470
|
+
* Get invoice details
|
|
471
|
+
*/
|
|
472
|
+
export async function getInvoiceRoute(c) {
|
|
473
|
+
try {
|
|
474
|
+
const invoiceId = c.req.param('id');
|
|
475
|
+
if (!invoiceId) {
|
|
476
|
+
return c.json({ success: false, error: 'MISSING_INVOICE_ID', message: 'Invoice ID is required' }, 400);
|
|
477
|
+
}
|
|
478
|
+
const result = await getInvoice(c.env.INVOICES, invoiceId);
|
|
479
|
+
if (!result.success) {
|
|
480
|
+
return c.json({ success: false, error: 'INVOICE_NOT_FOUND', message: result.error || 'Invoice not found' }, 404);
|
|
481
|
+
}
|
|
482
|
+
return c.json({
|
|
483
|
+
success: true,
|
|
484
|
+
...result.invoice,
|
|
485
|
+
created_at: new Date(result.invoice.created_at).toISOString(),
|
|
486
|
+
expires_at: new Date(result.invoice.expires_at).toISOString(),
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
catch (error) {
|
|
490
|
+
console.error('Invoice retrieval error:', error);
|
|
491
|
+
return c.json({ success: false, error: 'INTERNAL_ERROR', message: 'Internal server error' }, 500);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* POST /v1/invoices/:id/verify-iou
|
|
496
|
+
* Verify a Browsing IOU against an invoice
|
|
497
|
+
*/
|
|
498
|
+
export async function verifyIOURoute(c) {
|
|
499
|
+
try {
|
|
500
|
+
const invoiceId = c.req.param('id');
|
|
501
|
+
if (!invoiceId) {
|
|
502
|
+
return c.json({ success: false, error: 'MISSING_INVOICE_ID', message: 'Invoice ID is required' }, 400);
|
|
503
|
+
}
|
|
504
|
+
const body = await c.req.json().catch(() => ({}));
|
|
505
|
+
if (!body.browsingIOU) {
|
|
506
|
+
return c.json({ success: false, error: 'MISSING_IOU', message: 'browsingIOU object is required' }, 400);
|
|
507
|
+
}
|
|
508
|
+
// Get the invoice
|
|
509
|
+
const invoiceResult = await getInvoice(c.env.INVOICES, invoiceId);
|
|
510
|
+
if (!invoiceResult.success || !invoiceResult.invoice) {
|
|
511
|
+
return c.json({ success: false, error: 'INVOICE_NOT_FOUND', message: 'Invoice not found or expired' }, 404);
|
|
512
|
+
}
|
|
513
|
+
// Get the agent's public key for signature verification
|
|
514
|
+
const agentKeyId = body.browsingIOU.kid;
|
|
515
|
+
if (!agentKeyId) {
|
|
516
|
+
return c.json({ success: false, error: 'MISSING_KEY_ID', message: 'browsingIOU must include kid' }, 400);
|
|
517
|
+
}
|
|
518
|
+
// For now, try to find the key in our agent registry
|
|
519
|
+
// Future: also check federated sources
|
|
520
|
+
let publicKey = null;
|
|
521
|
+
const agentIndex = await c.env.AGENTS.get(`app_agents:${invoiceResult.invoice.app_id}`, 'text');
|
|
522
|
+
if (agentIndex) {
|
|
523
|
+
const agentIds = JSON.parse(agentIndex);
|
|
524
|
+
for (const agentId of agentIds) {
|
|
525
|
+
const agentData = await c.env.AGENTS.get(`agent:${agentId}`, 'text');
|
|
526
|
+
if (agentData) {
|
|
527
|
+
const agent = JSON.parse(agentData);
|
|
528
|
+
if (agent.public_key) {
|
|
529
|
+
publicKey = agent.public_key;
|
|
530
|
+
break;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (!publicKey) {
|
|
536
|
+
return c.json({ success: false, error: 'KEY_NOT_FOUND', message: 'Could not resolve public key for verification' }, 404);
|
|
537
|
+
}
|
|
538
|
+
// Verify the IOU
|
|
539
|
+
const iouResult = await verifyBrowsingIOU(body.browsingIOU, invoiceResult.invoice, publicKey, body.browsingIOU.alg || 'ES256');
|
|
540
|
+
if (!iouResult.valid) {
|
|
541
|
+
return c.json({ success: false, verified: false, error: iouResult.error }, 400);
|
|
542
|
+
}
|
|
543
|
+
// Fulfill the invoice
|
|
544
|
+
const fulfillResult = await fulfillInvoice(c.env.INVOICES, invoiceId, body.browsingIOU);
|
|
545
|
+
return c.json({
|
|
546
|
+
success: true,
|
|
547
|
+
verified: true,
|
|
548
|
+
access_token: fulfillResult.access_token,
|
|
549
|
+
expires_at: fulfillResult.access_token ? new Date(Date.now() + 300000).toISOString() : undefined,
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
catch (error) {
|
|
553
|
+
console.error('IOU verification error:', error);
|
|
554
|
+
return c.json({ success: false, error: 'INTERNAL_ERROR', message: 'Internal server error' }, 500);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
// ============ TAP VERIFICATION UTILITY ROUTES ============
|
|
558
|
+
/**
|
|
559
|
+
* POST /v1/verify/consumer
|
|
560
|
+
* Verify an Agentic Consumer Recognition Object (utility endpoint)
|
|
561
|
+
*/
|
|
562
|
+
export async function verifyConsumerRoute(c) {
|
|
563
|
+
try {
|
|
564
|
+
const body = await c.req.json().catch(() => ({}));
|
|
565
|
+
const consumer = parseAgenticConsumer(body);
|
|
566
|
+
if (!consumer) {
|
|
567
|
+
return c.json({ success: false, error: 'INVALID_CONSUMER_OBJECT', message: 'Invalid or missing agenticConsumer object' }, 400);
|
|
568
|
+
}
|
|
569
|
+
// Need header nonce and public key for full verification
|
|
570
|
+
const headerNonce = body.headerNonce || c.req.header('x-tap-nonce');
|
|
571
|
+
const publicKey = body.publicKey;
|
|
572
|
+
const algorithm = body.algorithm || consumer.alg;
|
|
573
|
+
if (!publicKey) {
|
|
574
|
+
return c.json({
|
|
575
|
+
success: true,
|
|
576
|
+
parsed: true,
|
|
577
|
+
verified: false,
|
|
578
|
+
message: 'Consumer object parsed but publicKey required for signature verification',
|
|
579
|
+
contextualData: consumer.contextualData,
|
|
580
|
+
hasIdToken: Boolean(consumer.idToken),
|
|
581
|
+
nonceLinked: headerNonce ? consumer.nonce === headerNonce : null,
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
const result = await verifyAgenticConsumer(consumer, headerNonce || '', publicKey, algorithm);
|
|
585
|
+
return c.json({
|
|
586
|
+
success: true,
|
|
587
|
+
...result,
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
catch (error) {
|
|
591
|
+
console.error('Consumer verification error:', error);
|
|
592
|
+
return c.json({ success: false, error: 'INTERNAL_ERROR', message: 'Internal server error' }, 500);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* POST /v1/verify/payment
|
|
597
|
+
* Verify an Agentic Payment Container (utility endpoint)
|
|
598
|
+
*/
|
|
599
|
+
export async function verifyPaymentRoute(c) {
|
|
600
|
+
try {
|
|
601
|
+
const body = await c.req.json().catch(() => ({}));
|
|
602
|
+
const container = parsePaymentContainer(body);
|
|
603
|
+
if (!container) {
|
|
604
|
+
return c.json({ success: false, error: 'INVALID_PAYMENT_CONTAINER', message: 'Invalid or missing agenticPaymentContainer object' }, 400);
|
|
605
|
+
}
|
|
606
|
+
const headerNonce = body.headerNonce || c.req.header('x-tap-nonce');
|
|
607
|
+
const publicKey = body.publicKey;
|
|
608
|
+
const algorithm = body.algorithm || container.alg;
|
|
609
|
+
if (!publicKey) {
|
|
610
|
+
return c.json({
|
|
611
|
+
success: true,
|
|
612
|
+
parsed: true,
|
|
613
|
+
verified: false,
|
|
614
|
+
message: 'Payment container parsed but publicKey required for signature verification',
|
|
615
|
+
nonceLinked: headerNonce ? container.nonce === headerNonce : null,
|
|
616
|
+
hasCardMetadata: Boolean(container.cardMetadata),
|
|
617
|
+
hasCredentialHash: Boolean(container.credentialHash),
|
|
618
|
+
hasPayload: Boolean(container.payload),
|
|
619
|
+
hasBrowsingIOU: Boolean(container.browsingIOU),
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
const result = await verifyPaymentContainer(container, headerNonce || '', publicKey, algorithm);
|
|
623
|
+
return c.json({
|
|
624
|
+
success: true,
|
|
625
|
+
...result,
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
catch (error) {
|
|
629
|
+
console.error('Payment verification error:', error);
|
|
630
|
+
return c.json({ success: false, error: 'INTERNAL_ERROR', message: 'Internal server error' }, 500);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
364
633
|
// ============ UTILITY FUNCTIONS ============
|
|
365
634
|
async function generateKeyFingerprint(publicKey) {
|
|
366
635
|
const normalized = publicKey.replace(/\s/g, '').replace(/-----[^-]+-----/g, '');
|
|
@@ -375,5 +644,11 @@ export default {
|
|
|
375
644
|
getTAPAgentRoute,
|
|
376
645
|
listTAPAgentsRoute,
|
|
377
646
|
createTAPSessionRoute,
|
|
378
|
-
getTAPSessionRoute
|
|
647
|
+
getTAPSessionRoute,
|
|
648
|
+
rotateKeyRoute,
|
|
649
|
+
createInvoiceRoute,
|
|
650
|
+
getInvoiceRoute,
|
|
651
|
+
verifyIOURoute,
|
|
652
|
+
verifyConsumerRoute,
|
|
653
|
+
verifyPaymentRoute,
|
|
379
654
|
};
|
package/dist/tap-verify.d.ts
CHANGED
|
@@ -4,7 +4,15 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Integrates with existing BOTCHA verification middleware to provide
|
|
6
6
|
* enterprise-grade cryptographic agent authentication
|
|
7
|
+
*
|
|
8
|
+
* FEATURES:
|
|
9
|
+
* - Ed25519, ECDSA P-256, RSA-PSS signature verification
|
|
10
|
+
* - Full RFC 9421 compliance (sig1/sig2 labels, expires, nonce, tag)
|
|
11
|
+
* - Nonce replay protection via KV
|
|
12
|
+
* - TAP timestamp validation (created, expires, 8-minute max window)
|
|
13
|
+
* - Backward compatible with existing BOTCHA agents
|
|
7
14
|
*/
|
|
15
|
+
import type { KVNamespace } from './agents.js';
|
|
8
16
|
export interface TAPVerificationRequest {
|
|
9
17
|
method: string;
|
|
10
18
|
path: string;
|
|
@@ -26,6 +34,10 @@ export interface TAPVerificationResult {
|
|
|
26
34
|
signature_valid?: boolean;
|
|
27
35
|
intent_valid?: boolean;
|
|
28
36
|
capabilities?: string[];
|
|
37
|
+
tag?: string;
|
|
38
|
+
nonce?: string;
|
|
39
|
+
key_id?: string;
|
|
40
|
+
algorithm?: string;
|
|
29
41
|
};
|
|
30
42
|
}
|
|
31
43
|
export interface TAPHeaders {
|
|
@@ -36,12 +48,34 @@ export interface TAPHeaders {
|
|
|
36
48
|
'signature'?: string;
|
|
37
49
|
'signature-input'?: string;
|
|
38
50
|
}
|
|
51
|
+
export interface ParsedSignatureInput {
|
|
52
|
+
label: string;
|
|
53
|
+
components: string[];
|
|
54
|
+
created: number;
|
|
55
|
+
expires?: number;
|
|
56
|
+
keyId: string;
|
|
57
|
+
algorithm: string;
|
|
58
|
+
nonce?: string;
|
|
59
|
+
tag?: string;
|
|
60
|
+
}
|
|
39
61
|
/**
|
|
40
62
|
* Verify HTTP Message Signature according to RFC 9421
|
|
41
63
|
*/
|
|
42
|
-
export declare function verifyHTTPMessageSignature(request: TAPVerificationRequest, publicKey: string, algorithm: string): Promise<{
|
|
64
|
+
export declare function verifyHTTPMessageSignature(request: TAPVerificationRequest, publicKey: string, algorithm: string, nonces?: KVNamespace | null): Promise<{
|
|
43
65
|
valid: boolean;
|
|
44
66
|
error?: string;
|
|
67
|
+
metadata?: {
|
|
68
|
+
nonce?: string;
|
|
69
|
+
tag?: string;
|
|
70
|
+
key_id?: string;
|
|
71
|
+
};
|
|
72
|
+
}>;
|
|
73
|
+
/**
|
|
74
|
+
* Check if nonce was already used and store it if new
|
|
75
|
+
* Returns { replay: true } if nonce was seen before
|
|
76
|
+
*/
|
|
77
|
+
export declare function checkAndStoreNonce(nonces: KVNamespace | null, nonce: string): Promise<{
|
|
78
|
+
replay: boolean;
|
|
45
79
|
}>;
|
|
46
80
|
/**
|
|
47
81
|
* Parse and validate TAP intent from headers
|
|
@@ -58,10 +92,12 @@ export declare function parseTAPIntent(intentString: string): {
|
|
|
58
92
|
};
|
|
59
93
|
/**
|
|
60
94
|
* Extract TAP-specific headers from request
|
|
95
|
+
* Supports BOTH standard TAP (sig2 + tag) and BOTCHA extended (x-tap-* headers)
|
|
61
96
|
*/
|
|
62
97
|
export declare function extractTAPHeaders(headers: Record<string, string>): {
|
|
63
98
|
hasTAPHeaders: boolean;
|
|
64
99
|
tapHeaders: TAPHeaders;
|
|
100
|
+
isTAPStandard?: boolean;
|
|
65
101
|
};
|
|
66
102
|
/**
|
|
67
103
|
* Determine appropriate verification mode based on headers
|
|
@@ -71,6 +107,10 @@ export declare function getVerificationMode(headers: Record<string, string>): {
|
|
|
71
107
|
hasTAPHeaders: boolean;
|
|
72
108
|
hasChallenge: boolean;
|
|
73
109
|
};
|
|
110
|
+
/**
|
|
111
|
+
* Map TAP action to appropriate tag
|
|
112
|
+
*/
|
|
113
|
+
export declare function actionToTag(action: string): 'agent-browser-auth' | 'agent-payer-auth';
|
|
74
114
|
/**
|
|
75
115
|
* Build appropriate challenge response for TAP verification failure
|
|
76
116
|
*/
|
|
@@ -81,6 +121,8 @@ declare const _default: {
|
|
|
81
121
|
extractTAPHeaders: typeof extractTAPHeaders;
|
|
82
122
|
getVerificationMode: typeof getVerificationMode;
|
|
83
123
|
buildTAPChallengeResponse: typeof buildTAPChallengeResponse;
|
|
124
|
+
checkAndStoreNonce: typeof checkAndStoreNonce;
|
|
125
|
+
actionToTag: typeof actionToTag;
|
|
84
126
|
};
|
|
85
127
|
export default _default;
|
|
86
128
|
//# sourceMappingURL=tap-verify.d.ts.map
|
package/dist/tap-verify.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tap-verify.d.ts","sourceRoot":"","sources":["../src/tap-verify.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tap-verify.d.ts","sourceRoot":"","sources":["../src/tap-verify.ts"],"names":[],"mappings":"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"}
|