@devlab.group/agent-commerce 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -5
- package/dist/ap2.js +3 -3
- package/dist/{chunk-SY6GUYSQ.js → chunk-7ZMMXZ4G.js} +3 -3
- package/dist/{chunk-SY6GUYSQ.js.map → chunk-7ZMMXZ4G.js.map} +1 -1
- package/dist/{chunk-UHMYRV3J.js → chunk-HNRDZLSN.js} +7 -5
- package/dist/chunk-HNRDZLSN.js.map +1 -0
- package/dist/{chunk-LZS5BL3W.js → chunk-IEW7NSP2.js} +23 -5
- package/dist/chunk-IEW7NSP2.js.map +1 -0
- package/dist/{chunk-IFGRCXME.js → chunk-Y4RE3XYF.js} +3 -3
- package/dist/{chunk-IFGRCXME.js.map → chunk-Y4RE3XYF.js.map} +1 -1
- package/dist/cli/ap2-MBMQHFX4.js +678 -0
- package/dist/cli/ap2-MBMQHFX4.js.map +1 -0
- package/dist/cli/chunk-2ZZOGI5I.js +1352 -0
- package/dist/cli/chunk-2ZZOGI5I.js.map +1 -0
- package/dist/cli/chunk-3EQBCFZY.js +53 -0
- package/dist/cli/chunk-3EQBCFZY.js.map +1 -0
- package/dist/cli/chunk-3M6U7ILB.js +8 -0
- package/dist/cli/chunk-3M6U7ILB.js.map +1 -0
- package/dist/cli/chunk-3MGAJ5FX.js +70 -0
- package/dist/cli/chunk-3MGAJ5FX.js.map +1 -0
- package/dist/cli/chunk-5K4XEAZV.js +113 -0
- package/dist/cli/chunk-5K4XEAZV.js.map +1 -0
- package/dist/cli/chunk-7JNYFUT3.js +256 -0
- package/dist/cli/chunk-7JNYFUT3.js.map +1 -0
- package/dist/cli/chunk-AA3FIEAR.js +27 -0
- package/dist/cli/chunk-AA3FIEAR.js.map +1 -0
- package/dist/cli/chunk-FHCFR2GS.js +17 -0
- package/dist/cli/chunk-FHCFR2GS.js.map +1 -0
- package/dist/cli/chunk-FRMLWGSS.js +8 -0
- package/dist/cli/chunk-FRMLWGSS.js.map +1 -0
- package/dist/cli/chunk-KLX2YZDG.js +1400 -0
- package/dist/cli/chunk-KLX2YZDG.js.map +1 -0
- package/dist/cli/chunk-NSPPEF5M.js +334 -0
- package/dist/cli/chunk-NSPPEF5M.js.map +1 -0
- package/dist/cli/chunk-OSTCU6ZK.js +44 -0
- package/dist/cli/chunk-OSTCU6ZK.js.map +1 -0
- package/dist/cli/chunk-QQ3WY5L3.js +271 -0
- package/dist/cli/chunk-QQ3WY5L3.js.map +1 -0
- package/dist/cli/chunk-RWVPYAKC.js +1742 -0
- package/dist/cli/chunk-RWVPYAKC.js.map +1 -0
- package/dist/cli/chunk-SPAYKVUP.js +118 -0
- package/dist/cli/chunk-SPAYKVUP.js.map +1 -0
- package/dist/cli/chunk-SS3QFF5N.js +614 -0
- package/dist/cli/chunk-SS3QFF5N.js.map +1 -0
- package/dist/cli/chunk-TPC4EJLT.js +11 -0
- package/dist/cli/chunk-TPC4EJLT.js.map +1 -0
- package/dist/cli/config-4IBGVFSP.js +11 -0
- package/dist/cli/config-4IBGVFSP.js.map +1 -0
- package/dist/cli/index.js +150 -3627
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-CNWQ2MOE.js +559 -0
- package/dist/cli/mcp-CNWQ2MOE.js.map +1 -0
- package/dist/cli/near-5AY3HWYF.js +58 -0
- package/dist/cli/near-5AY3HWYF.js.map +1 -0
- package/dist/cli/provider-4BQDH56Y.js +396 -0
- package/dist/cli/provider-4BQDH56Y.js.map +1 -0
- package/dist/cli/run-5MB2D45X.js +7286 -0
- package/dist/cli/run-5MB2D45X.js.map +1 -0
- package/dist/cli/svm-3MMYFPC7.js +33 -0
- package/dist/cli/svm-3MMYFPC7.js.map +1 -0
- package/dist/cli/x402-NKR3WQDQ.js +96 -0
- package/dist/cli/x402-NKR3WQDQ.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +48 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +6 -16
- package/dist/mcp.js.map +1 -1
- package/dist/mpp.js +3 -3
- package/dist/x402.d.ts +5 -0
- package/dist/x402.js +4 -4
- package/package.json +2 -2
- package/dist/chunk-LZS5BL3W.js.map +0 -1
- package/dist/chunk-UHMYRV3J.js.map +0 -1
package/README.md
CHANGED
|
@@ -70,12 +70,24 @@ agent-commerce doctor
|
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
Requires **Node >= 22**. The package includes the `agent-commerce` CLI
|
|
73
|
-
(`init`, `validate`, `doctor`, `demo`, `import openapi`, `version`) and
|
|
74
|
-
for embedding the gateway.
|
|
73
|
+
(`init`, `validate`, `start`, `doctor`, `demo`, `import openapi`, `version`) and
|
|
74
|
+
a library for embedding the gateway.
|
|
75
75
|
The default install excludes optional protocol, payment and authorization
|
|
76
76
|
peers. The OpenAPI parser is a regular dependency because import is part of the
|
|
77
77
|
CLI.
|
|
78
78
|
|
|
79
|
+
```bash
|
|
80
|
+
agent-commerce start --config config.yaml --env-file .env
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`start` runs the configured gateway in the foreground until SIGTERM or SIGINT.
|
|
84
|
+
Install the optional peers for the features you enable, listed below. Missing
|
|
85
|
+
startup imports stop the gateway with an error naming the package; missing
|
|
86
|
+
Solana, NEAR or CDP peers fail provider health checks or payment requests.
|
|
87
|
+
`start`, `validate` and `doctor` accept `--env-file <path>` to load environment
|
|
88
|
+
variables before reading the config. Variables already set in the environment
|
|
89
|
+
take precedence. To embed the gateway in your own process, use the library:
|
|
90
|
+
|
|
79
91
|
```ts
|
|
80
92
|
import { createGateway, loadConfig, receipts } from '@devlab.group/agent-commerce';
|
|
81
93
|
|
|
@@ -135,6 +147,24 @@ missing package.
|
|
|
135
147
|
`facilitator.auth.type: cdp` and brings the larger CDP dependency tree. A
|
|
136
148
|
facilitator with a static token can use `auth.type: bearer` without it.
|
|
137
149
|
|
|
150
|
+
## Integrate with an AI coding agent
|
|
151
|
+
|
|
152
|
+
The repository includes an experimental [Agent Skills](https://agentskills.io)
|
|
153
|
+
skill, [`skills/agent-commerce`](skills/agent-commerce/SKILL.md), for adding the
|
|
154
|
+
gateway to an existing API. It covers Base Sepolia configuration, startup and
|
|
155
|
+
checks through an unpaid 402 challenge. Its instructions keep secrets out of
|
|
156
|
+
chat and leave payment signing to the user. The skill has automated CLI and
|
|
157
|
+
config checks.
|
|
158
|
+
|
|
159
|
+
```text
|
|
160
|
+
# Claude Code
|
|
161
|
+
/plugin marketplace add devlab-group/agent-commerce
|
|
162
|
+
/plugin install agent-commerce@agent-commerce
|
|
163
|
+
|
|
164
|
+
# Codex, Cursor and other agents (a third-party installer)
|
|
165
|
+
DISABLE_TELEMETRY=1 npx skills add devlab-group/agent-commerce --skill agent-commerce
|
|
166
|
+
```
|
|
167
|
+
|
|
138
168
|
## Quickstart
|
|
139
169
|
|
|
140
170
|
Requirements: **Node >= 22**, **npm 10**, **Docker**. Nothing else - no API
|
|
@@ -281,8 +311,8 @@ Minor releases may break experimental configurations, integrations or types.
|
|
|
281
311
|
This applies to MPP, A2A, ACP, AP2 and `agent-commerce import openapi`.
|
|
282
312
|
Runtime adapters and providers report `status: experimental` in
|
|
283
313
|
`GET /.well-known/agent-commerce`. Pin an exact version and test upgrades
|
|
284
|
-
before deploying them. 2.1
|
|
285
|
-
|
|
314
|
+
before deploying them. Since 2.1, some supported x402 behavior and types
|
|
315
|
+
differ from 2.0; see [Upgrading from 2.0 to 2.x](docs/migration-2.1.md).
|
|
286
316
|
|
|
287
317
|
## Payment model
|
|
288
318
|
|
|
@@ -427,7 +457,7 @@ INFO ACP disabled
|
|
|
427
457
|
INFO AP2 disabled
|
|
428
458
|
PASS Payments x402 v2 (scheme=exact) enabled - LOCAL dev chain (eip155:31337), destination=0x7099…79C8, facilitator=local (in-process), paymentFlow=authorization
|
|
429
459
|
INFO Payments (MPP) MPP not configured
|
|
430
|
-
PASS Storage sqlite schema
|
|
460
|
+
PASS Storage sqlite schema v3 writable; receipts=2
|
|
431
461
|
PASS Protocol versions reported by gateway /.well-known/agent-commerce
|
|
432
462
|
|
|
433
463
|
Score: 7/7 checks passed
|
package/dist/ap2.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AP2_CHECKOUT_MANDATE_VCT, AP2_SIGNING_ALGORITHM, AP2_DIGEST_ALGORITHM, AP2_CHECKOUT_PROFILE, AP2_SPEC_VERSION, AP2_KEY_TYPE, AP2_JWK_CURVE, openSqliteDatabase } from './chunk-
|
|
2
|
-
export { AP2_CHECKOUT_MANDATE_VCT, AP2_CHECKOUT_PROFILE, AP2_DEFAULT_CLOCK_SKEW_SECONDS, AP2_MAX_CLOCK_SKEW_SECONDS, AP2_SIGNING_ALGORITHM, AP2_SPEC_VERSION } from './chunk-
|
|
3
|
-
import { systemClock, NOOP_LOGGER, CommerceError, PACKAGE_VERSION } from './chunk-
|
|
1
|
+
import { AP2_CHECKOUT_MANDATE_VCT, AP2_SIGNING_ALGORITHM, AP2_DIGEST_ALGORITHM, AP2_CHECKOUT_PROFILE, AP2_SPEC_VERSION, AP2_KEY_TYPE, AP2_JWK_CURVE, openSqliteDatabase } from './chunk-IEW7NSP2.js';
|
|
2
|
+
export { AP2_CHECKOUT_MANDATE_VCT, AP2_CHECKOUT_PROFILE, AP2_DEFAULT_CLOCK_SKEW_SECONDS, AP2_MAX_CLOCK_SKEW_SECONDS, AP2_SIGNING_ALGORITHM, AP2_SPEC_VERSION } from './chunk-IEW7NSP2.js';
|
|
3
|
+
import { systemClock, NOOP_LOGGER, CommerceError, PACKAGE_VERSION } from './chunk-7ZMMXZ4G.js';
|
|
4
4
|
import { isRecord } from './chunk-2CJNA7MS.js';
|
|
5
5
|
import { SignJWT, importPKCS8, importJWK, jwtVerify, decodeProtectedHeader, decodeJwt } from 'jose';
|
|
6
6
|
import canonicalize from 'canonicalize';
|
|
@@ -306,8 +306,8 @@ var systemClock = {
|
|
|
306
306
|
nowIso: () => (/* @__PURE__ */ new Date()).toISOString(),
|
|
307
307
|
monotonicMs: () => performance.now()
|
|
308
308
|
};
|
|
309
|
-
var PACKAGE_VERSION = "2.
|
|
309
|
+
var PACKAGE_VERSION = "2.2.0" ;
|
|
310
310
|
|
|
311
311
|
export { AUTHORIZATION_HEADER, AUTHORIZATION_INPUT_FIELD, COMMERCE_ERROR_CODES, COMMERCE_ERROR_HTTP_STATUS, COMMERCE_EVENT_TYPES, CommerceError, DEFAULT_BACKEND_TIMEOUT_MS, DELIVERY_SUMMARY_META_KEY, MAX_AUTHORIZATION_HEADER_BYTES, NOOP_LOGGER, PACKAGE_VERSION, PAYMENT_HEADER, PAYMENT_INPUT_FIELD, PAYMENT_METHOD_NAMES, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, PROTOCOL_NAMES, RESERVED_INPUT_FIELDS, RETRYABLE_ERROR_CODES, describeError, extractReservedInputFields, isCommerceError, isHttpProtocolAdapter, isPaymentRequiredEnvelope, parseAuthorizationHeader, parseAuthorizationSubmission, redactedErrorText, systemClock, toCommerceError, toDeliverySummary, toErrorEnvelope, toLogInfo, toPaymentRequiredEnvelope };
|
|
312
|
-
//# sourceMappingURL=chunk-
|
|
313
|
-
//# sourceMappingURL=chunk-
|
|
312
|
+
//# sourceMappingURL=chunk-7ZMMXZ4G.js.map
|
|
313
|
+
//# sourceMappingURL=chunk-7ZMMXZ4G.js.map
|
|
@@ -1 +1 @@
|
|
|
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-SY6GUYSQ.js","sourcesContent":["// Shared primitive aliases for the canonical domain model. FROZEN CONTRACT\n\n/**\n * A JSON Schema document (in practice a draft 2020-12 subset). Deliberately\n * loose: adapters translate it to their own schema representation. Never treat\n * it as trusted input without validation.\n */\nexport type JsonSchema = Record<string, unknown>;\n\n/** Protocol surfaces a resource can be exposed through */\nexport type ProtocolName = 'http' | 'mcp' | 'a2a' | 'acp';\n\n// A Record over the union fails to compile when a name is missing or extra\nconst PROTOCOL_NAME_KEYS: Record<ProtocolName, true> = {\n http: true,\n mcp: true,\n a2a: true,\n acp: true,\n};\n\n/**\n * The same names as a value, for code that checks one at runtime: config\n * validation and the OpenAPI importer's `--expose`\n */\nexport const PROTOCOL_NAMES: readonly ProtocolName[] = Object.keys(\n PROTOCOL_NAME_KEYS,\n) as ProtocolName[];\n\n/**\n * Payment rails a resource can accept.\n *\n * A resource's list is an ordered candidate list, not a buyer-selected menu.\n * The pipeline uses the first method with an enabled provider, and a\n * rejection ends the request instead of trying another rail. Config requires at\n * least one named rail to be enabled and permits others that are not.\n */\nexport type PaymentMethodName = 'x402' | 'mpp';\n\n// Checked for completeness the same way as PROTOCOL_NAME_KEYS\nconst PAYMENT_METHOD_NAME_KEYS: Record<PaymentMethodName, true> = { x402: true, mpp: true };\n\n/** The same names as a value, for config validation */\nexport const PAYMENT_METHOD_NAMES: readonly PaymentMethodName[] = Object.keys(\n PAYMENT_METHOD_NAME_KEYS,\n) as PaymentMethodName[];\n\n/**\n * Authorization methods a resource can require. Neither a transport nor a\n * payment rail: it proves the purchase was approved, and sits beside the\n * payment rather than 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 as a string in the currency's display unit (for example\n * \"0.01\" USDC), never a float and never base units. Payment providers convert\n * it to on-chain base units.\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 * Results per checked part, such as each x402 offer. Names and statuses\n * may be published; exclude diagnostic detail.\n */\n readonly components?: readonly AdapterHealthComponent[];\n}\n\n/** One part of an {@link AdapterHealth} result */\nexport interface AdapterHealthComponent {\n readonly name: string;\n readonly status: 'pass' | 'warn' | 'fail';\n}\n\n/** Describes an adapter's supported surface for diagnostics */\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, printed by `doctor` */\n readonly unsupported?: readonly string[];\n}\n","/**\n * Canonical commerce events. FROZEN CONTRACT. Every event in one flow shares\n * one `requestId`, which correlates logs, payment attempts, backend calls and\n * receipts.\n */\nimport type { IsoTimestamp } from './common';\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 for every authorization method, so an audit-trail\n // reader never 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. `emit` must not throw: a sink failure must never\n * fail an otherwise successful commerce flow.\n */\nexport interface EventSink {\n emit(event: CommerceEvent): Promise<void>;\n}\n","// Canonical resource model. FROZEN CONTRACT\nimport type {\n AuthorizationMethodName,\n DecimalAmount,\n JsonSchema,\n PaymentMethodName,\n ProtocolName,\n} from './common';\n\n/** HTTP methods a backend handler may use */\nexport type BackendMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\n/**\n * How the gateway calls the merchant's existing backend.\n *\n * Backend URLs come from operator configuration only, never from users or\n * agents (docs/security.md, SSRF). Secret header values belong in `${ENV_VAR}`\n * placeholders resolved by the config loader, not in 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 * When absent, `{param}` values come from top-level input and everything left\n * over becomes the query string (GET/DELETE) or the whole JSON body\n * (POST/PUT/PATCH). That cannot express an operation with path, query and\n * body at once, such as `POST /users/{userId}/orders?notify=true`.\n *\n * When present, each group comes from its named property, and top-level input\n * that no binding names is not forwarded.\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. `dynamic` exists in the type for forward compatibility;\n * config validation rejects it and the pipeline refuses it as defense in depth.\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. Protocol adapters map it outward and\n * 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. Opt-in per\n * resource. It sits beside `paymentMethods`, not inside it, because an\n * authorization method is not a payment rail and must never be selectable as\n * 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. FROZEN CONTRACT. Protocol adapters map them into\n * their own response format. Never throw a bare string or untyped Error across\n * an area 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. Every payment failure maps to a\n * 4xx or 5xx status, never to a 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: a 402 tells a client to pay and retry, which cannot fix a\n // missing or rejected mandate, and a client that auto-pays on 402 would be\n // charged for a request that was 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 // The verifier or replay store was unreachable, so the mandate got no\n // verdict. The same proof can verify once the outage clears.\n 'AUTHORIZATION_PROVIDER_UNAVAILABLE',\n 'BACKEND_TIMEOUT',\n // Load shedding is transient: the caller should back off and try again.\n // Clients act on this flag, and leaving it out would make a momentary\n // throttle look like a permanent failure.\n 'GATEWAY_BUSY',\n]);\n","// The single error type crossing area boundaries. FROZEN CONTRACT\nimport { COMMERCE_ERROR_HTTP_STATUS, type CommerceErrorCode, RETRYABLE_ERROR_CODES } from './codes';\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/** Serializable 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. `cause` is never included */\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 * Passes an existing CommerceError through. Other thrown values become a\n * CommerceError with a caller-chosen message, for example\n * `toCommerceError(err, 'BACKEND_ERROR', 'Backend call failed')`.\n *\n * Arbitrary Error messages may contain internal URLs, hostnames or file paths.\n * The original value remains on `cause` for internal logging; `toInfo()` and\n * `toErrorEnvelope()` do not serialize it.\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/** A thrown value reduced to its message and name, for a log line */\nexport function describeError(error: unknown): { message: string; name?: string } {\n if (error instanceof Error) return { message: error.message, name: error.name };\n return { message: String(error) };\n}\n\n/**\n * `Name: message` for a log line, with every URL cut to its scheme and host,\n * because a backend or RPC URL can carry a credential in its userinfo, path or\n * query\n */\nexport function redactedErrorText(value: unknown): string {\n const text = value instanceof Error ? `${value.name}: ${value.message}` : String(value);\n return text.replace(/\\b[a-z][a-z\\d+.-]*:\\/\\/[^\\s\"'<>]+/gi, (match) => {\n try {\n const url = new URL(match);\n return `${url.protocol}//${url.host}`;\n } catch {\n return '[unparseable URL]';\n }\n });\n}\n\n// Deepest `cause` level toLogInfo() follows, which also ends a cyclic chain\nconst MAX_LOGGED_CAUSES = 5;\n\n/**\n * An error for an operator log line: the `toInfo()` fields plus the `cause`\n * chain that `toInfo()` leaves out, each level as `redactedErrorText()` gives it\n */\nexport function toLogInfo(\n value: unknown,\n): CommerceErrorInfo & { readonly cause?: readonly string[] } {\n const error = toCommerceError(value);\n const cause: string[] = [];\n let current = error.cause;\n while (current !== undefined && cause.length < MAX_LOGGED_CAUSES) {\n cause.push(redactedErrorText(current));\n current = current instanceof Error ? current.cause : undefined;\n }\n return cause.length > 0 ? { ...error.toInfo(), cause } : error.toInfo();\n}\n","/**\n * Gateway-defined wire envelopes and carriers. FROZEN CONTRACT.\n *\n * The HTTP routes and the MCP and A2A adapters build their \"payment required\"\n * and \"error\" bodies with these helpers, so those surfaces send the same\n * shapes. The ACP adapter maps errors to ACP's own error format instead.\n */\n\nimport { CommerceError, type CommerceErrorCode } from '../errors';\nimport { isRecord } from '../is-record';\nimport type { AuthorizationRequirement, AuthorizationSubmission } from './authorization';\nimport type { DecimalAmount, IsoTimestamp, PaymentMethodName } from './common';\nimport type { PaymentSubmission } from './payment';\nimport type { DeliveredOutcome, PaymentRequiredOutcome } from './request';\nimport type { CommerceResource } from './resource';\n\n/**\n * Reserved input property carrying a payment proof on protocols with no header\n * channel (MCP tool calls, A2A message data). HTTP uses a header instead.\n */\nexport const PAYMENT_INPUT_FIELD = '_payment';\n\n/**\n * HTTP request header carrying an x402 payment proof. MPP proofs use\n * `Authorization: Payment ...` instead.\n *\n * The x402 v2 header names, lowercased as Node presents incoming headers. v1's\n * `X-PAYMENT` / `X-PAYMENT-RESPONSE` pair is not accepted: honoring both\n * versions would mean 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 counterpart of\n * {@link PAYMENT_INPUT_FIELD}.\n *\n * `_payment` is a bare string whose method is taken from the resource's first\n * payment method. This field is a `{ method, payload }` object, because the\n * method of a security control should be stated, not inferred.\n */\nexport const AUTHORIZATION_INPUT_FIELD = '_authorization';\n\n/**\n * Every input property name the gateway claims for itself. The config loader\n * rejects a resource declaring one, protocol adapters lift them out of client\n * input, and the pipeline strips them again as defense in depth.\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 JSON\n * of the same `{ method, payload }` object the reserved input field carries.\n *\n * An Agent Commerce carrier, not a header from any authorization\n * specification. It is namespaced rather than reusing `Authorization`, which\n * already carries other credentials, including MPP payment proofs.\n */\nexport const AUTHORIZATION_HEADER = 'agent-authorization';\n\n/**\n * Hard cap on the encoded `Agent-Authorization` header.\n *\n * Node's default limit is 16 KiB across all request headers, and a request over\n * it is refused before the gateway sees it. Capping well below that gives an\n * oversized proof a deterministic `AUTHORIZATION_INVALID` naming the limit.\n */\nexport const MAX_AUTHORIZATION_HEADER_BYTES = 8192;\n\n/**\n * HTTP response header carrying the base64 x402 challenge on a 402.\n *\n * The body still carries the richer {@link PaymentRequiredEnvelope}, the only\n * channel MCP has, but an x402 v2 client reads the challenge from this header\n * 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 the A2A task artifact's\n * metadata.\n *\n * Part of the frozen contract because producer and consumer must agree on it;\n * both import this constant. Follows MCP's `<namespace>/<name>` convention for\n * `_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 /**\n * @deprecated Read each offer's `payTo` in `accepts`. Absent when the\n * challenge offers several destinations.\n */\n readonly destination?: string;\n /** @deprecated Read each offer's `network` in `accepts` */\n readonly network?: string;\n /** @deprecated Read each offer's `asset` in `accepts` */\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 it straight to its SDK.\n */\n readonly envelope?: Readonly<Record<string, unknown>>;\n };\n /**\n * Present only when the resource also requires an authorization proof, so a\n * client learns before it spends anything that paying alone will not get the\n * resource delivered. A client that ignores the field sees the plain\n * envelope. The proof comes from the merchant's own approval flow, outside\n * 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: the request, whether\n * it settled, and the settlement reference they can check on-chain. The\n * merchant's ledger is not theirs to read, which is why `/api/receipts` is an\n * operator route behind `server.adminToken`.\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 ...(r.destination !== undefined ? { 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 object, whichever carrier\n * brought it. Absent returns `undefined`; malformed throws\n * `AUTHORIZATION_INVALID`.\n *\n * An unusable `_payment` is dropped, which leaves the buyer a 402 to act on. A\n * dropped authorization would instead come back as \"not authorized\", with no\n * way to tell a rejected mandate from a typo in the object 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 (!isRecord(value)) {\n return fail(`expected an object with \"method\" and \"payload\", got ${typeof value}`);\n }\n const method = value['method'];\n const payload = value['payload'];\n\n // Compared against the literal rather than a registry: a second method needs\n // a second verifier, a deliberate addition rather than a string that starts\n // working because 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. The size check runs\n * on the encoded value, so an oversized header costs a length comparison rather\n * than a decode and a JSON parse.\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, for\n * protocols that carry them in the input object (MCP tool arguments, A2A\n * message data). HTTP carries both in headers.\n *\n * A payment proof is labeled with the resource's first payment method.\n * `createGateway` puts provider-backed methods first so the label matches the\n * pipeline's selection; a custom registry must keep that order. A resource with\n * no payment method gets no payment proof, so the request reaches the pipeline\n * unpaid.\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. Core does not depend on pino; the gateway injects\n * a pino instance that satisfies this shape.\n *\n * Never log secrets: private keys, seed phrases, Authorization headers or\n * payment authorization 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 */\nexport const NOOP_LOGGER: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n child: () => NOOP_LOGGER,\n};\n","/**\n * Protocol adapter boundary. FROZEN CONTRACT.\n *\n * An adapter translates a protocol's wire format into a `CanonicalRequest`,\n * hands it to the execution pipeline and maps the outcome back. It must not\n * call merchant backends, implement payment logic or hold its own copy of the\n * canonical model. A failure while starting or serving one adapter must not\n * stop the others.\n */\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { AdapterDescriptor, AdapterHealth, ProtocolName } from '../domain/common';\nimport type { EventSink } from '../domain/event';\nimport type { ExecutionPipeline } from '../domain/request';\nimport type { ResourceRegistry } from '../domain/resource';\nimport type { Logger } from './logger';\nimport type { Clock, IdGenerator } from './runtime';\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. The gateway mounts `handleHttp` at\n * `mountPath` with raw Node request and response objects, so adapters stay\n * independent of the HTTP framework.\n *\n * Guarantee: `req` arrives with its body stream unread. The gateway suppresses\n * every body parser on the mount, so an adapter whose SDK reads the body itself\n * (MCP's Streamable HTTP transport) can do so. The adapter owns reading,\n * size-limiting beyond the gateway's own cap, and parsing.\n *\n * The guarantee can break silently. Fastify prefers its exact-match\n * `application/json` and `text/plain` parsers over a `'*'` wildcard, so a\n * wildcard no-op alone lets the JSON parser drain the body and the adapter\n * reads an empty stream. The MCP conformance suite drives `handleHttp` over a\n * bare `node:http` server and cannot catch it, so any change to adapter mounting\n * needs a test that POSTs a JSON body through the real gateway and asserts the\n * adapter received 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`: unread\n * body, concurrency cap and failure isolation.\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 and 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","// Time and ids are injected so tests can be deterministic\nimport type { IsoTimestamp } from '../domain/common';\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 * The build injects `__OAC_PACKAGE_VERSION__` (tsup.config.ts), because a\n * relative manifest path resolves from the wrong depth once `src/**` is\n * bundled. From source, the root manifest is read instead. `typeof` on an\n * undeclared identifier is safe, so the source path runs without the constant.\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
|
+
{"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-7ZMMXZ4G.js","sourcesContent":["// Shared primitive aliases for the canonical domain model. FROZEN CONTRACT\n\n/**\n * A JSON Schema document (in practice a draft 2020-12 subset). Deliberately\n * loose: adapters translate it to their own schema representation. Never treat\n * it as trusted input without validation.\n */\nexport type JsonSchema = Record<string, unknown>;\n\n/** Protocol surfaces a resource can be exposed through */\nexport type ProtocolName = 'http' | 'mcp' | 'a2a' | 'acp';\n\n// A Record over the union fails to compile when a name is missing or extra\nconst PROTOCOL_NAME_KEYS: Record<ProtocolName, true> = {\n http: true,\n mcp: true,\n a2a: true,\n acp: true,\n};\n\n/**\n * The same names as a value, for code that checks one at runtime: config\n * validation and the OpenAPI importer's `--expose`\n */\nexport const PROTOCOL_NAMES: readonly ProtocolName[] = Object.keys(\n PROTOCOL_NAME_KEYS,\n) as ProtocolName[];\n\n/**\n * Payment rails a resource can accept.\n *\n * A resource's list is an ordered candidate list, not a buyer-selected menu.\n * The pipeline uses the first method with an enabled provider, and a\n * rejection ends the request instead of trying another rail. Config requires at\n * least one named rail to be enabled and permits others that are not.\n */\nexport type PaymentMethodName = 'x402' | 'mpp';\n\n// Checked for completeness the same way as PROTOCOL_NAME_KEYS\nconst PAYMENT_METHOD_NAME_KEYS: Record<PaymentMethodName, true> = { x402: true, mpp: true };\n\n/** The same names as a value, for config validation */\nexport const PAYMENT_METHOD_NAMES: readonly PaymentMethodName[] = Object.keys(\n PAYMENT_METHOD_NAME_KEYS,\n) as PaymentMethodName[];\n\n/**\n * Authorization methods a resource can require. Neither a transport nor a\n * payment rail: it proves the purchase was approved, and sits beside the\n * payment rather than 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 as a string in the currency's display unit (for example\n * \"0.01\" USDC), never a float and never base units. Payment providers convert\n * it to on-chain base units.\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 * Results per checked part, such as each x402 offer. Names and statuses\n * may be published; exclude diagnostic detail.\n */\n readonly components?: readonly AdapterHealthComponent[];\n}\n\n/** One part of an {@link AdapterHealth} result */\nexport interface AdapterHealthComponent {\n readonly name: string;\n readonly status: 'pass' | 'warn' | 'fail';\n}\n\n/** Describes an adapter's supported surface for diagnostics */\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, printed by `doctor` */\n readonly unsupported?: readonly string[];\n}\n","/**\n * Canonical commerce events. FROZEN CONTRACT. Every event in one flow shares\n * one `requestId`, which correlates logs, payment attempts, backend calls and\n * receipts.\n */\nimport type { IsoTimestamp } from './common';\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 for every authorization method, so an audit-trail\n // reader never 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. `emit` must not throw: a sink failure must never\n * fail an otherwise successful commerce flow.\n */\nexport interface EventSink {\n emit(event: CommerceEvent): Promise<void>;\n}\n","// Canonical resource model. FROZEN CONTRACT\nimport type {\n AuthorizationMethodName,\n DecimalAmount,\n JsonSchema,\n PaymentMethodName,\n ProtocolName,\n} from './common';\n\n/** HTTP methods a backend handler may use */\nexport type BackendMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n\n/**\n * How the gateway calls the merchant's existing backend.\n *\n * Backend URLs come from operator configuration only, never from users or\n * agents (docs/security.md, SSRF). Secret header values belong in `${ENV_VAR}`\n * placeholders resolved by the config loader, not in 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 * When absent, `{param}` values come from top-level input and everything left\n * over becomes the query string (GET/DELETE) or the whole JSON body\n * (POST/PUT/PATCH). That cannot express an operation with path, query and\n * body at once, such as `POST /users/{userId}/orders?notify=true`.\n *\n * When present, each group comes from its named property, and top-level input\n * that no binding names is not forwarded.\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. `dynamic` exists in the type for forward compatibility;\n * config validation rejects it and the pipeline refuses it as defense in depth.\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. Protocol adapters map it outward and\n * 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. Opt-in per\n * resource. It sits beside `paymentMethods`, not inside it, because an\n * authorization method is not a payment rail and must never be selectable as\n * 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. FROZEN CONTRACT. Protocol adapters map them into\n * their own response format. Never throw a bare string or untyped Error across\n * an area 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. Every payment failure maps to a\n * 4xx or 5xx status, never to a 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: a 402 tells a client to pay and retry, which cannot fix a\n // missing or rejected mandate, and a client that auto-pays on 402 would be\n // charged for a request that was 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 // The verifier or replay store was unreachable, so the mandate got no\n // verdict. The same proof can verify once the outage clears.\n 'AUTHORIZATION_PROVIDER_UNAVAILABLE',\n 'BACKEND_TIMEOUT',\n // Load shedding is transient: the caller should back off and try again.\n // Clients act on this flag, and leaving it out would make a momentary\n // throttle look like a permanent failure.\n 'GATEWAY_BUSY',\n]);\n","// The single error type crossing area boundaries. FROZEN CONTRACT\nimport { COMMERCE_ERROR_HTTP_STATUS, type CommerceErrorCode, RETRYABLE_ERROR_CODES } from './codes';\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/** Serializable 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. `cause` is never included */\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 * Passes an existing CommerceError through. Other thrown values become a\n * CommerceError with a caller-chosen message, for example\n * `toCommerceError(err, 'BACKEND_ERROR', 'Backend call failed')`.\n *\n * Arbitrary Error messages may contain internal URLs, hostnames or file paths.\n * The original value remains on `cause` for internal logging; `toInfo()` and\n * `toErrorEnvelope()` do not serialize it.\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/** A thrown value reduced to its message and name, for a log line */\nexport function describeError(error: unknown): { message: string; name?: string } {\n if (error instanceof Error) return { message: error.message, name: error.name };\n return { message: String(error) };\n}\n\n/**\n * `Name: message` for a log line, with every URL cut to its scheme and host,\n * because a backend or RPC URL can carry a credential in its userinfo, path or\n * query\n */\nexport function redactedErrorText(value: unknown): string {\n const text = value instanceof Error ? `${value.name}: ${value.message}` : String(value);\n return text.replace(/\\b[a-z][a-z\\d+.-]*:\\/\\/[^\\s\"'<>]+/gi, (match) => {\n try {\n const url = new URL(match);\n return `${url.protocol}//${url.host}`;\n } catch {\n return '[unparseable URL]';\n }\n });\n}\n\n// Deepest `cause` level toLogInfo() follows, which also ends a cyclic chain\nconst MAX_LOGGED_CAUSES = 5;\n\n/**\n * An error for an operator log line: the `toInfo()` fields plus the `cause`\n * chain that `toInfo()` leaves out, each level as `redactedErrorText()` gives it\n */\nexport function toLogInfo(\n value: unknown,\n): CommerceErrorInfo & { readonly cause?: readonly string[] } {\n const error = toCommerceError(value);\n const cause: string[] = [];\n let current = error.cause;\n while (current !== undefined && cause.length < MAX_LOGGED_CAUSES) {\n cause.push(redactedErrorText(current));\n current = current instanceof Error ? current.cause : undefined;\n }\n return cause.length > 0 ? { ...error.toInfo(), cause } : error.toInfo();\n}\n","/**\n * Gateway-defined wire envelopes and carriers. FROZEN CONTRACT.\n *\n * The HTTP routes and the MCP and A2A adapters build their \"payment required\"\n * and \"error\" bodies with these helpers, so those surfaces send the same\n * shapes. The ACP adapter maps errors to ACP's own error format instead.\n */\n\nimport { CommerceError, type CommerceErrorCode } from '../errors';\nimport { isRecord } from '../is-record';\nimport type { AuthorizationRequirement, AuthorizationSubmission } from './authorization';\nimport type { DecimalAmount, IsoTimestamp, PaymentMethodName } from './common';\nimport type { PaymentSubmission } from './payment';\nimport type { DeliveredOutcome, PaymentRequiredOutcome } from './request';\nimport type { CommerceResource } from './resource';\n\n/**\n * Reserved input property carrying a payment proof on protocols with no header\n * channel (MCP tool calls, A2A message data). HTTP uses a header instead.\n */\nexport const PAYMENT_INPUT_FIELD = '_payment';\n\n/**\n * HTTP request header carrying an x402 payment proof. MPP proofs use\n * `Authorization: Payment ...` instead.\n *\n * The x402 v2 header names, lowercased as Node presents incoming headers. v1's\n * `X-PAYMENT` / `X-PAYMENT-RESPONSE` pair is not accepted: honoring both\n * versions would mean 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 counterpart of\n * {@link PAYMENT_INPUT_FIELD}.\n *\n * `_payment` is a bare string whose method is taken from the resource's first\n * payment method. This field is a `{ method, payload }` object, because the\n * method of a security control should be stated, not inferred.\n */\nexport const AUTHORIZATION_INPUT_FIELD = '_authorization';\n\n/**\n * Every input property name the gateway claims for itself. The config loader\n * rejects a resource declaring one, protocol adapters lift them out of client\n * input, and the pipeline strips them again as defense in depth.\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 JSON\n * of the same `{ method, payload }` object the reserved input field carries.\n *\n * An Agent Commerce carrier, not a header from any authorization\n * specification. It is namespaced rather than reusing `Authorization`, which\n * already carries other credentials, including MPP payment proofs.\n */\nexport const AUTHORIZATION_HEADER = 'agent-authorization';\n\n/**\n * Hard cap on the encoded `Agent-Authorization` header.\n *\n * Node's default limit is 16 KiB across all request headers, and a request over\n * it is refused before the gateway sees it. Capping well below that gives an\n * oversized proof a deterministic `AUTHORIZATION_INVALID` naming the limit.\n */\nexport const MAX_AUTHORIZATION_HEADER_BYTES = 8192;\n\n/**\n * HTTP response header carrying the base64 x402 challenge on a 402.\n *\n * The body still carries the richer {@link PaymentRequiredEnvelope}, the only\n * channel MCP has, but an x402 v2 client reads the challenge from this header\n * 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 the A2A task artifact's\n * metadata.\n *\n * Part of the frozen contract because producer and consumer must agree on it;\n * both import this constant. Follows MCP's `<namespace>/<name>` convention for\n * `_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 /**\n * @deprecated Read each offer's `payTo` in `accepts`. Absent when the\n * challenge offers several destinations.\n */\n readonly destination?: string;\n /** @deprecated Read each offer's `network` in `accepts` */\n readonly network?: string;\n /** @deprecated Read each offer's `asset` in `accepts` */\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 it straight to its SDK.\n */\n readonly envelope?: Readonly<Record<string, unknown>>;\n };\n /**\n * Present only when the resource also requires an authorization proof, so a\n * client learns before it spends anything that paying alone will not get the\n * resource delivered. A client that ignores the field sees the plain\n * envelope. The proof comes from the merchant's own approval flow, outside\n * 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: the request, whether\n * it settled, and the settlement reference they can check on-chain. The\n * merchant's ledger is not theirs to read, which is why `/api/receipts` is an\n * operator route behind `server.adminToken`.\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 ...(r.destination !== undefined ? { 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 object, whichever carrier\n * brought it. Absent returns `undefined`; malformed throws\n * `AUTHORIZATION_INVALID`.\n *\n * An unusable `_payment` is dropped, which leaves the buyer a 402 to act on. A\n * dropped authorization would instead come back as \"not authorized\", with no\n * way to tell a rejected mandate from a typo in the object 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 (!isRecord(value)) {\n return fail(`expected an object with \"method\" and \"payload\", got ${typeof value}`);\n }\n const method = value['method'];\n const payload = value['payload'];\n\n // Compared against the literal rather than a registry: a second method needs\n // a second verifier, a deliberate addition rather than a string that starts\n // working because 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. The size check runs\n * on the encoded value, so an oversized header costs a length comparison rather\n * than a decode and a JSON parse.\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, for\n * protocols that carry them in the input object (MCP tool arguments, A2A\n * message data). HTTP carries both in headers.\n *\n * A payment proof is labeled with the resource's first payment method.\n * `createGateway` puts provider-backed methods first so the label matches the\n * pipeline's selection; a custom registry must keep that order. A resource with\n * no payment method gets no payment proof, so the request reaches the pipeline\n * unpaid.\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. Core does not depend on pino; the gateway injects\n * a pino instance that satisfies this shape.\n *\n * Never log secrets: private keys, seed phrases, Authorization headers or\n * payment authorization 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 */\nexport const NOOP_LOGGER: Logger = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n child: () => NOOP_LOGGER,\n};\n","/**\n * Protocol adapter boundary. FROZEN CONTRACT.\n *\n * An adapter translates a protocol's wire format into a `CanonicalRequest`,\n * hands it to the execution pipeline and maps the outcome back. It must not\n * call merchant backends, implement payment logic or hold its own copy of the\n * canonical model. A failure while starting or serving one adapter must not\n * stop the others.\n */\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { AdapterDescriptor, AdapterHealth, ProtocolName } from '../domain/common';\nimport type { EventSink } from '../domain/event';\nimport type { ExecutionPipeline } from '../domain/request';\nimport type { ResourceRegistry } from '../domain/resource';\nimport type { Logger } from './logger';\nimport type { Clock, IdGenerator } from './runtime';\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. The gateway mounts `handleHttp` at\n * `mountPath` with raw Node request and response objects, so adapters stay\n * independent of the HTTP framework.\n *\n * Guarantee: `req` arrives with its body stream unread. The gateway suppresses\n * every body parser on the mount, so an adapter whose SDK reads the body itself\n * (MCP's Streamable HTTP transport) can do so. The adapter owns reading,\n * size-limiting beyond the gateway's own cap, and parsing.\n *\n * The guarantee can break silently. Fastify prefers its exact-match\n * `application/json` and `text/plain` parsers over a `'*'` wildcard, so a\n * wildcard no-op alone lets the JSON parser drain the body and the adapter\n * reads an empty stream. The MCP conformance suite drives `handleHttp` over a\n * bare `node:http` server and cannot catch it, so any change to adapter mounting\n * needs a test that POSTs a JSON body through the real gateway and asserts the\n * adapter received 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`: unread\n * body, concurrency cap and failure isolation.\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 and 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","// Time and ids are injected so tests can be deterministic\nimport type { IsoTimestamp } from '../domain/common';\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 * The build injects `__OAC_PACKAGE_VERSION__` (tsup.config.ts), because a\n * relative manifest path resolves from the wrong depth once `src/**` is\n * bundled. From source, the root manifest is read instead. `typeof` on an\n * undeclared identifier is safe, so the source path runs without the constant.\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,5 +1,5 @@
|
|
|
1
|
-
import { findX402Network, normalizeAddress, assertPayToIsNotDevAddress, resolveX402Deployment, assertDevKeyIsLocalOnly, describeRpc, X402_DEFAULT_PAYMENT_FLOW, REUSE_REJECTED_AUTHORIZATION_METADATA_KEY, SETTLE_AFTER_BACKEND_METADATA_KEY, sameAddress, LOCAL_CHAIN_ID, isTransactionReference, x402OfferName, isEvmAddress, describeDeploymentMode } from './chunk-
|
|
2
|
-
import { CommerceError, systemClock, NOOP_LOGGER, PACKAGE_VERSION, redactedErrorText } from './chunk-
|
|
1
|
+
import { findX402Network, normalizeAddress, assertPayToIsNotDevAddress, resolveX402Deployment, assertDevKeyIsLocalOnly, describeRpc, X402_DEFAULT_PAYMENT_FLOW, REUSE_REJECTED_AUTHORIZATION_METADATA_KEY, SETTLE_AFTER_BACKEND_METADATA_KEY, sameAddress, LOCAL_CHAIN_ID, isTransactionReference, x402OfferName, isEvmAddress, describeDeploymentMode } from './chunk-Y4RE3XYF.js';
|
|
2
|
+
import { CommerceError, systemClock, NOOP_LOGGER, PACKAGE_VERSION, redactedErrorText } from './chunk-7ZMMXZ4G.js';
|
|
3
3
|
import { computeReplayKey, computePermit2ReplayKey } from './chunk-KA2AX5FH.js';
|
|
4
4
|
import { isRecord } from './chunk-2CJNA7MS.js';
|
|
5
5
|
import { x402ExactPermit2ProxyAddress, toFacilitatorEvmSigner, PERMIT2_ADDRESS } from '@x402/evm';
|
|
@@ -876,7 +876,9 @@ function createRequirementBuilders(ctx, svmFeePayer) {
|
|
|
876
876
|
resource: {
|
|
877
877
|
url: single ? `resource://agent-commerce/${encodeURIComponent(single.network)}/${single.payTo}/resources/${resourceId}` : `resource://agent-commerce/resources/${resourceId}`,
|
|
878
878
|
description: context.resource.description ?? context.resource.name,
|
|
879
|
-
|
|
879
|
+
// The media type the merchant declares, else `application/json`; an HTTP
|
|
880
|
+
// delivery carries the backend's own type when it is text and fits the body
|
|
881
|
+
mimeType: options.resourceMimeTypes?.[context.resource.id] ?? DEFAULT_MIME_TYPE
|
|
880
882
|
},
|
|
881
883
|
accepts
|
|
882
884
|
};
|
|
@@ -1392,5 +1394,5 @@ function loadOptionalModule(load, missing) {
|
|
|
1392
1394
|
}
|
|
1393
1395
|
|
|
1394
1396
|
export { DEFAULT_IDS, chainIdFromCaip2, createX402PaymentProvider, parseCanonicalAmount };
|
|
1395
|
-
//# sourceMappingURL=chunk-
|
|
1396
|
-
//# sourceMappingURL=chunk-
|
|
1397
|
+
//# sourceMappingURL=chunk-HNRDZLSN.js.map
|
|
1398
|
+
//# sourceMappingURL=chunk-HNRDZLSN.js.map
|