@devlab.group/agent-commerce 1.3.0 → 1.4.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.
package/dist/index.d.ts CHANGED
@@ -1,8 +1,11 @@
1
- import { I as IsoTimestamp, D as DecimalAmount, P as PaymentMethodName, B as BackendHandler, A as AdapterDescriptor, a as AdapterHealth, C as CommerceResource, R as ResourceRegistry, b as PaymentProvider, L as Logger, c as Clock, d as IdGenerator } from './runtime-Plk5Peqi.js';
2
- export { e as BackendMethod, f as DEFAULT_BACKEND_TIMEOUT_MS, J as JsonSchema, N as NOOP_LOGGER, g as PROTOCOL_NAMES, h as PaymentChallenge, i as PaymentContext, j as PaymentRequirement, k as PaymentResult, l as PaymentSettlementContext, m as PaymentSubmission, n as PaymentVerificationContext, o as Pricing, p as ProtocolName, s as systemClock } from './runtime-Plk5Peqi.js';
1
+ import { f as Ap2AuthorizationConfig } from './types-CJtwLu1c.js';
2
+ import { I as IsoTimestamp, D as DecimalAmount, P as PaymentMethodName, a as CommerceResource, b as PaymentSubmission, B as BackendHandler, A as AdapterDescriptor, c as AdapterHealth, R as ResourceRegistry, d as PaymentProvider, L as Logger, C as Clock, e as IdGenerator } from './runtime-CKq3d_3K.js';
3
+ export { f as AuthorizationMethodName, g as BackendMethod, h as DEFAULT_BACKEND_TIMEOUT_MS, J as JsonSchema, N as NOOP_LOGGER, i as PROTOCOL_NAMES, j as PaymentChallenge, k as PaymentContext, l as PaymentRequirement, m as PaymentResult, n as PaymentSettlementContext, o as PaymentVerificationContext, p as Pricing, q as ProtocolName, s as systemClock } from './runtime-CKq3d_3K.js';
3
4
  import { X as X402FacilitatorConfig } from './guardrails-Dmwi63KB.js';
4
- import { D as DeliveredOutcome, P as PaymentRequiredOutcome, C as CommerceEvent, a as PaymentAttempt, b as CommerceReceipt, E as ExecutionPipeline, c as ProtocolAdapter, H as HttpProtocolAdapter, A as AdapterHttpRoute, d as ProtocolAdapterContext } from './protocol-adapter-DTFGWGXq.js';
5
- export { e as COMMERCE_EVENT_TYPES, f as CanonicalRequest, g as CommerceEventType, h as EventSink, i as ExecutionOutcome, j as isHttpProtocolAdapter } from './protocol-adapter-DTFGWGXq.js';
5
+ import { a as AuthorizationRequirement, b as AuthorizationSubmission, A as AuthorizationProvider } from './authorization-CPDcpJVa.js';
6
+ export { c as AuthorizationFinalizeContext, d as AuthorizationRecord, e as AuthorizationVerification, f as AuthorizationVerificationContext } from './authorization-CPDcpJVa.js';
7
+ import { D as DeliveredOutcome, P as PaymentRequiredOutcome, C as CommerceEvent, a as PaymentAttempt, b as CommerceReceipt, E as ExecutionPipeline, c as ProtocolAdapter, H as HttpProtocolAdapter, A as AdapterHttpRoute, d as ProtocolAdapterContext } from './protocol-adapter-Bebmggf_.js';
8
+ export { e as COMMERCE_EVENT_TYPES, f as CanonicalRequest, g as CommerceEventType, h as EventSink, i as ExecutionOutcome, j as isHttpProtocolAdapter } from './protocol-adapter-Bebmggf_.js';
6
9
  import { FastifyInstance } from 'fastify';
7
10
  import { IncomingMessage, ServerResponse } from 'node:http';
8
11
 
@@ -12,7 +15,7 @@ import { IncomingMessage, ServerResponse } from 'node:http';
12
15
  * FROZEN CONTRACT. Protocol adapters map these codes into their own response
13
16
  * format. Never throw a bare string or untyped Error across a package boundary.
14
17
  */
15
- declare const COMMERCE_ERROR_CODES: readonly ["CONFIG_INVALID", "RESOURCE_NOT_FOUND", "INPUT_INVALID", "PAYMENT_REQUIRED", "PAYMENT_INVALID", "PAYMENT_REPLAYED", "PAYMENT_PROVIDER_UNAVAILABLE", "PAYMENT_SETTLEMENT_FAILED", "BACKEND_TIMEOUT", "BACKEND_ERROR", "PROTOCOL_UNSUPPORTED", "GATEWAY_BUSY", "STORAGE_ERROR", "INTERNAL_ERROR"];
18
+ declare const COMMERCE_ERROR_CODES: readonly ["CONFIG_INVALID", "RESOURCE_NOT_FOUND", "INPUT_INVALID", "PAYMENT_REQUIRED", "PAYMENT_INVALID", "PAYMENT_REPLAYED", "PAYMENT_PROVIDER_UNAVAILABLE", "PAYMENT_SETTLEMENT_FAILED", "AUTHORIZATION_REQUIRED", "AUTHORIZATION_INVALID", "AUTHORIZATION_REPLAYED", "AUTHORIZATION_PROVIDER_UNAVAILABLE", "BACKEND_TIMEOUT", "BACKEND_ERROR", "PROTOCOL_UNSUPPORTED", "GATEWAY_BUSY", "STORAGE_ERROR", "INTERNAL_ERROR"];
16
19
  type CommerceErrorCode = (typeof COMMERCE_ERROR_CODES)[number];
17
20
  /**
18
21
  * Canonical HTTP status for each error code.
@@ -109,6 +112,47 @@ declare const PAYMENT_INPUT_FIELD = "_payment";
109
112
  declare const PAYMENT_HEADER = "payment-signature";
110
113
  /** HTTP response header carrying the settlement result. */
111
114
  declare const PAYMENT_RESPONSE_HEADER = "payment-response";
115
+ /**
116
+ * Reserved input property carrying an authorization proof, the authorization
117
+ * counterpart of {@link PAYMENT_INPUT_FIELD}.
118
+ *
119
+ * Unlike `_payment`, which is a bare string, this one carries an object:
120
+ * `{ method, payload }`. There is exactly one payment rail per resource, so a
121
+ * payment proof's method can be inferred from the resource; an authorization
122
+ * proof cannot lean on that, and guessing the method of a security control is
123
+ * not a thing to do implicitly.
124
+ */
125
+ declare const AUTHORIZATION_INPUT_FIELD = "_authorization";
126
+ /**
127
+ * Every input property name the gateway claims for itself.
128
+ *
129
+ * One list, read by the config loader (which rejects a resource declaring any
130
+ * of them), by the protocol adapters that lift them out of client input, and
131
+ * by the pipeline that strips them again as defence in depth. Those three
132
+ * agree by construction instead of by three copies of two strings.
133
+ */
134
+ declare const RESERVED_INPUT_FIELDS: readonly string[];
135
+ /**
136
+ * HTTP request header carrying the authorization proof, base64url-encoded
137
+ * JSON of the same `{ method, payload }` envelope the reserved input field
138
+ * carries.
139
+ *
140
+ * This is an Agent Commerce transport carrier, not a header defined by any
141
+ * authorization specification, so it is namespaced rather than borrowing
142
+ * `Authorization`, which already means something else on every one of these
143
+ * routes.
144
+ */
145
+ declare const AUTHORIZATION_HEADER = "agent-authorization";
146
+ /**
147
+ * Hard cap on the encoded `Agent-Authorization` header.
148
+ *
149
+ * Node's own limit is ~16 KiB across *all* request headers, so an
150
+ * authorization near that size would start evicting everything else and fail
151
+ * as an unreadable transport error rather than a legible one. Capping well
152
+ * below it means an oversized proof gets a deterministic
153
+ * AUTHORIZATION_INVALID naming the limit.
154
+ */
155
+ declare const MAX_AUTHORIZATION_HEADER_BYTES = 8192;
112
156
  /**
113
157
  * HTTP response header carrying the base64 payment challenge on a 402.
114
158
  *
@@ -154,6 +198,19 @@ interface PaymentRequiredEnvelope {
154
198
  */
155
199
  readonly envelope?: Readonly<Record<string, unknown>>;
156
200
  };
201
+ /**
202
+ * Present only when the resource requires an authorization proof as well.
203
+ *
204
+ * Additive: a client that does not understand the field sees exactly the
205
+ * envelope it saw before. A client that does learns, before it spends
206
+ * anything, that paying alone will not get the resource delivered.
207
+ *
208
+ * This advertises a requirement; it does not issue anything. The proof is
209
+ * obtained from the merchant's own approval flow, outside the gateway.
210
+ */
211
+ readonly authorization?: {
212
+ readonly required: readonly AuthorizationRequirement[];
213
+ };
157
214
  }
158
215
  interface ErrorEnvelope {
159
216
  readonly status: 'error';
@@ -196,6 +253,42 @@ declare function toDeliverySummary(outcome: DeliveredOutcome): DeliverySummary;
196
253
  declare function toPaymentRequiredEnvelope(outcome: PaymentRequiredOutcome): PaymentRequiredEnvelope;
197
254
  declare function toErrorEnvelope(error: CommerceError): ErrorEnvelope;
198
255
  declare function isPaymentRequiredEnvelope(value: unknown): value is PaymentRequiredEnvelope;
256
+ /**
257
+ * Parses the `{ method, payload }` authorization envelope, whichever carrier
258
+ * brought it.
259
+ *
260
+ * Absent is `undefined`. Present but malformed throws, rather than being
261
+ * dropped the way an unusable `_payment` is. A dropped payment leaves the
262
+ * buyer holding a 402 they can act on. A silently dropped authorization would
263
+ * come back as "not authorized" for a proof the client believes it sent, with
264
+ * no way to tell a rejected mandate from a typo in the envelope around it.
265
+ */
266
+ declare function parseAuthorizationSubmission(value: unknown, requestId?: string): AuthorizationSubmission | undefined;
267
+ /**
268
+ * Decodes the base64url-JSON `Agent-Authorization` header.
269
+ *
270
+ * The size check runs on the encoded value before any decoding, so an
271
+ * oversized header costs a length comparison rather than a base64 decode and
272
+ * a JSON parse of whatever a caller chose to send.
273
+ */
274
+ declare function parseAuthorizationHeader(raw: string | readonly string[] | undefined, requestId?: string): AuthorizationSubmission | undefined;
275
+ /**
276
+ * Splits raw client input into resource input plus the reserved fields the
277
+ * gateway claims, for every protocol that carries them in the input object
278
+ * (MCP tool arguments, A2A message data). HTTP carries both in headers and
279
+ * uses the two parse helpers directly.
280
+ *
281
+ * The payment method comes from the resource's own declaration. This is not
282
+ * the place that decides which rail a resource uses, so a proof for a
283
+ * resource with no configured rail is dropped rather than forwarded under an
284
+ * invented method. The pipeline then treats the request as unpaid and decides
285
+ * on its own terms.
286
+ */
287
+ declare function extractReservedInputFields(rawInput: Record<string, unknown>, resource: CommerceResource | undefined, requestId?: string): {
288
+ input: Record<string, unknown>;
289
+ payment?: PaymentSubmission;
290
+ authorization?: AuthorizationSubmission;
291
+ };
199
292
 
200
293
  /**
201
294
  * Merchant backend execution boundary.
@@ -210,6 +303,16 @@ interface BackendRequest {
210
303
  readonly resourceId: string;
211
304
  /** Validated resource input. */
212
305
  readonly input: unknown;
306
+ /**
307
+ * Names the *operation*, so the merchant can recognise a repeat of it.
308
+ *
309
+ * Not `requestId`, which is fresh per call and would make every retry look
310
+ * like new work. An adapter sets this only when it can derive a value that
311
+ * survives a client retry, a reconnect and a gateway restart; the HTTP
312
+ * executor forwards it as the `Idempotency-Key` request header. Absent
313
+ * means the protocol has no such notion, and the merchant sees no header.
314
+ */
315
+ readonly idempotencyKey?: string;
213
316
  }
214
317
  interface BackendResponse {
215
318
  readonly status: number;
@@ -444,6 +547,13 @@ interface GatewayConfig {
444
547
  readonly allowUnauthenticatedFacilitator?: boolean;
445
548
  };
446
549
  };
550
+ /**
551
+ * Absent when no `authorization:` block is configured, which is how every
552
+ * config written before AP2 existed reads.
553
+ */
554
+ readonly authorization?: {
555
+ readonly ap2: Ap2AuthorizationConfig;
556
+ };
447
557
  }
448
558
  declare function parseConfig(raw: unknown, env: NodeJS.ProcessEnv): GatewayConfig;
449
559
 
@@ -463,6 +573,8 @@ interface GatewayOptions {
463
573
  readonly config: GatewayConfig;
464
574
  readonly store: ReceiptStore;
465
575
  readonly paymentProviders: readonly PaymentProvider[];
576
+ /** Absent means no resource requires authorization, which is the default */
577
+ readonly authorizationProviders?: readonly AuthorizationProvider[];
466
578
  readonly protocolAdapters: readonly ProtocolAdapter[];
467
579
  readonly logger?: Logger;
468
580
  readonly clock?: Clock;
@@ -528,8 +640,14 @@ declare class AcpProtocolAdapter implements HttpProtocolAdapter {
528
640
  private readonly token;
529
641
  private readonly operations;
530
642
  private readonly idempotencyOptions;
531
- /** Derived once: the token is fixed, and only its digest may be persisted. */
532
- private readonly identityHash;
643
+ /**
644
+ * What an idempotency claim is scoped to, from `context.publicBaseUrl`.
645
+ *
646
+ * Not readonly because, unlike the token, it is known only once the adapter
647
+ * starts. Worth that: scoping by the credential meant a rotation freed
648
+ * every outstanding claim.
649
+ */
650
+ private deployment;
533
651
  private readonly discoveryMetadata;
534
652
  private idempotency;
535
653
  private resources;
@@ -579,4 +697,4 @@ interface SqliteReceiptStoreOptions {
579
697
  }
580
698
  declare function createSqliteReceiptStore(options: SqliteReceiptStoreOptions): ReceiptStore;
581
699
 
582
- export { ACP_API_VERSION, ACP_SPEC_VERSION, ACP_WELL_KNOWN_PATH, type AcpAdapterOptions, AdapterDescriptor, AdapterHealth, AdapterHttpRoute, type BackendExecutor, BackendHandler, type BackendRequest, type BackendResponse, COMMERCE_ERROR_CODES, COMMERCE_ERROR_HTTP_STATUS, Clock, CommerceError, type CommerceErrorCode, type CommerceErrorInfo, type CommerceErrorOptions, CommerceEvent, CommerceReceipt, CommerceResource, DELIVERY_SUMMARY_META_KEY, DecimalAmount, DeliveredOutcome, type DeliverySummary, type ErrorEnvelope, ExecutionPipeline, type GatewayConfig, type GatewayInstance, type GatewayOptions, HttpProtocolAdapter, IdGenerator, IsoTimestamp, type ListOptions, Logger, PAYMENT_HEADER, PAYMENT_INPUT_FIELD, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, PaymentAttempt, type PaymentAttemptReservation, type PaymentAttemptUpdate, PaymentMethodName, PaymentProvider, type PaymentRequiredEnvelope, PaymentRequiredOutcome, ProtocolAdapter, ProtocolAdapterContext, RETRYABLE_ERROR_CODES, type ReceiptStore, ResourceRegistry, createAcpAdapter, createGateway, createSqliteReceiptStore, isCommerceError, isPaymentRequiredEnvelope, loadConfig, parseConfig, createSqliteReceiptStore as receipts, toCommerceError, toDeliverySummary, toErrorEnvelope, toPaymentRequiredEnvelope };
700
+ export { ACP_API_VERSION, ACP_SPEC_VERSION, ACP_WELL_KNOWN_PATH, AUTHORIZATION_HEADER, AUTHORIZATION_INPUT_FIELD, type AcpAdapterOptions, AdapterDescriptor, AdapterHealth, AdapterHttpRoute, AuthorizationProvider, AuthorizationRequirement, AuthorizationSubmission, type BackendExecutor, BackendHandler, type BackendRequest, type BackendResponse, COMMERCE_ERROR_CODES, COMMERCE_ERROR_HTTP_STATUS, Clock, CommerceError, type CommerceErrorCode, type CommerceErrorInfo, type CommerceErrorOptions, CommerceEvent, CommerceReceipt, CommerceResource, DELIVERY_SUMMARY_META_KEY, DecimalAmount, DeliveredOutcome, type DeliverySummary, type ErrorEnvelope, ExecutionPipeline, type GatewayConfig, type GatewayInstance, type GatewayOptions, HttpProtocolAdapter, IdGenerator, IsoTimestamp, type ListOptions, Logger, MAX_AUTHORIZATION_HEADER_BYTES, PAYMENT_HEADER, PAYMENT_INPUT_FIELD, PAYMENT_REQUIRED_HEADER, PAYMENT_RESPONSE_HEADER, PaymentAttempt, type PaymentAttemptReservation, type PaymentAttemptUpdate, PaymentMethodName, PaymentProvider, type PaymentRequiredEnvelope, PaymentRequiredOutcome, PaymentSubmission, ProtocolAdapter, ProtocolAdapterContext, RESERVED_INPUT_FIELDS, RETRYABLE_ERROR_CODES, type ReceiptStore, ResourceRegistry, createAcpAdapter, createGateway, createSqliteReceiptStore, extractReservedInputFields, isCommerceError, isPaymentRequiredEnvelope, loadConfig, parseAuthorizationHeader, parseAuthorizationSubmission, parseConfig, createSqliteReceiptStore as receipts, toCommerceError, toDeliverySummary, toErrorEnvelope, toPaymentRequiredEnvelope };