@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/README.md CHANGED
@@ -12,6 +12,7 @@
12
12
  <img alt="x402" src="https://img.shields.io/badge/x402-supported-0052ff">
13
13
  <img alt="A2A" src="https://img.shields.io/badge/A2A-experimental-f0a30a">
14
14
  <img alt="ACP" src="https://img.shields.io/badge/ACP-experimental-f0a30a">
15
+ <img alt="AP2" src="https://img.shields.io/badge/AP2-experimental-f0a30a">
15
16
  </p>
16
17
 
17
18
  ## What it is, in ten seconds
@@ -23,13 +24,14 @@ Agent Commerce Gateway sits in front of your existing API, in **your**
23
24
  infrastructure, and does that for you. You describe an endpoint in a YAML file -
24
25
  or generate that description from an OpenAPI document you already have - and
25
26
  agents get an MCP tool and an x402 paywall. Switch on the experimental adapters
26
- and the same resource is also an A2A skill, or an ACP checkout session. The
27
- money goes straight to your wallet - the gateway never holds it, and never holds
28
- your keys.
27
+ and the same resource is also an A2A skill, or an ACP checkout session. Switch
28
+ on AP2 and a paid resource can also demand a signed mandate: proof the human
29
+ behind the agent approved that exact purchase. The money goes straight to your
30
+ wallet - the gateway never holds it, and never holds your keys.
29
31
 
30
32
  ```text
31
33
  Your existing API → Agent Commerce Gateway → AI Agent
32
- MCP · A2A · ACP · x402 · receipts · doctor
34
+ MCP · A2A · ACP · x402 · AP2 · receipts · doctor
33
35
  ```
34
36
 
35
37
  ## Demo
@@ -54,11 +56,9 @@ Your existing API → Agent Commerce Gateway → AI Agent
54
56
  ```
55
57
 
56
58
  The dashboard at <http://localhost:5173> shows the same request as it happens.
57
- It polls the authenticated events route on a short interval rather than
58
- streaming: a browser `EventSource` cannot send the admin token, and the operator
59
- routes are closed without one - so the SSE endpoint is reachable by a
60
- header-capable client, never by a browser. Polling is the dashboard's intended
61
- path, not a degraded mode.
59
+ It polls the authenticated events route rather than streaming, because a browser
60
+ cannot send the admin token over `EventSource`; see
61
+ [why the stream is polled](SECURITY.md#the-live-event-stream-is-polled-not-streamed).
62
62
 
63
63
  ## Install
64
64
 
@@ -79,9 +79,15 @@ onboarding an existing API is the CLI's main job.
79
79
  import { createGateway, loadConfig, receipts } from '@devlab.group/agent-commerce';
80
80
 
81
81
  const config = await loadConfig({ path: 'config.yaml' });
82
+ const store = receipts({ path: './receipts.sqlite' });
83
+ // Every ReceiptStore must be initialised before anything else touches it -
84
+ // for the SQLite one this is where a schema written by a newer version is
85
+ // caught, at boot rather than at the first query
86
+ await store.init();
87
+
82
88
  const gateway = await createGateway({
83
89
  config,
84
- store: receipts({ path: './receipts.sqlite' }),
90
+ store,
85
91
  paymentProviders: [],
86
92
  protocolAdapters: [],
87
93
  });
@@ -90,17 +96,18 @@ const { url } = await gateway.listen();
90
96
 
91
97
  ### Optional peers - install only the rails you use
92
98
 
93
- The MCP adapter and the x402 provider live on their own subpaths, because each
94
- needs a dependency the rest of the package does not - the x402 rail brings the
95
- whole EVM signing and RPC stack, which a gateway serving a free HTTP resource
96
- has no business installing.
99
+ The MCP adapter, the x402 provider and AP2 verification live on their own
100
+ subpaths, because each needs a dependency the rest of the package does not -
101
+ the x402 rail brings the whole EVM signing and RPC stack, which a gateway
102
+ serving a free HTTP resource has no business installing.
97
103
 
98
- | You want | Install | Import |
99
- | --------------------------------- | ------------------------------ | ------------------------------------------ |
100
- | gateway, config, receipts, CLI | `@devlab.group/agent-commerce` | `from '@devlab.group/agent-commerce'` |
101
- | expose resources as MCP tools | `+ @modelcontextprotocol/sdk` | `from '@devlab.group/agent-commerce/mcp'` |
102
- | accept x402 payments | `+ @x402/core @x402/evm viem` | `from '@devlab.group/agent-commerce/x402'` |
103
- | authenticate to a CDP facilitator | `+ @coinbase/x402` | (no import - loaded on demand) |
104
+ | You want | Install | Import |
105
+ | --------------------------------------- | ---------------------------------- | ------------------------------------------ |
106
+ | gateway, config, receipts, CLI | `@devlab.group/agent-commerce` | `from '@devlab.group/agent-commerce'` |
107
+ | expose resources as MCP tools | `+ @modelcontextprotocol/sdk` | `from '@devlab.group/agent-commerce/mcp'` |
108
+ | accept x402 payments | `+ @x402/core @x402/evm viem` | `from '@devlab.group/agent-commerce/x402'` |
109
+ | verify AP2 mandates, sign checkout JWTs | `+ jose @sd-jwt/core canonicalize` | `from '@devlab.group/agent-commerce/ap2'` |
110
+ | authenticate to a CDP facilitator | `+ @coinbase/x402` | (no import - loaded on demand) |
104
111
 
105
112
  ```bash
106
113
  npm install @devlab.group/agent-commerce @modelcontextprotocol/sdk @x402/core @x402/evm viem
@@ -109,8 +116,14 @@ npm install @devlab.group/agent-commerce @modelcontextprotocol/sdk @x402/core @x
109
116
  ```ts
110
117
  import { mcp } from '@devlab.group/agent-commerce/mcp';
111
118
  import { x402 } from '@devlab.group/agent-commerce/x402';
119
+ import { ap2 } from '@devlab.group/agent-commerce/ap2';
112
120
  ```
113
121
 
122
+ The AP2 three are small - about 1.3 MB installed between them, against roughly
123
+ 63 MB for the x402 stack - but they stay optional on the same principle: a
124
+ deployment that gates nothing on a mandate should not carry a JOSE stack and an
125
+ SD-JWT parser to serve a resource.
126
+
114
127
  Peers are pinned exactly: x402's schemas and EIP-712 domains cross this
115
128
  boundary, so a version skew is a correctness problem rather than a convenience
116
129
  one. Import a subpath without its
@@ -157,30 +170,33 @@ To stop and wipe state: `docker compose down -v`.
157
170
  ## How it works
158
171
 
159
172
  ```text
160
- ┌──────────────────────────────────────────────────────┐
161
- │ AI Agent │
162
- └──────────────┬───────────────────────────────────────┘
163
- │ MCP · HTTP + PAYMENT-SIGNATURE
164
- ┌──────────────▼───────────────────────────────────────┐
165
- │ Agent Commerce Gateway (yours) │
166
- │ │
167
- │ protocol adapters → ExecutionPipeline → … │
168
- │ │ │
169
- │ ┌─────────────────────┼──────────────┐ │
170
- │ ▼ ▼ ▼ │
171
- │ PaymentProvider BackendExecutor ReceiptStore │
172
- │ (x402) (bounded HTTP) (SQLite) │
173
- └────────┬─────────────────────┬───────────────────────┘
174
- │ │
175
- buyer → merchant ┌──────▼───────────────┐
176
- (never through us) │ Your backend API │
177
- └───────────────────────┘
173
+ ┌──────────────────────────────────────────────────────────────────────────────┐
174
+ │ AI Agent │
175
+ └───────────────────────────────────────┬──────────────────────────────────────┘
176
+ │ MCP · A2A · ACP · HTTP
177
+ │ PAYMENT-SIGNATURE
178
+ │ Agent-Authorization
179
+ ┌───────────────────────────────────────▼──────────────────────────────────────┐
180
+ │ Agent Commerce Gateway (yours) │
181
+ │ │
182
+ │ protocol adapters → ExecutionPipeline │
183
+ │ │ │
184
+ │ ┌────────────────────┬──────────────┴──┬────────────────┐ │
185
+ │ ▼ ▼ ▼ ▼ │
186
+ │ AuthorizationProvider PaymentProvider BackendExecutor ReceiptStore │
187
+ │ (ap2) (x402) (bounded HTTP) (SQLite) │
188
+ └───────────────────────────────────────┬──────────────────────────────────────┘
189
+ │
190
+ ┌──────────▼─────────┐
191
+ │ Your backend API │
192
+ └────────────────────┘
178
193
  ```
179
194
 
180
195
  Every protocol adapter converges on **one execution pipeline**. That is what
181
196
  makes payment enforcement a property of the system rather than something each
182
- adapter has to remember. Full detail in
183
- [docs/architecture.md](docs/architecture.md).
197
+ adapter has to remember. Money never passes through the box: the buyer pays the
198
+ merchant directly on chain, and the gateway holds neither the funds nor a key.
199
+ Full detail in [docs/architecture.md](docs/architecture.md).
184
200
 
185
201
  ## Configure a resource
186
202
 
@@ -219,33 +235,39 @@ It writes a reviewable `resources:` fragment - path, query and JSON body
219
235
  mapped, schemas converted to what the gateway actually enforces - and
220
236
  deliberately leaves `pricing` and `expose` out, because an OpenAPI document has
221
237
  no opinion on what an operation costs or who may see it. Credentials are never
222
- imported. See [docs/openapi-import.md](docs/openapi-import.md) for the exact
223
- supported subset.
238
+ imported. See [OpenAPI import](docs/openapi-import.md) for the exact supported subset.
224
239
 
225
240
  See [docs/configuration.md](docs/configuration.md).
226
241
 
227
242
  ## Protocol support
228
243
 
229
- | Protocol | Status | Pinned revision |
230
- | --------------- | ------------ | -------------------------------------------------------- |
231
- | **MCP** | Supported | `@modelcontextprotocol/sdk@1.30.0` |
232
- | **x402** | Supported | x402 v2 (`@x402/core`, `@x402/evm`), scheme `exact`, EVM |
233
- | **HTTP** | Supported | native routes |
234
- | **A2A** | Experimental | A2A v1.0.0, binding `JSONRPC`, method `SendMessage` |
235
- | **ACP** | Experimental | ACP `2026-04-17`, REST checkout + discovery |
236
- | UCP · MPP · AP2 | Planned | - |
244
+ | Protocol | Status | Pinned revision |
245
+ | --------- | ------------ | -------------------------------------------------------- |
246
+ | **MCP** | Supported | `@modelcontextprotocol/sdk@1.30.0` |
247
+ | **x402** | Supported | x402 v2 (`@x402/core`, `@x402/evm`), scheme `exact`, EVM |
248
+ | **HTTP** | Supported | native routes |
249
+ | **A2A** | Experimental | A2A v1.0.0, binding `JSONRPC`, method `SendMessage` |
250
+ | **ACP** | Experimental | ACP `2026-04-17`, REST checkout + discovery |
251
+ | **AP2** | Experimental | AP2 `v0.2.0`, Direct Checkout Mandate verification |
252
+ | UCP · MPP | Planned | - |
253
+
254
+ [AP2](docs/ap2.md) is in that table because people look there, but it is an **authorization**
255
+ method rather than a transport: it gates settlement on a resource that still
256
+ takes a real payment, and it is the verifying half only - the gateway holds no
257
+ signing key and issues no Checkout Receipt.
237
258
 
238
259
  "Planned" means **no code ships for it**. "Experimental" means the code ships,
239
260
  is tested against the protocol's own official artifacts, and serves a narrow
240
- named subset - A2A and ACP are both off by default and documented in full at
241
- [docs/protocols.md](docs/protocols.md#a2a) and
242
- [docs/protocols.md](docs/protocols.md#acp). ACP serves the five stable checkout
243
- operations and advertises `services: ["checkout"]` and nothing more; its
244
- `payment_data` stays with the merchant's own checkout and is never turned into
245
- an x402 payment. Each adapter reports its own
246
- `supportedSpec`, `capabilities` and `unsupported` list at runtime via
247
- `GET /.well-known/agent-commerce` and `agent-commerce doctor` - so the claim is
248
- checkable, not marketing. Detail: [docs/protocols.md](docs/protocols.md).
261
+ named subset: [A2A](docs/protocols.md#a2a) and [ACP](docs/protocols.md#acp) are
262
+ both off by default and documented in full there, as are
263
+ [MCP](docs/protocols.md#mcp) and [x402](docs/protocols.md#x402). ACP serves the
264
+ five stable checkout operations and advertises `services: ["checkout"]` and
265
+ nothing more; its `payment_data` stays with the merchant's own checkout and is
266
+ never turned into an x402 payment.
267
+
268
+ Each adapter reports its own `supportedSpec`, `capabilities` and `unsupported`
269
+ list at runtime through `GET /.well-known/agent-commerce` and
270
+ `agent-commerce doctor`, so the claim is checkable rather than marketing.
249
271
 
250
272
  ## Payment model
251
273
 
@@ -260,8 +282,10 @@ checkable, not marketing. Detail: [docs/protocols.md](docs/protocols.md).
260
282
  - **Real settlement in CI.** The end-to-end test asserts the buyer's balance
261
283
  falls and the merchant's rises by exactly the price, with a real transaction
262
284
  hash in the receipt. A log line saying "payment successful" would not count.
263
-
264
- Detail: [docs/payment-flow.md](docs/payment-flow.md).
285
+ - **Authorization is separate from payment.** A resource can also require an
286
+ AP2 mandate, verified before settlement and spendable exactly once. It never
287
+ moves money and never unlocks a resource on its own - the payment still has
288
+ to be real.
265
289
 
266
290
  ## Public networks
267
291
 
@@ -378,6 +402,7 @@ PASS Backend 2/2 backend host(s) reachable
378
402
  PASS Protocols http=on mcp=on (/mcp) a2a=off acp=off
379
403
  INFO A2A disabled
380
404
  INFO ACP disabled
405
+ INFO AP2 disabled
381
406
  PASS Payments x402 v2 (scheme=exact) enabled - LOCAL dev chain (eip155:84532, chain id shared with Base Sepolia), destination=0x7099…79C8, facilitator=local
382
407
  INFO Payments (MPP) planned - not implemented in this release
383
408
  PASS Storage sqlite schema v1 writable; receipts=2
@@ -398,8 +423,9 @@ Exits non-zero if anything fails. `--json` for machines.
398
423
  The demo binds everything to `127.0.0.1`. Before putting the gateway anywhere
399
424
  reachable by anyone else, know the split:
400
425
 
401
- - **Agent routes** (`/api/resources/:id/invoke`, `/mcp`) are unauthenticated by
402
- design - paid resources are protected by payment, not by a password.
426
+ - **Agent routes** (`/api/resources/:id/invoke`, `/mcp`, the A2A mount) are
427
+ unauthenticated by design - paid resources are protected by payment, not by a
428
+ password. ACP is the exception: its checkout routes require a bearer token.
403
429
  - **Operator routes** (`/api/receipts`, `/api/events`, `/api/events/stream`) are
404
430
  the merchant's commerce ledger: payer addresses, amounts, settlement hashes.
405
431
  They require `server.adminToken`, and return **404** if none is configured.
@@ -425,11 +451,13 @@ See [CONTRIBUTING.md](CONTRIBUTING.md).
425
451
 
426
452
  **Now** - MCP, x402 v2, settlement on the local chain, Base Sepolia and Base
427
453
  mainnet, receipts, doctor, deterministic demo, experimental A2A v1.0.0 and ACP
428
- `2026-04-17` checkout adapters, and experimental OpenAPI import.
454
+ `2026-04-17` checkout adapters, experimental AP2 v0.2.0 mandate verification,
455
+ and experimental OpenAPI import.
429
456
 
430
- **Next** - a `doctor` GitHub Action · UCP · MPP · AP2 · more of ACP (carts,
431
- feed, delegated payment) · Shopify and WooCommerce examples · PostgreSQL ·
432
- richer observability · multi-file and remote OpenAPI sources.
457
+ **Next** - a `doctor` GitHub Action · UCP · MPP · autonomous-mode AP2 (open
458
+ mandates, agent key binding, constraint evaluation) · more of ACP (carts, feed,
459
+ delegated payment) · Shopify and WooCommerce examples · PostgreSQL · richer
460
+ observability · multi-file and remote OpenAPI sources.
433
461
 
434
462
  New protocols land only after the adapter model survives real use. Scope
435
463
  discipline is a release requirement, not a mood.
@@ -441,6 +469,7 @@ discipline is a release requirement, not a mood.
441
469
  | [Architecture](docs/architecture.md) | how the pieces fit |
442
470
  | [Payment flow](docs/payment-flow.md) | the paid round trip, and every way it fails |
443
471
  | [Protocols](docs/protocols.md) | exactly what is and is not supported |
472
+ | [AP2](docs/ap2.md) | mandate verification and the trust model |
444
473
  | [Configuration](docs/configuration.md) | `config.yaml` reference |
445
474
  | [OpenAPI import](docs/openapi-import.md) | generate resources from an existing API |
446
475
  | [Security model](docs/security.md) | trust boundaries, and what we do not defend |
package/dist/ap2.d.ts ADDED
@@ -0,0 +1,164 @@
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-CPDcpJVa.js';
4
+ import { C as Clock, L as Logger } from './runtime-CKq3d_3K.js';
5
+
6
+ /**
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.
9
+ */
10
+ type Ap2SigningKey = Readonly<Record<string, unknown>> | string;
11
+ interface CreateCheckoutJwtOptions {
12
+ readonly privateKey: Ap2SigningKey;
13
+ /** Must match a `kid` configured under the gateway's `checkoutIssuers` */
14
+ readonly kid: string;
15
+ /** Must match that issuer's configured `issuer` */
16
+ readonly issuer: string;
17
+ /** Must match that issuer's configured `audience` */
18
+ readonly audience: string;
19
+ readonly resourceId: string;
20
+ /**
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.
23
+ */
24
+ readonly input: unknown;
25
+ /**
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
28
+ * whatever the agent asked for.
29
+ */
30
+ readonly amount: string;
31
+ readonly currency: string;
32
+ /** The rail that will settle, e.g. `x402` */
33
+ readonly paymentMethod: string;
34
+ /**
35
+ * Settlement coordinates. Required whenever the gateway's requirement names
36
+ * them, which under x402 is always. A mandate silent about the chain will
37
+ * not unlock a settlement on one.
38
+ */
39
+ readonly destination?: string;
40
+ readonly network?: string;
41
+ readonly asset?: string;
42
+ /** Defaults to a random UUID. Recorded on the receipt and used for replay defence */
43
+ readonly jwtId?: string;
44
+ /** Defaults to 900: a human approval sits inside this window */
45
+ readonly expiresInSeconds?: number;
46
+ /** Injectable so a test need not move the wall clock */
47
+ readonly now?: Date;
48
+ }
49
+ /**
50
+ * Returns the compact JWT to hand to the agent, which wraps it in the Checkout
51
+ * Mandate the buyer signs.
52
+ */
53
+ declare function createCheckoutJwt(options: CreateCheckoutJwtOptions): Promise<string>;
54
+
55
+ /**
56
+ * Adapter self-description.
57
+ *
58
+ * Imports nothing but core types and the pins, so `doctor` can report AP2
59
+ * without pulling `jose` or `@sd-jwt/core` into the CLI bundle.
60
+ */
61
+
62
+ /** What this provider actually verifies */
63
+ declare const AP2_CAPABILITIES: readonly string[];
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.
68
+ */
69
+ declare const AP2_UNSUPPORTED: readonly string[];
70
+
71
+ /**
72
+ * Every failure the AP2 verifier can report.
73
+ *
74
+ * `CommerceError.message` reaches the client, and a mandate carries the
75
+ * buyer's purchase and often personal data, so messages are fixed phrases from
76
+ * the list below. The machine-readable code goes in `details.reason` and the
77
+ * original exception on `cause`, which is never serialised.
78
+ *
79
+ * Three codes: AUTHORIZATION_INVALID when the buyer's mandate is bad,
80
+ * AUTHORIZATION_REPLAYED when it is good but spent, and
81
+ * AUTHORIZATION_PROVIDER_UNAVAILABLE when our verifier never reached a
82
+ * verdict. Blaming the buyer for our outage refuses a good mandate.
83
+ */
84
+
85
+ /**
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.
88
+ */
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"];
90
+ type Ap2RejectionReason = (typeof AP2_REJECTION_REASONS)[number];
91
+
92
+ /**
93
+ * `released` is "nothing happened" and the only state a mandate can be
94
+ * presented from again. `uncertain` is a settlement whose outcome we never
95
+ * learned: not reusable, but findable by an operator reconciling by hand.
96
+ */
97
+ type Ap2AuthorizationState = 'reserved' | 'consumed' | 'released' | 'uncertain';
98
+ /**
99
+ * A digest and a few identifiers: everything replay defence needs, and nothing
100
+ * a leaked database would hand an attacker
101
+ */
102
+ interface Ap2ReservationRequest {
103
+ /**
104
+ * Digest of the ISSUER-SIGNED TOKEN, not of the presentation. Selective
105
+ * disclosure gives one mandate many presentation strings, so keying on the
106
+ * presentation would let it be spent once per disclosed subset.
107
+ */
108
+ readonly reference: string;
109
+ /** `jti` of the merchant checkout JWT the mandate binds */
110
+ readonly checkoutJti: string;
111
+ readonly mandateIssuer: string;
112
+ readonly checkoutIssuer: string;
113
+ readonly resourceId: string;
114
+ readonly requestId: string;
115
+ }
116
+ type Ap2ReservationResult = {
117
+ readonly kind: 'reserved';
118
+ }
119
+ /** Already reserved, consumed, or of uncertain outcome. Never re-spendable */
120
+ | {
121
+ readonly kind: 'replayed';
122
+ readonly state: Ap2AuthorizationState;
123
+ };
124
+ interface Ap2ReplayStore {
125
+ /** Atomically claim a mandate, or report that something already holds it */
126
+ reserve(request: Ap2ReservationRequest): Ap2ReservationResult;
127
+ /** Settlement succeeded: spend it permanently */
128
+ consume(reference: string): void;
129
+ /** Nothing happened: hand it back so a corrected retry can use it */
130
+ release(reference: string): void;
131
+ /** Settlement outcome unknown. Not reusable, and flagged for a human */
132
+ markUncertain(reference: string): void;
133
+ /** Current state, for tests and diagnostics */
134
+ stateOf(reference: string): Ap2AuthorizationState | undefined;
135
+ close(): void;
136
+ }
137
+
138
+ /**
139
+ * The AP2 authorization provider: the seam between core's generic contract and
140
+ * the mandate machinery.
141
+ *
142
+ * Owns the replay database, so the gateway owns this object's lifetime and
143
+ * closes it on shutdown.
144
+ */
145
+
146
+ interface Ap2AuthorizationProviderOptions {
147
+ readonly config: EnabledAp2Config;
148
+ readonly clock?: Clock;
149
+ readonly logger?: Logger;
150
+ /** Injectable so tests need not touch the filesystem */
151
+ readonly replayStore?: Ap2ReplayStore;
152
+ }
153
+ interface Ap2AuthorizationProvider extends AuthorizationProvider {
154
+ /** Closes the replay database */
155
+ close(): void;
156
+ }
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
+ declare function createAp2AuthorizationProvider(options: Ap2AuthorizationProviderOptions): Ap2AuthorizationProvider;
163
+
164
+ export { AP2_CAPABILITIES, AP2_REJECTION_REASONS, AP2_UNSUPPORTED, type Ap2AuthorizationProvider, type Ap2AuthorizationProviderOptions, type Ap2RejectionReason, type Ap2SigningKey, type CreateCheckoutJwtOptions, EnabledAp2Config, createAp2AuthorizationProvider as ap2, createAp2AuthorizationProvider, createCheckoutJwt };