@devlab.group/agent-commerce 1.3.0 → 1.4.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 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
 
@@ -90,17 +90,18 @@ const { url } = await gateway.listen();
90
90
 
91
91
  ### Optional peers - install only the rails you use
92
92
 
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.
93
+ The MCP adapter, the x402 provider and AP2 verification live on their own
94
+ subpaths, because each needs a dependency the rest of the package does not -
95
+ the x402 rail brings the whole EVM signing and RPC stack, which a gateway
96
+ serving a free HTTP resource has no business installing.
97
97
 
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) |
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
+ | verify AP2 mandates, sign checkout JWTs | `+ jose @sd-jwt/core canonicalize` | `from '@devlab.group/agent-commerce/ap2'` |
104
+ | authenticate to a CDP facilitator | `+ @coinbase/x402` | (no import - loaded on demand) |
104
105
 
105
106
  ```bash
106
107
  npm install @devlab.group/agent-commerce @modelcontextprotocol/sdk @x402/core @x402/evm viem
@@ -109,8 +110,14 @@ npm install @devlab.group/agent-commerce @modelcontextprotocol/sdk @x402/core @x
109
110
  ```ts
110
111
  import { mcp } from '@devlab.group/agent-commerce/mcp';
111
112
  import { x402 } from '@devlab.group/agent-commerce/x402';
113
+ import { ap2 } from '@devlab.group/agent-commerce/ap2';
112
114
  ```
113
115
 
116
+ The AP2 three are small - about 1.3 MB installed between them, against roughly
117
+ 63 MB for the x402 stack - but they stay optional on the same principle: a
118
+ deployment that gates nothing on a mandate should not carry a JOSE stack and an
119
+ SD-JWT parser to serve a resource.
120
+
114
121
  Peers are pinned exactly: x402's schemas and EIP-712 domains cross this
115
122
  boundary, so a version skew is a correctness problem rather than a convenience
116
123
  one. Import a subpath without its
@@ -157,30 +164,33 @@ To stop and wipe state: `docker compose down -v`.
157
164
  ## How it works
158
165
 
159
166
  ```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
- └───────────────────────┘
167
+ ┌──────────────────────────────────────────────────────────────────────────────┐
168
+ │ AI Agent │
169
+ └───────────────────────────────────────┬──────────────────────────────────────┘
170
+ │ MCP · A2A · ACP · HTTP
171
+ │ PAYMENT-SIGNATURE
172
+ │ Agent-Authorization
173
+ ┌───────────────────────────────────────▼──────────────────────────────────────┐
174
+ │ Agent Commerce Gateway (yours) │
175
+ │ │
176
+ │ protocol adapters → ExecutionPipeline │
177
+ │ │ │
178
+ │ ┌────────────────────┬──────────────┴──┬────────────────┐ │
179
+ │ ▼ ▼ ▼ ▼ │
180
+ │ AuthorizationProvider PaymentProvider BackendExecutor ReceiptStore │
181
+ │ (ap2) (x402) (bounded HTTP) (SQLite) │
182
+ └───────────────────────────────────────┬──────────────────────────────────────┘
183
+ │
184
+ ┌──────────▼─────────┐
185
+ │ Your backend API │
186
+ └────────────────────┘
178
187
  ```
179
188
 
180
189
  Every protocol adapter converges on **one execution pipeline**. That is what
181
190
  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).
191
+ adapter has to remember. Money never passes through the box: the buyer pays the
192
+ merchant directly on chain, and the gateway holds neither the funds nor a key.
193
+ Full detail in [docs/architecture.md](docs/architecture.md).
184
194
 
185
195
  ## Configure a resource
186
196
 
@@ -219,33 +229,39 @@ It writes a reviewable `resources:` fragment - path, query and JSON body
219
229
  mapped, schemas converted to what the gateway actually enforces - and
220
230
  deliberately leaves `pricing` and `expose` out, because an OpenAPI document has
221
231
  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.
232
+ imported. See [OpenAPI import](docs/openapi-import.md) for the exact supported subset.
224
233
 
225
234
  See [docs/configuration.md](docs/configuration.md).
226
235
 
227
236
  ## Protocol support
228
237
 
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 | - |
238
+ | Protocol | Status | Pinned revision |
239
+ | --------- | ------------ | -------------------------------------------------------- |
240
+ | **MCP** | Supported | `@modelcontextprotocol/sdk@1.30.0` |
241
+ | **x402** | Supported | x402 v2 (`@x402/core`, `@x402/evm`), scheme `exact`, EVM |
242
+ | **HTTP** | Supported | native routes |
243
+ | **A2A** | Experimental | A2A v1.0.0, binding `JSONRPC`, method `SendMessage` |
244
+ | **ACP** | Experimental | ACP `2026-04-17`, REST checkout + discovery |
245
+ | **AP2** | Experimental | AP2 `v0.2.0`, Direct Checkout Mandate verification |
246
+ | UCP · MPP | Planned | - |
247
+
248
+ [AP2](docs/ap2.md) is in that table because people look there, but it is an **authorization**
249
+ method rather than a transport: it gates settlement on a resource that still
250
+ takes a real payment, and it is the verifying half only - the gateway holds no
251
+ signing key and issues no Checkout Receipt.
237
252
 
238
253
  "Planned" means **no code ships for it**. "Experimental" means the code ships,
239
254
  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).
255
+ named subset: [A2A](docs/protocols.md#a2a) and [ACP](docs/protocols.md#acp) are
256
+ both off by default and documented in full there, as are
257
+ [MCP](docs/protocols.md#mcp) and [x402](docs/protocols.md#x402). ACP serves the
258
+ five stable checkout operations and advertises `services: ["checkout"]` and
259
+ nothing more; its `payment_data` stays with the merchant's own checkout and is
260
+ never turned into an x402 payment.
261
+
262
+ Each adapter reports its own `supportedSpec`, `capabilities` and `unsupported`
263
+ list at runtime through `GET /.well-known/agent-commerce` and
264
+ `agent-commerce doctor`, so the claim is checkable rather than marketing.
249
265
 
250
266
  ## Payment model
251
267
 
@@ -260,8 +276,10 @@ checkable, not marketing. Detail: [docs/protocols.md](docs/protocols.md).
260
276
  - **Real settlement in CI.** The end-to-end test asserts the buyer's balance
261
277
  falls and the merchant's rises by exactly the price, with a real transaction
262
278
  hash in the receipt. A log line saying "payment successful" would not count.
263
-
264
- Detail: [docs/payment-flow.md](docs/payment-flow.md).
279
+ - **Authorization is separate from payment.** A resource can also require an
280
+ AP2 mandate, verified before settlement and spendable exactly once. It never
281
+ moves money and never unlocks a resource on its own - the payment still has
282
+ to be real.
265
283
 
266
284
  ## Public networks
267
285
 
@@ -378,6 +396,7 @@ PASS Backend 2/2 backend host(s) reachable
378
396
  PASS Protocols http=on mcp=on (/mcp) a2a=off acp=off
379
397
  INFO A2A disabled
380
398
  INFO ACP disabled
399
+ INFO AP2 disabled
381
400
  PASS Payments x402 v2 (scheme=exact) enabled - LOCAL dev chain (eip155:84532, chain id shared with Base Sepolia), destination=0x7099…79C8, facilitator=local
382
401
  INFO Payments (MPP) planned - not implemented in this release
383
402
  PASS Storage sqlite schema v1 writable; receipts=2
@@ -398,8 +417,9 @@ Exits non-zero if anything fails. `--json` for machines.
398
417
  The demo binds everything to `127.0.0.1`. Before putting the gateway anywhere
399
418
  reachable by anyone else, know the split:
400
419
 
401
- - **Agent routes** (`/api/resources/:id/invoke`, `/mcp`) are unauthenticated by
402
- design - paid resources are protected by payment, not by a password.
420
+ - **Agent routes** (`/api/resources/:id/invoke`, `/mcp`, the A2A mount) are
421
+ unauthenticated by design - paid resources are protected by payment, not by a
422
+ password. ACP is the exception: its checkout routes require a bearer token.
403
423
  - **Operator routes** (`/api/receipts`, `/api/events`, `/api/events/stream`) are
404
424
  the merchant's commerce ledger: payer addresses, amounts, settlement hashes.
405
425
  They require `server.adminToken`, and return **404** if none is configured.
@@ -425,11 +445,13 @@ See [CONTRIBUTING.md](CONTRIBUTING.md).
425
445
 
426
446
  **Now** - MCP, x402 v2, settlement on the local chain, Base Sepolia and Base
427
447
  mainnet, receipts, doctor, deterministic demo, experimental A2A v1.0.0 and ACP
428
- `2026-04-17` checkout adapters, and experimental OpenAPI import.
448
+ `2026-04-17` checkout adapters, experimental AP2 v0.2.0 mandate verification,
449
+ and experimental OpenAPI import.
429
450
 
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.
451
+ **Next** - a `doctor` GitHub Action · UCP · MPP · autonomous-mode AP2 (open
452
+ mandates, agent key binding, constraint evaluation) · more of ACP (carts, feed,
453
+ delegated payment) · Shopify and WooCommerce examples · PostgreSQL · richer
454
+ observability · multi-file and remote OpenAPI sources.
433
455
 
434
456
  New protocols land only after the adapter model survives real use. Scope
435
457
  discipline is a release requirement, not a mood.
@@ -441,6 +463,7 @@ discipline is a release requirement, not a mood.
441
463
  | [Architecture](docs/architecture.md) | how the pieces fit |
442
464
  | [Payment flow](docs/payment-flow.md) | the paid round trip, and every way it fails |
443
465
  | [Protocols](docs/protocols.md) | exactly what is and is not supported |
466
+ | [AP2](docs/ap2.md) | mandate verification and the trust model |
444
467
  | [Configuration](docs/configuration.md) | `config.yaml` reference |
445
468
  | [OpenAPI import](docs/openapi-import.md) | generate resources from an existing API |
446
469
  | [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 };