@devlab.group/agent-commerce 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +73 -71
  2. package/dist/ap2.d.ts +20 -23
  3. package/dist/ap2.js +53 -75
  4. package/dist/ap2.js.map +1 -1
  5. package/dist/authorization-BpbWGGrf.d.ts +115 -0
  6. package/dist/chunk-AFI2CEZS.js +10 -0
  7. package/dist/chunk-AFI2CEZS.js.map +1 -0
  8. package/dist/{chunk-PBYN7EK2.js → chunk-CBJIT7QP.js} +10 -9
  9. package/dist/chunk-CBJIT7QP.js.map +1 -0
  10. package/dist/{chunk-NKNXVDHN.js → chunk-JKEKKXRJ.js} +45 -66
  11. package/dist/chunk-JKEKKXRJ.js.map +1 -0
  12. package/dist/{chunk-5GEWKNIH.js → chunk-N5KRK7YA.js} +63 -27
  13. package/dist/chunk-N5KRK7YA.js.map +1 -0
  14. package/dist/{chunk-6D2EZ5ME.js → chunk-V2V2E7HX.js} +2 -2
  15. package/dist/{chunk-6D2EZ5ME.js.map → chunk-V2V2E7HX.js.map} +1 -1
  16. package/dist/{chunk-US622BKF.js → chunk-VKDXMXHL.js} +5 -8
  17. package/dist/chunk-VKDXMXHL.js.map +1 -0
  18. package/dist/cli/index.js +501 -494
  19. package/dist/cli/index.js.map +1 -1
  20. package/dist/{constants-6mypC60h.d.ts → constants-Bkq04FRZ.d.ts} +1 -3
  21. package/dist/guardrails-71XwtXlT.d.ts +31 -0
  22. package/dist/index.d.ts +230 -265
  23. package/dist/index.js +1050 -607
  24. package/dist/index.js.map +1 -1
  25. package/dist/mcp.d.ts +6 -59
  26. package/dist/mcp.js +61 -53
  27. package/dist/mcp.js.map +1 -1
  28. package/dist/mpp.d.ts +4 -4
  29. package/dist/mpp.js +21 -19
  30. package/dist/mpp.js.map +1 -1
  31. package/dist/protocol-adapter-DTkrXTev.d.ts +238 -0
  32. package/dist/runtime-CiYbgGpi.d.ts +303 -0
  33. package/dist/{types-CJtwLu1c.d.ts → types-O6lg3Q5V.d.ts} +17 -23
  34. package/dist/x402.d.ts +43 -75
  35. package/dist/x402.js +10 -9
  36. package/dist/x402.js.map +1 -1
  37. package/package.json +7 -5
  38. package/dist/authorization-DA7mjy_O.d.ts +0 -123
  39. package/dist/chunk-5GEWKNIH.js.map +0 -1
  40. package/dist/chunk-NKNXVDHN.js.map +0 -1
  41. package/dist/chunk-PBYN7EK2.js.map +0 -1
  42. package/dist/chunk-US622BKF.js.map +0 -1
  43. package/dist/guardrails-Dmwi63KB.d.ts +0 -38
  44. package/dist/protocol-adapter-APRjs1E2.d.ts +0 -273
  45. package/dist/runtime-DC5XQ9Cc.d.ts +0 -351
package/README.md CHANGED
@@ -26,7 +26,8 @@ generate draft resource definitions from OpenAPI. Resources can be exposed over
26
26
  HTTP, MCP or experimental A2A; dedicated resources can implement experimental
27
27
  ACP checkout operations. Paid resources use x402 or experimental MPP and can
28
28
  also require an AP2 mandate proving that the buyer approved the purchase. Funds
29
- go directly to the merchant wallet; the gateway never holds them or your keys.
29
+ go directly to the merchant wallet, and the gateway needs neither the buyer's
30
+ nor the merchant's private key.
30
31
 
31
32
  ```text
32
33
  Your existing API → Agent Commerce Gateway → AI Agent
@@ -36,28 +37,29 @@ Your existing API → Agent Commerce Gateway → AI Agent
36
37
  ## Demo
37
38
 
38
39
  ```text
39
- [agent] Discovering resources over MCP...
40
- [agent] Found: market_report - Premium Market Report (0.01 USDC)
41
- [agent] Requesting resource...
42
-
43
- [gateway] Payment required: 0.01 USDC → 0x7099…79C8
44
- [buyer] Signing x402 authorisation...
45
- [gateway] Payment verified
46
- [gateway] Payment settled tx 0x4f2c…9ab1
47
- [gateway] Calling merchant backend...
48
- [gateway] Resource delivered
49
-
50
- [receipt] payment: settled
51
- [receipt] amount: 0.01 USDC
52
- [receipt] merchant: 0x7099…79C8
53
- [receipt] buyer balance 100.00 → 99.99 mUSDC
54
- [receipt] merchant balance 0.00 → 0.01 mUSDC
40
+ [agent] Agent Commerce Gateway: deterministic buyer demo
41
+ [buyer] balance before 100 MockUSDC
42
+ [agent] merchant balance before 0 MockUSDC
43
+ [gateway] connected to http://localhost:8080/mcp
44
+ [agent] discovered 2 tool(s): weather_basic, market_report
45
+ [agent] paid tool: "market_report", free tool: "weather_basic"
46
+ [gateway] 402 payment required: 0.01 USDC to 0x7099…79C8
47
+ [buyer] challenge checked before signing: pays 10000 units of 0x5fbd…0aa3 to 0x7099…79C8
48
+ [buyer] signed x402 payment proof (LOCAL DEVELOPMENT ONLY - DO NOT FUND)
49
+ [gateway] delivered "market_report"
50
+ [receipt] id=receipt_484b…1eba requestId=mcp_4292…c930 status=settled settlementTx=0x0b19…1c7f
51
+ [buyer] balance after 99.99 MockUSDC (Δ -0.01)
52
+ [agent] merchant balance after 0.01 MockUSDC (Δ 0.01)
53
+ [agent] on-chain balance changes match the expected payment amount
54
+ [gateway] delivered free tool "weather_basic": {"city":"Paris","temperatureC":-4,…}
55
+ [agent] demo complete: free and paid delivery both verified
55
56
  ```
56
57
 
57
- The dashboard at <http://localhost:5173> shows the same request as it happens.
58
- It polls the authenticated events route rather than streaming, because a browser
59
- cannot send the admin token over `EventSource`; see
60
- [why the stream is polled](SECURITY.md#the-live-event-stream-is-polled-not-streamed).
58
+ This excerpt of `npm run demo:agent` omits the address lines and shortens long
59
+ values. Balances, IDs and hashes differ from run to run.
60
+
61
+ The dashboard at <http://localhost:5173> polls the gateway's events route and
62
+ shows the same request within a few seconds.
61
63
 
62
64
  ## Install
63
65
 
@@ -68,7 +70,8 @@ agent-commerce doctor
68
70
  ```
69
71
 
70
72
  Requires **Node >= 22**. The package includes the `agent-commerce` CLI
71
- (`init`, `validate`, `doctor`, `demo`) and a library for embedding the gateway.
73
+ (`init`, `validate`, `doctor`, `demo`, `import openapi`, `version`) and a library
74
+ for embedding the gateway.
72
75
  The default install excludes optional protocol, payment and authorization
73
76
  peers. The OpenAPI parser is a regular dependency because import is part of the
74
77
  CLI.
@@ -97,7 +100,7 @@ free HTTP resources does not install MCP, EVM, JOSE or SD-JWT packages.
97
100
 
98
101
  | You want | Install | Import |
99
102
  | --------------------------------------- | ---------------------------------- | ------------------------------------------ |
100
- | gateway, config, receipts, CLI | `@devlab.group/agent-commerce` | `from '@devlab.group/agent-commerce'` |
103
+ | gateway, config, receipts, A2A/ACP, CLI | `@devlab.group/agent-commerce` | `from '@devlab.group/agent-commerce'` |
101
104
  | expose resources as MCP tools | `+ @modelcontextprotocol/sdk` | `from '@devlab.group/agent-commerce/mcp'` |
102
105
  | accept x402 payments | `+ @x402/core @x402/evm viem` | `from '@devlab.group/agent-commerce/x402'` |
103
106
  | accept MPP payments | `+ mppx viem @x402/core @x402/evm` | `from '@devlab.group/agent-commerce/mpp'` |
@@ -183,9 +186,7 @@ To stop and wipe state: `docker compose down -v`.
183
186
  ```
184
187
 
185
188
  Every protocol adapter uses one execution pipeline, so payment enforcement does
186
- not depend on the adapter. The buyer pays the merchant directly on-chain; the
187
- gateway holds neither the funds nor a buyer or merchant key. See
188
- [Architecture](docs/architecture.md).
189
+ not depend on the adapter. See [Architecture](docs/architecture.md).
189
190
 
190
191
  ## Configure a resource
191
192
 
@@ -206,7 +207,7 @@ resources:
206
207
  payments: [x402]
207
208
  ```
208
209
 
209
- That is the integration. No SDK in your backend, no rewrite.
210
+ The gateway calls your existing backend, which needs no SDK or changes.
210
211
 
211
212
  ```bash
212
213
  npm run agent-commerce -- init # generate a config interactively
@@ -221,8 +222,9 @@ agent-commerce import openapi ./openapi.yaml
221
222
  ```
222
223
 
223
224
  It writes a reviewable `resources:` fragment with path, query and JSON body
224
- bindings and supported schemas. It omits `pricing`, `expose` and credentials;
225
- the source document cannot decide price or exposure. See
225
+ bindings and supported schemas. The source document never decides price or
226
+ exposure: `pricing` appears only with `--free` and `expose` only with
227
+ `--expose`, and credentials are never imported. See
226
228
  [OpenAPI import](docs/openapi-import.md) for the supported subset.
227
229
 
228
230
  See [docs/configuration.md](docs/configuration.md).
@@ -253,16 +255,17 @@ converted into a gateway payment proof.
253
255
 
254
256
  `GET /.well-known/agent-commerce` reports `supportedSpec`, `capabilities` and
255
257
  `unsupported` for registered adapters and providers. `agent-commerce doctor`
256
- prints the `unsupported` lists for A2A, ACP and AP2.
258
+ prints the `unsupported` lists for A2A, ACP and AP2 when they are enabled.
257
259
 
258
260
  ## Payment model
259
261
 
260
- - **Non-custodial.** The gateway never holds funds, and never asks for a
261
- merchant or buyer private key. `payTo` is your address.
262
+ - **Non-custodial.** Buyer payments go directly to the merchant address in
263
+ `payTo` (`recipient` for MPP). The gateway does not require buyer or merchant
264
+ private keys. Local facilitator mode does hold a separate gas-paying signer.
262
265
  - **Fail closed.** Missing, malformed, expired, replayed, wrong-amount,
263
266
  wrong-recipient, wrong-network and wrong-asset payments are rejected.
264
267
  - **Replay-safe twice over.** EIP-3009 stops a double spend on-chain; the
265
- gateway additionally reserves a `replayKey` derived from the authorisation
268
+ gateway additionally reserves a `replayKey` derived from the authorization
266
269
  before it settles anything.
267
270
  - **On-chain settlement in CI.** The end-to-end test asserts the buyer's balance
268
271
  falls and the merchant's rises by exactly the price, with a real transaction
@@ -277,8 +280,8 @@ prints the `unsupported` lists for A2A, ACP and AP2.
277
280
 
278
281
  ## Public networks
279
282
 
280
- Same gateway, same pipeline - a different `network` and a facilitator that is
281
- not this process. No code changes, and no "live mode" to switch on.
283
+ Public networks use the same execution pipeline with a remote facilitator.
284
+ Choose the network in config; Base mainnet also requires `allowMainnet: true`.
282
285
 
283
286
  ### It has actually settled
284
287
 
@@ -292,33 +295,33 @@ remote facilitator:
292
295
  | MPP | Base Sepolia | [`0x5d9fcd111b…`](https://sepolia.basescan.org/tx/0x5d9fcd111b615bb8fc9e56d55096f119fc81c3c72c334f813cfaecee402d0ac3) |
293
296
  | MPP | Base | [`0xf4255bd7ec…`](https://basescan.org/tx/0xf4255bd7ec46ed06505dedfb5f9537924bd2633816e7952ec6f2b468395b1087) |
294
297
 
295
- The buyer signed each EIP-3009 authorisation without ETH; the remote facilitator
298
+ The buyer signed each EIP-3009 authorization without ETH; the remote facilitator
296
299
  paid gas and broadcast it. The gateway path received no buyer or merchant key.
297
300
  The public-network smoke suites verify balance changes and fetch the transaction
298
301
  receipt from the chain instead of trusting the gateway's response.
299
302
 
300
- Reproduce with `npm run test:testnet` / `npm run test:mainnet` - both spend
301
- real funds, skip themselves without credentials, and never run in CI.
303
+ Reproduce with `npm run test:testnet`, which spends test USDC, or
304
+ `npm run test:mainnet`, which spends real USDC. Both run only by hand; see
305
+ [Base mainnet](#base-mainnet).
302
306
 
303
307
  ### The facilitator model
304
308
 
305
- A **facilitator** verifies the buyer's authorisation and broadcasts the
306
- transfer. It is the only component that needs gas, and it is never this
307
- gateway on a public network.
309
+ A **facilitator** verifies the buyer's authorization and broadcasts the
310
+ transfer. It is the only component that needs gas.
308
311
 
309
- | `facilitator.mode` | Who signs | Where it is allowed |
310
- | ------------------ | ----------------------------------- | ------------------------ |
311
- | `local` | this process, with an Anvil dev key | the local dev chain only |
312
- | `remote` | an HTTP facilitator you point at | anywhere |
312
+ | `facilitator.mode` | Who signs | Where it is allowed |
313
+ | ------------------ | -------------------------------------- | ------------------------------------------------------------------ |
314
+ | `local` | this process, with a key you configure | a local Anvil chain; refused on mainnet, fails readiness elsewhere |
315
+ | `remote` | an HTTP facilitator you point at | anywhere |
313
316
 
314
317
  With `remote`, the gateway holds no facilitator signing key. The buyer signs an
315
- EIP-3009 authorisation without ETH, and the facilitator pays gas. Because the
316
- authorisation fixes the recipient, amount and chain, the facilitator cannot
317
- redirect the transfer. It can see authorisations and refuse service.
318
+ EIP-3009 authorization without ETH, and the facilitator pays gas. Because the
319
+ authorization fixes the recipient, amount and chain, the facilitator cannot
320
+ redirect the transfer. It can see authorizations and refuse service.
318
321
 
319
- Remote facilitator auth supports `none`, `bearer` and `cdp`. CDP signs a fresh
320
- JWT per request and conditionally loads `@coinbase/x402`; bearer auth needs no
321
- extra peer. Other types are rejected at config load.
322
+ Remote facilitator auth supports `none`, `bearer` and `cdp`. `cdp` loads the
323
+ optional peer `@coinbase/x402`, which signs a fresh JWT per request; bearer auth
324
+ needs no extra peer. Other types are rejected at config load.
322
325
 
323
326
  ### Base Sepolia
324
327
 
@@ -354,13 +357,13 @@ together, and reported by `doctor`, `health()` and `/.well-known`.
354
357
 
355
358
  Mainnet moves real funds. Config validation requires:
356
359
 
357
- | Required | |
358
- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
359
- | `allowMainnet: true` | mainnet is never a default |
360
- | `facilitator.mode: remote` | `local` needs a funded gas key inside this process |
361
- | an HTTPS `facilitator.url` | |
362
- | `allowUnauthenticatedFacilitator: true` | only if that facilitator takes no credential |
363
- | a non-development destination (`payTo` or `recipient`) | |
360
+ | Required | |
361
+ | -------------------------------------------------------------- | -------------------------------------------------------------- |
362
+ | `allowMainnet: true` | mainnet is never a default |
363
+ | `facilitator.mode: remote` | `local` needs a funded gas key inside this process |
364
+ | an HTTPS `facilitator.url` | |
365
+ | `allowUnauthenticatedFacilitator: true` | required when `facilitator.auth.type` is `none` |
366
+ | a non-development destination (`payTo` or `recipient`) | |
364
367
  | Base USDC with `assetName: "USD Coin"` and `assetVersion: "2"` | the buyer signs this EIP-712 domain; `"USDC"` is wrong on Base |
365
368
 
366
369
  Full config in [`examples/base-mainnet/`](examples/base-mainnet/), and
@@ -371,26 +374,25 @@ spend real USDC when their opt-ins and credentials are present.
371
374
  `agent-commerce validate` reports any of the above before anything starts, and
372
375
  `doctor` prints `LIVE MAINNET MODE - REAL FUNDS`.
373
376
 
374
- > Neither public-network suite runs in CI - there is no workflow and there must
375
- > not be one. A workflow means a funded key in repository secrets, spendable by
376
- > anyone with write access. Both suites run from the machine that holds the
377
- > wallet, and skip themselves without credentials.
377
+ > The public-network suites never run in CI, because a workflow would need a
378
+ > funded buyer key in repository secrets. Run them from the machine that holds
379
+ > the wallet. A test whose required settings are missing skips itself.
378
380
 
379
381
  ## Diagnostics
380
382
 
381
383
  ```console
382
384
  $ npm run agent-commerce -- doctor --config config-demo.yaml
383
385
 
384
- PASS Config valid - 2 resource(s), merchant "Demo Data Store" (using local chain manifest .deploy/local.json for X402_ASSET, X402_ASSET_NAME, X402_ASSET_VERSION, X402_ASSET_DECIMALS, MERCHANT_WALLET, X402_FACILITATOR_PRIVATE_KEY)
386
+ PASS Config valid: 2 resource(s), merchant "Demo Data Store" (using local chain manifest .deploy/local.json for X402_ASSET, X402_ASSET_NAME, X402_ASSET_VERSION, X402_ASSET_DECIMALS, MERCHANT_WALLET, X402_FACILITATOR_PRIVATE_KEY)
385
387
  PASS Gateway healthy and ready at http://127.0.0.1:8080
386
388
  PASS Backend 2/2 backend host(s) reachable
387
389
  PASS Protocols http=on mcp=on (/mcp) a2a=off acp=off
388
390
  INFO A2A disabled
389
391
  INFO ACP disabled
390
392
  INFO AP2 disabled
391
- PASS Payments x402 v2 (scheme=exact) enabled - LOCAL dev chain (eip155:84532, chain id shared with Base Sepolia), destination=0x7099…79C8, facilitator=local
393
+ PASS Payments x402 v2 (scheme=exact) enabled - LOCAL dev chain (eip155:84532, chain id shared with Base Sepolia), destination=0x7099…79C8, facilitator=local (in-process)
392
394
  INFO Payments (MPP) MPP not configured
393
- PASS Storage sqlite schema v1 writable; receipts=2
395
+ PASS Storage sqlite schema v2 writable; receipts=2
394
396
  PASS Protocol versions reported by gateway /.well-known/agent-commerce
395
397
 
396
398
  Score: 7/7 checks passed
@@ -409,8 +411,8 @@ reachable by anyone else, know the split:
409
411
  - **Agent routes** (`/api/resources/:id/invoke`, `/mcp`, the A2A mount) are
410
412
  unauthenticated by design - paid resources are protected by payment, not by a
411
413
  password. ACP is the exception: its checkout routes require a bearer token.
412
- - **Operator routes** (`/api/receipts`, `/api/events`, `/api/events/stream`) are
413
- the merchant's commerce ledger: payer addresses, amounts, settlement hashes.
414
+ - **Operator routes** (`/api/receipts`, `/api/events`) are the merchant's
415
+ commerce ledger: payer addresses, amounts, settlement hashes.
414
416
  They require `server.adminToken`, and return **404** if none is configured.
415
417
  - **Browsers** are governed by `server.allowedOrigins`, an explicit allowlist
416
418
  that defaults to empty.
@@ -442,8 +444,8 @@ autonomous-mode AP2 (open mandates, agent key binding, constraint evaluation) ·
442
444
  more of ACP (carts, feed, delegated payment) · Shopify and WooCommerce examples ·
443
445
  PostgreSQL · richer observability · multi-file and remote OpenAPI sources.
444
446
 
445
- New protocols land only after the adapter model survives real use. Scope
446
- discipline is a release requirement, not a mood.
447
+ New protocols need evidence that the adapter model works in real use before
448
+ they are added to a release.
447
449
 
448
450
  ## Documentation
449
451
 
@@ -456,9 +458,9 @@ discipline is a release requirement, not a mood.
456
458
  | [Configuration](docs/configuration.md) | `config.yaml` reference |
457
459
  | [OpenAPI import](docs/openapi-import.md) | generate resources from an existing API |
458
460
  | [Security model](docs/security.md) | trust boundaries, and what we do not defend |
459
- | [Contracts](docs/contracts.md) | the frozen cross-package contract |
461
+ | [Contracts](docs/contracts.md) | the frozen cross-area contract |
460
462
  | [Adapter guide](docs/contributing-adapters.md) | add a protocol or a payment rail |
461
463
 
462
- ## Licence
464
+ ## License
463
465
 
464
466
  [Apache-2.0](LICENSE).
package/dist/ap2.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { E as EnabledAp2Config } from './types-CJtwLu1c.js';
2
- export { A as AP2_CHECKOUT_MANDATE_VCT, a as AP2_CHECKOUT_PROFILE, b as AP2_DEFAULT_CLOCK_SKEW_SECONDS, c as AP2_MAX_CLOCK_SKEW_SECONDS, d as AP2_SIGNING_ALGORITHM, e as AP2_SPEC_VERSION, f as Ap2AuthorizationConfig, g as Ap2Mode, h as Ap2TrustedIssuer, i as Ap2TrustedKey } from './types-CJtwLu1c.js';
3
- import { A as AuthorizationProvider } from './authorization-DA7mjy_O.js';
4
- import { C as Clock, L as Logger } from './runtime-DC5XQ9Cc.js';
1
+ import { E as EnabledAp2Config } from './types-O6lg3Q5V.js';
2
+ export { A as AP2_CHECKOUT_MANDATE_VCT, a as AP2_CHECKOUT_PROFILE, b as AP2_DEFAULT_CLOCK_SKEW_SECONDS, c as AP2_MAX_CLOCK_SKEW_SECONDS, d as AP2_SIGNING_ALGORITHM, e as AP2_SPEC_VERSION, f as Ap2AuthorizationConfig, g as Ap2Mode, h as Ap2TrustedIssuer, i as Ap2TrustedKey } from './types-O6lg3Q5V.js';
3
+ import { A as AuthorizationProvider } from './authorization-BpbWGGrf.js';
4
+ import { C as Clock, L as Logger } from './runtime-CiYbgGpi.js';
5
5
 
6
6
  /**
7
7
  * A private ES256 key: either a private JWK (the pair of the public one in the
8
- * gateway's `checkoutIssuers`) or a PKCS#8 PEM, as `openssl` emits it.
8
+ * gateway's `checkoutIssuers`) or a PKCS#8 PEM, as `openssl` emits it
9
9
  */
10
10
  type Ap2SigningKey = Readonly<Record<string, unknown>> | string;
11
11
  interface CreateCheckoutJwtOptions {
@@ -19,12 +19,12 @@ interface CreateCheckoutJwtOptions {
19
19
  readonly resourceId: string;
20
20
  /**
21
21
  * The resource input this purchase is for, exactly as the buyer will send
22
- * it: no reserved fields, no request id, no transport metadata.
22
+ * it: no reserved fields, no request id, no transport metadata
23
23
  */
24
24
  readonly input: unknown;
25
25
  /**
26
26
  * Decimal string, never a number, and compared as a string: `0.10` and `0.1`
27
- * are different mandates. Take it from your own catalogue rather than from
27
+ * are different mandates. Take it from your own catalog rather than from
28
28
  * whatever the agent asked for.
29
29
  */
30
30
  readonly amount: string;
@@ -39,7 +39,7 @@ interface CreateCheckoutJwtOptions {
39
39
  readonly destination?: string;
40
40
  readonly network?: string;
41
41
  readonly asset?: string;
42
- /** Defaults to a random UUID. Recorded on the receipt and used for replay defence */
42
+ /** Defaults to a random UUID. Recorded on the receipt and used for replay defense */
43
43
  readonly jwtId?: string;
44
44
  /** Defaults to 900: a human approval sits inside this window */
45
45
  readonly expiresInSeconds?: number;
@@ -48,7 +48,7 @@ interface CreateCheckoutJwtOptions {
48
48
  }
49
49
  /**
50
50
  * Returns the compact JWT to hand to the agent, which wraps it in the Checkout
51
- * Mandate the buyer signs.
51
+ * Mandate the buyer signs
52
52
  */
53
53
  declare function createCheckoutJwt(options: CreateCheckoutJwtOptions): Promise<string>;
54
54
 
@@ -62,9 +62,9 @@ declare function createCheckoutJwt(options: CreateCheckoutJwtOptions): Promise<s
62
62
  /** What this provider actually verifies */
63
63
  declare const AP2_CAPABILITIES: readonly string[];
64
64
  /**
65
- * Everything an AP2 client may reasonably expect and will not get here.
66
- * Complete on purpose: a short list reads as "mostly compatible", which is the
67
- * blanket claim alpha honesty forbids.
65
+ * Major AP2 features this provider does not support, published in its
66
+ * descriptor and printed by `doctor`, so no client assumes full protocol
67
+ * support
68
68
  */
69
69
  declare const AP2_UNSUPPORTED: readonly string[];
70
70
 
@@ -74,7 +74,7 @@ declare const AP2_UNSUPPORTED: readonly string[];
74
74
  * `CommerceError.message` reaches the client, and a mandate carries the
75
75
  * buyer's purchase and often personal data, so messages are fixed phrases from
76
76
  * the list below. The machine-readable code goes in `details.reason` and the
77
- * original exception on `cause`, which is never serialised.
77
+ * original exception on `cause`, which is never serialized.
78
78
  *
79
79
  * Three codes: AUTHORIZATION_INVALID when the buyer's mandate is bad,
80
80
  * AUTHORIZATION_REPLAYED when it is good but spent, and
@@ -84,9 +84,11 @@ declare const AP2_UNSUPPORTED: readonly string[];
84
84
 
85
85
  /**
86
86
  * Coarse on purpose: a client learns roughly where its mandate was refused,
87
- * not which check failed. Finer detail is an oracle for probing trust policy.
87
+ * not which check failed. Finer detail is an oracle for probing trust policy,
88
+ * so a mandate signed with a disallowed algorithm reports `invalid_signature`
89
+ * and one declaring a digest other than sha-256 `malformed_presentation`.
88
90
  */
89
- declare const AP2_REJECTION_REASONS: readonly ["malformed_presentation", "untrusted_issuer", "unknown_key", "invalid_signature", "unsupported_algorithm", "invalid_claims", "expired", "wrong_audience", "unsupported_mandate_type", "checkout_binding_failed", "purchase_mismatch"];
91
+ declare const AP2_REJECTION_REASONS: readonly ["malformed_presentation", "untrusted_issuer", "unknown_key", "invalid_signature", "invalid_claims", "expired", "wrong_audience", "unsupported_mandate_type", "checkout_binding_failed", "purchase_mismatch"];
90
92
  type Ap2RejectionReason = (typeof AP2_REJECTION_REASONS)[number];
91
93
 
92
94
  /**
@@ -96,7 +98,7 @@ type Ap2RejectionReason = (typeof AP2_REJECTION_REASONS)[number];
96
98
  */
97
99
  type Ap2AuthorizationState = 'reserved' | 'consumed' | 'released' | 'uncertain';
98
100
  /**
99
- * A digest and a few identifiers: everything replay defence needs, and nothing
101
+ * A digest and a few identifiers: everything replay defense needs, and nothing
100
102
  * a leaked database would hand an attacker
101
103
  */
102
104
  interface Ap2ReservationRequest {
@@ -139,8 +141,8 @@ interface Ap2ReplayStore {
139
141
  * The AP2 authorization provider: the seam between core's generic contract and
140
142
  * the mandate machinery.
141
143
  *
142
- * The provider owns its replay store. The caller that creates the provider must
143
- * call `close()`; `createGateway` does not close authorization providers.
144
+ * It owns its replay store, so whoever creates it must call `close()`:
145
+ * `createGateway` does not close authorization providers.
144
146
  */
145
147
 
146
148
  interface Ap2AuthorizationProviderOptions {
@@ -154,11 +156,6 @@ interface Ap2AuthorizationProvider extends AuthorizationProvider {
154
156
  /** Closes the replay store */
155
157
  close(): void;
156
158
  }
157
- /**
158
- * A reservation is keyed by the mandate reference, so the handle and the
159
- * receipt's identity are the same digest. Kept as one name rather than two
160
- * fields that must never disagree.
161
- */
162
159
  declare function createAp2AuthorizationProvider(options: Ap2AuthorizationProviderOptions): Ap2AuthorizationProvider;
163
160
 
164
161
  export { AP2_CAPABILITIES, AP2_REJECTION_REASONS, AP2_UNSUPPORTED, type Ap2AuthorizationProvider, type Ap2AuthorizationProviderOptions, type Ap2RejectionReason, type Ap2SigningKey, type CreateCheckoutJwtOptions, EnabledAp2Config, createAp2AuthorizationProvider as ap2, createAp2AuthorizationProvider, createCheckoutJwt };