@devlab.group/agent-commerce 1.5.0 → 1.6.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 (45) hide show
  1. package/README.md +73 -71
  2. package/dist/ap2.d.ts +20 -23
  3. package/dist/ap2.js +53 -75
  4. package/dist/ap2.js.map +1 -1
  5. package/dist/authorization-BpbWGGrf.d.ts +115 -0
  6. package/dist/chunk-AFI2CEZS.js +10 -0
  7. package/dist/chunk-AFI2CEZS.js.map +1 -0
  8. package/dist/{chunk-PBYN7EK2.js → chunk-CBJIT7QP.js} +10 -9
  9. package/dist/chunk-CBJIT7QP.js.map +1 -0
  10. package/dist/{chunk-NKNXVDHN.js → chunk-JKEKKXRJ.js} +45 -66
  11. package/dist/chunk-JKEKKXRJ.js.map +1 -0
  12. package/dist/{chunk-5GEWKNIH.js → chunk-N5KRK7YA.js} +63 -27
  13. package/dist/chunk-N5KRK7YA.js.map +1 -0
  14. package/dist/{chunk-6D2EZ5ME.js → chunk-V2V2E7HX.js} +2 -2
  15. package/dist/{chunk-6D2EZ5ME.js.map → chunk-V2V2E7HX.js.map} +1 -1
  16. package/dist/{chunk-US622BKF.js → chunk-VKDXMXHL.js} +5 -8
  17. package/dist/chunk-VKDXMXHL.js.map +1 -0
  18. package/dist/cli/index.js +501 -494
  19. package/dist/cli/index.js.map +1 -1
  20. package/dist/{constants-6mypC60h.d.ts → constants-Bkq04FRZ.d.ts} +1 -3
  21. package/dist/guardrails-71XwtXlT.d.ts +31 -0
  22. package/dist/index.d.ts +230 -265
  23. package/dist/index.js +1050 -607
  24. package/dist/index.js.map +1 -1
  25. package/dist/mcp.d.ts +6 -59
  26. package/dist/mcp.js +61 -53
  27. package/dist/mcp.js.map +1 -1
  28. package/dist/mpp.d.ts +4 -4
  29. package/dist/mpp.js +21 -19
  30. package/dist/mpp.js.map +1 -1
  31. package/dist/protocol-adapter-DTkrXTev.d.ts +238 -0
  32. package/dist/runtime-CiYbgGpi.d.ts +303 -0
  33. package/dist/{types-CJtwLu1c.d.ts → types-O6lg3Q5V.d.ts} +17 -23
  34. package/dist/x402.d.ts +43 -75
  35. package/dist/x402.js +10 -9
  36. package/dist/x402.js.map +1 -1
  37. package/package.json +7 -5
  38. package/dist/authorization-DA7mjy_O.d.ts +0 -123
  39. package/dist/chunk-5GEWKNIH.js.map +0 -1
  40. package/dist/chunk-NKNXVDHN.js.map +0 -1
  41. package/dist/chunk-PBYN7EK2.js.map +0 -1
  42. package/dist/chunk-US622BKF.js.map +0 -1
  43. package/dist/guardrails-Dmwi63KB.d.ts +0 -38
  44. package/dist/protocol-adapter-APRjs1E2.d.ts +0 -273
  45. package/dist/runtime-DC5XQ9Cc.d.ts +0 -351
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devlab.group/agent-commerce",
3
- "version": "1.5.0",
3
+ "version": "1.6.1",
4
4
  "description": "Open-source, self-hosted, non-custodial commerce and payment orchestration gateway for AI agents.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -110,7 +110,7 @@
110
110
  "ajv-formats": "3.0.1",
111
111
  "better-sqlite3": "13.0.3",
112
112
  "commander": "15.0.0",
113
- "fastify": "5.12.0",
113
+ "fastify": "5.12.5",
114
114
  "picocolors": "1.1.1",
115
115
  "pino": "10.3.1",
116
116
  "yaml": "2.9.0",
@@ -167,7 +167,7 @@
167
167
  "@types/react": "19.2.18",
168
168
  "@types/react-dom": "19.2.4",
169
169
  "@vitejs/plugin-react": "6.0.5",
170
- "@vitest/coverage-v8": "4.1.10",
170
+ "@vitest/coverage-v8": "4.1.11",
171
171
  "@x402/core": "2.23.0",
172
172
  "@x402/evm": "2.23.0",
173
173
  "canonicalize": "5.0.0",
@@ -181,11 +181,13 @@
181
181
  "typescript": "5.9.3",
182
182
  "viem": "2.55.18",
183
183
  "vite": "8.2.1",
184
- "vitest": "4.1.10"
184
+ "vitest": "4.1.11"
185
185
  },
186
186
  "overrides": {
187
187
  "@coinbase/x402": {
188
- "zod": "3.25.76"
188
+ "zod": "3.25.76",
189
+ "@coinbase/cdp-sdk": "1.55.0",
190
+ "axios": "1.20.0"
189
191
  },
190
192
  "@sd-jwt/core": {
191
193
  "@owf/identity-common": "0.3.2"
@@ -1,123 +0,0 @@
1
- import { f as AuthorizationMethodName, A as AdapterDescriptor, m as PaymentRequirement, c as AdapterHealth } from './runtime-DC5XQ9Cc.js';
2
-
3
- /**
4
- * Canonical authorization model.
5
- *
6
- * FROZEN CONTRACT.
7
- *
8
- * Authorization answers a different question from payment. Payment proves
9
- * that funds moved; authorization proves that the human behind the agent
10
- * approved *this exact purchase*. A valid authorization never unlocks a paid
11
- * resource on its own and never moves money. It gates settlement, and a
12
- * resource that requires one still needs a real payment proof as well.
13
- *
14
- * Core decides *that* a resource requires authorization and *when* in the
15
- * pipeline it is checked. Authorization providers decide how a submission is
16
- * parsed, verified and bound to the purchase. No AP2, SD-JWT or JWT type may
17
- * appear in this file.
18
- */
19
-
20
- /**
21
- * Opaque authorization proof supplied by the buyer's client.
22
- *
23
- * Over HTTP this arrives base64url-JSON-encoded in the `Agent-Authorization`
24
- * header; over MCP and A2A it is the same `{ method, payload }` object carried
25
- * in the reserved `_authorization` input field.
26
- *
27
- * `payload` is preserved byte-for-byte from the wire. It is opaque to transport
28
- * adapters and may contain signed or encoding-sensitive provider data, so they
29
- * must not normalise it before passing it to the provider.
30
- */
31
- interface AuthorizationSubmission {
32
- readonly method: AuthorizationMethodName;
33
- readonly payload: string;
34
- }
35
- /**
36
- * What a buyer must present, advertised alongside the payment challenge so a
37
- * client learns before it pays that a proof of payment alone will not do.
38
- *
39
- * The gateway never issues the authorization itself. It states the method,
40
- * the spec version it verifies against, and the payload profile it expects.
41
- */
42
- interface AuthorizationRequirement {
43
- readonly method: AuthorizationMethodName;
44
- readonly version: string;
45
- readonly profile?: string;
46
- }
47
- /**
48
- * Safe audit identity of an authorization, fit for a receipt. `reference` is a
49
- * digest: a receipt outlives its request, and a stored proof would be a
50
- * spendable secret at rest.
51
- */
52
- interface AuthorizationRecord {
53
- readonly method: AuthorizationMethodName;
54
- readonly reference: string;
55
- /** Safe audit summary only. Never the proof, its disclosures, or PII */
56
- readonly metadata?: Readonly<Record<string, unknown>>;
57
- }
58
- /**
59
- * A verified, reserved authorization. `reservationId` is the live handle the
60
- * pipeline consumes, releases or marks uncertain once settlement resolves; it
61
- * stays out of the record above because a handle is not an audit fact.
62
- */
63
- interface AuthorizationVerification extends AuthorizationRecord {
64
- readonly status: 'verified';
65
- readonly reservationId: string;
66
- }
67
- /** Input to {@link AuthorizationProvider.verifyAndReserve}. */
68
- interface AuthorizationVerificationContext {
69
- readonly requestId: string;
70
- readonly resourceId: string;
71
- /**
72
- * The validated resource input, reserved fields already stripped: the same
73
- * bytes the merchant backend will be called with. A provider that binds a
74
- * proof to the request hashes this, so it must not include `_payment`,
75
- * `_authorization`, the request id or any transport metadata.
76
- */
77
- readonly input: unknown;
78
- readonly submission: AuthorizationSubmission;
79
- /** The resolved price and destination the proof must match. */
80
- readonly requirement: PaymentRequirement;
81
- }
82
- /** Input to {@link AuthorizationProvider.consume} and `release`. */
83
- interface AuthorizationFinalizeContext {
84
- readonly requestId: string;
85
- readonly resourceId: string;
86
- }
87
- /**
88
- * Contract every authorization method implements.
89
- *
90
- * The lifecycle straddles settlement: a proof must be reserved *before* funds
91
- * move so a replay cannot race one, and its fate is only known *after*.
92
- *
93
- * Release only for a failure that provably moved no money. Anything ambiguous
94
- * is marked uncertain: a proof handed back after a settlement that may have
95
- * landed can be spent twice.
96
- */
97
- interface AuthorizationProvider {
98
- readonly name: AuthorizationMethodName;
99
- readonly descriptor: AdapterDescriptor;
100
- /** What a buyer must present, advertised beside the payment challenge */
101
- readonly requirement: AuthorizationRequirement;
102
- /**
103
- * Verify a submission against the resolved purchase and atomically reserve
104
- * it against reuse.
105
- *
106
- * Throws a `CommerceError` with an `AUTHORIZATION_*` code, never a payment
107
- * code. A verifier or store outage is
108
- * `AUTHORIZATION_PROVIDER_UNAVAILABLE`, not the buyer's fault.
109
- */
110
- verifyAndReserve(context: AuthorizationVerificationContext): Promise<AuthorizationVerification>;
111
- /** Mark a reservation permanently spent. Called after settlement succeeds. */
112
- consume(reservationId: string, context: AuthorizationFinalizeContext): Promise<void>;
113
- /** Return a reservation to unused. Only for failures that moved no funds. */
114
- release(reservationId: string, context: AuthorizationFinalizeContext): Promise<void>;
115
- /**
116
- * Settlement broadcast but never confirmed: neither spend the reservation
117
- * nor hand it back, and flag it for an operator
118
- */
119
- markUncertain(reservationId: string, context: AuthorizationFinalizeContext): Promise<void>;
120
- health(): Promise<AdapterHealth>;
121
- }
122
-
123
- export type { AuthorizationProvider as A, AuthorizationRequirement as a, AuthorizationSubmission as b, AuthorizationFinalizeContext as c, AuthorizationRecord as d, AuthorizationVerification as e, AuthorizationVerificationContext as f };
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/domain/common.ts","../src/core/domain/event.ts","../src/core/domain/resource.ts","../src/core/errors/codes.ts","../src/core/errors/commerce-error.ts","../src/core/domain/wire.ts","../src/core/interfaces/logger.ts","../src/core/interfaces/protocol-adapter.ts","../src/core/interfaces/runtime.ts","../src/version.ts"],"names":[],"mappings":"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","file":"chunk-5GEWKNIH.js","sourcesContent":["/**\n * Shared primitive aliases used across the canonical domain model.\n *\n * FROZEN CONTRACT. Every consumer codes against these shapes; changing one\n * is a breaking change.\n */\n\n/**\n * A JSON Schema document (draft 2020-12 subset in practice).\n *\n * Deliberately loose: protocol adapters translate this to their own schema\n * representation, and the gateway only validates structurally at trust\n * boundaries. Never treat this as trusted input without validation.\n */\nexport type JsonSchema = Record<string, unknown>;\n\n/**\n * Protocol surfaces a resource can be exposed through.\n *\n * The runtime list is the definition and the type is derived from it, so a\n * caller that has to *check* a name (config validation, the OpenAPI\n * importer's `--expose`) reads the same strings the type is built from\n * rather than keeping a second copy that can drift.\n */\nexport type ProtocolName = 'http' | 'mcp' | 'a2a' | 'acp';\n\n/**\n * The same names as a value, for code that has to *check* one at\n * runtime - config validation, the OpenAPI importer's `--expose`. Typed\n * against `ProtocolName` so an unsupported name cannot enter the list, which\n * is what keeps this from becoming a second definition that drifts.\n */\nexport const PROTOCOL_NAMES: readonly ProtocolName[] = ['http', 'mcp', 'a2a', 'acp'];\n\n/**\n * Payment rails a resource can accept.\n *\n * This is an ordered candidate list, not a buyer-selected menu. The pipeline\n * uses the first method with a configured provider; a rejection ends the\n * request instead of trying another rail. Config requires at least one named\n * rail to be enabled but permits additional unavailable candidates.\n */\nexport type PaymentMethodName = 'x402' | 'mpp';\n\n/**\n * The same names as a value, for config validation, which checks a name at\n * runtime. The annotation rejects an entry that is not a\n * `PaymentMethodName`, but nothing makes the list exhaustive, so a new rail\n * has to be added here as well as to the type.\n */\nexport const PAYMENT_METHOD_NAMES: readonly PaymentMethodName[] = ['x402', 'mpp'];\n\n/**\n * Authorization methods a resource can require.\n *\n * Deliberately not a `ProtocolName` and not a `PaymentMethodName`: an\n * authorization method is neither a transport nor a payment rail. It proves\n * the purchase was approved, and sits beside the payment rather than\n * replacing it.\n */\nexport type AuthorizationMethodName = 'ap2';\n\n/** ISO-8601 timestamp string, always UTC with millisecond precision. */\nexport type IsoTimestamp = string;\n\n/**\n * A decimal amount expressed as a string in the *display* unit of the currency\n * (for example \"0.01\" USDC), never as a float and never in base units.\n *\n * Conversion to on-chain base units is a payment-provider responsibility.\n */\nexport type DecimalAmount = string;\n\n/** Health of an individual adapter or subsystem. */\nexport interface AdapterHealth {\n readonly status: 'pass' | 'warn' | 'fail';\n readonly detail?: string;\n readonly checkedAt: IsoTimestamp;\n readonly durationMs?: number;\n}\n\n/**\n * Describes an adapter's supported surface for diagnostics\n */\nexport interface AdapterDescriptor {\n readonly name: string;\n readonly kind: 'protocol' | 'payment' | 'storage' | 'authorization';\n /** Version of this adapter implementation (independent of the spec). */\n readonly implementationVersion: string;\n /** Exact pinned specification revision this adapter targets. */\n readonly supportedSpec: string;\n readonly capabilities: readonly string[];\n readonly status: 'stable' | 'experimental' | 'planned';\n /** Capabilities explicitly NOT implemented, surfaced by `doctor`. */\n readonly unsupported?: readonly string[];\n}\n","/**\n * Canonical commerce events.\n *\n * FROZEN CONTRACT. Every event in a single flow shares one `requestId` so that\n * logs, payment attempts, backend calls and receipts are correlatable.\n */\nimport type { IsoTimestamp } from './common.js';\n\nexport const COMMERCE_EVENT_TYPES = [\n 'resource.discovered',\n 'resource.requested',\n 'payment.required',\n 'payment.rejected',\n 'payment.verified',\n 'payment.settled',\n // The same two types whatever the method, so an audit-trail reader never\n // has to know what AP2 is\n 'authorization.verified',\n 'authorization.rejected',\n 'backend.called',\n 'backend.failed',\n 'resource.delivered',\n] as const;\n\nexport type CommerceEventType = (typeof COMMERCE_EVENT_TYPES)[number];\n\nexport interface CommerceEvent {\n readonly id: string;\n readonly type: CommerceEventType;\n readonly requestId: string;\n readonly resourceId?: string;\n readonly at: IsoTimestamp;\n /** Protocol adapter that originated the request, e.g. 'mcp' or 'http'. */\n readonly adapter?: string;\n readonly paymentProvider?: string;\n readonly durationMs?: number;\n readonly status?: 'ok' | 'error';\n /** Non-secret, structured detail. Must never contain keys, headers or proofs. */\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\n/**\n * Sink for canonical events.\n *\n * Implementations must be non-throwing from the caller's perspective: an event\n * sink failure must never fail an otherwise successful commerce flow.\n */\nexport interface EventSink {\n emit(event: CommerceEvent): Promise<void>;\n}\n","/**\n * Canonical resource model.\n *\n * FROZEN CONTRACT.\n */\nimport type {\n AuthorizationMethodName,\n DecimalAmount,\n JsonSchema,\n PaymentMethodName,\n ProtocolName,\n} from './common.js';\n\n/** HTTP methods a backend handler may use. */\nexport type BackendMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\n/**\n * Describes how the gateway calls the merchant's existing backend.\n *\n * Backend URLs are administrator-controlled configuration only. User- or\n * agent-controlled backend URLs are forbidden (see docs/security.md, SSRF).\n * Secret header values must come from `${ENV_VAR}` placeholders resolved by\n * the config loader, never from plaintext configuration.\n */\nexport interface BackendHandler {\n readonly type: 'http';\n readonly method: BackendMethod;\n readonly url: string;\n readonly headers?: Readonly<Record<string, string>>;\n /** Hard upper bound on the backend call. Defaults to DEFAULT_BACKEND_TIMEOUT_MS. */\n readonly timeoutMs?: number;\n /**\n * Names the top-level input properties carrying each part of the request.\n *\n * Absent (the default) keeps the original mapping: `{param}` values are read\n * from top-level input and everything left over becomes either the query\n * string (GET/DELETE) or the entire JSON body (POST/PUT/PATCH). That mapping\n * cannot express `POST /users/{userId}/orders?notify=true` with a JSON body\n * - one perfectly ordinary REST operation with all three parts at once.\n *\n * When present, each group is sourced independently and top-level input that\n * no binding names is not forwarded to the backend at all.\n */\n readonly inputBindings?: {\n readonly path?: string;\n readonly query?: string;\n readonly body?: string;\n };\n}\n\n/** Default backend timeout when a resource does not specify one. */\nexport const DEFAULT_BACKEND_TIMEOUT_MS = 10_000;\n\n/**\n * Canonical pricing.\n *\n * `dynamic` exists in the type system for forward compatibility but is\n * REJECTED by config validation in this release.\n */\nexport type Pricing =\n | { readonly type: 'free' }\n | {\n readonly type: 'fixed';\n readonly amount: DecimalAmount;\n readonly currency: string;\n }\n | {\n readonly type: 'dynamic';\n readonly resolver: string;\n };\n\n/**\n * A merchant capability exposed to agents.\n *\n * The canonical resource is the single source of truth: protocol adapters map\n * it outward, they never define their own parallel notion of a resource.\n */\nexport interface CommerceResource {\n readonly id: string;\n readonly name: string;\n readonly description?: string;\n readonly inputSchema?: JsonSchema;\n readonly outputSchema?: JsonSchema;\n readonly handler: BackendHandler;\n readonly pricing: Pricing;\n readonly exposedVia: readonly ProtocolName[];\n readonly paymentMethods: readonly PaymentMethodName[];\n /**\n * Authorization the buyer must present in addition to payment.\n *\n * Opt-in per resource and absent by default, so every resource configured\n * before this existed behaves exactly as it did. It sits beside\n * `paymentMethods` rather than inside it: an authorization method is not a\n * payment rail and must never be selectable as one.\n */\n readonly authorization?: {\n readonly required: readonly AuthorizationMethodName[];\n };\n}\n\n/** Read-only view of every configured resource. */\nexport interface ResourceRegistry {\n get(id: string): CommerceResource | undefined;\n list(): readonly CommerceResource[];\n /** Resources exposed through a given protocol surface. */\n listExposedVia(protocol: ProtocolName): readonly CommerceResource[];\n has(id: string): boolean;\n}\n","/**\n * Typed domain error codes.\n *\n * FROZEN CONTRACT. Protocol adapters map these codes into their own response\n * format. Never throw a bare string or untyped Error across a package boundary.\n */\nexport const COMMERCE_ERROR_CODES = [\n 'CONFIG_INVALID',\n 'RESOURCE_NOT_FOUND',\n 'INPUT_INVALID',\n 'PAYMENT_REQUIRED',\n 'PAYMENT_INVALID',\n 'PAYMENT_REPLAYED',\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n 'PAYMENT_SETTLEMENT_FAILED',\n 'AUTHORIZATION_REQUIRED',\n 'AUTHORIZATION_INVALID',\n 'AUTHORIZATION_REPLAYED',\n 'AUTHORIZATION_PROVIDER_UNAVAILABLE',\n 'BACKEND_TIMEOUT',\n 'BACKEND_ERROR',\n 'PROTOCOL_UNSUPPORTED',\n 'GATEWAY_BUSY',\n 'STORAGE_ERROR',\n 'INTERNAL_ERROR',\n] as const;\n\nexport type CommerceErrorCode = (typeof COMMERCE_ERROR_CODES)[number];\n\n/**\n * Canonical HTTP status for each error code.\n *\n * Paid resources fail closed: every payment failure maps to a 4xx/5xx status\n * and never to a successful delivery.\n */\nexport const COMMERCE_ERROR_HTTP_STATUS: Readonly<Record<CommerceErrorCode, number>> = {\n CONFIG_INVALID: 500,\n RESOURCE_NOT_FOUND: 404,\n INPUT_INVALID: 400,\n PAYMENT_REQUIRED: 402,\n PAYMENT_INVALID: 402,\n PAYMENT_REPLAYED: 409,\n PAYMENT_PROVIDER_UNAVAILABLE: 503,\n PAYMENT_SETTLEMENT_FAILED: 502,\n // 403, not 402: the buyer's money is not the problem. A 402 tells a client\n // \"pay and retry\", which cannot fix a missing or rejected mandate, and a\n // client that auto-pays on 402 would be charged for a request that was\n // never going to be delivered.\n AUTHORIZATION_REQUIRED: 403,\n AUTHORIZATION_INVALID: 403,\n AUTHORIZATION_REPLAYED: 409,\n AUTHORIZATION_PROVIDER_UNAVAILABLE: 503,\n BACKEND_TIMEOUT: 504,\n BACKEND_ERROR: 502,\n PROTOCOL_UNSUPPORTED: 501,\n GATEWAY_BUSY: 503,\n STORAGE_ERROR: 500,\n INTERNAL_ERROR: 500,\n};\n\n/** Codes for which a client may reasonably retry the same request. */\nexport const RETRYABLE_ERROR_CODES: ReadonlySet<CommerceErrorCode> = new Set([\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n // Our verifier or our replay store was unreachable, so no verdict on the\n // mandate was ever reached. That is an outage on our side, and the same\n // proof will verify once it clears.\n 'AUTHORIZATION_PROVIDER_UNAVAILABLE',\n 'BACKEND_TIMEOUT',\n // Load shedding is transient by definition: the caller should back off and\n // try again. Before this code existed the MCP adapter's queue-full path threw\n // PROTOCOL_UNSUPPORTED — HTTP 501, retryable:false — so an agent framework\n // keyed on the machine-readable flag (which exists precisely so clients need\n // not parse prose) would read a momentary throttle as a permanent capability\n // gap and stop calling the tool.\n 'GATEWAY_BUSY',\n]);\n","/**\n * The single error type crossing package boundaries.\n *\n * FROZEN CONTRACT.\n */\nimport {\n COMMERCE_ERROR_HTTP_STATUS,\n type CommerceErrorCode,\n RETRYABLE_ERROR_CODES,\n} from './codes.js';\n\nexport interface CommerceErrorOptions {\n /** Structured, non-secret detail safe to return to a client. */\n readonly details?: Readonly<Record<string, unknown>>;\n readonly cause?: unknown;\n readonly requestId?: string;\n readonly resourceId?: string;\n /** Override the default HTTP status for this code. */\n readonly httpStatus?: number;\n}\n\n/** Serialisable wire form of a CommerceError. */\nexport interface CommerceErrorInfo {\n readonly code: CommerceErrorCode;\n readonly message: string;\n readonly httpStatus: number;\n readonly retryable: boolean;\n readonly requestId?: string;\n readonly resourceId?: string;\n readonly details?: Readonly<Record<string, unknown>>;\n}\n\nexport class CommerceError extends Error {\n readonly code: CommerceErrorCode;\n readonly httpStatus: number;\n readonly retryable: boolean;\n readonly details?: Readonly<Record<string, unknown>>;\n readonly requestId?: string;\n readonly resourceId?: string;\n\n constructor(code: CommerceErrorCode, message: string, options: CommerceErrorOptions = {}) {\n super(message, options.cause !== undefined ? { cause: options.cause } : undefined);\n this.name = 'CommerceError';\n this.code = code;\n this.httpStatus = options.httpStatus ?? COMMERCE_ERROR_HTTP_STATUS[code];\n this.retryable = RETRYABLE_ERROR_CODES.has(code);\n if (options.details !== undefined) this.details = options.details;\n if (options.requestId !== undefined) this.requestId = options.requestId;\n if (options.resourceId !== undefined) this.resourceId = options.resourceId;\n Error.captureStackTrace?.(this, CommerceError);\n }\n\n /** Non-secret, client-safe representation. */\n toInfo(): CommerceErrorInfo {\n return {\n code: this.code,\n message: this.message,\n httpStatus: this.httpStatus,\n retryable: this.retryable,\n ...(this.requestId !== undefined ? { requestId: this.requestId } : {}),\n ...(this.resourceId !== undefined ? { resourceId: this.resourceId } : {}),\n ...(this.details !== undefined ? { details: this.details } : {}),\n };\n }\n}\n\nexport function isCommerceError(value: unknown): value is CommerceError {\n return value instanceof CommerceError;\n}\n\n/**\n * Normalise any thrown value into a CommerceError.\n *\n * Used at package boundaries so an unexpected failure never escapes untyped.\n *\n * SECURITY — do not \"improve\" this by propagating `value.message`.\n * `CommerceError.message` is client-visible: it is serialised by `toInfo()`\n * and `toErrorEnvelope()` and returned over HTTP and MCP. An arbitrary thrown\n * Error's message routinely carries internal detail — database connection\n * strings, internal hostnames, filesystem paths, backend URLs. Copying it into\n * a client-facing field turns every unexpected exception into an information\n * disclosure.\n *\n * The original value is preserved on `cause`, which is never serialised, so\n * logs and diagnostics keep the full detail while clients get only the\n * caller's deliberate, reviewed `fallbackMessage`.\n *\n * A caller that *wants* a specific client-facing message passes one:\n * toCommerceError(err, 'BACKEND_ERROR', 'Backend call failed')\n */\nexport function toCommerceError(\n value: unknown,\n fallbackCode: CommerceErrorCode = 'INTERNAL_ERROR',\n fallbackMessage = 'Unexpected internal error',\n): CommerceError {\n if (isCommerceError(value)) return value;\n return new CommerceError(fallbackCode, fallbackMessage, { cause: value });\n}\n","/**\n * Gateway-defined wire envelopes.\n *\n * FROZEN CONTRACT. These are the *only* representations of \"payment required\"\n * and \"error\" that leave the gateway, whichever protocol carries them. The HTTP\n * routes, the MCP adapter and the demo buyer agent all use these helpers so the\n * three can never drift apart.\n */\n\nimport { CommerceError, type CommerceErrorCode } from '../errors/index.js';\nimport type { AuthorizationRequirement, AuthorizationSubmission } from './authorization.js';\nimport type { DecimalAmount, IsoTimestamp, PaymentMethodName } from './common.js';\nimport type { PaymentSubmission } from './payment.js';\nimport type { DeliveredOutcome, PaymentRequiredOutcome } from './request.js';\nimport type { CommerceResource } from './resource.js';\n\n/**\n * Reserved input property carrying a payment proof on protocols that have no\n * header channel (MCP tool calls). Over HTTP the `PAYMENT-SIGNATURE` header is\n * used.\n */\nexport const PAYMENT_INPUT_FIELD = '_payment';\n\n/**\n * HTTP request header carrying the payment proof.\n *\n * x402 v2 header names, lowercased because that is how Node presents incoming\n * headers. v1's `X-PAYMENT` / `X-PAYMENT-RESPONSE` pair is not accepted: this\n * gateway speaks one protocol version, and quietly honouring both would mean\n * two verification paths for the same money.\n */\nexport const PAYMENT_HEADER = 'payment-signature';\n\n/** HTTP response header carrying the settlement result. */\nexport const PAYMENT_RESPONSE_HEADER = 'payment-response';\n\n/**\n * Reserved input property carrying an authorization proof, the authorization\n * counterpart of {@link PAYMENT_INPUT_FIELD}.\n *\n * Unlike `_payment`, which is a bare string, this one carries an object:\n * `{ method, payload }`. There is exactly one payment rail per resource, so a\n * payment proof's method can be inferred from the resource; an authorization\n * proof cannot lean on that, and guessing the method of a security control is\n * not a thing to do implicitly.\n */\nexport const AUTHORIZATION_INPUT_FIELD = '_authorization';\n\n/**\n * Every input property name the gateway claims for itself.\n *\n * One list, read by the config loader (which rejects a resource declaring any\n * of them), by the protocol adapters that lift them out of client input, and\n * by the pipeline that strips them again as defence in depth. Those three\n * agree by construction instead of by three copies of two strings.\n */\nexport const RESERVED_INPUT_FIELDS: readonly string[] = [\n PAYMENT_INPUT_FIELD,\n AUTHORIZATION_INPUT_FIELD,\n];\n\n/**\n * HTTP request header carrying the authorization proof, base64url-encoded\n * JSON of the same `{ method, payload }` envelope the reserved input field\n * carries.\n *\n * This is an Agent Commerce transport carrier, not a header defined by any\n * authorization specification, so it is namespaced rather than borrowing\n * `Authorization`, which already means something else on every one of these\n * routes.\n */\nexport const AUTHORIZATION_HEADER = 'agent-authorization';\n\n/**\n * Hard cap on the encoded `Agent-Authorization` header.\n *\n * Node's own limit is ~16 KiB across *all* request headers, so an\n * authorization near that size would start evicting everything else and fail\n * as an unreadable transport error rather than a legible one. Capping well\n * below it means an oversized proof gets a deterministic\n * AUTHORIZATION_INVALID naming the limit.\n */\nexport const MAX_AUTHORIZATION_HEADER_BYTES = 8192;\n\n/**\n * HTTP response header carrying the base64 payment challenge on a 402.\n *\n * The 402 body still carries {@link PaymentRequiredEnvelope} — richer, and the\n * only channel MCP has — but an x402 v2 client reads the challenge from this\n * header and ignores the body, so both are sent.\n */\nexport const PAYMENT_REQUIRED_HEADER = 'payment-required';\n\n/**\n * Key under which a protocol adapter attaches a {@link DeliverySummary} to its\n * result metadata — MCP's `CallToolResult._meta`, and anywhere else a protocol\n * offers an out-of-band metadata channel.\n *\n * Frozen deliberately. The bug this whole mechanism exists to fix was two\n * surfaces disagreeing about what a payer gets back; a key name enforced only\n * by one side's tests would reintroduce exactly that drift. Producer and\n * consumer both import this constant.\n *\n * Follows MCP's `<namespace>/<name>` convention for `_meta` keys.\n */\nexport const DELIVERY_SUMMARY_META_KEY = 'agent-commerce/delivery';\n\nexport interface PaymentRequiredEnvelope {\n readonly status: 'payment-required';\n readonly code: 'PAYMENT_REQUIRED';\n readonly requestId: string;\n readonly resourceId: string;\n readonly message: string;\n readonly payment: {\n readonly provider: PaymentMethodName;\n readonly version: string;\n readonly amount: DecimalAmount;\n readonly currency: string;\n readonly destination: string;\n readonly network?: string;\n readonly asset?: string;\n readonly expiresAt?: IsoTimestamp;\n /** Provider-native requirement objects, passed through verbatim. */\n readonly accepts: readonly Readonly<Record<string, unknown>>[];\n /**\n * The provider's own challenge document, verbatim — see\n * {@link PaymentChallenge.envelope}. Present for providers that have one;\n * a buyer's protocol client can hand this straight to its SDK.\n */\n readonly envelope?: Readonly<Record<string, unknown>>;\n };\n /**\n * Present only when the resource requires an authorization proof as well.\n *\n * Additive: a client that does not understand the field sees exactly the\n * envelope it saw before. A client that does learns, before it spends\n * anything, that paying alone will not get the resource delivered.\n *\n * This advertises a requirement; it does not issue anything. The proof is\n * obtained from the merchant's own approval flow, outside the gateway.\n */\n readonly authorization?: {\n readonly required: readonly AuthorizationRequirement[];\n };\n}\n\nexport interface ErrorEnvelope {\n readonly status: 'error';\n readonly code: CommerceErrorCode;\n readonly message: string;\n readonly retryable: boolean;\n readonly requestId?: string;\n readonly resourceId?: string;\n readonly details?: Readonly<Record<string, unknown>>;\n}\n\n/**\n * What a buyer learns about their own completed purchase.\n *\n * A payer is entitled to the record of their own transaction — the request it\n * belonged to, whether it settled, and the settlement reference they can check\n * on-chain. They are NOT entitled to the merchant's ledger, which is why\n * `/api/receipts` is an operator route behind `server.adminToken`.\n *\n * Before this existed the two surfaces disagreed: HTTP callers received a\n * settlement summary in the payment-response header while MCP callers received\n * nothing, so an MCP buyer's only route to their own receipt was the merchant's\n * ledger. Both surfaces now emit this same shape.\n */\nexport interface DeliverySummary {\n readonly requestId: string;\n readonly resourceId: string;\n readonly receiptId: string;\n readonly deliveredAt: IsoTimestamp;\n readonly payment?: {\n readonly status: 'verified' | 'settled' | 'rejected';\n readonly amount: DecimalAmount;\n readonly currency: string;\n /** Settlement reference, e.g. an on-chain transaction hash. */\n readonly externalReference?: string;\n readonly network?: string;\n };\n}\n\n/** Build the payer-facing summary of a delivered outcome. */\nexport function toDeliverySummary(outcome: DeliveredOutcome): DeliverySummary {\n const p = outcome.payment;\n return {\n requestId: outcome.requestId,\n resourceId: outcome.resourceId,\n receiptId: outcome.receipt.id,\n deliveredAt: outcome.receipt.deliveredAt,\n ...(p !== undefined\n ? {\n payment: {\n status: p.status,\n amount: p.amount,\n currency: p.currency,\n ...(p.externalReference !== undefined\n ? { externalReference: p.externalReference }\n : {}),\n ...(p.network !== undefined ? { network: p.network } : {}),\n },\n }\n : {}),\n };\n}\n\nexport function toPaymentRequiredEnvelope(\n outcome: PaymentRequiredOutcome,\n): PaymentRequiredEnvelope {\n const r = outcome.requirement;\n return {\n status: 'payment-required',\n code: 'PAYMENT_REQUIRED',\n requestId: outcome.requestId,\n resourceId: outcome.resourceId,\n message: `Payment of ${r.amount} ${r.currency} is required for resource \"${outcome.resourceId}\". Retry with a ${r.provider} payment proof.`,\n payment: {\n provider: r.provider,\n version: r.challenge.version,\n amount: r.amount,\n currency: r.currency,\n destination: r.destination,\n ...(r.network !== undefined ? { network: r.network } : {}),\n ...(r.asset !== undefined ? { asset: r.asset } : {}),\n ...(r.expiresAt !== undefined ? { expiresAt: r.expiresAt } : {}),\n accepts: r.challenge.accepts,\n ...(r.challenge.envelope !== undefined ? { envelope: r.challenge.envelope } : {}),\n },\n ...(outcome.authorization !== undefined && outcome.authorization.length > 0\n ? { authorization: { required: outcome.authorization } }\n : {}),\n };\n}\n\nexport function toErrorEnvelope(error: CommerceError): ErrorEnvelope {\n const info = error.toInfo();\n return {\n status: 'error',\n code: info.code,\n message: info.message,\n retryable: info.retryable,\n ...(info.requestId !== undefined ? { requestId: info.requestId } : {}),\n ...(info.resourceId !== undefined ? { resourceId: info.resourceId } : {}),\n ...(info.details !== undefined ? { details: info.details } : {}),\n };\n}\n\nexport function isPaymentRequiredEnvelope(value: unknown): value is PaymentRequiredEnvelope {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as PaymentRequiredEnvelope).status === 'payment-required' &&\n typeof (value as PaymentRequiredEnvelope).payment === 'object'\n );\n}\n\n/**\n * Parses the `{ method, payload }` authorization envelope, whichever carrier\n * brought it.\n *\n * Absent is `undefined`. Present but malformed throws, rather than being\n * dropped the way an unusable `_payment` is. A dropped payment leaves the\n * buyer holding a 402 they can act on. A silently dropped authorization would\n * come back as \"not authorized\" for a proof the client believes it sent, with\n * no way to tell a rejected mandate from a typo in the envelope around it.\n */\nexport function parseAuthorizationSubmission(\n value: unknown,\n requestId?: string,\n): AuthorizationSubmission | undefined {\n if (value === undefined || value === null) return undefined;\n\n const fail = (detail: string): never => {\n throw new CommerceError('AUTHORIZATION_INVALID', `Malformed authorization: ${detail}`, {\n ...(requestId !== undefined ? { requestId } : {}),\n });\n };\n\n if (typeof value !== 'object' || Array.isArray(value)) {\n fail(`expected an object with \"method\" and \"payload\", got ${typeof value}`);\n }\n const record = value as Record<string, unknown>;\n const method = record['method'];\n const payload = record['payload'];\n\n // 'ap2' is the only method in this release. Compared against the literal\n // rather than a registry: a second method means a second verifier, and that\n // is a deliberate addition, not a string that should start working because\n // a client sent it.\n if (method !== 'ap2') {\n fail(`unsupported method ${typeof method === 'string' ? `\"${method}\"` : typeof method}`);\n }\n if (typeof payload !== 'string' || payload.length === 0) {\n fail('\"payload\" must be a non-empty string');\n }\n\n return { method: 'ap2', payload: payload as string };\n}\n\n/**\n * Decodes the base64url-JSON `Agent-Authorization` header.\n *\n * The size check runs on the encoded value before any decoding, so an\n * oversized header costs a length comparison rather than a base64 decode and\n * a JSON parse of whatever a caller chose to send.\n */\nexport function parseAuthorizationHeader(\n raw: string | readonly string[] | undefined,\n requestId?: string,\n): AuthorizationSubmission | undefined {\n const value = Array.isArray(raw) ? raw[0] : (raw as string | undefined);\n if (value === undefined || value.length === 0) return undefined;\n\n const fail = (detail: string): never => {\n throw new CommerceError('AUTHORIZATION_INVALID', `Malformed authorization: ${detail}`, {\n ...(requestId !== undefined ? { requestId } : {}),\n });\n };\n\n if (Buffer.byteLength(value, 'utf8') > MAX_AUTHORIZATION_HEADER_BYTES) {\n fail(`header exceeds the ${MAX_AUTHORIZATION_HEADER_BYTES}-byte limit`);\n }\n\n let decoded: unknown;\n try {\n decoded = JSON.parse(Buffer.from(value, 'base64url').toString('utf8'));\n } catch {\n // Nothing from the exception is repeated back: a JSON parse error quotes\n // the input it choked on, which here is whatever the caller sent.\n fail('header is not base64url-encoded JSON');\n }\n return parseAuthorizationSubmission(decoded, requestId);\n}\n\n/**\n * Splits raw client input into resource input plus the reserved fields the\n * gateway claims, for every protocol that carries them in the input object\n * (MCP tool arguments, A2A message data). HTTP carries both in headers and\n * uses the two parse helpers directly.\n *\n * A payment proof is labelled with the resource's first method. `createGateway`\n * puts provider-backed methods first so the label matches pipeline selection;\n * custom registries must preserve that ordering. Without a method, the proof is\n * dropped and the pipeline receives an unpaid request.\n */\nexport function extractReservedInputFields(\n rawInput: Record<string, unknown>,\n resource: CommerceResource | undefined,\n requestId?: string,\n): {\n input: Record<string, unknown>;\n payment?: PaymentSubmission;\n authorization?: AuthorizationSubmission;\n} {\n const {\n [PAYMENT_INPUT_FIELD]: paymentValue,\n [AUTHORIZATION_INPUT_FIELD]: authorizationValue,\n ...input\n } = rawInput;\n\n const method = resource?.paymentMethods[0];\n const payment =\n typeof paymentValue === 'string' && paymentValue.length > 0 && method !== undefined\n ? ({ method, payload: paymentValue } satisfies PaymentSubmission)\n : undefined;\n const authorization = parseAuthorizationSubmission(authorizationValue, requestId);\n\n return {\n input,\n ...(payment !== undefined ? { payment } : {}),\n ...(authorization !== undefined ? { authorization } : {}),\n };\n}\n","/**\n * Minimal structural logger interface.\n *\n * Core must not depend on pino directly; the gateway injects a pino instance\n * that satisfies this shape. Never log secrets: private keys, seed phrases,\n * Authorization headers or payment authorisation payloads.\n */\nexport interface Logger {\n debug(obj: Record<string, unknown>, msg?: string): void;\n info(obj: Record<string, unknown>, msg?: string): void;\n warn(obj: Record<string, unknown>, msg?: string): void;\n error(obj: Record<string, unknown>, msg?: string): void;\n child(bindings: Record<string, unknown>): Logger;\n}\n\n/** A logger that discards everything. Useful in unit tests. */\nexport const NOOP_LOGGER: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n child: () => NOOP_LOGGER,\n};\n","/**\n * Protocol adapter boundary.\n *\n * FROZEN CONTRACT. An adapter translates a protocol's wire format into a\n * `CanonicalRequest`, hands it to the execution pipeline and maps the outcome\n * back. It must not call merchant backends, implement payment logic, or hold\n * its own copy of the canonical model.\n *\n * Adapter isolation: a failure while starting or serving one adapter must not\n * prevent the others from operating.\n */\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { AdapterDescriptor, AdapterHealth, ProtocolName } from '../domain/common.js';\nimport type { EventSink } from '../domain/event.js';\nimport type { ExecutionPipeline } from '../domain/request.js';\nimport type { ResourceRegistry } from '../domain/resource.js';\nimport type { Logger } from './logger.js';\nimport type { Clock, IdGenerator } from './runtime.js';\n\n/** Everything an adapter is given. Nothing else is available to it. */\nexport interface ProtocolAdapterContext {\n readonly pipeline: ExecutionPipeline;\n readonly resources: ResourceRegistry;\n readonly events: EventSink;\n readonly logger: Logger;\n readonly clock: Clock;\n readonly ids: IdGenerator;\n /** Externally reachable base URL of the gateway, from config. */\n readonly publicBaseUrl: string;\n}\n\nexport interface ProtocolAdapter {\n readonly name: ProtocolName;\n readonly descriptor: AdapterDescriptor;\n\n start(context: ProtocolAdapterContext): Promise<void>;\n health(): Promise<AdapterHealth>;\n stop(): Promise<void>;\n}\n\n/**\n * A protocol adapter served over HTTP.\n *\n * The gateway mounts `handleHttp` at `mountPath` using raw Node request and\n * response objects, so adapters stay independent of the HTTP framework.\n *\n * GUARANTEE — the request body is **unconsumed**.\n *\n * `req` is handed over with its stream unread: the gateway suppresses every\n * body parser on this mount, so an adapter whose SDK reads the body itself\n * (MCP's Streamable HTTP transport does) can do so. The adapter owns reading,\n * size-limiting beyond the gateway's own cap, and parsing.\n *\n * This is load-bearing and easy to break silently. Fastify pre-registers\n * exact-match parsers for `application/json` and `text/plain` and prefers them\n * over a `'*'` wildcard, so registering only a wildcard no-op leaves the\n * built-in JSON parser draining the body first — the adapter then reads an\n * empty stream and every request fails to parse. That exact regression shipped\n * once and no unit test caught it, because adapter conformance suites drive\n * `handleHttp` over a bare `node:http` server and never traverse the gateway.\n *\n * Any change to how adapters are mounted must be covered by a test that POSTs\n * a real JSON body through the real gateway and asserts the adapter received\n * it intact.\n */\nexport interface HttpProtocolAdapter extends ProtocolAdapter {\n /** Path prefix the gateway mounts this adapter at, e.g. '/mcp'. */\n readonly mountPath: string;\n handleHttp(req: IncomingMessage, res: ServerResponse): Promise<void>;\n /**\n * Fixed paths this adapter owns *outside* its mount, for protocols whose\n * specification pins a discovery URL (A2A's `/.well-known/agent-card.json`).\n * The gateway mounts them with the same guarantees as `mountPath` — same\n * unconsumed body, same concurrency cap, same failure isolation — so the\n * gateway needs no per-protocol routing knowledge.\n *\n * Omitted by adapters that need none.\n */\n readonly additionalHttpRoutes?: readonly AdapterHttpRoute[];\n}\n\n/**\n * One fixed, method-scoped route owned by an adapter. Unlike `mountPath` it\n * registers no wildcard: it matches exactly the path given.\n */\nexport interface AdapterHttpRoute {\n readonly method: 'GET' | 'POST';\n /** Absolute gateway path, e.g. '/.well-known/agent-card.json'. */\n readonly path: string;\n handleHttp(req: IncomingMessage, res: ServerResponse): Promise<void>;\n}\n\nexport function isHttpProtocolAdapter(adapter: ProtocolAdapter): adapter is HttpProtocolAdapter {\n return typeof (adapter as HttpProtocolAdapter).handleHttp === 'function';\n}\n","/**\n * Injected runtime primitives.\n *\n * Everything non-deterministic (time, ids) is injected so tests can be exact.\n */\nimport type { IsoTimestamp } from '../domain/common.js';\n\nexport interface Clock {\n now(): Date;\n nowIso(): IsoTimestamp;\n /** Milliseconds since an arbitrary origin; use for durations only. */\n monotonicMs(): number;\n}\n\nexport interface IdGenerator {\n /** Opaque, collision-resistant identifier. */\n next(prefix?: string): string;\n}\n\nexport const systemClock: Clock = {\n now: () => new Date(),\n nowIso: () => new Date().toISOString(),\n monotonicMs: () => performance.now(),\n};\n","/**\n * The package version, resolved once for the whole package.\n *\n * Two paths, deliberately:\n *\n * - **Development** reads the root manifest, so the number is always live.\n * - **The published bundle cannot.** tsup collapses `src/**` into\n * `dist/index.js` and `dist/cli/index.js`, so any `require('../../package.json')`\n * written against a source path resolves from the wrong depth once bundled —\n * which is exactly how this broke during the single-package refactor, and how\n * it earlier produced a CLI reporting `v0.0.0-unknown`. The build injects\n * `__OAC_PACKAGE_VERSION__` instead (see tsup.config.ts).\n *\n * `typeof` on an undeclared identifier is safe in JS, so the dev path is\n * unaffected by the constant not existing.\n */\nimport { createRequire } from 'node:module';\n\ndeclare const __OAC_PACKAGE_VERSION__: string | undefined;\n\nfunction readFromManifest(): string {\n try {\n const require = createRequire(import.meta.url);\n // src/version.ts -> repository root\n return (require('../package.json') as { version?: string }).version ?? '0.0.0-unknown';\n } catch {\n return '0.0.0-unknown';\n }\n}\n\nexport const PACKAGE_VERSION: string =\n typeof __OAC_PACKAGE_VERSION__ === 'string' ? __OAC_PACKAGE_VERSION__ : readFromManifest();\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/payments/x402/amount.ts","../src/payments/x402/chain.ts","../src/payments/x402/facilitator.ts","../src/payments/x402/payload.ts","../src/payments/x402/replay-key.ts","../src/payments/x402/provider.ts"],"names":[],"mappings":"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","file":"chunk-NKNXVDHN.js","sourcesContent":["/**\n * Deterministic decimal <-> base-unit conversion.\n *\n * `DecimalAmount` (see src/core) is a decimal string in\n * *display* units (\"0.01\" USDC). x402 / EIP-3009 need base units (integer\n * string, e.g. \"10000\" for 0.01 USDC at 6 decimals). This conversion must\n * never go through a JS `number` — floating point cannot represent most\n * decimal fractions exactly, and a silently-rounded payment amount is a\n * security bug in a payment provider.\n *\n * viem's own `parseUnits` rounds silently when given more fractional digits\n * than `decimals` supports; we need a hard error instead (a merchant asking\n * for \"0.0000001\" against a 6-decimal asset is a configuration bug, not a\n * roundable amount), so this module implements its own strict parser.\n */\nimport { CommerceError } from '../../core/index.js';\n\nconst DECIMAL_STRING_PATTERN = /^\\d+(?:\\.\\d+)?$/;\n\n/**\n * Parses a canonical decimal display amount (e.g. \"0.01\") into base units\n * for an asset with the given number of decimals, without floating point.\n *\n * Throws `CommerceError('PAYMENT_INVALID')` if the string is not a plain\n * non-negative decimal, or if it carries more fractional digits than the\n * asset supports.\n */\nexport function parseCanonicalAmount(amount: string, decimals: number): bigint {\n if (!Number.isInteger(decimals) || decimals < 0) {\n throw new CommerceError('INTERNAL_ERROR', `Invalid asset decimals: ${decimals}`);\n }\n if (!DECIMAL_STRING_PATTERN.test(amount)) {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n `Amount \"${amount}\" is not a valid non-negative decimal string`,\n {\n details: { amount },\n },\n );\n }\n\n const [integerPart = '0', fractionPart = ''] = amount.split('.');\n\n if (fractionPart.length > decimals) {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n `Amount \"${amount}\" has more precision than the asset supports (${decimals} decimals)`,\n { details: { amount, assetDecimals: decimals } },\n );\n }\n\n const paddedFraction = fractionPart.padEnd(decimals, '0');\n const combined = `${integerPart}${paddedFraction}`;\n // Strip leading zeros so BigInt doesn't choke on e.g. \"007\" — BigInt() is\n // fine with leading zeros in decimal strings, but normalise defensively.\n return BigInt(combined);\n}\n\n/**\n * Formats base units back into a canonical decimal display string.\n *\n * Exact (no rounding is possible going from integer base units to a wider\n * decimal representation), so this is safe to implement directly.\n */\nexport function formatCanonicalAmount(baseUnits: bigint, decimals: number): string {\n if (!Number.isInteger(decimals) || decimals < 0) {\n throw new CommerceError('INTERNAL_ERROR', `Invalid asset decimals: ${decimals}`);\n }\n const negative = baseUnits < 0n;\n const abs = negative ? -baseUnits : baseUnits;\n const digits = abs.toString().padStart(decimals + 1, '0');\n const integerPart = digits.slice(0, digits.length - decimals) || '0';\n const fractionPart = digits.slice(digits.length - decimals).replace(/0+$/, '');\n const sign = negative ? '-' : '';\n return fractionPart.length > 0\n ? `${sign}${integerPart}.${fractionPart}`\n : `${sign}${integerPart}`;\n}\n","/**\n * Local deterministic chain wiring.\n *\n * The x402 SDK resolves RPC endpoints for public networks from its own\n * tables — exactly what we must never touch: the tests must stay\n * deterministic. Instead we build plain viem clients pointed at\n * `options.rpcUrl`, using a custom `Chain` object whose id is 84532, the\n * chain id carried by the CAIP-2 network identifier the gateway advertises\n * (`eip155:84532`).\n *\n * The `Local` prefix on everything here describes the *chain* these clients\n * are built for, not a test-only status: `provider.ts` calls\n * `createLocalPublicClient` and `createLocalFacilitatorClient` on the real\n * settlement path, and this is not demo scaffolding a production build could\n * drop.\n *\n * Public networks are supported, and `buildLocalChain` now takes the chain id\n * as a parameter — exactly what this comment used to say would be required.\n * What stays local is the *facilitator* client: signing in-process is refused\n * on any mainnet, so that client can only ever exist on the dev chain. The\n * read-only health client is built for whatever network is configured.\n *\n * `dev-key-guard.ts` is the boundary that keeps that arrangement safe: it\n * refuses at provider construction if a dev key or dev `payTo` is pointed at\n * anything other than a loopback/private RPC.\n */\nimport {\n type Account,\n type Chain,\n type Client,\n createPublicClient,\n createWalletClient,\n http,\n type PublicActions,\n type PublicClient,\n publicActions,\n type Transport,\n type WalletActions,\n} from 'viem';\nimport { privateKeyToAccount } from 'viem/accounts';\n\n/** A wallet client that can also read chain state — matches x402's `SignerWallet`. */\nexport type LocalFacilitatorClient = Client<\n Transport,\n Chain,\n Account,\n undefined,\n PublicActions<Transport, Chain, Account> & WalletActions<Chain, Account>\n>;\n\n/**\n * Chain id of the local deterministic dev chain. Shared with the public Base\n * Sepolia testnet, which is why nothing may infer \"this is a public network\"\n * from the id alone — `provider.ts` probes for a real Anvil node instead.\n */\nexport const LOCAL_CHAIN_ID = 84532;\n\n/** CAIP-2 identifier the local dev chain is advertised under. */\nexport const LOCAL_NETWORK = `eip155:${LOCAL_CHAIN_ID}`;\n\n/**\n * Chain id carried by a CAIP-2 `eip155` network identifier.\n *\n * x402 v2 identifies networks as CAIP-2 strings rather than the v1 name table,\n * so the chain id a signature is bound to is read straight off the wire value\n * instead of looked up. Returns `undefined` for anything that is not an\n * `eip155` identifier — a caller must never fall back to a default chain id,\n * because the chain id is part of the EIP-712 domain a buyer signed.\n */\nexport function chainIdFromCaip2(network: string): number | undefined {\n const match = /^eip155:(\\d+)$/.exec(network);\n if (!match?.[1]) return undefined;\n const chainId = Number(match[1]);\n return Number.isSafeInteger(chainId) && chainId > 0 ? chainId : undefined;\n}\n\n/**\n * `chainId` defaults to the local dev chain because the *facilitator* client\n * can only ever exist there — a local facilitator is refused on any mainnet.\n * The read-only health client is different: it is built for whatever network\n * is configured, including Base, and inherited 84532 on every one of them.\n * Inert while it only issues raw `getChainId`/`getCode`/`anvil_nodeInfo`, and\n * wrong the moment anything through it consults `chain.id`.\n */\nexport function buildLocalChain(rpcUrl: string, chainId: number = LOCAL_CHAIN_ID): Chain {\n return {\n id: chainId,\n name: 'agent-commerce-local',\n nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },\n rpcUrls: {\n default: { http: [rpcUrl] },\n },\n } satisfies Chain;\n}\n\n/**\n * A viem `PublicClient` for the local chain — read-only, no signing capability.\n *\n * `timeoutMs`, when given, is passed straight to viem's `http()` transport,\n * which ties it to a real `AbortController` around the underlying `fetch`\n * (see viem's `utils/promise/withTimeout.js` — `signal: true`). That is a\n * genuine cancellation, unlike a bare `Promise.race` against a timer, which\n * only stops *waiting* for the request while the request itself keeps\n * running server-side. Omit it to keep viem's own default (10s).\n */\nexport function createLocalPublicClient(\n rpcUrl: string,\n timeoutMs?: number,\n chainId?: number,\n): PublicClient {\n return createPublicClient({\n chain: buildLocalChain(rpcUrl, chainId),\n transport: http(rpcUrl, timeoutMs !== undefined ? { timeout: timeoutMs } : undefined),\n });\n}\n\n/**\n * A viem `WalletClient` extended with public actions, for the local\n * facilitator signer only. x402's `settle()` calls `writeContract`,\n * `waitForTransactionReceipt` and `getCode` on this client — i.e. it needs\n * both `WalletActions` and `PublicActions`, matching x402's `SignerWallet`\n * type.\n *\n * LOCAL DEVELOPMENT ONLY — the private key behind this client must always be\n * an Anvil well-known development key, never a merchant or buyer key, and\n * never a production key of any kind.\n */\nexport function createLocalFacilitatorClient(\n rpcUrl: string,\n signerPrivateKey: `0x${string}`,\n): LocalFacilitatorClient {\n const chain = buildLocalChain(rpcUrl);\n const account = privateKeyToAccount(signerPrivateKey);\n return createWalletClient({\n account,\n chain,\n transport: http(rpcUrl),\n }).extend(publicActions);\n}\n","/**\n * The facilitator seam.\n *\n * A facilitator is whatever verifies an authorisation and broadcasts the\n * transfer. This gateway supports two, behind one interface:\n *\n * local the SDK's in-process `x402Facilitator` signing against a dev node\n * remote an HTTP facilitator, with or without a credential\n *\n * Both are the SDK's own `FacilitatorClient` contract underneath, so neither\n * is a bespoke reimplementation of the protocol — the local one is the same\n * code a hosted facilitator runs, pointed at the local chain.\n *\n * A *session* is opened per verify/settle call rather than reused, because\n * `transportFailed()` has to be scoped to one request: two concurrent\n * payments must not see each other's transport failures. The cost is an\n * object literal against an RPC or HTTP round-trip.\n */\nimport { x402Facilitator } from '@x402/core/facilitator';\nimport { HTTPFacilitatorClient } from '@x402/core/http';\nimport type {\n Network,\n PaymentPayload,\n PaymentRequirements,\n SettleResponse,\n VerifyResponse,\n} from '@x402/core/types';\nimport { toFacilitatorEvmSigner } from '@x402/evm';\nimport { registerExactEvmScheme } from '@x402/evm/exact/facilitator';\nimport { CommerceError } from '../../core/index.js';\nimport type { LocalFacilitatorClient } from './chain.js';\nimport type { FacilitatorAuth } from './guardrails.js';\n\n/** One verify or one settle, with its own transport-failure flag. */\nexport interface FacilitatorSession {\n verify(payload: PaymentPayload, requirements: PaymentRequirements): Promise<VerifyResponse>;\n settle(payload: PaymentPayload, requirements: PaymentRequirements): Promise<SettleResponse>;\n /**\n * True when the call failed to reach the facilitator (or the chain behind\n * it) rather than producing a verdict.\n *\n * The SDK's `exact`/EVM scheme catches its own RPC errors and reports them\n * as an ordinary verification failure — an unreachable node comes back as\n * `invalid_exact_evm_signature`. Fail-closed still holds, but the buyer is\n * told their signature is bad and the attempt is recorded as their fault,\n * when nothing about their payment was ever checked. This flag is how the\n * provider tells \"we looked and it was wrong\" apart from \"we could not\n * look\".\n */\n transportFailed(): boolean;\n}\n\nexport interface SupportedKind {\n readonly x402Version: number;\n readonly scheme: string;\n readonly network: string;\n}\n\nexport interface FacilitatorBinding {\n readonly kind: 'local' | 'remote';\n /** Human-readable, never a credential. */\n readonly describe: string;\n open(): FacilitatorSession;\n /** What the facilitator says it can settle. Used by health(), not by the payment path. */\n supported(): Promise<readonly SupportedKind[]>;\n}\n\n/** Bounds every receipt wait the in-process facilitator performs. */\nexport const SETTLEMENT_CONFIRMATION_TIMEOUT_MS = 60_000;\n\n/**\n * An in-process `x402Facilitator` with the `exact`/EVM scheme registered\n * against exactly one network.\n *\n * One network, not the `eip155:*` wildcard the SDK would otherwise derive: a\n * payload naming some other chain must find no facilitator at all rather than\n * reaching a scheme that would then have to reject it.\n */\nexport function createLocalFacilitatorBinding(\n client: LocalFacilitatorClient,\n network: string,\n isTransportError: (err: unknown) => boolean,\n): FacilitatorBinding {\n const build = (): { facilitator: x402Facilitator; failed: () => boolean } => {\n let failed = false;\n const watch = <T>(promise: Promise<T>): Promise<T> =>\n promise.catch((err: unknown) => {\n if (isTransportError(err)) failed = true;\n throw err;\n });\n\n // Exactly the `FacilitatorEvmSigner` surface, so the wrapper covers every\n // call the SDK can make. `toFacilitatorEvmSigner` wants a flat `address`,\n // which viem carries on `client.account` instead.\n const signer = {\n address: client.account.address,\n readContract: (args: Parameters<LocalFacilitatorClient['readContract']>[0]) =>\n watch(client.readContract(args)),\n verifyTypedData: (args: Parameters<LocalFacilitatorClient['verifyTypedData']>[0]) =>\n watch(client.verifyTypedData(args)),\n writeContract: (args: Parameters<LocalFacilitatorClient['writeContract']>[0]) =>\n watch(client.writeContract(args)),\n sendTransaction: (args: Parameters<LocalFacilitatorClient['sendTransaction']>[0]) =>\n watch(client.sendTransaction(args)),\n waitForTransactionReceipt: (\n args: Parameters<LocalFacilitatorClient['waitForTransactionReceipt']>[0],\n ) => watch(client.waitForTransactionReceipt(args)),\n getCode: (args: Parameters<LocalFacilitatorClient['getCode']>[0]) =>\n watch(client.getCode(args)),\n } as unknown as Parameters<typeof toFacilitatorEvmSigner>[0];\n\n // `confirmationTimeoutMs` is what turns a lost receipt wait into\n // `settlement_pending` + the broadcast hash instead of a discarded broadcast.\n const facilitator = registerExactEvmScheme(new x402Facilitator(), {\n signer: toFacilitatorEvmSigner(signer, {\n confirmationTimeoutMs: SETTLEMENT_CONFIRMATION_TIMEOUT_MS,\n }),\n networks: network as Network,\n });\n\n return { facilitator, failed: () => failed };\n };\n\n return {\n kind: 'local',\n describe: 'local (in-process)',\n open(): FacilitatorSession {\n const { facilitator, failed } = build();\n return {\n verify: (payload, requirements) => facilitator.verify(payload, requirements),\n settle: (payload, requirements) => facilitator.settle(payload, requirements),\n transportFailed: failed,\n };\n },\n async supported(): Promise<readonly SupportedKind[]> {\n return build().facilitator.getSupported().kinds;\n },\n };\n}\n\nexport interface RemoteFacilitatorOptions {\n readonly url: string;\n readonly auth: FacilitatorAuth;\n readonly timeoutMs?: number;\n}\n\n/** The SDK's path-keyed auth-header shape. A flat object throws inside it. */\ntype AuthHeaderFactory = () => Promise<Record<string, Record<string, string>>>;\n\n/**\n * CDP signs a fresh JWT per request over method + host + path, so a static\n * header cannot express it. `@coinbase/x402` does that signing, and is\n * imported dynamically: a static import would drag the whole CDP SDK — and its\n * Solana, axios and JOSE dependencies — into the `/x402` subpath for everyone,\n * including the majority who use a facilitator that needs no credential at all.\n *\n * The import is started at construction rather than on the first payment. A\n * missing peer must surface as an unhealthy provider before a buyer signs\n * anything, not as a failure inside verify() with their authorisation already\n * spent.\n */\nfunction cdpAuthHeaders(apiKeyId: string, apiKeySecret: string): AuthHeaderFactory {\n const loading = import('@coinbase/x402').then(\n (mod) => mod.createCdpAuthHeaders(apiKeyId, apiKeySecret),\n (cause: unknown) => {\n throw new CommerceError(\n 'CONFIG_INVALID',\n 'x402 provider: facilitator.auth.type is \"cdp\", which needs the optional peer ' +\n '\"@coinbase/x402\". Install it (npm install @coinbase/x402), or use a facilitator ' +\n 'that accepts a static token with auth.type \"bearer\".',\n { cause },\n );\n },\n );\n // Nothing awaits this until the first call; without a handler the rejection\n // above would be an unhandled promise rejection at startup.\n loading.catch(() => {});\n\n return async () => {\n const create = await loading;\n if (!create) {\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n 'x402 provider: @coinbase/x402 returned no auth-header factory',\n );\n }\n return (await create()) as Record<string, Record<string, string>>;\n };\n}\n\n/**\n * An HTTP facilitator.\n *\n * Auth headers are produced per request by the SDK client and never logged,\n * never echoed into `/.well-known`, and never included in `describe`.\n */\nexport function createRemoteFacilitatorBinding(\n options: RemoteFacilitatorOptions,\n): FacilitatorBinding {\n const auth = options.auth;\n let createAuthHeaders: AuthHeaderFactory | undefined;\n if (auth.type === 'bearer') {\n createAuthHeaders = async () => {\n // The SDK requires a path-keyed object; a flat headers object throws\n // rather than silently dropping auth on every request.\n const headers = { Authorization: `Bearer ${auth.token}` };\n return { verify: headers, settle: headers, supported: headers };\n };\n } else if (auth.type === 'cdp') {\n createAuthHeaders = cdpAuthHeaders(auth.apiKeyId, auth.apiKeySecret);\n }\n\n const client = new HTTPFacilitatorClient({\n url: options.url,\n timeoutMs: options.timeoutMs ?? SETTLEMENT_CONFIRMATION_TIMEOUT_MS,\n ...(createAuthHeaders ? { createAuthHeaders } : {}),\n });\n\n return {\n kind: 'remote',\n describe: `remote ${new URL(options.url).origin} (auth=${auth.type})`,\n open(): FacilitatorSession {\n let failed = false;\n const watch = async <T>(call: () => Promise<T>): Promise<T> => {\n try {\n return await call();\n } catch (err) {\n // *Any* throw out of the SDK client means no verdict was obtained.\n // A verdict arrives as a returned `VerifyResponse`/`SettleResponse`,\n // including a negative one; the client only throws when it could not\n // reach the facilitator, could not authenticate to it, got a non-2xx,\n // or could not parse what came back. None of those are facts about\n // the payment, and recording them against the payer would blame the\n // buyer for our credential or the facilitator's outage.\n //\n // Deliberately not a predicate over error shapes: the SDK throws a\n // bare `Error` for an HTTP status (`Facilitator verify failed (401)`)\n // and a `FacilitatorResponseError` for a bad body, so matching on\n // type or message would have missed exactly the credential case that\n // matters most. For settle() this also preserves the indeterminate\n // reading — a timeout may have settled after we stopped waiting.\n failed = true;\n throw err;\n }\n };\n return {\n verify: (payload, requirements) => watch(() => client.verify(payload, requirements)),\n settle: (payload, requirements) => watch(() => client.settle(payload, requirements)),\n transportFailed: () => failed,\n };\n },\n async supported(): Promise<readonly SupportedKind[]> {\n const response = await client.getSupported();\n return response.kinds as readonly SupportedKind[];\n },\n };\n}\n","/**\n * Decoding and validation for the base64 `PAYMENT-SIGNATURE` submission.\n *\n * A malformed payload (not base64, valid base64 but not JSON, valid JSON but\n * the wrong shape) must yield a `rejected` verification result, never a\n * thrown/crashed request — this module returns `undefined` on any failure so\n * callers can turn that into a typed rejection. That is why it parses the\n * schema itself rather than calling the SDK's `decodePaymentSignatureHeader`,\n * which throws.\n */\nimport { PaymentPayloadV2Schema } from '@x402/core/schemas';\nimport type { PaymentPayload } from '@x402/core/types';\nimport { type ExactEIP3009Payload, isEIP3009Payload } from '@x402/evm';\n\nexport function decodePaymentSubmission(payloadBase64: string): PaymentPayload | undefined {\n let json: unknown;\n try {\n const decoded = Buffer.from(payloadBase64, 'base64').toString('utf8');\n json = JSON.parse(decoded);\n } catch {\n return undefined;\n }\n\n const result = PaymentPayloadV2Schema.safeParse(json);\n return result.success ? (result.data as PaymentPayload) : undefined;\n}\n\n/**\n * Narrows a decoded payload to the EIP-3009 `exact`/EVM shape this provider\n * settles.\n *\n * x402 v2's `exact` scheme on EVM has two asset-transfer methods — EIP-3009\n * `transferWithAuthorization` and Permit2. Only the first is supported here,\n * and the challenge says so (`extra.assetTransferMethod`), so a Permit2\n * payload arriving anyway is rejected rather than handed to the SDK: the\n * Permit2 proxy is not deployed on the local chain and a failure there would\n * surface as an opaque settlement revert instead of a clear rejection.\n */\nexport function isExactEvmPayload(\n payload: PaymentPayload,\n): payload is PaymentPayload & { payload: ExactEIP3009Payload } {\n return (\n payload.accepted.scheme === 'exact' &&\n typeof payload.payload === 'object' &&\n payload.payload !== null &&\n isEIP3009Payload(payload.payload as ExactEIP3009Payload) &&\n typeof (payload.payload as ExactEIP3009Payload).signature === 'string'\n );\n}\n","/**\n * Replay-key derivation.\n *\n *Per docs/contracts.md, `PaymentResult.replayKey` MUST be\n * derived only from the payment authorisation (chain id, asset, payer,\n * nonce) — never from the request id — so that the same authorisation\n * replayed against a *different* request still collides in the gateway's\n * receipt-store reservation.\n */\nimport { encodeAbiParameters, keccak256 } from 'viem';\n\nexport interface ReplayKeyInput {\n readonly chainId: number;\n readonly asset: `0x${string}`;\n readonly from: `0x${string}`;\n readonly nonce: `0x${string}`;\n}\n\nexport function computeReplayKey(input: ReplayKeyInput): string {\n const encoded = encodeAbiParameters(\n [{ type: 'uint256' }, { type: 'address' }, { type: 'address' }, { type: 'bytes32' }],\n [BigInt(input.chainId), input.asset, input.from, input.nonce],\n );\n return keccak256(encoded);\n}\n","/**\n * x402 payment provider — protocol version 2, `exact` scheme, EVM,\n * EIP-3009 `transferWithAuthorization`.\n *\n * Implements the frozen `PaymentProvider` interface (src/core/domain/payment.ts).\n * `verify()` never moves funds; only `settle()` does, and only after a\n * successful `verify()` (enforced by the gateway's execution pipeline, not by\n * this file, but this file never calls settle-like RPCs from verify()).\n *\n * Verification and settlement run through the SDK's own `x402Facilitator`\n * with the `exact`/EVM scheme registered against a single CAIP-2 network. The\n * facilitator is in-process — it is the same code a hosted facilitator runs,\n * pointed at the local dev chain — so there is no network hop and no third\n * party in the settlement path.\n *\n * The SDK behaviour relied on here is verified, not assumed: see the notes\n * beside each call site below.\n */\n\nimport type {\n Network,\n PaymentRequired,\n PaymentRequirements,\n SettleResponse,\n VerifyResponse,\n} from '@x402/core/types';\nimport {\n ContractFunctionExecutionError,\n ContractFunctionRevertedError,\n getAddress,\n HttpRequestError,\n isAddress,\n TimeoutError,\n WaitForTransactionReceiptTimeoutError,\n} from 'viem';\nimport {\n type AdapterDescriptor,\n type AdapterHealth,\n type Clock,\n CommerceError,\n type IdGenerator,\n type Logger,\n NOOP_LOGGER,\n type PaymentContext,\n type PaymentProvider,\n type PaymentRequirement,\n type PaymentResult,\n type PaymentSettlementContext,\n type PaymentVerificationContext,\n systemClock,\n} from '../../core/index.js';\nimport { PACKAGE_VERSION } from '../../version.js';\nimport { formatCanonicalAmount, parseCanonicalAmount } from './amount.js';\nimport {\n chainIdFromCaip2,\n createLocalFacilitatorClient,\n createLocalPublicClient,\n type LocalFacilitatorClient,\n} from './chain.js';\nimport {\n assertDevKeyIsLocalOnly,\n assertPayToIsNotDevAddress,\n describeRpc,\n} from './dev-key-guard.js';\nimport {\n createLocalFacilitatorBinding,\n createRemoteFacilitatorBinding,\n type FacilitatorBinding,\n} from './facilitator.js';\nimport { resolveX402Deployment, type X402FacilitatorConfig } from './guardrails.js';\nimport { describeDeploymentMode } from './networks.js';\nimport { decodePaymentSubmission, isExactEvmPayload } from './payload.js';\nimport { computeReplayKey } from './replay-key.js';\n\nconst X402_VERSION = 2;\nconst X402_PROTOCOL_VERSION = String(X402_VERSION);\nconst DEFAULT_MAX_TIMEOUT_SECONDS = 60;\nconst DEFAULT_MIME_TYPE = 'application/json';\nconst HEALTH_TIMEOUT_MS = 4_000;\n/** `SettleResponse.errorReason` the SDK uses for \"broadcast, not confirmed\". */\nconst SETTLEMENT_PENDING_REASON = 'settlement_pending';\n/**\n * The SDK's catch-all for a throw from the broadcast call, and its reason for\n * a mined transaction that reverted. Only the second carries a hash. A revert\n * the SDK recognises during gas estimation gets its own reason instead.\n */\nconst TRANSACTION_FAILED_REASON = 'invalid_exact_evm_transaction_failed';\n/**\n * `invalidReason`/`errorReason` are `z.string()` in the SDK schema — no length\n * or charset bound. They become the message a buyer is told about their own\n * payment, a persisted and SSE-streamed event field, and a column in the\n * merchant's ledger. A remote facilitator is a counterparty this design\n * explicitly contemplates having no account or terms with, so treat its\n * strings as untrusted input rather than as diagnostics.\n */\nconst MAX_REASON_LENGTH = 64;\nconst REASON_SHAPE = /^[a-z0-9_.-]+$/i;\n\nfunction sanitiseReason(reason: string | undefined, fallback: string): string {\n if (reason === undefined) return fallback;\n const trimmed = reason.trim();\n if (trimmed.length === 0 || trimmed.length > MAX_REASON_LENGTH) return fallback;\n return REASON_SHAPE.test(trimmed) ? trimmed : fallback;\n}\n\nexport interface X402ProviderOptions {\n /**\n * CAIP-2 network identifier, e.g. `eip155:84532`. The chain id it carries is\n * part of the EIP-712 domain the buyer signs, so it is read from this value\n * rather than defaulted.\n */\n readonly network: string;\n /** RPC endpoint. Local chain: http://127.0.0.1:8545 */\n readonly rpcUrl: string;\n /** ERC-20 (EIP-3009) asset address used for settlement. */\n readonly asset: `0x${string}`;\n /** EIP-712 domain name of the asset, e.g. 'MockUSDC'. */\n readonly assetName: string;\n /** EIP-712 domain version of the asset, e.g. '2'. */\n readonly assetVersion: string;\n readonly assetDecimals: number;\n /** Merchant-controlled settlement destination. Never a gateway-owned wallet. */\n readonly payTo: `0x${string}`;\n readonly maxTimeoutSeconds?: number;\n /**\n * Which facilitator verifies and broadcasts.\n *\n * `local` runs the facilitator in this process against the dev chain, and\n * its `signerPrivateKey` must be an Anvil well-known key — LOCAL DEVELOPMENT\n * ONLY — DO NOT FUND. `remote` calls an HTTP facilitator, and this gateway\n * then holds no signing key at all.\n */\n readonly facilitator: X402FacilitatorConfig;\n /**\n * Required to be `true` before anything settles on a mainnet. Never a\n * default — see `guardrails.ts`.\n */\n readonly allowMainnet?: boolean;\n /**\n * Required to be `true` to settle on a mainnet through a facilitator that\n * takes no credential. Never a default.\n */\n readonly allowUnauthenticatedFacilitator?: boolean;\n readonly logger?: Logger;\n readonly clock?: Clock;\n readonly ids?: IdGenerator;\n}\n\nconst DEFAULT_IDS: IdGenerator = {\n next: (prefix?: string) => `${prefix ? `${prefix}_` : ''}${crypto.randomUUID()}`,\n};\n\nexport function createX402PaymentProvider(options: X402ProviderOptions): PaymentProvider {\n if (!isAddress(options.asset)) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `x402 provider: \"asset\" is not a valid EVM address: ${options.asset}`,\n );\n }\n if (!isAddress(options.payTo)) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `x402 provider: \"payTo\" is not a valid EVM address: ${options.payTo}`,\n );\n }\n // Applies regardless of facilitator.mode — which account signs settlement\n // has no bearing on whether the destination address's private key is\n // public knowledge. `resolveX402Deployment` below covers the other half of\n // the same question: a dev payTo on any non-local *deployment*, where the\n // RPC host says nothing about where the money lands.\n assertPayToIsNotDevAddress(options.rpcUrl, options.payTo);\n if (!Number.isInteger(options.assetDecimals) || options.assetDecimals < 0) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `x402 provider: \"assetDecimals\" must be a non-negative integer`,\n );\n }\n // The chain id is not a display detail: it is signed into the buyer's\n // EIP-712 domain, so a network identifier we cannot resolve one from is a\n // startup failure, never a request-time default. `resolveX402Deployment`\n // also decides what this deployment *is* — local, testnet or mainnet — and\n // refuses every combination that could move real money by accident.\n const { profile, mode } = resolveX402Deployment({\n network: options.network,\n payTo: options.payTo,\n asset: options.asset,\n assetName: options.assetName,\n assetVersion: options.assetVersion,\n facilitator: options.facilitator,\n ...(options.allowMainnet !== undefined ? { allowMainnet: options.allowMainnet } : {}),\n ...(options.allowUnauthenticatedFacilitator !== undefined\n ? { allowUnauthenticatedFacilitator: options.allowUnauthenticatedFacilitator }\n : {}),\n });\n const network = options.network as Network;\n // Constructed once, here, rather than inside settle(): assertDevKeyIsLocalOnly\n // above already proves the key is well-formed, so privateKeyToAccount is not\n // expected to throw — but if it somehow does (or the key/RPC combination is\n // otherwise unusable), that is a *configuration* problem, and a bad key\n // should fail the provider at startup, not on the first paying customer's\n // request, after their replayKey is already reserved. This mirrors the other\n // CONFIG_INVALID checks above, which are all one-time, construction-time\n // validation rather than per-request checks.\n let binding: FacilitatorBinding;\n if (options.facilitator.mode === 'local') {\n assertDevKeyIsLocalOnly(options.rpcUrl, options.facilitator.signerPrivateKey);\n let client: LocalFacilitatorClient;\n try {\n client = createLocalFacilitatorClient(\n options.rpcUrl,\n options.facilitator.signerPrivateKey as `0x${string}`,\n );\n } catch (cause) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n 'x402 provider: could not construct a local facilitator signer from ' +\n 'facilitator.signerPrivateKey — it must be a valid 32-byte hex private key',\n { cause },\n );\n }\n binding = createLocalFacilitatorBinding(client, network, isProviderUnavailableError);\n } else {\n binding = createRemoteFacilitatorBinding({\n url: options.facilitator.url,\n auth: options.facilitator.auth,\n });\n }\n\n // health()'s own read-only client, with a real transport-level timeout (see\n // createLocalPublicClient's doc comment). Verification and settlement read\n // the chain through the facilitator signer instead, so this is the only\n // public client the provider builds.\n // Health details are logged, so they name the RPC by origin only\n const rpcOrigin = describeRpc(options.rpcUrl);\n const healthPublicClient = createLocalPublicClient(\n options.rpcUrl,\n HEALTH_TIMEOUT_MS,\n profile.chainId,\n );\n\n const clock = options.clock ?? systemClock;\n const ids = options.ids ?? DEFAULT_IDS;\n const logger = options.logger ?? NOOP_LOGGER;\n const maxTimeoutSeconds = options.maxTimeoutSeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS;\n\n const descriptor: AdapterDescriptor = {\n name: 'x402',\n kind: 'payment',\n implementationVersion: PACKAGE_VERSION,\n supportedSpec: `x402/v${X402_VERSION} scheme=exact family=eip155`,\n capabilities: [\n 'exact-evm',\n `${binding.kind}-facilitator`,\n 'eip-3009',\n 'caip-2',\n `mode=${mode}`,\n ],\n status: 'stable',\n unsupported: ['svm', 'permit2', 'upto scheme'],\n };\n\n async function createRequirement(context: PaymentContext): Promise<PaymentRequirement> {\n const amount = parseCanonicalAmount(context.amount, options.assetDecimals).toString();\n\n const requirements: PaymentRequirements = {\n scheme: 'exact',\n network,\n asset: options.asset,\n amount,\n payTo: options.payTo,\n maxTimeoutSeconds,\n // `name`/`version` are what let a buyer and the facilitator build the\n // same EIP-712 domain without an on-chain `version()` call, so\n // verification stays deterministic against a token that has none.\n //\n // `assetTransferMethod` is stated rather than left to default: x402 v2's\n // `exact`/EVM scheme also has a Permit2 path, and a client that picked it\n // would produce a payload this provider cannot settle. Declaring the one\n // supported method turns that into a client-side non-choice instead of a\n // server-side rejection.\n extra: {\n name: options.assetName,\n version: options.assetVersion,\n assetTransferMethod: 'eip3009',\n },\n };\n\n // The v2 challenge document, verbatim on the wire: the HTTP adapter\n // base64-encodes this into `PAYMENT-REQUIRED`, and MCP passes it through\n // in the payment-required envelope. Built once, here, so both surfaces\n // describe the same challenge rather than each assembling their own.\n //\n // `resource.url` is descriptive metadata: nothing in the EIP-3009\n // authorisation (`from`/`to`/`value`/`validAfter`/`validBefore`/`nonce`)\n // covers it, nothing verifies against it, and the replay key is keyed on\n // the authorisation instead. It still carries `network` and `payTo` —\n // both already public in this same challenge — because the\n // `agent-commerce` authority is not reserved to us across the wider x402\n // ecosystem, so the pair is what keeps it unambiguous.\n const envelope: PaymentRequired = {\n x402Version: X402_VERSION,\n resource: {\n url: `resource://agent-commerce/${encodeURIComponent(options.network)}/${options.payTo}/resources/${encodeURIComponent(context.resource.id)}`,\n description: context.resource.description ?? context.resource.name,\n mimeType: DEFAULT_MIME_TYPE,\n },\n accepts: [requirements],\n };\n\n const expiresAt = new Date(clock.now().getTime() + maxTimeoutSeconds * 1000).toISOString();\n\n return {\n id: ids.next('payreq'),\n requestId: context.requestId,\n resourceId: context.resource.id,\n provider: 'x402',\n amount: context.amount,\n currency: context.currency,\n destination: options.payTo,\n network: options.network,\n asset: options.asset,\n expiresAt,\n challenge: {\n provider: 'x402',\n version: X402_PROTOCOL_VERSION,\n accepts: [requirements as unknown as Record<string, unknown>],\n envelope: envelope as unknown as Record<string, unknown>,\n },\n };\n }\n\n /**\n * Verifies a payment submission against a payment requirement.\n *\n * Every check below runs against *our* requirement — the one this provider\n * built and the pipeline held onto — never against `payload.accepted`, the\n * copy of the requirements the client echoes back. That echo is attacker\n * data; the SDK's scheme facilitator likewise takes the requirements as an\n * explicit argument rather than reading them off the payload.\n *\n * The amount must match **exactly**. This once accepted overpayment on the\n * reading that `amount` names a floor — but the pinned `@x402/evm@2.23.0`\n * exact/EVM scheme compares with `!==` and rejects anything else as\n * `invalid_exact_evm_payload_authorization_value_mismatch`, in both verify\n * and settle, and hosted facilitators run that same code. Accepting more\n * here only moved the rejection downstream and turned a clean\n * `wrong_amount` into an opaque SDK reason.\n */\n async function verify(context: PaymentVerificationContext): Promise<PaymentResult> {\n const { requirement, submission } = context;\n\n const rejected = (reason: string): PaymentResult => ({\n status: 'rejected',\n provider: 'x402',\n amount: requirement.amount,\n currency: requirement.currency,\n ...(requirement.network !== undefined ? { network: requirement.network } : {}),\n ...(requirement.asset !== undefined ? { asset: requirement.asset } : {}),\n rejectionReason: reason,\n });\n\n if (requirement.provider !== 'x402' || requirement.challenge.provider !== 'x402') {\n return rejected('wrong_provider');\n }\n\n const requirements = requirement.challenge.accepts[0] as PaymentRequirements | undefined;\n if (!requirements) {\n return rejected('missing_payment_requirements');\n }\n\n // Defence in depth, not the real expiry: the pipeline calls\n // createRequirement() fresh on every request, so by the time verify()\n // runs this requirement is only ever seconds old — this check will\n // essentially never fire in the current flow. The actual expiry\n // enforcement is EIP-3009's validBefore, checked inside the SDK's scheme\n // facilitator. Kept because it is cheap and correct, not because it is\n // load-bearing.\n if (\n requirement.expiresAt !== undefined &&\n Date.parse(requirement.expiresAt) < clock.now().getTime()\n ) {\n return rejected('requirement_expired');\n }\n\n // Defensive invariant: the requirement we're verifying against must still\n // describe *this* provider's configured asset. It always will in normal\n // operation (we generated it), but a corrupted/mismatched requirement\n // must never be allowed to authorise a transfer for a different asset.\n if (\n !isAddress(requirements.asset) ||\n getAddress(requirements.asset) !== getAddress(options.asset)\n ) {\n return rejected('wrong_asset');\n }\n\n const payload = decodePaymentSubmission(submission.payload);\n if (!payload) {\n return rejected('malformed_payment_payload');\n }\n if (payload.x402Version !== X402_VERSION) {\n return rejected('unsupported_x402_version');\n }\n if (!isExactEvmPayload(payload)) {\n return rejected('unsupported_scheme');\n }\n\n const { authorization } = payload.payload;\n\n if (!isAddress(authorization.from) || !isAddress(authorization.to)) {\n return rejected('malformed_payment_payload');\n }\n // The network the buyer signed for is `accepted.network` — it is what the\n // scheme derives the EIP-712 chain id from — so a mismatch here means the\n // signature is bound to a different chain than the one we settle on.\n if (payload.accepted.network !== options.network) {\n return rejected('wrong_network');\n }\n if (getAddress(authorization.to) !== getAddress(options.payTo)) {\n return rejected('wrong_recipient');\n }\n let authorizedValue: bigint;\n let required: bigint;\n try {\n authorizedValue = BigInt(authorization.value);\n required = BigInt(requirements.amount);\n } catch {\n return rejected('malformed_payment_payload');\n }\n if (authorizedValue !== required) {\n // Both directions: the scheme enforces equality, so an overpayment is\n // rejected here with a reason the buyer can act on rather than by the\n // facilitator with one they cannot.\n return rejected('wrong_amount');\n }\n\n const scope = binding.open();\n let sdkResult: VerifyResponse;\n try {\n sdkResult = await scope.verify(payload, requirements);\n } catch (err) {\n if (isProviderUnavailableError(err) || scope.transportFailed()) {\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n `x402 provider: ${binding.kind} facilitator unreachable during verify()`,\n {\n cause: err,\n },\n );\n }\n logger.warn({ err: describeError(err) }, 'x402 verify(): unexpected SDK error');\n return rejected('unexpected_verify_error');\n }\n\n if (!sdkResult.isValid) {\n // An RPC that never answered is not a payment that failed a check.\n if (scope.transportFailed()) {\n if (sdkResult.invalidReason !== undefined) {\n logger.debug(\n { reportedReason: sdkResult.invalidReason },\n 'x402 verify(): local facilitator transport failure reason',\n );\n }\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n `x402 provider: ${binding.kind} facilitator unreachable during verify()`,\n );\n }\n // The raw string still reaches the operator's logs below; only what is\n // shown to the buyer and written to the ledger is constrained.\n if (sdkResult.invalidReason !== undefined) {\n logger.debug(\n { reportedReason: sdkResult.invalidReason },\n 'x402 verify(): facilitator rejection reason',\n );\n }\n return rejected(sanitiseReason(sdkResult.invalidReason, 'invalid_payment'));\n }\n\n // Derived from the chain id the authorisation is actually bound to, never\n // from a provider-instance constant, so the key stays correct the moment\n // there is more than one chain id in play.\n const payloadChainId = chainIdFromCaip2(payload.accepted.network);\n if (payloadChainId === undefined) {\n return rejected('wrong_network');\n }\n const replayKey = computeReplayKey({\n chainId: payloadChainId,\n asset: getAddress(requirements.asset),\n from: getAddress(authorization.from),\n nonce: authorization.nonce,\n });\n\n return {\n status: 'verified',\n provider: 'x402',\n payer: getAddress(authorization.from),\n payee: getAddress(authorization.to),\n amount: formatCanonicalAmount(authorizedValue, options.assetDecimals),\n currency: requirement.currency,\n network: payload.accepted.network,\n asset: getAddress(requirements.asset),\n replayKey,\n };\n }\n\n async function settle(context: PaymentSettlementContext): Promise<PaymentResult> {\n const { requirement, submission, verification } = context;\n\n if (verification.status !== 'verified') {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n 'x402 provider: settle() called without a successful verify()',\n );\n }\n\n const requirements = requirement.challenge.accepts[0] as PaymentRequirements | undefined;\n if (!requirements) {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n 'x402 provider: settle() found no payment requirements to settle against',\n );\n }\n\n const payload = decodePaymentSubmission(submission.payload);\n if (!payload || !isExactEvmPayload(payload)) {\n throw new CommerceError(\n 'PAYMENT_INVALID',\n 'x402 provider: settle() received an undecodable payment payload',\n );\n }\n\n const rejectedSettlement = (rejectionReason: string): PaymentResult => ({\n status: 'rejected',\n provider: 'x402',\n amount: verification.amount,\n currency: requirement.currency,\n ...(verification.network !== undefined ? { network: verification.network } : {}),\n ...(verification.asset !== undefined ? { asset: verification.asset } : {}),\n ...(verification.replayKey !== undefined ? { replayKey: verification.replayKey } : {}),\n rejectionReason,\n });\n\n const scope = binding.open();\n let sdkResult: SettleResponse;\n try {\n sdkResult = await scope.settle(payload, requirements);\n } catch (err) {\n if (isProviderUnavailableError(err) || scope.transportFailed()) {\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n `x402 provider: ${binding.kind} facilitator unreachable during settle()`,\n { cause: err },\n );\n }\n // A revert is the chain's own statement that the transfer did not\n // happen, so it is a real rejection and the pipeline may release what\n // it holds. Anything else out of settle() is unclassified: we cannot\n // tell whether the transfer was broadcast, so it must not come back as\n // a rejection the buyer can be blamed for. It goes back as an\n // unavailable provider, and the pipeline records it unresolved.\n if (!isOnChainRevertError(err)) {\n logger.warn(\n { err: describeError(err) },\n 'x402 settle(): settlement failed with an unclassified error; outcome unknown',\n );\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n 'x402 provider: settlement failed with an unclassified error; outcome unknown',\n { cause: err },\n );\n }\n logger.warn(\n { err: describeError(err), rejectionReason: 'transaction_reverted' },\n 'x402 settle(): settlement transaction reverted on chain',\n );\n return rejectedSettlement('transaction_reverted');\n }\n\n if (!sdkResult.success) {\n // \"Broadcast, never confirmed\" is not \"did not happen\": the transfer may\n // already be on-chain, so it surfaces as an *unavailable* provider\n // carrying the hash, letting the pipeline record the attempt\n // `settlement-uncertain` rather than `failed`. The SDK's catch-all with\n // no hash is treated the same way: its throw may have followed a\n // broadcast, and the message cannot tell, because viem reports an RPC\n // error on the send as a revert. Everything else is a real rejection.\n if (\n sdkResult.errorReason === TRANSACTION_FAILED_REASON &&\n !/^0x[0-9a-f]{64}$/i.test(sdkResult.transaction)\n ) {\n logger.warn(\n { reportedReason: sdkResult.errorReason },\n 'x402 settle(): the broadcast failed without a transaction hash; outcome unknown',\n );\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n 'x402 provider: settlement failed with an unclassified error; outcome unknown',\n );\n }\n if (sdkResult.errorReason === SETTLEMENT_PENDING_REASON || scope.transportFailed()) {\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n 'x402 provider: settlement was broadcast but could not be confirmed',\n {\n ...(sdkResult.transaction\n ? { details: { transactionHash: sdkResult.transaction } }\n : {}),\n },\n );\n }\n if (sdkResult.errorReason !== undefined) {\n logger.debug(\n { reportedReason: sdkResult.errorReason },\n 'x402 settle(): facilitator failure reason',\n );\n }\n return {\n ...rejectedSettlement(sanitiseReason(sdkResult.errorReason, 'settlement_failed')),\n network: sdkResult.network,\n ...(sdkResult.payer !== undefined ? { payer: sdkResult.payer } : {}),\n };\n }\n\n return {\n status: 'settled',\n provider: 'x402',\n externalReference: sdkResult.transaction,\n ...(sdkResult.payer !== undefined ? { payer: sdkResult.payer } : {}),\n payee: requirements.payTo,\n amount: verification.amount,\n currency: requirement.currency,\n network: sdkResult.network,\n ...(verification.asset !== undefined ? { asset: verification.asset } : {}),\n ...(verification.replayKey !== undefined ? { replayKey: verification.replayKey } : {}),\n settledAt: clock.nowIso(),\n };\n }\n\n async function computeHealth(): Promise<AdapterHealth> {\n const startedAt = clock.monotonicMs();\n const checkedAt = clock.nowIso();\n\n try {\n const chainId = await healthPublicClient.getChainId();\n if (chainId !== profile.chainId) {\n return {\n status: 'fail',\n detail: `RPC at ${rpcOrigin} reports chain id ${chainId}, expected ${profile.chainId} (${profile.displayName})`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n\n const code = await healthPublicClient.getCode({ address: options.asset });\n if (!code || code === '0x') {\n return {\n status: 'fail',\n detail: `No contract code found at configured asset address ${options.asset}`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n\n if (binding.kind === 'remote') {\n // \"Reachable\" is not the question — \"will it settle *this*\" is. A\n // facilitator that is up but does not carry our scheme on our network\n // fails every payment, and does it after the buyer has signed.\n const kinds = await binding.supported();\n const supportsUs = kinds.some(\n (kind) =>\n kind.x402Version === X402_VERSION &&\n kind.scheme === 'exact' &&\n kind.network === options.network,\n );\n if (!supportsUs) {\n return {\n status: 'fail',\n detail:\n `Facilitator ${binding.describe} does not advertise x402 v${X402_VERSION} scheme=exact ` +\n `on ${options.network} (${profile.displayName}); no payment on this deployment can settle`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n return {\n status: 'pass',\n detail:\n `${describeDeploymentMode(mode)} — RPC ${rpcOrigin} reachable, chain id ` +\n `${profile.chainId} (${profile.displayName}), asset ${options.asset} has code, ` +\n `facilitator ${binding.describe} supports exact/${options.network}`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n\n // Chain id alone cannot prove this is a dev chain: real Base Sepolia\n // reports the same id (84532) as this project's local chain, by design.\n // Probe an Anvil-only RPC method — present only on a real Anvil node —\n // before trusting a well-known dev key against it.\n const isAnvil = await probeIsAnvilNode(healthPublicClient);\n if (!isAnvil) {\n return {\n status: 'fail',\n detail:\n `RPC at ${rpcOrigin} reports chain id ${profile.chainId} but does not answer ` +\n '\"anvil_nodeInfo\" — it does not look like a local Anvil dev node. Refusing to treat it ' +\n 'as safe for a local-facilitator dev key.',\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n\n return {\n status: 'pass',\n detail:\n `${describeDeploymentMode(mode)} — RPC ${rpcOrigin} reachable, chain id ` +\n `${profile.chainId}, asset ${options.asset} has code, confirmed Anvil dev node`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n } catch (err) {\n return {\n status: 'fail',\n detail: `x402 health check failed: ${describeError(err)}`,\n checkedAt,\n durationMs: clock.monotonicMs() - startedAt,\n };\n }\n }\n\n // /ready has no auth, no cache and no\n // rate limit, and called computeHealth() — 3 live RPC calls — on every\n // single request; measured 3x amplification of billed upstream calls\n // under an unauthenticated flood. Memoise behind a short TTL and collapse\n // concurrent callers onto one in-flight probe, so N requests within the\n // window produce at most one round-trip instead of N.\n //\n // 5s: short enough that a readiness probe (Kubernetes' own default\n // `periodSeconds` is 10s) never observes data older than its own poll\n // interval, long enough to fully decouple RPC call volume from HTTP\n // request volume — which is the property that closes the amplification,\n // not the exact number of seconds.\n //\n // pass and fail are cached for the same TTL, deliberately: a shorter TTL\n // for fail would re-introduce the amplification exactly when an upstream\n // outage makes every call expensive/slow, which is the worst possible time\n // to remove the cache's protection. 5s of recovery latency after the RPC\n // comes back is an acceptable trade — it is already within the noise of a\n // single health probe's own round-trip time, and well inside a normal\n // probe's own poll interval.\n //\n // This only memoises this provider's own RPC probe. `core` separately\n // memoises the whole /ready aggregation (src/gateway/readiness.ts)\n // — a second, independent layer at a different scope; the two compose\n // without conflict since neither assumes anything about the other's TTL.\n //\n // Does not affect `doctor`'s deployment-mismatch cross-check: that reads\n // asset/network/payTo straight from `/.well-known/agent-commerce` (static\n // provider config, echoed live, never cached), not from health().\n const HEALTH_CACHE_MS = 5_000;\n let cachedHealth: { at: number; value: AdapterHealth } | undefined;\n let inFlightHealth: Promise<AdapterHealth> | undefined;\n\n async function health(): Promise<AdapterHealth> {\n const now = clock.monotonicMs();\n if (cachedHealth && now - cachedHealth.at < HEALTH_CACHE_MS) {\n return cachedHealth.value;\n }\n if (inFlightHealth) return inFlightHealth;\n\n inFlightHealth = computeHealth()\n .then((value) => {\n cachedHealth = { at: clock.monotonicMs(), value };\n return value;\n })\n .finally(() => {\n inFlightHealth = undefined;\n });\n return inFlightHealth;\n }\n\n return {\n name: 'x402',\n descriptor,\n createRequirement,\n verify,\n settle,\n health,\n };\n}\n\nfunction isOnChainRevertError(err: unknown): boolean {\n return (\n err instanceof ContractFunctionRevertedError || err instanceof ContractFunctionExecutionError\n );\n}\n\n/**\n * `instanceof` checks first — these are the real error classes the pinned\n * viem@2.55.18 HTTP transport throws (see viem's `utils/rpc/http.js`, which\n * wraps every fetch failure, including connection-refused, in\n * `HttpRequestError` unless it is already a `TimeoutError`), plus the error\n * `waitForTransactionReceipt` itself throws when it gives up polling for a\n * receipt — precisely the \"broadcast succeeded, confirmation didn't\" case\n * this classification exists to catch. Substring matching\n * is kept only as a fallback for shapes not covered by a typed viem class\n * (e.g. a raw Node/undici error surfacing through some other path) — pinning\n * behaviour to message text is brittle across viem/undici upgrades, so the\n * instanceof checks should be preferred and grown over time as more real\n * failure shapes are seen.\n */\nfunction isProviderUnavailableError(err: unknown): boolean {\n if (\n err instanceof HttpRequestError ||\n err instanceof TimeoutError ||\n err instanceof WaitForTransactionReceiptTimeoutError\n ) {\n return true;\n }\n const message = describeError(err).toLowerCase();\n return (\n message.includes('econnrefused') ||\n message.includes('fetch failed') ||\n message.includes('enotfound') ||\n message.includes('etimedout') ||\n message.includes('timed out') ||\n message.includes('network error')\n );\n}\n\n// Error class name and message. viem puts the request URL in its messages and\n// an RPC URL often carries an API key, so each URL is cut to its origin.\nfunction describeError(err: unknown): string {\n const text = err instanceof Error ? `${err.name}: ${err.message}` : String(err);\n return text.replace(/\\bhttps?:\\/\\/[^\\s\"'<>]+/gi, (url) => describeRpc(url));\n}\n\n/**\n * True only when the RPC answers Anvil's own `anvil_nodeInfo` method — a\n * real network (including real Base Sepolia, which shares chain id 84532\n * with this project's local chain by design) returns a JSON-RPC \"method\n * not found\" error instead. Never throws.\n */\nasync function probeIsAnvilNode(\n client: ReturnType<typeof createLocalPublicClient>,\n): Promise<boolean> {\n // Anvil-only method: not part of viem's typed PublicRpcSchema, hence the cast.\n const request = client.request as unknown as (args: {\n method: string;\n params: unknown[];\n }) => Promise<unknown>;\n try {\n await request({ method: 'anvil_nodeInfo', params: [] });\n return true;\n } catch {\n return false;\n }\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/payments/x402/networks.ts","../src/payments/x402/local-chain/accounts.ts","../src/payments/x402/dev-key-guard.ts","../src/payments/x402/guardrails.ts"],"names":[],"mappings":"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","file":"chunk-PBYN7EK2.js","sourcesContent":["/**\n * The networks this gateway will settle on, as data.\n *\n * x402 v2 identifies a network by its CAIP-2 id, so the only thing an\n * operator has to change to move between environments is that string. What\n * the code needs on top of it — the chain id to sign against, a name a human\n * recognises, and whether real money is involved — lives here rather than\n * being derived at each call site.\n *\n * A registry rather than \"parse any `eip155:*`\" on purpose. The chain id is\n * parseable from any such string, but `mainnet` is not, and every guardrail in\n * `guardrails.ts` keys off it. An unknown id is refused at startup instead of\n * being quietly treated as a testnet.\n *\n * Base Sepolia and the local dev chain share the id `eip155:84532`: the local\n * chain deliberately reuses Base Sepolia's chain id so the unmodified x402 SDK\n * can talk to it. Nothing may infer \"public network\" from the network id alone\n * — that is what `resolveDeploymentMode` and the Anvil probe in `provider.ts`\n * are for.\n */\nimport { CommerceError } from '../../core/index.js';\n\nexport interface NetworkProfile {\n /** CAIP-2 identifier, e.g. `eip155:84532`. */\n readonly id: string;\n /** Signed into the buyer's EIP-712 domain. */\n readonly chainId: number;\n readonly displayName: string;\n readonly kind: 'testnet' | 'mainnet';\n /**\n * The USDC deployment this network is expected to settle in, with the EIP-712\n * domain the token actually reports. Enforced only on mainnet (see\n * `guardrails.ts`) — a testnet is where a mock token is a legitimate thing to\n * point at.\n *\n * `name` is not decorative and is not the symbol: it is signed into every\n * buyer's EIP-712 domain, and the two USDC deployments disagree. Base Sepolia\n * reports `\"USDC\"`; Base mainnet reports `\"USD Coin\"`. Configure the wrong\n * one and every payment is refused `invalid_exact_evm_token_name_mismatch`\n * after the buyer has signed. Read back from the contracts, not assumed.\n */\n readonly canonicalAsset?: {\n readonly symbol: string;\n readonly address: string;\n readonly name: string;\n readonly version: string;\n };\n}\n\nconst PROFILES: readonly NetworkProfile[] = [\n {\n id: 'eip155:84532',\n chainId: 84532,\n displayName: 'Base Sepolia',\n kind: 'testnet',\n canonicalAsset: {\n symbol: 'USDC',\n address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n name: 'USDC',\n version: '2',\n },\n },\n {\n id: 'eip155:8453',\n chainId: 8453,\n displayName: 'Base',\n kind: 'mainnet',\n canonicalAsset: {\n symbol: 'USDC',\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n name: 'USD Coin',\n version: '2',\n },\n },\n];\n\nconst BY_ID = new Map(PROFILES.map((profile) => [profile.id, profile]));\n\nexport const SUPPORTED_NETWORK_IDS: readonly string[] = PROFILES.map((p) => p.id);\n\nexport function findNetworkProfile(id: string): NetworkProfile | undefined {\n return BY_ID.get(id);\n}\n\nexport function requireNetworkProfile(id: string, path: string): NetworkProfile {\n const profile = BY_ID.get(id);\n if (!profile) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `${path}: \"${id}\" is not a supported network. Supported CAIP-2 identifiers: ${SUPPORTED_NETWORK_IDS.join(', ')}`,\n { details: { path, network: id } },\n );\n }\n return profile;\n}\n\n/**\n * What this deployment actually is, as opposed to what it is called.\n *\n * `local` is a property of the *facilitator*, not the network: settling\n * through the in-process facilitator against a dev node is local regardless of\n * the CAIP-2 id that node answers to. This distinction is the whole reason\n * diagnostics can say `eip155:84532` without claiming to be on public Base\n * Sepolia.\n */\nexport type DeploymentMode = 'local' | 'testnet' | 'mainnet';\n\nexport function resolveDeploymentMode(\n profile: NetworkProfile,\n facilitatorMode: 'local' | 'remote',\n): DeploymentMode {\n if (facilitatorMode === 'local') return 'local';\n return profile.kind;\n}\n\n/** The banner an operator must not be able to miss. Never printed for anything else. */\nexport const LIVE_MAINNET_BANNER = 'LIVE MAINNET MODE — REAL FUNDS';\n\nexport function describeDeploymentMode(mode: DeploymentMode): string {\n return mode === 'mainnet' ? LIVE_MAINNET_BANNER : mode.toUpperCase();\n}\n","/**\n * Anvil's well-known development accounts.\n *\n * LOCAL DEVELOPMENT ONLY — DO NOT FUND. These addresses and private keys are\n * derived from Foundry's public, well-documented default test mnemonic\n * (\"test test test test test test test test test test test junk\") and are\n * known to everyone who has ever run `anvil`. Anyone who sends real value to\n * one of these addresses on a real network will lose it.\n *\n * Index layout used by the local demo chain (see docs/contracts.md):\n * 0 — deployer / local facilitator signer (pays gas, broadcasts settlement)\n * 1 — merchant settlement destination (`payTo`)\n * 2 — buyer (signs EIP-3009 authorisations; never held by the gateway)\n */\nexport interface AnvilWellKnownAccount {\n readonly address: `0x${string}`;\n readonly privateKey: `0x${string}`;\n}\n\n/** Fixed-length tuple (not a bare array) so indexing by the documented layout above is fully typed. */\nexport const ANVIL_WELL_KNOWN_ACCOUNTS: readonly [\n AnvilWellKnownAccount,\n AnvilWellKnownAccount,\n AnvilWellKnownAccount,\n] = [\n {\n address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',\n privateKey: '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',\n },\n {\n address: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',\n privateKey: '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d',\n },\n {\n address: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',\n privateKey: '0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a',\n },\n];\n\nexport const LOCAL_FACILITATOR_ACCOUNT = ANVIL_WELL_KNOWN_ACCOUNTS[0];\nexport const LOCAL_MERCHANT_ACCOUNT = ANVIL_WELL_KNOWN_ACCOUNTS[1];\nexport const LOCAL_BUYER_ACCOUNT = ANVIL_WELL_KNOWN_ACCOUNTS[2];\n\n/** Safe label used everywhere a dev key appears in output, logs or manifests. */\nexport const DEV_KEY_LABEL = 'LOCAL DEVELOPMENT ONLY - DO NOT FUND';\n","/**\n * Prevents a well-known Anvil development private key — or a well-known\n * Anvil development *address* — from ever being used against anything other\n * than a loopback/private/dev RPC. Two symmetric mistakes, both covered:\n * signing settlement with a dev key (`assertDevKeyIsLocalOnly`), and routing\n * settlement revenue to a dev address (`assertPayToIsNotDevAddress`). The\n * second is the more consequential of the two — a wrong key merely fails to\n * sign, a wrong payTo silently succeeds and gives the money away, since the\n * private key behind every well-known Anvil address is public knowledge.\n *\n * Chain id alone cannot tell a real network from this project's local dev\n * chain: Base Sepolia's own chain id is 84532, the same id this project\n * deliberately reuses for the local chain so the unmodified x402 SDK can talk\n * to it. A dev key or dev payTo pointed at a real RPC by a config mistake is\n * instantly drainable — this is checked once at provider construction, not per\n * payment.\n */\nimport { CommerceError } from '../../core/index.js';\nimport { ANVIL_WELL_KNOWN_ACCOUNTS } from './local-chain/accounts.js';\n\nconst WELL_KNOWN_DEV_KEYS: ReadonlySet<string> = new Set(\n ANVIL_WELL_KNOWN_ACCOUNTS.map((a) => a.privateKey.toLowerCase()),\n);\n\nconst WELL_KNOWN_DEV_ADDRESSES: ReadonlySet<string> = new Set(\n ANVIL_WELL_KNOWN_ACCOUNTS.map((a) => a.address.toLowerCase()),\n);\n\n/** `0x` + 64 hex chars — the only shape `privateKeyToAccount` accepts. */\nconst PRIVATE_KEY_SHAPE = /^0x[0-9a-fA-F]{64}$/;\n\nexport function isWellKnownDevKey(privateKey: string): boolean {\n return WELL_KNOWN_DEV_KEYS.has(privateKey.toLowerCase());\n}\n\nexport function isWellKnownDevAddress(address: string): boolean {\n return WELL_KNOWN_DEV_ADDRESSES.has(address.toLowerCase());\n}\n\n/**\n * True for loopback addresses, RFC1918 private ranges, and bare (dot-free)\n * hostnames — the shape of a docker-compose/k8s service name (e.g.\n * \"anvil\"), which a real public DNS name essentially never has.\n *\n * ASSUMPTION, and the loosest edge of this guard: every dot-free, colon-free\n * hostname is treated as private, with no exceptions. A single-label *public* hostname (no dots) is\n * essentially nonexistent in practice — ICANN does not delegate bare\n * gTLDs/TLDs as public A/AAAA records — but this function cannot tell \"no\n * dots because it's a compose service name\" from \"no dots because it's an\n * unusual real host\" if one somehow existed. If that assumption ever stops\n * holding, this is the line to revisit.\n */\nexport function isLikelyLocalOrPrivateHost(hostname: string): boolean {\n const h = hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n if (h === 'localhost' || h === '127.0.0.1' || h === '::1') return true;\n if (/^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(h)) return true;\n if (/^10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(h)) return true;\n if (/^192\\.168\\.\\d{1,3}\\.\\d{1,3}$/.test(h)) return true;\n if (/^172\\.(1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}$/.test(h)) return true;\n if (!h.includes('.') && !h.includes(':')) return true; // bare hostname\n return false;\n}\n\nfunction parseHostnameOrThrow(rpcUrl: string): string {\n try {\n return new URL(rpcUrl).hostname;\n } catch (cause) {\n // Not the URL itself: every commercial EVM RPC provider embeds an API key\n // in the path, and these messages reach `validate`, `doctor`, startup\n // output and CI logs.\n throw new CommerceError('CONFIG_INVALID', 'x402 provider: rpcUrl is not a valid URL', {\n cause,\n });\n }\n}\n\n/** Host only, for diagnostics. An RPC URL's path routinely carries a key. */\n/** Origin only: RPC URLs often carry an API key in the path or query */\nexport function describeRpc(rpcUrl: string): string {\n try {\n return new URL(rpcUrl).origin;\n } catch {\n return '[unparseable rpcUrl]';\n }\n}\n\n/**\n * Throws CONFIG_INVALID if a well-known dev key would sign against a non-local\n * RPC — or if `signerPrivateKey` isn't shaped like a private key at all.\n *\n * The shape check runs first and unconditionally. \"Not a key I recognise\"\n * (falls through `isWellKnownDevKey`, silently treated as someone's own real\n * facilitator key) and \"not a key at all\" (e.g. a truncated 63-char string)\n * must never share a code path: a malformed key that slips past this guard\n * only fails later, inside `settle()`, after the buyer's replayKey is already\n * reserved.\n */\nexport function assertDevKeyIsLocalOnly(rpcUrl: string, signerPrivateKey: string): void {\n if (!PRIVATE_KEY_SHAPE.test(signerPrivateKey)) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n 'x402 provider: facilitator.signerPrivateKey is not a well-formed private key ' +\n '(expected \"0x\" followed by exactly 64 hex characters).',\n );\n }\n\n if (!isWellKnownDevKey(signerPrivateKey)) return; // a real facilitator key: not our business\n\n const hostname = parseHostnameOrThrow(rpcUrl);\n\n if (!isLikelyLocalOrPrivateHost(hostname)) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n 'x402 provider: facilitator.signerPrivateKey is a well-known Anvil development key, but rpcUrl ' +\n `${describeRpc(rpcUrl)} does not look like a local/private chain. A public dev key must never sign against ` +\n 'a public network — it is instantly drainable and can grief real settlements via nonce exhaustion. ' +\n 'Use a real facilitator key for any non-local RPC, or point rpcUrl at your local/dev chain.',\n );\n }\n}\n\n/**\n * Throws CONFIG_INVALID if `payTo` (the settlement destination) is a\n * well-known Anvil development address and `rpcUrl` doesn't look\n * local/private.\n *\n * Mirrors `assertDevKeyIsLocalOnly`, but guards the *receiving* side of the\n * payment instead of the signing side, and — unlike the key guard — applies\n * regardless of facilitator mode: which account signs the settlement\n * transaction has no bearing on whether the destination address is one whose\n * private key is public knowledge. `agent-commerce init` defaults `payTo` to\n * a well-known Anvil address as a local-demo convenience; on a real network\n * that default routes every payment to an address anyone on earth can sweep.\n */\nexport function assertPayToIsNotDevAddress(rpcUrl: string, payTo: string): void {\n if (!isWellKnownDevAddress(payTo)) return; // not a dev address: not our business\n\n const hostname = parseHostnameOrThrow(rpcUrl);\n\n if (!isLikelyLocalOrPrivateHost(hostname)) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `x402 provider: \"payTo\" (${payTo}) is a well-known Anvil development address, but rpcUrl ` +\n `${describeRpc(rpcUrl)} does not look like a local/private chain. The private key behind that address ` +\n 'is public knowledge, so any revenue settled to it is immediately spendable by anyone. Set ' +\n '\"payTo\" to your own merchant wallet for any non-local RPC, or point rpcUrl at your ' +\n 'local/dev chain.',\n );\n }\n}\n","/**\n * Everything that must be true before this gateway is allowed to settle a\n * payment on the configured network.\n *\n * One definition, two callers: the provider runs it at construction so a\n * library consumer who never touches our config loader still gets the checks,\n * and `doctor` runs it against the parsed config so an operator sees the same\n * verdict without starting the gateway. Sharing a *call* is not sharing a\n * definition — the checks live here, and nothing re-implements them.\n *\n * Every failure is a startup failure. None of these are request-time\n * decisions: a deployment that is unsafe is unsafe before the first buyer\n * arrives, and finding out during `settle()` means the buyer's authorisation\n * is already burned.\n *\n * Peer-free by construction (no viem, no `@x402/*`) so the CLI can import it.\n */\nimport { CommerceError } from '../../core/index.js';\nimport { isLikelyLocalOrPrivateHost, isWellKnownDevAddress } from './dev-key-guard.js';\nimport {\n type DeploymentMode,\n type NetworkProfile,\n requireNetworkProfile,\n resolveDeploymentMode,\n} from './networks.js';\n\n/**\n * How the gateway authenticates to a remote facilitator.\n *\n * Deliberately a list, not a vendor: x402 facilitators are not a Coinbase-only\n * category, and a scheme that only fitted one vendor's credentials would make\n * the abstraction a fiction.\n *\n * - `none` — the facilitator takes no credential (the public testnet one).\n * - `bearer` — a static token. Covers most self-hosted and third-party\n * facilitators, and needs nothing installed.\n * - `cdp` — Coinbase Developer Platform, which signs a fresh JWT per request\n * over method + host + path, so a static header cannot express it. Handled by\n * the optional peer `@coinbase/x402`, imported only when this type is\n * configured. Anyone not using CDP never installs it.\n *\n * A facilitator whose scheme is none of these is refused at config load rather\n * than sent nothing.\n */\nexport type FacilitatorAuth =\n | { readonly type: 'none' }\n | { readonly type: 'bearer'; readonly token: string }\n | { readonly type: 'cdp'; readonly apiKeyId: string; readonly apiKeySecret: string };\n\nexport type X402FacilitatorConfig =\n | { readonly mode: 'local'; readonly signerPrivateKey: string }\n | { readonly mode: 'remote'; readonly url: string; readonly auth: FacilitatorAuth };\n\nexport interface X402DeploymentInput {\n readonly network: string;\n readonly payTo: string;\n readonly asset: string;\n /** EIP-712 domain of the asset, as the token itself reports it. */\n readonly assetName?: string;\n readonly assetVersion?: string;\n readonly facilitator: X402FacilitatorConfig;\n /** Required, and required to be `true`, before anything settles on a mainnet. */\n readonly allowMainnet?: boolean;\n /**\n * Required, and required to be `true`, to settle on a mainnet through a\n * facilitator that takes no credential.\n *\n * Separate from `allowMainnet` because it names a different decision: not\n * \"I meant to use real money\" but \"I accept this particular counterparty\n * without an account, terms, or anyone to call\".\n */\n readonly allowUnauthenticatedFacilitator?: boolean;\n /** Error-path prefix, `payments.x402` by default */\n readonly configPath?: string;\n /** Settlement-recipient field named in errors, `payTo` by default */\n readonly payToField?: string;\n}\n\nexport interface X402Deployment {\n readonly profile: NetworkProfile;\n readonly mode: DeploymentMode;\n}\n\nfunction invalid(message: string, path: string): CommerceError {\n return new CommerceError('CONFIG_INVALID', message, { details: { path } });\n}\n\n/**\n * Resolves the deployment and refuses every combination that could move real\n * money by accident. Order matters only in that the network must resolve\n * first; the rest are independent.\n */\nexport function resolveX402Deployment(input: X402DeploymentInput): X402Deployment {\n const at = input.configPath ?? 'payments.x402';\n const payTo = input.payToField ?? 'payTo';\n const profile = requireNetworkProfile(input.network, `${at}.network`);\n const mode = resolveDeploymentMode(profile, input.facilitator.mode);\n\n // The in-process facilitator signs with a key this process holds. Not a\n // custody problem — that signer never holds buyer or merchant funds, it pays\n // gas and broadcasts `transferWithAuthorization`, and the money moves buyer\n // to merchant directly on-chain. What it *is*, on a mainnet, is a funded key\n // inside the resource server: compromise that process and an attacker drains\n // the gas wallet and broadcasts from it. Separate processes, separate blast\n // radius — so it is refused, not warned about.\n if (profile.kind === 'mainnet' && input.facilitator.mode === 'local') {\n throw invalid(\n `${at}: network \"${profile.id}\" (${profile.displayName}) is a mainnet and cannot be served by facilitator.mode \"local\". A mainnet deployment must settle through a remote facilitator.`,\n `${at}.facilitator.mode`,\n );\n }\n\n if (mode === 'mainnet' && input.allowMainnet !== true) {\n throw invalid(\n `${at}: network \"${profile.id}\" (${profile.displayName}) settles real funds. Set ${at}.allowMainnet: true to acknowledge this explicitly - it is never the default.`,\n `${at}.allowMainnet`,\n );\n }\n\n if (input.facilitator.mode === 'remote') {\n assertFacilitatorUrlIsSafe(input.facilitator.url, mode, at);\n // Not a funds check. An EIP-3009 authorisation names its recipient, its\n // amount and its chain, so a facilitator can broadcast exactly that\n // transfer or nothing — it cannot redirect the money. What a credential\n // buys is a *relationship*: rate limits, terms, someone to call when\n // settlement stops. Running production payments through a counterparty you\n // have none of that with is a real choice, and this is where it gets made\n // explicitly rather than by omission.\n if (\n mode === 'mainnet' &&\n input.facilitator.auth.type === 'none' &&\n input.allowUnauthenticatedFacilitator !== true\n ) {\n throw invalid(\n `${at}: facilitator ${describeOrigin(input.facilitator.url)} takes no credential, and this is a mainnet deployment. It will see every payment authorisation you handle, with no account, terms or support behind it. Set ${at}.allowUnauthenticatedFacilitator: true to accept that, or configure facilitator.auth.`,\n `${at}.allowUnauthenticatedFacilitator`,\n );\n }\n // An empty credential is refused rather than sent: a blank token or key\n // reaches the facilitator as \"unauthenticated\" and fails every payment\n // after the buyer has already signed. `${VAR:- }` resolving to whitespace\n // is the realistic way this happens.\n for (const [field, value] of credentialFields(input.facilitator.auth)) {\n if (value.trim() === '') {\n throw invalid(\n `${at}: facilitator.auth.type is \"${input.facilitator.auth.type}\" but ${field} is empty. An empty credential is refused rather than sent.`,\n `${at}.facilitator.auth.${field}`,\n );\n }\n }\n }\n\n // The private key behind every well-known Anvil address is public knowledge.\n // `dev-key-guard` already refuses one against a public *RPC*; this refuses\n // one on any non-local *deployment*, which is the case a remote facilitator\n // creates — there the RPC host says nothing about where settlement lands.\n // The zero address lived only in the config loader, so a library consumer\n // calling `createX402PaymentProvider` directly — the path this shared\n // definition exists to cover — could boot a mainnet provider whose every\n // payment burns — sharing a *call* is not sharing a definition, and this\n // check had drifted out of the shared one.\n if (/^0x0{40}$/i.test(input.payTo)) {\n throw invalid(\n `${at}: \"${payTo}\" is the zero address. Every payment settled there is destroyed.`,\n `${at}.${payTo}`,\n );\n }\n\n if (mode !== 'local' && isWellKnownDevAddress(input.payTo)) {\n throw invalid(\n `${at}: \"${payTo}\" (${input.payTo}) is a well-known Anvil development address and this is a ${mode} deployment. Anyone can spend what settles there. Set ${payTo} to your own merchant wallet.`,\n `${at}.${payTo}`,\n );\n }\n\n // Mainnet only. A testnet is exactly where pointing at a mock token is the\n // right thing to do, so the same check there would block the normal case.\n const canonical = profile.canonicalAsset;\n if (mode === 'mainnet' && canonical) {\n if (!sameAddress(input.asset, canonical.address)) {\n throw invalid(\n `${at}: asset ${input.asset} is not ${canonical.symbol} on ${profile.displayName} (expected ${canonical.address}). Settling a mainnet payment in an unintended token is refused.`,\n `${at}.asset`,\n );\n }\n // The EIP-712 domain is signed by the buyer and checked by the scheme. Get\n // it wrong and every payment is refused `invalid_exact_evm_token_name_mismatch`\n // *after* the buyer signed — a config error charged to the buyer's patience.\n // Caught here instead, before the gateway starts.\n if (input.assetName !== undefined && input.assetName !== canonical.name) {\n throw invalid(\n `${at}: assetName \"${input.assetName}\" is not the EIP-712 domain name ${canonical.symbol} reports on ${profile.displayName} (expected \"${canonical.name}\"). Every payment would be refused after the buyer signed.`,\n `${at}.assetName`,\n );\n }\n if (input.assetVersion !== undefined && input.assetVersion !== canonical.version) {\n throw invalid(\n `${at}: assetVersion \"${input.assetVersion}\" is not the EIP-712 domain version ${canonical.symbol} reports on ${profile.displayName} (expected \"${canonical.version}\").`,\n `${at}.assetVersion`,\n );\n }\n }\n\n return { profile, mode };\n}\n\n/**\n * A facilitator sees every payment authorisation this gateway handles. Plain\n * HTTP to one on a public network puts those on the wire in the clear and\n * lets anyone in the path rewrite a settlement result, so it is allowed only\n * where the endpoint cannot leave the host — a local or private address.\n */\nfunction assertFacilitatorUrlIsSafe(url: string, mode: DeploymentMode, at: string): void {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch (cause) {\n throw new CommerceError('CONFIG_INVALID', `${at}: facilitator.url is not a valid URL`, {\n cause,\n details: { path: `${at}.facilitator.url` },\n });\n }\n\n if (parsed.protocol === 'https:') return;\n if (parsed.protocol !== 'http:') {\n throw invalid(\n `${at}: facilitator ${describeOrigin(url)} must be reached over https (or http on a local/private host); got \"${parsed.protocol}//\"`,\n `${at}.facilitator.url`,\n );\n }\n if (mode !== 'mainnet' && isLikelyLocalOrPrivateHost(parsed.hostname)) return;\n\n // The origin, never the whole URL: the path can carry a tenant or an API\n // key, which is why `/.well-known` withholds this field entirely. A refusal\n // message goes to `validate`, `doctor`, startup output and CI logs.\n throw invalid(\n `${at}: facilitator ${describeOrigin(url)} is reached over plain HTTP. Payment authorisations and settlement results would travel unencrypted. Use https, or point at a local/private host on a non-mainnet deployment.`,\n `${at}.facilitator.url`,\n );\n}\n\n/** Host only — a facilitator URL can carry a tenant path or an API key. */\nfunction describeOrigin(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n return '[unparseable facilitator.url]';\n }\n}\n\n/** The secret-bearing fields of an auth block, for emptiness checks only. Never logged. */\nfunction credentialFields(auth: FacilitatorAuth): readonly (readonly [string, string])[] {\n switch (auth.type) {\n case 'bearer':\n return [['token', auth.token]];\n case 'cdp':\n return [\n ['apiKeyId', auth.apiKeyId],\n ['apiKeySecret', auth.apiKeySecret],\n ];\n default:\n return [];\n }\n}\n\nfunction sameAddress(a: string, b: string): boolean {\n return a.toLowerCase() === b.toLowerCase();\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/authorization/ap2/constants.ts","../src/storage/sqlite.ts"],"names":["fsConstants"],"mappings":";;;;;;AAQO,IAAM,gBAAA,GAAmB;AAOzB,IAAM,SAAA,GAAY,CAAC,QAAQ;AAO3B,IAAM,qBAAA,GAAwB;AAG9B,IAAM,YAAA,GAAe;AACrB,IAAM,aAAA,GAAgB;AAGtB,IAAM,wBAAA,GAA2B;AASjC,IAAM,eAAA,GAAkB,CAAC,KAAA,EAAO,KAAA,EAAO,KAAK,GAAA,EAAK,KAAA,EAAO,OAAO,KAAK;AAOpE,IAAM,wBAAA,GAA2B;AAajC,IAAM,oBAAA,GAAuB;AAO7B,IAAM,oBAAA,GAAuB;AAG7B,IAAM,8BAAA,GAAiC;AAMvC,IAAM,0BAAA,GAA6B;ACzCnC,SAAS,mBAAmB,OAAA,EAA+C;AAChF,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,MAAA,EAAO,GAAI,OAAA;AAChC,EAAA,MAAM,eAAe,IAAA,KAAS,UAAA;AAE9B,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,MAAM,GAAA,GAAM,QAAQ,IAAI,CAAA;AACxB,IAAA,IAAI,QAAQ,EAAA,IAAM,GAAA,KAAQ,OAAO,CAAC,UAAA,CAAW,GAAG,CAAA,EAAG;AAGjD,MAAA,SAAA,CAAU,KAAK,EAAE,SAAA,EAAW,IAAA,EAAM,IAAA,EAAM,KAAO,CAAA;AAAA,IACjD;AAAA,EACF;AAUA,EAAA,IAAI,YAAA,IAAgB,UAAA,CAAW,IAAI,CAAA,EAAG;AACpC,IAAA,IAAI;AACF,MAAA,UAAA,CAAW,IAAA,EAAMA,UAAY,IAAI,CAAA;AAAA,IACnC,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,eAAA;AAAA,QACA,CAAA,EAAG,KAAK,CAAA,EAAA,EAAK,IAAI,CAAA,kDAAA,EAAqD,OAAO,OAAA,CAAQ,MAAA,KAAW,UAAA,GAAa,OAAA,CAAQ,MAAA,EAAO,GAAI,SAAS,CAAA,4KAAA,CAAA;AAAA,QACzI,EAAE,OAAA,EAAS,EAAE,IAAA,EAAK;AAAE,OACtB;AAAA,IACF;AAAA,EACF;AASA,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,IAAI;AACF,MAAA,SAAA,CAAU,QAAA,CAAS,IAAA,EAAM,GAAA,EAAK,GAAK,CAAC,CAAA;AAAA,IACtC,CAAA,CAAA,MAAQ;AAAA,IAIR;AAAA,EACF;AAEA,EAAA,MAAM,EAAA,GAAK,IAAI,QAAA,CAAS,IAAI,CAAA;AAC5B,EAAA,EAAA,CAAG,OAAO,oBAAoB,CAAA;AAC9B,EAAA,EAAA,CAAG,OAAO,mBAAmB,CAAA;AAC7B,EAAA,IAAI,YAAA,EAAc,2BAAA,CAA4B,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AACjE,EAAA,OAAO,EAAA;AACT;AAkBA,SAAS,2BAAA,CAA4B,IAAA,EAAc,KAAA,EAAe,MAAA,EAAsB;AACtF,EAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,IAAA,CAAA,EAAQ,CAAA,EAAG,IAAI,CAAA,IAAA,CAAM,CAAA,EAAG;AACvD,IAAA,IAAI;AACF,MAAA,SAAA,CAAU,MAAM,GAAK,CAAA;AAAA,IACvB,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,OAAQ,KAAA,CAAgC,IAAA;AAC9C,MAAA,IAAI,SAAS,QAAA,EAAU;AACvB,MAAA,MAAA,CAAO,IAAA;AAAA,QACL,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,QAAQ,SAAA,EAAU;AAAA,QACxC;AAAA,OACF;AAAA,IACF;AAAA,EACF;AACF","file":"chunk-US622BKF.js","sourcesContent":["/**\n * Pinned AP2 identifiers and key policy.\n *\n * AP2 v0.2.0 (2026-04-28, commit b4587ac) is the tagged release this gateway\n * verifies against; unversioned `main` is never implemented against. Config,\n * the verifier and `doctor` all read these, so a bump lands in one place.\n */\n\nexport const AP2_SPEC_VERSION = '0.2.0';\n\n/**\n * Autonomous mode needs open mandates, cnf-bound agent keys and constraint\n * evaluation over `checkout.line_items`. Half of that would be worse than a\n * declared Direct-only profile, so it is refused rather than partly served.\n */\nexport const AP2_MODES = ['direct'] as const;\nexport type Ap2Mode = (typeof AP2_MODES)[number];\n\n/**\n * One entry, so `alg=none` and the HMAC family are excluded by construction\n * rather than by a check that has to remember them\n */\nexport const AP2_SIGNING_ALGORITHM = 'ES256';\n\n/** The key type and curve ES256 implies. Any other pair is refused at load */\nexport const AP2_KEY_TYPE = 'EC';\nexport const AP2_JWK_CURVE = 'P-256';\n\n/** Byte length of a P-256 coordinate, before base64url encoding */\nexport const AP2_JWK_COORDINATE_BYTES = 32;\n\n/**\n * JWK members a verification key may carry.\n *\n * An allowlist, so private material (`d`) and anything naming a URL (`x5u`,\n * or a smuggled `jku`) is refused without this list having to name it. Keys\n * are configured inline and never fetched; see docs/security.md.\n */\nexport const AP2_JWK_MEMBERS = ['kty', 'crv', 'x', 'y', 'kid', 'alg', 'use'] as const;\n\n/**\n * Compared against this literal, never as a prefix. `mandate.checkout.open.1`\n * carries spending constraints this release does not evaluate, so accepting it\n * would tell a buyer their limits were checked when nothing read them.\n */\nexport const AP2_CHECKOUT_MANDATE_VCT = 'mandate.checkout.1';\n\n/**\n * The checkout profile every merchant checkout JWT must declare.\n *\n * Ours, not AP2's: AP2 leaves the checkout payload outside its scope, so the\n * claims a paid-resource invocation needs had to be specified somewhere.\n *\n * A bare name, matching the gateway's other wire identifiers\n * (`agent-commerce/delivery`, `agent-commerce/v1.0.0`). A profile id is a\n * namespace and is never dereferenced, so a URL would only tie the wire format\n * to a domain. Frozen once released: merchants sign it into every checkout JWT.\n */\nexport const AP2_CHECKOUT_PROFILE = 'agent-commerce/ap2/checkout/v1';\n\n/**\n * Taken from the SD-JWT `_sd_alg`, which defaults to sha-256 when absent.\n * Anything else is refused rather than hashed as sha-256 anyway, which would\n * check a presentation under an algorithm it never claimed.\n */\nexport const AP2_DIGEST_ALGORITHM = 'sha-256';\n\n/** Seconds of clock skew tolerated on mandate and checkout time claims */\nexport const AP2_DEFAULT_CLOCK_SKEW_SECONDS = 60;\n\n/**\n * Skew wide enough to cover a mandate's validity window stops `exp` rejecting\n * anything. An operator needing more than five minutes has a clock to fix.\n */\nexport const AP2_MAX_CLOCK_SKEW_SECONDS = 300;\n","/**\n * Opening a SQLite file safely.\n *\n * One definition, because every rule below was learned once and must not be\n * re-learned per store: the file is pre-created at 0600 before SQLite can\n * create it at `0666 & ~umask`, the WAL sidecars are narrowed after WAL is\n * enabled (they do not exist until then), and an existing but unwritable file\n * fails at startup instead of on the first write.\n *\n * Callers own their schema. This function opens and hardens; it migrates\n * nothing.\n */\nimport {\n accessSync,\n chmodSync,\n closeSync,\n existsSync,\n constants as fsConstants,\n mkdirSync,\n openSync,\n} from 'node:fs';\nimport { dirname } from 'node:path';\nimport Database from 'better-sqlite3';\nimport { CommerceError, type Logger } from '../core/index.js';\n\nexport interface OpenSqliteOptions {\n /** File path, or ':memory:' for tests. Parent directory is created if missing. */\n readonly path: string;\n /** Names the database in operator-facing errors, e.g. \"Receipt database\". */\n readonly label: string;\n readonly logger: Logger;\n}\n\nexport function openSqliteDatabase(options: OpenSqliteOptions): Database.Database {\n const { path, label, logger } = options;\n const isFileBacked = path !== ':memory:';\n\n if (isFileBacked) {\n const dir = dirname(path);\n if (dir !== '' && dir !== '.' && !existsSync(dir)) {\n // 0700 on directories we create ourselves. An existing directory is the\n // operator's to own and is deliberately left alone.\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n }\n\n // Fail at startup, not on the first write. `new Database(path)` happily opens\n // a file the process cannot write, and SQLite only says \"attempt to write a\n // readonly database\" once a write is attempted - which on a paid resource is\n // *after* the payment attempt reservation, surfacing as an opaque\n // STORAGE_ERROR per request. Readiness does catch it (503), but the operator\n // is left guessing. This is not hypothetical: switching the demo containers\n // to a non-root user left an existing named volume root-owned, and that is\n // exactly how it presented.\n if (isFileBacked && existsSync(path)) {\n try {\n accessSync(path, fsConstants.W_OK);\n } catch {\n throw new CommerceError(\n 'STORAGE_ERROR',\n `${label} \"${path}\" exists but is not writable by this process (uid ${typeof process.getuid === 'function' ? process.getuid() : 'unknown'}). If this is a container that recently changed user, an existing volume may still be owned by the previous one - recreate it (docker compose down -v) or fix its ownership.`,\n { details: { path } },\n );\n }\n }\n\n // Create the file ourselves, at 0600, *before* SQLite can create it at\n // `0666 & ~umask`. The chmod below only narrows the mode after the fact: a\n // local co-tenant who opens the file inside that window keeps a readable\n // descriptor across the chmod and reads everything written afterwards.\n // SQLite copies the main file's mode onto the -wal/-shm sidecars, so this one\n // call covers all three. `mode` applies on creation only, so an existing file\n // is untouched here and left to the chmod.\n if (isFileBacked) {\n try {\n closeSync(openSync(path, 'a', 0o600));\n } catch {\n // Deliberately silent: whatever stopped us (unwritable directory, exotic\n // filesystem) is about to be reported by `new Database` with a better\n // message, or is harmless and covered by the chmod below.\n }\n }\n\n const db = new Database(path);\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n if (isFileBacked) restrictDatabasePermissions(path, label, logger);\n return db;\n}\n\n/**\n * Narrow the database and its WAL sidecars to owner-only.\n *\n * `new Database(path)` opens with `0666 & ~umask`, so on a standard host the\n * `.sqlite`, `-wal` and `-shm` files landed at 0644 - any other local user\n * could read the whole commerce ledger: payer and payee addresses, amounts,\n * settlement transaction hashes, replay keys and the entire event stream. No\n * key material (the gateway is non-custodial and `redact.ts` is recursive), but\n * business metadata all the same.\n *\n * Called *after* `journal_mode = WAL`, because the sidecars do not exist until\n * then. Belt-and-braces since the main file is pre-created at 0600 above: this\n * still tightens a database that already existed with a looser mode.\n * Best-effort by design: a filesystem without POSIX modes must not stop the\n * gateway from starting, so a failure warns rather than throws.\n */\nfunction restrictDatabasePermissions(path: string, label: string, logger: Logger): void {\n for (const file of [path, `${path}-wal`, `${path}-shm`]) {\n try {\n chmodSync(file, 0o600);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') continue;\n logger.warn(\n { file, label, error: code ?? 'unknown' },\n 'could not restrict database permissions to owner-only',\n );\n }\n }\n}\n"]}