@tangle-network/agent-gateway 0.7.1 → 0.8.1

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 (64) hide show
  1. package/README.md +90 -3
  2. package/dist/chunk-C7Z2BRYV.js +5693 -0
  3. package/dist/chunk-C7Z2BRYV.js.map +1 -0
  4. package/dist/chunk-GITV7CPT.js +84 -0
  5. package/dist/chunk-GITV7CPT.js.map +1 -0
  6. package/dist/chunk-J5SDVHOL.js +104 -0
  7. package/dist/chunk-J5SDVHOL.js.map +1 -0
  8. package/dist/index.d.ts +70 -10
  9. package/dist/index.js +303 -21
  10. package/dist/index.js.map +1 -1
  11. package/dist/middleware.d.ts +7 -2
  12. package/dist/middleware.js +3 -2
  13. package/dist/nonce-store.d.ts +47 -11
  14. package/dist/nonce-store.js +9 -3
  15. package/dist/observer-types-A0RtA8uL.d.ts +95 -0
  16. package/dist/observer.d.ts +79 -0
  17. package/dist/observer.js +11 -0
  18. package/dist/observer.js.map +1 -0
  19. package/dist/{types-DEsMmS-X.d.ts → types-oQ58UakD.d.ts} +447 -172
  20. package/dist/types.d.ts +2 -1
  21. package/package.json +1 -1
  22. package/src/a2a/execution-fence.ts +162 -0
  23. package/src/a2a/handler.ts +506 -560
  24. package/src/a2a/message-send-execution.ts +241 -0
  25. package/src/a2a/message-stream-execution.ts +392 -0
  26. package/src/a2a/payment-recovery.ts +431 -0
  27. package/src/a2a/push-config-methods.ts +158 -0
  28. package/src/a2a/push-notifications.ts +172 -22
  29. package/src/a2a/task-cancellation.ts +50 -0
  30. package/src/a2a/task-finalization.ts +451 -0
  31. package/src/a2a/task-lifecycle.ts +54 -0
  32. package/src/a2a/task-methods.ts +163 -0
  33. package/src/a2a/task-push-delivery.ts +119 -0
  34. package/src/a2a/task-recovery.ts +11 -0
  35. package/src/a2a/task-state.ts +99 -0
  36. package/src/a2a/task-store-sql.ts +222 -24
  37. package/src/a2a/task-store.ts +58 -1
  38. package/src/a2a/task-submission-recovery.ts +178 -0
  39. package/src/a2a/types.ts +1 -0
  40. package/src/dispatch-authorization.ts +468 -0
  41. package/src/dispatch-payment-recovery.ts +248 -0
  42. package/src/dispatch-payment.ts +425 -0
  43. package/src/dispatch-pricing.ts +108 -0
  44. package/src/dispatch-sandbox.ts +424 -0
  45. package/src/dispatch-settlement.ts +139 -0
  46. package/src/dispatch-types.ts +84 -0
  47. package/src/dispatch.ts +35 -483
  48. package/src/index.ts +59 -1
  49. package/src/middleware.ts +339 -35
  50. package/src/mpp-payment.ts +117 -0
  51. package/src/nonce-store.ts +122 -20
  52. package/src/observer-types.ts +63 -0
  53. package/src/observer.ts +3 -63
  54. package/src/payment-operations.ts +485 -0
  55. package/src/payment-recovery-sql.ts +108 -0
  56. package/src/payment-recovery-worker.ts +488 -0
  57. package/src/payment-recovery.ts +331 -0
  58. package/src/payment-types.ts +48 -0
  59. package/src/types.ts +188 -49
  60. package/src/verify.ts +240 -71
  61. package/dist/chunk-M7ZJAK4K.js +0 -53
  62. package/dist/chunk-M7ZJAK4K.js.map +0 -1
  63. package/dist/chunk-Q4YAIEZY.js +0 -1763
  64. package/dist/chunk-Q4YAIEZY.js.map +0 -1
@@ -0,0 +1,84 @@
1
+ // src/observer.ts
2
+ var ConsoleObserver = class {
3
+ constructor(log = (e) => console.log(JSON.stringify(e))) {
4
+ this.log = log;
5
+ }
6
+ log;
7
+ emit(level, event, ctx, rest = {}) {
8
+ this.log({
9
+ level,
10
+ event,
11
+ time: (/* @__PURE__ */ new Date()).toISOString(),
12
+ requestId: ctx.requestId,
13
+ agentSlug: ctx.agentSlug,
14
+ durationMs: Date.now() - ctx.startMs,
15
+ ...rest
16
+ });
17
+ }
18
+ onRequestStart(ctx) {
19
+ this.emit("info", "gateway.request.start", ctx);
20
+ }
21
+ onPaymentVerified(ctx, info) {
22
+ this.emit("info", "gateway.payment.verified", ctx, info);
23
+ }
24
+ onAuthFailure(ctx, reason) {
25
+ this.emit("warn", "gateway.auth.failure", ctx, reason);
26
+ }
27
+ onRateLimited(ctx, info) {
28
+ this.emit("warn", "gateway.rate_limit", ctx, info);
29
+ }
30
+ onBodyTooLarge(ctx, contentLength) {
31
+ this.emit("warn", "gateway.body_too_large", ctx, { contentLength });
32
+ }
33
+ onInjectionDetected(ctx, info) {
34
+ this.emit("warn", "gateway.injection", ctx, info);
35
+ }
36
+ onRequestComplete(ctx, usage) {
37
+ this.emit("info", "gateway.request.complete", ctx, usage);
38
+ }
39
+ onStreamError(ctx, info) {
40
+ this.emit("error", "gateway.stream.error", ctx, info);
41
+ }
42
+ onSettlementError(ctx, info) {
43
+ this.emit("error", "gateway.settlement.error", ctx, info);
44
+ }
45
+ };
46
+ var CompositeObserver = class {
47
+ constructor(observers) {
48
+ this.observers = observers;
49
+ }
50
+ observers;
51
+ async fanOut(event, ...args) {
52
+ for (const obs of this.observers) {
53
+ const fn = obs[event];
54
+ if (!fn) continue;
55
+ try {
56
+ await fn.apply(obs, args);
57
+ } catch (err) {
58
+ console.warn(`[agent-gateway] observer ${event} threw:`, err instanceof Error ? err.message : err);
59
+ }
60
+ }
61
+ }
62
+ onRequestStart = (ctx) => this.fanOut("onRequestStart", ctx);
63
+ onPaymentVerified = (ctx, info) => this.fanOut("onPaymentVerified", ctx, info);
64
+ onAuthFailure = (ctx, reason) => this.fanOut("onAuthFailure", ctx, reason);
65
+ onRateLimited = (ctx, info) => this.fanOut("onRateLimited", ctx, info);
66
+ onBodyTooLarge = (ctx, contentLength) => this.fanOut("onBodyTooLarge", ctx, contentLength);
67
+ onInjectionDetected = (ctx, info) => this.fanOut("onInjectionDetected", ctx, info);
68
+ onRequestComplete = (ctx, usage) => this.fanOut("onRequestComplete", ctx, usage);
69
+ onStreamError = (ctx, info) => this.fanOut("onStreamError", ctx, info);
70
+ onSettlementError = (ctx, info) => this.fanOut("onSettlementError", ctx, info);
71
+ };
72
+ function generateRequestId() {
73
+ const bytes = new Uint8Array(16);
74
+ globalThis.crypto.getRandomValues(bytes);
75
+ const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
76
+ return `req_${hex}`;
77
+ }
78
+
79
+ export {
80
+ ConsoleObserver,
81
+ CompositeObserver,
82
+ generateRequestId
83
+ };
84
+ //# sourceMappingURL=chunk-GITV7CPT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/observer.ts"],"sourcesContent":["/**\n * Observability hook surface.\n *\n * Consumers implement GatewayObserver to wire the gateway into their existing\n * telemetry stack (Langfuse, OTEL, structured logs, Prometheus, etc.) without\n * the gateway itself depending on any of those libraries.\n *\n * Every event carries a requestId so downstream metrics can correlate the\n * payment verification, sandbox execution, and settlement for one request.\n * When no observer is configured, the gateway stays silent.\n */\n\nimport type { GatewayUsageEvent, PaymentMethod } from './payment-types'\nimport type { AuthFailureReason, GatewayObserver, RequestContext } from './observer-types'\n\nexport type { AuthFailureReason, GatewayObserver, RequestContext } from './observer-types'\n\n// ---------------------------------------------------------------------------\n// Convenience implementations\n// ---------------------------------------------------------------------------\n\n/**\n * Structured-log observer. Emits one JSON line per event on the `log` function.\n * Default sink: console.log. Production consumers usually pipe their own\n * structured logger (pino, winston, the cf Logs binding).\n *\n * Usage:\n * new ConsoleObserver(({ level, event, ...rest }) => logger.info({ event, ...rest }))\n */\nexport class ConsoleObserver implements GatewayObserver {\n constructor(\n private readonly log: (entry: Record<string, unknown>) => void = (e) => console.log(JSON.stringify(e)),\n ) {}\n\n private emit(level: 'info' | 'warn' | 'error', event: string, ctx: RequestContext, rest: Record<string, unknown> = {}) {\n this.log({\n level,\n event,\n time: new Date().toISOString(),\n requestId: ctx.requestId,\n agentSlug: ctx.agentSlug,\n durationMs: Date.now() - ctx.startMs,\n ...rest,\n })\n }\n\n onRequestStart(ctx: RequestContext) { this.emit('info', 'gateway.request.start', ctx) }\n onPaymentVerified(ctx: RequestContext, info: { method: PaymentMethod; consumerId: string; keyId?: string }) {\n this.emit('info', 'gateway.payment.verified', ctx, info)\n }\n onAuthFailure(ctx: RequestContext, reason: AuthFailureReason) {\n this.emit('warn', 'gateway.auth.failure', ctx, reason as unknown as Record<string, unknown>)\n }\n onRateLimited(ctx: RequestContext, info: { consumerId: string; retryAfterSeconds: number }) {\n this.emit('warn', 'gateway.rate_limit', ctx, info)\n }\n onBodyTooLarge(ctx: RequestContext, contentLength: number) {\n this.emit('warn', 'gateway.body_too_large', ctx, { contentLength })\n }\n onInjectionDetected(ctx: RequestContext, info: { consumerId: string; patterns: string[]; blocked: boolean }) {\n this.emit('warn', 'gateway.injection', ctx, info)\n }\n onRequestComplete(ctx: RequestContext, usage: GatewayUsageEvent) {\n this.emit('info', 'gateway.request.complete', ctx, usage as unknown as Record<string, unknown>)\n }\n onStreamError(ctx: RequestContext, info: { consumerId: string; errorMessage: string }) {\n this.emit('error', 'gateway.stream.error', ctx, info)\n }\n onSettlementError(ctx: RequestContext, info: { consumerId: string; method: PaymentMethod; errorMessage: string }) {\n this.emit('error', 'gateway.settlement.error', ctx, info)\n }\n}\n\n/**\n * Compose multiple observers into one. Errors in any individual observer\n * don't break the others (fire-and-forget telemetry).\n */\nexport class CompositeObserver implements GatewayObserver {\n constructor(private readonly observers: GatewayObserver[]) {}\n\n private async fanOut<K extends keyof GatewayObserver>(event: K, ...args: unknown[]): Promise<void> {\n for (const obs of this.observers) {\n const fn = obs[event] as ((...a: unknown[]) => void | Promise<void>) | undefined\n if (!fn) continue\n try {\n await fn.apply(obs, args)\n } catch (err) {\n console.warn(`[agent-gateway] observer ${event} threw:`, err instanceof Error ? err.message : err)\n }\n }\n }\n\n onRequestStart = (ctx: RequestContext) => this.fanOut('onRequestStart', ctx)\n onPaymentVerified = (ctx: RequestContext, info: Parameters<Required<GatewayObserver>['onPaymentVerified']>[1]) =>\n this.fanOut('onPaymentVerified', ctx, info)\n onAuthFailure = (ctx: RequestContext, reason: AuthFailureReason) =>\n this.fanOut('onAuthFailure', ctx, reason)\n onRateLimited = (ctx: RequestContext, info: Parameters<Required<GatewayObserver>['onRateLimited']>[1]) =>\n this.fanOut('onRateLimited', ctx, info)\n onBodyTooLarge = (ctx: RequestContext, contentLength: number) =>\n this.fanOut('onBodyTooLarge', ctx, contentLength)\n onInjectionDetected = (ctx: RequestContext, info: Parameters<Required<GatewayObserver>['onInjectionDetected']>[1]) =>\n this.fanOut('onInjectionDetected', ctx, info)\n onRequestComplete = (ctx: RequestContext, usage: GatewayUsageEvent) =>\n this.fanOut('onRequestComplete', ctx, usage)\n onStreamError = (ctx: RequestContext, info: Parameters<Required<GatewayObserver>['onStreamError']>[1]) =>\n this.fanOut('onStreamError', ctx, info)\n onSettlementError = (ctx: RequestContext, info: Parameters<Required<GatewayObserver>['onSettlementError']>[1]) =>\n this.fanOut('onSettlementError', ctx, info)\n}\n\n/**\n * Generate a request-id. Crypto-random 16 bytes, hex-encoded with an `req_` prefix.\n * Works in Workers, Node, and browsers — all have globalThis.crypto.\n */\nexport function generateRequestId(): string {\n const bytes = new Uint8Array(16)\n globalThis.crypto.getRandomValues(bytes)\n const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join('')\n return `req_${hex}`\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,104 @@
1
+ // src/nonce-store.ts
2
+ function nonceTtlSeconds(expiry, nowSeconds = Math.floor(Date.now() / 1e3)) {
3
+ const remaining = expiry - BigInt(nowSeconds);
4
+ if (remaining <= 0n || remaining > BigInt(Number.MAX_SAFE_INTEGER)) return void 0;
5
+ return Math.max(Number(remaining), 60);
6
+ }
7
+ var MemoryNonceStore = class {
8
+ seen = /* @__PURE__ */ new Map();
9
+ lastEviction = Date.now();
10
+ async hasSeen(nonce) {
11
+ this.evictExpired();
12
+ const entry = this.seen.get(nonce);
13
+ if (!entry) return false;
14
+ if (entry.expiresAt < Date.now()) {
15
+ this.seen.delete(nonce);
16
+ return false;
17
+ }
18
+ return true;
19
+ }
20
+ async claim(nonce, ttlSeconds, ownerId) {
21
+ this.evictExpired();
22
+ const now = Date.now();
23
+ const entry = this.seen.get(nonce);
24
+ if (entry !== void 0 && entry.expiresAt >= now) {
25
+ return ownerId !== void 0 && entry.ownerId === ownerId;
26
+ }
27
+ this.seen.set(nonce, { expiresAt: now + ttlSeconds * 1e3, ownerId });
28
+ return true;
29
+ }
30
+ async markSeen(nonce, ttlSeconds) {
31
+ this.evictExpired();
32
+ this.seen.set(nonce, { expiresAt: Date.now() + ttlSeconds * 1e3 });
33
+ }
34
+ evictExpired() {
35
+ const now = Date.now();
36
+ if (now - this.lastEviction < 6e4) return;
37
+ this.lastEviction = now;
38
+ for (const [nonce, entry] of this.seen) {
39
+ if (entry.expiresAt < now) this.seen.delete(nonce);
40
+ }
41
+ }
42
+ };
43
+ var KvNonceStore = class {
44
+ constructor(kv, prefix = "nonce", options = {}) {
45
+ this.kv = kv;
46
+ this.prefix = prefix;
47
+ this.atomicClaim = options.atomicClaim ?? (kv.putIfAbsent ? async (key, ttlSeconds, ownerId) => {
48
+ const value = ownerId ?? "1";
49
+ if (ownerId !== void 0) {
50
+ const existing = await kv.get(key);
51
+ if (existing !== null) return existing === ownerId;
52
+ }
53
+ const inserted = await kv.putIfAbsent(key, value, { expirationTtl: ttlSeconds });
54
+ if (inserted || ownerId === void 0) return inserted;
55
+ return await kv.get(key) === ownerId;
56
+ } : void 0);
57
+ }
58
+ kv;
59
+ prefix;
60
+ atomicClaim;
61
+ async hasSeen(nonce) {
62
+ return await this.kv.get(this.key(nonce)) !== null;
63
+ }
64
+ async markSeen(nonce, ttlSeconds) {
65
+ const ttl = Math.max(ttlSeconds, 60);
66
+ await this.kv.put(this.key(nonce), "1", { expirationTtl: ttl });
67
+ }
68
+ async claim(nonce, ttlSeconds, ownerId) {
69
+ if (!this.atomicClaim) {
70
+ throw new Error(
71
+ "KvNonceStore requires an atomicClaim backed by D1, Durable Objects, or an atomic KV extension"
72
+ );
73
+ }
74
+ const ttl = Math.max(ttlSeconds, 60);
75
+ return this.atomicClaim(this.key(nonce), ttl, ownerId);
76
+ }
77
+ /** Used by gateway validation to reject plain, non-atomic KV bindings. */
78
+ hasAtomicClaim() {
79
+ return this.atomicClaim !== void 0;
80
+ }
81
+ key(nonce) {
82
+ return `${this.prefix}:${nonce}`;
83
+ }
84
+ };
85
+ async function claimStoredNonce(store, nonce, ttlSeconds, ownerId) {
86
+ if (typeof store.claim !== "function") {
87
+ throw new Error("NonceStore.claim is required for atomic payment replay protection");
88
+ }
89
+ return store.claim(nonce, ttlSeconds, ownerId);
90
+ }
91
+ function isAtomicNonceStore(store) {
92
+ const kvStore = store;
93
+ if (typeof kvStore.hasAtomicClaim === "function" && !kvStore.hasAtomicClaim()) return false;
94
+ return typeof store.claim === "function";
95
+ }
96
+
97
+ export {
98
+ nonceTtlSeconds,
99
+ MemoryNonceStore,
100
+ KvNonceStore,
101
+ claimStoredNonce,
102
+ isAtomicNonceStore
103
+ };
104
+ //# sourceMappingURL=chunk-J5SDVHOL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/nonce-store.ts"],"sourcesContent":["/**\n * Nonce replay protection for x402/MPP payments.\n * Tracks seen nonces to prevent the same payment from being used twice.\n */\n\nexport interface NonceStore {\n /** Check if nonce has been seen. This method never grants ownership. */\n hasSeen(nonce: string): Promise<boolean>\n /**\n * Atomically claim a nonce. An owner id makes a retry by the same payment\n * operation idempotent. This is optional only for the 0.7.1 check-and-mark\n * compatibility contract; durable owner claims require this method.\n */\n claim?(nonce: string, ttlSeconds: number, ownerId?: string): Promise<boolean>\n /** @deprecated Use claim() for atomic ownership in new stores. */\n markSeen?(nonce: string, ttlSeconds: number): Promise<void>\n}\n\nexport interface AtomicNonceStore extends NonceStore {\n claim(nonce: string, ttlSeconds: number, ownerId?: string): Promise<boolean>\n}\n\n/**\n * Return the seconds for which a signed nonce must remain stored.\n *\n * The signed expiry is the replay boundary. A fixed one-hour cap would allow\n * a still-valid authorization to replay after the nonce entry expires.\n */\nexport function nonceTtlSeconds(\n expiry: bigint,\n nowSeconds = Math.floor(Date.now() / 1000),\n): number | undefined {\n const remaining = expiry - BigInt(nowSeconds)\n if (remaining <= 0n || remaining > BigInt(Number.MAX_SAFE_INTEGER)) return undefined\n return Math.max(Number(remaining), 60)\n}\n\n// ---------------------------------------------------------------------------\n// In-memory implementation — single-worker, ephemeral\n// ---------------------------------------------------------------------------\n\n/** In-memory nonce store with automatic eviction. Use in tests or single-worker deploys. */\nexport class MemoryNonceStore implements NonceStore {\n private seen = new Map<string, { expiresAt: number; ownerId?: string }>()\n private lastEviction = Date.now()\n\n async hasSeen(nonce: string): Promise<boolean> {\n this.evictExpired()\n const entry = this.seen.get(nonce)\n if (!entry) return false\n if (entry.expiresAt < Date.now()) {\n this.seen.delete(nonce)\n return false\n }\n return true\n }\n\n async claim(nonce: string, ttlSeconds: number, ownerId?: string): Promise<boolean> {\n this.evictExpired()\n const now = Date.now()\n const entry = this.seen.get(nonce)\n if (entry !== undefined && entry.expiresAt >= now) {\n return ownerId !== undefined && entry.ownerId === ownerId\n }\n this.seen.set(nonce, { expiresAt: now + ttlSeconds * 1000, ownerId })\n return true\n }\n\n async markSeen(nonce: string, ttlSeconds: number): Promise<void> {\n this.evictExpired()\n this.seen.set(nonce, { expiresAt: Date.now() + ttlSeconds * 1000 })\n }\n\n private evictExpired() {\n const now = Date.now()\n // Evict at most every 60 seconds to avoid O(n) on every request\n if (now - this.lastEviction < 60_000) return\n this.lastEviction = now\n for (const [nonce, entry] of this.seen) {\n if (entry.expiresAt < now) this.seen.delete(nonce)\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Cloudflare KV implementation — multi-worker, distributed\n// ---------------------------------------------------------------------------\n\n/**\n * Minimal KVNamespace shape — matches Cloudflare Workers' @cloudflare/workers-types\n * without pulling that package as a dep. Production consumers cast their KV\n * binding to this interface at the construction site.\n */\nexport interface KVNamespace {\n get(key: string, options?: { type?: 'text' | 'json' }): Promise<string | null>\n put(key: string, value: string, options?: { expirationTtl?: number }): Promise<void>\n /** Optional linearizable create-if-absent extension. Cloudflare KV does not provide it. */\n putIfAbsent?(key: string, value: string, options?: { expirationTtl?: number }): Promise<boolean>\n delete(key: string): Promise<void>\n}\n\n/** Atomic claim supplied by D1, a Durable Object, or another linearizable store. */\nexport type AtomicKvNonceClaim = (\n key: string,\n ttlSeconds: number,\n ownerId?: string,\n) => Promise<boolean>\n\nexport interface KvNonceStoreOptions {\n /**\n * Claim the fully namespaced key atomically.\n * The callback must make same-owner retries idempotent.\n */\n atomicClaim?: AtomicKvNonceClaim\n}\n\n/**\n * KV-backed NonceStore for distributed Cloudflare Workers deployments.\n *\n * Why this exists: MemoryNonceStore works on a single worker instance, but\n * Cloudflare routes requests across multiple isolates. Without shared state,\n * an attacker could retry a replayed nonce against a different isolate and\n * have it accepted. Cloudflare KV has no conditional write, so a plain KV\n * binding is not an atomic payment store. Supply `atomicClaim` from D1,\n * Durable Objects, or another linearizable service before using this store\n * for paid requests.\n *\n * Usage:\n * const nonceStore = new KvNonceStore(env.NONCE_KV, 'x402')\n * createAgentGateway({ ...config, nonceStore })\n */\nexport class KvNonceStore implements NonceStore {\n private readonly atomicClaim?: AtomicKvNonceClaim\n\n constructor(\n private readonly kv: KVNamespace,\n /** Key prefix to namespace within a shared KV (default: \"nonce\"). */\n private readonly prefix: string = 'nonce',\n options: KvNonceStoreOptions = {},\n ) {\n this.atomicClaim = options.atomicClaim ?? (\n kv.putIfAbsent\n ? async (key, ttlSeconds, ownerId) => {\n const value = ownerId ?? '1'\n if (ownerId !== undefined) {\n const existing = await kv.get(key)\n if (existing !== null) return existing === ownerId\n }\n const inserted = await kv.putIfAbsent!(key, value, { expirationTtl: ttlSeconds })\n if (inserted || ownerId === undefined) return inserted\n return (await kv.get(key)) === ownerId\n }\n : undefined\n )\n }\n\n async hasSeen(nonce: string): Promise<boolean> {\n return (await this.kv.get(this.key(nonce))) !== null\n }\n\n async markSeen(nonce: string, ttlSeconds: number): Promise<void> {\n const ttl = Math.max(ttlSeconds, 60)\n await this.kv.put(this.key(nonce), '1', { expirationTtl: ttl })\n }\n\n async claim(nonce: string, ttlSeconds: number, ownerId?: string): Promise<boolean> {\n if (!this.atomicClaim) {\n throw new Error(\n 'KvNonceStore requires an atomicClaim backed by D1, Durable Objects, or an atomic KV extension',\n )\n }\n const ttl = Math.max(ttlSeconds, 60)\n return this.atomicClaim(this.key(nonce), ttl, ownerId)\n }\n\n /** Used by gateway validation to reject plain, non-atomic KV bindings. */\n hasAtomicClaim(): boolean {\n return this.atomicClaim !== undefined\n }\n\n private key(nonce: string): string {\n return `${this.prefix}:${nonce}`\n }\n}\n\n/** Claim through the one atomic contract used by every payment path. */\nexport async function claimStoredNonce(\n store: NonceStore,\n nonce: string,\n ttlSeconds: number,\n ownerId?: string,\n): Promise<boolean> {\n if (typeof store.claim !== 'function') {\n throw new Error('NonceStore.claim is required for atomic payment replay protection')\n }\n return store.claim(nonce, ttlSeconds, ownerId)\n}\n\n/** Durable payment paths must use a store with a single atomic claim operation. */\nexport function isAtomicNonceStore(store: NonceStore): store is AtomicNonceStore {\n const kvStore = store as NonceStore & { hasAtomicClaim?: () => boolean }\n if (typeof kvStore.hasAtomicClaim === 'function' && !kvStore.hasAtomicClaim()) return false\n return typeof store.claim === 'function'\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,17 +1,57 @@
1
1
  export { createAgentGateway } from './middleware.js';
2
- import { A as ApiKeyInfo, G as GatewayConfig, M as MppConfig, X as X402Config, C as ChatMessage } from './types-DEsMmS-X.js';
3
- export { a as A2A_ERROR_CODES, b as AgentCapabilities, c as AgentCard, d as AgentCardAuthentication, e as AgentMeta, f as AgentProvider, g as AgentSkill, h as Artifact, i as AuthFailureReason, j as ChatCompletionChunk, k as ChatCompletionRequest, l as CompositeObserver, m as ConsoleObserver, D as D1DatabaseLike, n as D1StmtLike, o as DataPart, F as FilePart, p as GatewayObserver, q as GatewayUsageEvent, I as InMemoryPushNotificationStore, r as InMemoryTaskStore, J as JSONRPCErrorResponse, s as JSONRPCRequest, t as JSONRPCResponse, u as JSONRPCSuccessResponse, v as Message, w as MessageSendParams, P as Part, x as PaymentMethod, y as PaymentResult, z as PushDeliveryResult, B as PushNotificationAuthentication, E as PushNotificationConfig, H as PushNotificationStore, R as RequestContext, S as SandboxBox, K as SandboxStreamEvent, L as SqlAdapter, N as SqlPushNotificationStore, O as SqlTaskStore, Q as StreamingEvent, T as Task, U as TaskArtifactUpdateEvent, V as TaskIdParams, W as TaskPushNotificationConfig, Y as TaskPushNotificationConfigGetParams, Z as TaskState, _ as TaskStatus, $ as TaskStatusUpdateEvent, a0 as TaskStore, a1 as TextPart, a2 as d1ToSqlAdapter, a3 as deliverPushNotifications, a4 as generateRequestId } from './types-DEsMmS-X.js';
2
+ import { G as GatewayConfig, P as PaymentOperationRecoveryResult, a as PaymentRecoveryRecord, M as MppAuthenticatedCredential, A as ApiKeyInfo, b as MppConfig, X as X402Config, c as PaymentRecoveryStore, S as SqlAdapter, C as ChatMessage } from './types-oQ58UakD.js';
3
+ export { d as A2A_ERROR_CODES, e as AgentCapabilities, f as AgentCard, g as AgentCardAuthentication, h as AgentMeta, i as AgentProvider, j as AgentSkill, k as ApiKeyGatewayConfig, l as Artifact, m as ChatCompletionChunk, n as ChatCompletionRequest, o as CreateAgentGatewayConfig, D as D1DatabaseLike, p as D1StmtLike, q as DataPart, F as FilePart, I as InMemoryPushNotificationStore, r as InMemoryTaskStore, J as JSONRPCErrorResponse, s as JSONRPCRequest, t as JSONRPCResponse, u as JSONRPCSuccessResponse, v as MPP_CHARGE_PROTOCOL_VERSION, w as MemoryPaymentOperations, x as MemoryPaymentOperationsOptions, y as MemoryPaymentRecoveryStore, z as Message, B as MessageSendParams, E as MppChargeLifecycle, H as MppChargeOperation, K as MppChargeOperationState, L as MppChargeRecoveryResult, N as MppChargeRequest, O as PAYMENT_PROTOCOL_VERSION, Q as PAYMENT_RECOVERY_VERSION, R as Part, T as PaymentAuthorizationContext, U as PaymentOperation, V as PaymentOperationNotFound, W as PaymentOperationState, Y as PaymentOperations, Z as PaymentRecoveryAttribution, _ as PaymentRecoveryConfig, $ as PaymentRecoveryFenceError, a0 as PaymentRecoveryState, a1 as PaymentRecoveryTarget, a2 as PaymentResult, a3 as PaymentSettlementInput, a4 as PushDeliveryResult, a5 as PushNotificationAuthentication, a6 as PushNotificationConfig, a7 as PushNotificationDeliveryOptions, a8 as PushNotificationStore, a9 as SandboxBox, aa as SandboxStreamEvent, ab as SqlPushNotificationStore, ac as SqlTaskStore, ad as StreamingEvent, ae as Task, af as TaskArtifactUpdateEvent, ag as TaskIdParams, ah as TaskPushNotificationConfig, ai as TaskPushNotificationConfigGetParams, aj as TaskState, ak as TaskStatus, al as TaskStatusUpdateEvent, am as TaskStore, an as TextPart, ao as d1ToSqlAdapter, ap as deliverDemoPushNotifications, aq as deliverPushNotifications, ar as mppPaymentOperationId, as as validatePushNotificationUrl } from './types-oQ58UakD.js';
4
4
  import { NonceStore } from './nonce-store.js';
5
- export { KvNonceStore, MemoryNonceStore } from './nonce-store.js';
5
+ export { AtomicKvNonceClaim, AtomicNonceStore, KvNonceStore, KvNonceStoreOptions, MemoryNonceStore, isAtomicNonceStore } from './nonce-store.js';
6
+ export { CompositeObserver, ConsoleObserver, generateRequestId } from './observer.js';
6
7
  export { KvRateLimitStore, MemoryRateLimitStore, RateLimitConfig, RateLimitResult, RateLimitStore, checkRateLimit } from './rate-limit.js';
8
+ import { S as SandboxUsageReceipt } from './observer-types-A0RtA8uL.js';
9
+ export { A as AuthFailureReason, G as GatewayObserver, a as GatewayUsageEvent, P as PaymentMethod, b as PaymentSettlementBasis, R as RequestContext, c as SandboxExecutionBudget } from './observer-types-A0RtA8uL.js';
7
10
  export { ApiKey, ApiKeyCreateRequest, ApiKeyRoutesConfig, ApiKeyStore, createApiKeyRoutes, verifyApiKeyFromStore } from './api-keys.js';
8
11
  export { PublishRequest, PublishRoutesConfig, PublishStore, PublishedConfig, createPublishRoutes } from './publish.js';
9
12
  import 'hono/types';
10
13
  import 'hono';
11
14
 
15
+ declare function reclaimPayment(operationId: string, config: GatewayConfig): Promise<PaymentOperationRecoveryResult>;
16
+
17
+ interface RecoveryWorkerOptions {
18
+ now?: number;
19
+ /** Fresh wall-clock source for each row's lease and retry timestamps. */
20
+ clock?: () => number;
21
+ workerId?: string;
22
+ }
23
+ interface RecoverPaymentOptions extends RecoveryWorkerOptions {
24
+ /** Process one requested row even when its normal retry time is later. */
25
+ force?: boolean;
26
+ /** Exact receipt recovered from a durable protocol record, such as an A2A task. */
27
+ usage?: SandboxUsageReceipt;
28
+ }
29
+ /** Batch recovery never accepts receipt data because each receipt belongs to one row. */
30
+ interface RecoverPaymentsOptions extends RecoveryWorkerOptions {
31
+ limit?: number;
32
+ }
33
+ interface PaymentRecoveryRun {
34
+ scanned: number;
35
+ reconciled: number;
36
+ deferred: number;
37
+ failed: number;
38
+ }
39
+ /** Scan and reconcile due payment rows. Safe to run concurrently on many workers. */
40
+ declare function recoverPayments(config: GatewayConfig, options?: RecoverPaymentsOptions): Promise<PaymentRecoveryRun>;
41
+ /** Reconcile one payment identity. Hosts can expose this through a private worker API. */
42
+ declare function recoverPayment(recoveryId: string, config: GatewayConfig, options?: RecoverPaymentOptions): Promise<PaymentRecoveryRecord | undefined>;
43
+
44
+ interface VerifiedMppCredential extends MppAuthenticatedCredential {
45
+ /** Opaque replay key. BlueprinTEVM shares the x402 nonce namespace. */
46
+ replayKey: string;
47
+ }
48
+ /** Return the legacy opaque nonce key used by older consumers. */
49
+ declare function mppReplayNonceKey(authHeader: string): string | undefined;
50
+ /** Return the decoded method credential for the post-guard charge lifecycle. */
51
+ declare function mppPaymentCredential(authHeader: string): string | undefined;
12
52
  /** Pure capability checks shared by discovery and every request protocol. */
13
53
  declare function isApiKeyAuthEnabled(config: Pick<GatewayConfig, 'verifyApiKey' | 'x402'>): boolean;
14
- /** MPP is enabled only when a real verifier or explicit demo mode exists. */
54
+ /** MPP is enabled only when authentication and method settlement are complete. */
15
55
  declare function isMppAuthEnabled(config: Pick<GatewayConfig, 'mpp' | 'x402'>): boolean;
16
56
  /**
17
57
  * Verify x402 SpendAuth signature (EIP-712).
@@ -24,25 +64,45 @@ declare function isMppAuthEnabled(config: Pick<GatewayConfig, 'mpp' | 'x402'>):
24
64
  * neither — rejected by createAgentGateway and
25
65
  * by this function as defense-in-depth.
26
66
  */
27
- declare function verifyX402(spendAuthHeader: string, config: X402Config, nonceStore?: NonceStore): Promise<string | null>;
67
+ declare function verifyX402(spendAuthHeader: string, config: X402Config, nonceStore?: NonceStore, minimumAmount?: bigint, markNonce?: boolean): Promise<string | null>;
28
68
  /**
29
69
  * Verify MPP (Machine Payments Protocol) Authorization: Payment header.
30
70
  *
31
71
  * MPP uses `Authorization: Payment <method> <credential>` format. The
32
- * credential is method-specific; `MppConfig.verifySigner` owns verification
33
- * and returns the consumer identity. The built-in `blueprintevm` path can
72
+ * credential is method-specific; `MppConfig.authenticateCredential` owns authentication
73
+ * and returns the consumer plus stable payment identity. The built-in `blueprintevm` path can
34
74
  * reuse the x402 verifier for credentials with the compatible payload shape.
35
75
  *
36
- * Returns the signer address if valid, null otherwise.
76
+ * Returns authenticated identity if valid, null otherwise.
37
77
  * In demo mode, accepts any well-formed Payment header with an identity.
38
78
  */
39
- declare function verifyMpp(authHeader: string, config: MppConfig, x402Config: X402Config, nonceStore?: NonceStore): Promise<string | null>;
79
+ declare function verifyMppCredential(authHeader: string, config: MppConfig, x402Config: X402Config, nonceStore?: NonceStore, minimumAmount?: bigint, markNonce?: boolean): Promise<VerifiedMppCredential | null>;
80
+ /**
81
+ * Verify an MPP credential using the 0.7.1 public return shape.
82
+ * Rich durable callers use verifyMppCredential instead.
83
+ */
84
+ declare function verifyMpp(authHeader: string, config: MppConfig, x402Config: X402Config, nonceStore?: NonceStore, minimumAmount?: bigint, markNonce?: boolean): Promise<string | null>;
40
85
  /**
41
86
  * Default API key verifier — accepts any `sk_agent_*` key (demo mode).
42
87
  * Override in GatewayConfig.verifyApiKey for production.
43
88
  */
44
89
  declare function defaultVerifyApiKey(authHeader: string): Promise<ApiKeyInfo | null>;
45
90
 
91
+ /** Durable recovery outbox for D1, sqlite, libSQL, or an adapted SQL driver. */
92
+ declare class SqlPaymentRecoveryStore implements PaymentRecoveryStore {
93
+ private readonly db;
94
+ private readonly table;
95
+ constructor(db: SqlAdapter, options?: {
96
+ table?: string;
97
+ });
98
+ /** Idempotent. Run this before the gateway starts accepting traffic. */
99
+ migrate(): Promise<void>;
100
+ createIfAbsent(record: PaymentRecoveryRecord): Promise<boolean>;
101
+ get(id: string): Promise<PaymentRecoveryRecord | undefined>;
102
+ compareAndSet(expected: PaymentRecoveryRecord, next: PaymentRecoveryRecord): Promise<boolean>;
103
+ listDue(now: number, limit: number): Promise<PaymentRecoveryRecord[]>;
104
+ }
105
+
46
106
  /**
47
107
  * Detect prompt injection attempts.
48
108
  * Returns array of matched pattern descriptions, empty if clean.
@@ -85,4 +145,4 @@ declare function filterConsumerMessagesStrict(messages: ChatMessage[], maxLength
85
145
  */
86
146
  declare function redactSystemPromptFromOutput(output: string, systemPrompt: string | undefined): string;
87
147
 
88
- export { ApiKeyInfo, ChatMessage, GatewayConfig, MppConfig, NonceStore, X402Config, defaultVerifyApiKey, detectInjection, filterConsumerMessages, filterConsumerMessagesStrict, isApiKeyAuthEnabled, isMppAuthEnabled, redactSystemPromptFromOutput, verifyMpp, verifyX402 };
148
+ export { ApiKeyInfo, ChatMessage, GatewayConfig, MppAuthenticatedCredential, MppConfig, NonceStore, PaymentOperationRecoveryResult, PaymentRecoveryRecord, type PaymentRecoveryRun, PaymentRecoveryStore, type RecoverPaymentOptions, type RecoverPaymentsOptions, SandboxUsageReceipt, SqlAdapter, SqlPaymentRecoveryStore, type VerifiedMppCredential, X402Config, defaultVerifyApiKey, detectInjection, filterConsumerMessages, filterConsumerMessagesStrict, isApiKeyAuthEnabled, isMppAuthEnabled, mppPaymentCredential, mppReplayNonceKey, reclaimPayment, recoverPayment, recoverPayments, redactSystemPromptFromOutput, verifyMpp, verifyMppCredential, verifyX402 };