Repository navigation
Expand file tree
/
Copy pathconfig.example.yaml
More file actions
253 lines (241 loc) · 9.38 KB
/
Copy pathconfig.example.yaml
File metadata and controls
253 lines (241 loc) · 9.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# ---------------------------------------------------------------------------
# Agent Commerce Gateway - example configuration
#
# Copy to `config.yaml` and edit, or generate one with:
# npm run agent-commerce -- init
#
# Validate it with:
# npm run agent-commerce -- validate
#
# `${VAR}` placeholders are resolved from the environment at load time. An
# unresolved one fails startup, and config errors never print a resolved value.
# ---------------------------------------------------------------------------
version: 1
merchant:
id: demo-store
name: Demo Data Store
publicBaseUrl: ${GATEWAY_PUBLIC_BASE_URL}
server:
port: ${GATEWAY_PORT}
host: 0.0.0.0
# Required for /api/receipts, /api/events and /api/payment-attempts.
# These routes expose the merchant's commerce ledger and return 404
# when this token is unset. Use a real secret if anyone else can reach
# the deployment.
adminToken: ${ADMIN_TOKEN}
# Browser origins permitted to read the gateway. Empty (the default) means
# none. Agent traffic needs no entry here.
allowedOrigins:
- ${DASHBOARD_ORIGIN}
storage:
receipts:
driver: sqlite
path: ${RECEIPT_STORE_PATH}
protocols:
http:
enabled: true
mcp:
enabled: true
mountPath: /mcp
# A2A (Agent2Agent) v1.0.1 - experimental, off by default.
# Serves JSON-RPC `SendMessage` at mountPath and the Agent Card at
# /.well-known/agent-card.json. Enable at least one resource with
# `expose: [a2a]`. Clients send `A2A-Version: 1.0`.
# See docs/protocols/a2a.md for supported features.
a2a:
enabled: false
mountPath: /a2a
# ACP (Agentic Commerce Protocol), stable snapshot 2026-04-17 - experimental,
# off by default. Enabling it serves the five checkout routes under mountPath
# and the specification-fixed discovery document at /.well-known/acp.json.
# Every checkout call needs `Authorization: Bearer <token>` and
# `API-Version: 2026-04-17`; a POST also needs an `Idempotency-Key`. Only the
# `checkout` service is served: carts, feed, orders, delegated payment and authentication, webhooks
# and the ACP MCP binding are not implemented.
#
# Enabling it needs the five mapped resources too - a complete, validating
# config is in examples/acp-checkout/. See docs/protocols/acp.md.
acp:
enabled: false
mountPath: /acp
resources:
# --- free resource: exposes a merchant API endpoint -----------------------
weather_basic:
name: Basic Weather
description: Current basic weather for a city. Free.
input:
type: object
properties:
city:
type: string
description: City name, e.g. "Berlin"
required: [city]
additionalProperties: false
backend:
type: http
method: GET
url: ${MERCHANT_API_BASE_URL}/api/weather/{city}
timeoutMs: 5000
pricing:
type: free
expose: [http, mcp]
# --- paid resource: requires x402 settlement ------------------------------
market_report:
name: Premium Market Report
description: Latest premium market analysis. Paid resource.
input:
type: object
properties: {}
additionalProperties: false
backend:
type: http
method: GET
url: ${MERCHANT_API_BASE_URL}/api/report
timeoutMs: 10000
pricing:
type: fixed
amount: "0.01"
currency: USDC
expose: [http, mcp]
payments: [x402]
# What the backend returns, declared in each x402 challenge before payment;
# an HTTP delivery keeps the backend's own Content-Type when it is text
# mimeType: application/json
payments:
x402:
enabled: true
network: ${X402_NETWORK}
rpcUrl: ${X402_RPC_URL}
asset: ${X402_ASSET}
assetName: ${X402_ASSET_NAME}
assetVersion: ${X402_ASSET_VERSION}
assetDecimals: ${X402_ASSET_DECIMALS}
# Merchant-controlled settlement destination.
# This is NEVER a gateway-owned wallet - see docs/security.md.
payTo: ${MERCHANT_WALLET}
# Seconds a payment challenge stays valid
maxTimeoutSeconds: 120
# Experimental ERC-8409 quotes for EVM offers in x402 challenges.
# Use a dedicated, unfunded key, never the merchant's. See
# docs/configuration.md#erc-8409-quotes.
# quote:
# enabled: true
# signerPrivateKey: ${X402_QUOTE_SIGNER_KEY}
# Settlement order: authorization (the default) calls the backend first
# and settles only if it succeeds; upfront settles first. A paid resource
# can set its own paymentFlow, which applies to the rail that serves it.
# paymentFlow: authorization
# Who verifies the authorization and broadcasts the transfer.
#
# mode: local the facilitator runs in this process and signs with
# signerPrivateKey. Meant for the local dev chain. Refused
# on mainnet, and a well-known Anvil key is refused against
# any RPC that is not local or private.
#
# mode: remote an HTTP facilitator handles settlement; the gateway holds no
# facilitator signing key. Requires https, except on a local or private
# host off mainnet, and on mainnet a credential unless
# allowUnauthenticatedFacilitator is set.
facilitator:
mode: local
signerPrivateKey: ${X402_FACILITATOR_PRIVATE_KEY}
#
# Public testnet example: no private key. Omit the MockUSDC asset fields
# to use the network's USDC.
#
# network: eip155:84532
# facilitator:
# mode: remote
# url: https://x402.org/facilitator
# auth:
# type: none
#
# Base mainnet, also without the asset fields. None of these are defaults.
# `auth` is required unless the facilitator takes no credential and
# allowUnauthenticatedFacilitator: true is set instead:
#
# network: eip155:8453
# allowMainnet: true
# facilitator:
# mode: remote
# url: ${X402_FACILITATOR_URL}
# auth:
# type: bearer
# token: ${X402_FACILITATOR_TOKEN}
# MPP (charge, evm, EIP-3009) is experimental and disabled by default. It
# settles through an x402 facilitator and can reuse the local values above.
# MPP resources use USDC; [x402, mpp] selects the first enabled rail.
#
# mpp:
# enabled: true
# network: eip155:31337 # the local chain; the default is Base Sepolia
# rpcUrl: ${X402_RPC_URL}
# asset: ${X402_ASSET}
# assetName: ${X402_ASSET_NAME}
# assetVersion: ${X402_ASSET_VERSION}
# recipient: ${MERCHANT_WALLET}
# realm: localhost
# challengeSecret: ${MPP_CHALLENGE_SECRET} # at least 32 characters
# # Same values as x402 above, but the default is upfront: MPP's charge
# # intent forbids running the backend before the payment is verified.
# # Under authorization, the backend must answer before the challenge
# # expires, by default 300 s after it was issued (challengeTtlSeconds).
# paymentFlow: upfront
# facilitator:
# mode: local
# signerPrivateKey: ${X402_FACILITATOR_PRIVATE_KEY}
# ---------------------------------------------------------------------------
# AP2 mandate verification - experimental, off by default.
#
# Makes a paid resource require proof that the human behind the agent approved
# THIS purchase: a signed AP2 v0.2.0 Direct Checkout Mandate, verified before
# the payment is allowed to settle. A mandate never unlocks a resource on its
# own and never moves money; the resource still takes a real payment.
#
# Public keys only, written here by you. Nothing is fetched at runtime: no
# JWKS, no `jku`, no `x5u`, no issuer discovery. Rotate by listing the new key
# beside the old one, moving the signer to the new `kid`, then removing the old.
#
# Needs the optional peers: npm install jose @sd-jwt/core canonicalize
# Full reference: docs/protocols/ap2.md
# ---------------------------------------------------------------------------
# authorization:
# ap2:
# enabled: true
# specVersion: "0.2.0" # the only supported value
# mode: direct # the only supported mode
# clockSkewSeconds: 60 # default; 300 is the ceiling
# # AP2 makes a mandate's `aud` and `exp` optional. Set these to refuse
# # mandates without them; the checkout JWT requires both regardless.
# requireMandateAudience: false
# requireMandateExpiry: false
# replay:
# # Its own file. An authorization replay is not a payment replay, and a
# # spent mandate must stay spent for as long as you can be asked what
# # you delivered.
# path: ./data/ap2-authorizations.sqlite
# trust:
# # Who may issue a Checkout Mandate. Usually the buyer's shopping agent
# # or credential provider.
# mandateIssuers:
# - issuer: https://surface.example
# audience: merchant.example # required: who the mandate is for
# keys:
# - kid: mandate-2026-01
# jwk: { kty: EC, crv: P-256, x: "...", y: "..." }
# # Who signs YOUR checkout documents. A separate list on purpose:
# # signing checkouts must not confer the power to issue mandates.
# checkoutIssuers:
# - issuer: https://merchant.example
# audience: agent-commerce
# keys:
# - kid: checkout-2026-01
# jwk: { kty: EC, crv: P-256, x: "...", y: "..." }
#
# Then require it on a paid resource, under `resources:`:
#
# market_report:
# pricing: { type: fixed, amount: "0.01", currency: USDC }
# payments: [x402]
# authorization:
# required: [ap2]