@agentsbloom/sdk 0.2.0 → 0.5.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/LICENSE +21 -21
- package/README.md +184 -254
- package/SECURITY.md +24 -19
- package/index.d.ts +355 -124
- package/index.js +1582 -342
- package/lib/ap2.js +1017 -422
- package/lib/http-signatures.js +874 -0
- package/lib/money.js +283 -0
- package/lib/outcomes.js +108 -0
- package/lib/protocol.d.ts +229 -0
- package/lib/protocol.js +85 -0
- package/lib/shared-store.js +298 -0
- package/lib/signature-base.js +436 -0
- package/lib/structured-fields.js +398 -0
- package/package.json +95 -81
- package/telemetry.js +77 -50
- package/assets/logo-mark.svg +0 -25
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 AgentsBloom
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AgentsBloom
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,254 +1,184 @@
|
|
|
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
|
-
import {
|
|
186
|
-
createAp2Mandate,
|
|
187
|
-
verifyAP2Mandates,
|
|
188
|
-
resetAp2ReplayCache
|
|
189
|
-
} from "@agentsbloom/sdk";
|
|
190
|
-
|
|
191
|
-
const { token } = createAp2Mandate({
|
|
192
|
-
audience: "https://store.example",
|
|
193
|
-
maxBudget: 100
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
const result = verifyAP2Mandates(
|
|
197
|
-
{ "x-ap2-mandate": `Bearer ${token}` },
|
|
198
|
-
{ orderTotal: 40 },
|
|
199
|
-
{ expectedAudience: "https://store.example" }
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
if (!result.valid) {
|
|
203
|
-
throw new Error(result.reason);
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
Presented mandates are cryptographically verified. The verifier enforces signature algorithms, issuer/audience binding, bounded lifetime, required `jti` replay protection, optional category restrictions, and budget limits.
|
|
208
|
-
|
|
209
|
-
## Telemetry
|
|
210
|
-
|
|
211
|
-
`setupTelemetry()` dynamically loads the optional OpenTelemetry packages and continues without an exporter when they are unavailable. `shutdown()` closes the configured provider and clears SDK in-memory state.
|
|
212
|
-
|
|
213
|
-
```js
|
|
214
|
-
import { setupTelemetry } from "@agentsbloom/sdk";
|
|
215
|
-
|
|
216
|
-
await setupTelemetry({
|
|
217
|
-
otlpEndpoint: process.env.AGENTSBLOOM_OTEL_ENDPOINT,
|
|
218
|
-
serviceName: "example-store",
|
|
219
|
-
samplingRatio: 1,
|
|
220
|
-
apiKey: process.env.AGENTSBLOOM_API_KEY
|
|
221
|
-
});
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
## Learn more
|
|
225
|
-
|
|
226
|
-
- [AgentsBloom documentation](https://docs.agentsbloom.com)
|
|
227
|
-
- [AgentsBloom marketing site](https://agentsbloom.com)
|
|
228
|
-
- [AgentsBloom blog](https://blog.agentsbloom.com)
|
|
229
|
-
- [AgentsBloom organization](https://github.com/AgentsBloom)
|
|
230
|
-
- [SDK issues and discussions](https://github.com/AgentsBloom/sdk/issues)
|
|
231
|
-
|
|
232
|
-
## Development and release checks
|
|
233
|
-
|
|
234
|
-
From this package directory:
|
|
235
|
-
|
|
236
|
-
```sh
|
|
237
|
-
npm ci
|
|
238
|
-
npm test
|
|
239
|
-
npm run lint
|
|
240
|
-
npm run check:package
|
|
241
|
-
npm run verify:consumer
|
|
242
|
-
npm run release:check
|
|
243
|
-
npm pack --dry-run --ignore-scripts
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
The package uses an explicit npm `files` allowlist. Tests and release scripts remain in the repository but are intentionally excluded from the published tarball. These commands do not publish to npm.
|
|
247
|
-
|
|
248
|
-
## Security
|
|
249
|
-
|
|
250
|
-
Please report suspected vulnerabilities privately. See [`SECURITY.md`](./SECURITY.md). Never include live credentials in an issue, pull request, test fixture, or support request.
|
|
251
|
-
|
|
252
|
-
## License
|
|
253
|
-
|
|
254
|
-
MIT. See [`LICENSE`](./LICENSE).
|
|
1
|
+
# @agentsbloom/sdk
|
|
2
|
+
|
|
3
|
+
`@agentsbloom/sdk` is a Node.js/Express middleware package for exposing commerce actions to AI agents through AgentsBloom discovery endpoints and supported agent-commerce protocols.
|
|
4
|
+
|
|
5
|
+
The package includes action discovery, idempotency and in-memory rate-limit helpers, legacy HMAC agent signatures, RFC HTTP Message Signature verification, AP2 mandate verification, optional OpenTelemetry export, and HTML metadata/WebMCP injection.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
- Node.js 20 or newer
|
|
10
|
+
- An Express 4 application
|
|
11
|
+
- A real `AGENTSBLOOM_SECRET` for protected legacy-signed write actions
|
|
12
|
+
|
|
13
|
+
The SDK does not contain a default or demo signing secret. If a protected write request uses the legacy `X-Agent-Signature` flow without a configured secret, it is rejected. RFC HTTP Message Signatures and AP2 mandates use their own verification paths.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm install @agentsbloom/sdk express
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`express` is a peer dependency. OpenTelemetry SDK packages are declared as optional dependencies and npm installs them by default; applications that do not need OTLP export can use `npm install --omit=optional`. The SDK also handles the optional packages being absent when `setupTelemetry()` is called.
|
|
22
|
+
|
|
23
|
+
## Minimal Express setup
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
import express from "express";
|
|
27
|
+
import { agentsbloom, shutdown } from "@agentsbloom/sdk";
|
|
28
|
+
|
|
29
|
+
const app = express();
|
|
30
|
+
const agentSecret = process.env.AGENTSBLOOM_SECRET;
|
|
31
|
+
|
|
32
|
+
if (!agentSecret) {
|
|
33
|
+
throw new Error("AGENTSBLOOM_SECRET must be configured before starting the server");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
app.use(express.json({ limit: "1mb" }));
|
|
37
|
+
app.use(agentsbloom({
|
|
38
|
+
apiKey: process.env.AGENTSBLOOM_API_KEY,
|
|
39
|
+
agentSecret,
|
|
40
|
+
baseUrl: process.env.PUBLIC_STORE_URL,
|
|
41
|
+
name: "Example Store",
|
|
42
|
+
description: "An example store for agent-driven commerce.",
|
|
43
|
+
actions: {
|
|
44
|
+
search: {
|
|
45
|
+
method: "POST",
|
|
46
|
+
description: "Search the product catalog.",
|
|
47
|
+
params: { query: "string" },
|
|
48
|
+
handler: async ({ query }) => ({ query, items: [] })
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}));
|
|
52
|
+
|
|
53
|
+
const server = app.listen(process.env.PORT || 3000);
|
|
54
|
+
const closeServer = () => new Promise((resolve, reject) => {
|
|
55
|
+
if (!server.listening) return resolve();
|
|
56
|
+
server.close((error) => error ? reject(error) : resolve());
|
|
57
|
+
});
|
|
58
|
+
const stop = async () => {
|
|
59
|
+
try {
|
|
60
|
+
await closeServer(); // stop accepting requests before clearing SDK state
|
|
61
|
+
} finally {
|
|
62
|
+
await shutdown();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
process.once("SIGTERM", stop);
|
|
66
|
+
process.once("SIGINT", stop);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`baseUrl` should be the canonical public HTTPS origin of the store. Do not put an API key or signing secret in source control, client-side code, logs, or package metadata.
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
72
|
+
|
|
73
|
+
- `apiKey`: AgentsBloom account key used for attribution and service integrations.
|
|
74
|
+
- `agentSecret`: shared secret used to verify legacy `X-Agent-Identifier`/`X-Agent-Signature` requests. If omitted, `AGENTSBLOOM_SECRET` is read from the environment; if neither is set, legacy signed writes fail closed. Each legacy signature must also include a fresh timestamp and one-time nonce and is bound to the method, path, and parsed request body.
|
|
75
|
+
- `agentKeys`: optional per-agent secrets keyed by `X-Agent-Identifier` (v4 medium pass). Checked before the shared secret, so one leaked agent credential can be replaced without touching every other agent.
|
|
76
|
+
- `revokedIdentifiers`: optional array of identifiers rejected outright before verification.
|
|
77
|
+
- `actionAccess`: optional map of action name to `'anonymous' | 'authenticated'`. `'authenticated'` requires a verified agent signature even for read (GET) invocations of that action.
|
|
78
|
+
- `actionIdentities`: optional per-action identity allow-lists. Entries match a verified identity exactly (`rfc:<keyid>`) or by prefix when ending with `:` (`legacy:`). Enforced on REST actions, `/ap2/checkout`, and MCP tool calls.
|
|
79
|
+
- `maxBodyBytes`: body-size cap in bytes (default 1 MiB), enforced against the received bytes as well as the Content-Length header.
|
|
80
|
+
- `baseUrl`: canonical store origin used for discovery and audience binding.
|
|
81
|
+
- `actions`: map of agent action names to handlers. Handlers receive `(params, req, res)` and may return a value or a promise. `method` defaults to `POST` and is enforced; declare `method: "GET"` explicitly for a read action.
|
|
82
|
+
- `rateLimit`: optional `{ max, windowMs }` in-memory per-IP limits. OPTIONS preflights count toward the bucket; the tracking map is bounded.
|
|
83
|
+
- `allowedHosts`: optional array of hostnames. When set, discovery URLs are derived from `baseUrl` for any request whose `Host` header is not on the list, preventing Host-header poisoning of the published documents.
|
|
84
|
+
- `idempotency`: optional `{ ttlMs, maxEntries }` for successful write responses keyed by `Idempotency-Key`. Protected action requests authenticate before cache lookup, cache entries are scoped to the middleware instance and verified agent identity, and the cache is bounded with oldest-first eviction.
|
|
85
|
+
- `ap2`: optional AP2 settings including `expectedAudience`, `maxMandateLifetimeSec`, `requireJti`, `requestedCategories`, and `expectedCurrency`. Set `trustedIssuersOnly: true` in production to reject self-certifying did:key mandates (which anyone can mint with an arbitrary budget) and accept only your configured trusted key. `/ap2/checkout` enforces the mandate budget against the total your checkout handler computes (`result.total`/`result.totalPrice`) — always return it; the client-declared `orderTotal` is never authoritative. Mandate and order currencies must agree when both are declared.
|
|
86
|
+
- `merchantJwks`: merchant JWKS document served at the HTTP Message Signatures discovery endpoint. When unset, that endpoint returns 503 rather than serving placeholder keys.
|
|
87
|
+
- `agentJwks`: inline trusted JWKS used to verify RFC HTTP Message Signatures. Key IDs must match a JWK `kid` exactly. Since v4 there is no default JWKS: RFC-signed writes fail closed (503) until this or `agentJwksUrl` is configured.
|
|
88
|
+
- `agentJwksUrl`: HTTPS URL for the trusted agent JWKS. The URL is configured by the merchant; a request cannot select an arbitrary remote JWKS URL.
|
|
89
|
+
- `signature`: optional `{ maxAgeMs, requireAuthority }`. `requireAuthority: true` makes the `@authority` covered component mandatory so the host is bound into every signature.
|
|
90
|
+
- `mcp`: optional `{ maxSessions }` bounding concurrent MCP SSE sessions (default 100).
|
|
91
|
+
- `corsOrigin`: a single origin string, an array of exact origins (matching origins are reflected with `Vary: Origin`; all others receive no allow-origin header), or unset (`*` — warns at startup).
|
|
92
|
+
- Quota operators: import { setQuotaExceededUntil, clearQuotaExceeded } from "@agentsbloom/sdk" to trip/clear the 402 quota gate process-wide, or set AGENTSBLOOM_QUOTA_EXCEEDED_UNTIL (epoch ms) in the environment.
|
|
93
|
+
- `signature`: optional `{ maxAgeMs }` for legacy HMAC timestamp validation; the default is five minutes.
|
|
94
|
+
- `demoMode`: explicit local/demo-only bypass for signature authentication. Never enable it in a production deployment.
|
|
95
|
+
- `disableSignatureAuth`: explicit compatibility bypass. It should not be enabled for an internet-facing deployment.
|
|
96
|
+
|
|
97
|
+
The middleware does not replace an application-level authorization layer, a distributed rate limiter, a durable idempotency store, TLS termination, or payment-provider verification.
|
|
98
|
+
|
|
99
|
+
## Legacy HMAC request signatures
|
|
100
|
+
|
|
101
|
+
For a mutating action that uses `X-Agent-Signature`, send these headers:
|
|
102
|
+
|
|
103
|
+
- `X-Agent-Identifier`: printable agent identifier.
|
|
104
|
+
- `X-Agent-Timestamp`: current Unix timestamp in seconds.
|
|
105
|
+
- `X-Agent-Nonce`: a unique printable nonce of at least 16 characters.
|
|
106
|
+
- `X-Agent-Signature`: lowercase or uppercase hexadecimal HMAC-SHA-256.
|
|
107
|
+
|
|
108
|
+
The signed payload is the JSON array `[identifier, method, originalUrl, timestamp, nonce, parsedBody]`, using the configured `agentSecret`. Signatures expire after five minutes by default and a nonce cannot be consumed twice by the same identifier within the process. This is an in-memory replay guard; use a durable authentication and replay store when running multiple instances. Identifier-only signatures from older SDK revisions are intentionally rejected; update the signer to include the timestamp and nonce before upgrading.
|
|
109
|
+
|
|
110
|
+
## RFC HTTP Message Signatures
|
|
111
|
+
|
|
112
|
+
Protected write requests using the RFC 9421-compatible path must sign `@method`, `@path`, and `content-digest`, and include `created`, `expires`, `nonce`, `keyid`, and `alg` signature parameters. The SDK validates the five-minute default lifetime, rejects reused nonces (atomically — concurrent replays cannot slip through), pins the declared algorithm family to the configured key type (RSA→`rs*`, EC→`es*`, Ed25519/Ed448→`ed*`; SHA-256/384/512 digests derived correctly), rejects multi-label signatures and mismatched Signature/Signature-Input labels, and recomputes `content-digest` from `req.rawBody` when present or the parsed request body otherwise. If an application needs byte-exact verification, configure its body parser to preserve the raw body on `req.rawBody`. Note: `@path` covers the path **including the query string** (self-consistent with this SDK's agent client); enable `signature.requireAuthority` to also bind the host into every signature.
|
|
113
|
+
|
|
114
|
+
## MCP message authentication
|
|
115
|
+
|
|
116
|
+
The SSE connection at `/mcp` can advertise the configured tools, but mutating MCP messages sent to `/mcp/messages` must pass the same configured RFC HTTP Message Signature or legacy `X-Agent-Signature` verification as other protected writes. This prevents an unauthenticated MCP client from invoking an action handler.
|
|
117
|
+
|
|
118
|
+
## AP2
|
|
119
|
+
|
|
120
|
+
The package exports helpers for creating and verifying signed AP2 mandates:
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
import {
|
|
124
|
+
createAp2Mandate,
|
|
125
|
+
verifyAP2Mandates,
|
|
126
|
+
resetAp2ReplayCache
|
|
127
|
+
} from "@agentsbloom/sdk";
|
|
128
|
+
|
|
129
|
+
const { token } = createAp2Mandate({
|
|
130
|
+
audience: "https://store.example",
|
|
131
|
+
maxBudget: 100
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const result = verifyAP2Mandates(
|
|
135
|
+
{ "x-ap2-mandate": `Bearer ${token}` },
|
|
136
|
+
{ orderTotal: 40 },
|
|
137
|
+
{ expectedAudience: "https://store.example" }
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
if (!result.valid) {
|
|
141
|
+
throw new Error(result.reason);
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Presented mandates are cryptographically verified. The verifier enforces signature algorithms, issuer/audience binding, bounded lifetime, required `jti` replay protection, optional category restrictions, and budget limits. Reset the replay cache only when the process is being deliberately reinitialized, such as in a test harness.
|
|
146
|
+
|
|
147
|
+
## Telemetry
|
|
148
|
+
|
|
149
|
+
`setupTelemetry()` dynamically loads the optional OpenTelemetry packages and continues without an exporter when they are unavailable. `samplingRatio` is accepted and reported for compatibility, but the current initializer does not apply an SDK-level sampler. `shutdown()` closes the configured provider and clears SDK in-memory state. Applications should call it during graceful process shutdown, after stopping the HTTP server from accepting new requests.
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
import { setupTelemetry } from "@agentsbloom/sdk";
|
|
153
|
+
|
|
154
|
+
await setupTelemetry({
|
|
155
|
+
otlpEndpoint: process.env.AGENTSBLOOM_OTEL_ENDPOINT,
|
|
156
|
+
serviceName: "example-store",
|
|
157
|
+
samplingRatio: 1,
|
|
158
|
+
apiKey: process.env.AGENTSBLOOM_API_KEY
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Development and release checks
|
|
163
|
+
|
|
164
|
+
From this package directory:
|
|
165
|
+
|
|
166
|
+
```sh
|
|
167
|
+
npm ci
|
|
168
|
+
npm test
|
|
169
|
+
npm run lint
|
|
170
|
+
npm run check:package
|
|
171
|
+
npm run verify:consumer
|
|
172
|
+
npm run release:check
|
|
173
|
+
npm pack --dry-run --ignore-scripts
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The package uses an explicit npm `files` allowlist. Tests and release scripts remain in the repository but are intentionally excluded from the published tarball. These commands do not publish to npm.
|
|
177
|
+
|
|
178
|
+
## Security
|
|
179
|
+
|
|
180
|
+
Please report suspected vulnerabilities privately. See [`SECURITY.md`](./SECURITY.md). Never include live credentials in an issue, pull request, test fixture, or support request.
|
|
181
|
+
|
|
182
|
+
## License
|
|
183
|
+
|
|
184
|
+
MIT. See [`LICENSE`](./LICENSE).
|
package/SECURITY.md
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
# Security policy
|
|
2
|
-
|
|
3
|
-
## Reporting a vulnerability
|
|
4
|
-
|
|
5
|
-
Please report suspected vulnerabilities privately to `contact@agentsbloom.com` with the subject `AgentsBloom SDK security report`. Include the affected package version, a concise reproduction, and the impact. Do not include live API keys, payment credentials, signing secrets, personal data, or private repository URLs in the report.
|
|
6
|
-
|
|
7
|
-
We will acknowledge a report when practical, investigate it privately, and coordinate a fix and disclosure timeline with the reporter. Please do not disclose an unpatched vulnerability in a public issue or pull request.
|
|
8
|
-
|
|
9
|
-
## Supported versions
|
|
10
|
-
|
|
11
|
-
The latest published version is the primary supported version. Security fixes may not be backported to end-of-life versions.
|
|
12
|
-
|
|
13
|
-
## Deployment guidance
|
|
14
|
-
|
|
15
|
-
- Configure a unique high-entropy `AGENTSBLOOM_SECRET` for every merchant deployment.
|
|
16
|
-
- Keep secrets in the deployment secret manager or environment, never in source control or browser bundles.
|
|
17
|
-
- Do not use `demoMode` or `disableSignatureAuth` for internet-facing production traffic.
|
|
18
|
-
-
|
|
19
|
-
-
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
## Reporting a vulnerability
|
|
4
|
+
|
|
5
|
+
Please report suspected vulnerabilities privately to `contact@agentsbloom.com` with the subject `AgentsBloom SDK security report`. Include the affected package version, a concise reproduction, and the impact. Do not include live API keys, payment credentials, signing secrets, personal data, or private repository URLs in the report.
|
|
6
|
+
|
|
7
|
+
We will acknowledge a report when practical, investigate it privately, and coordinate a fix and disclosure timeline with the reporter. Please do not disclose an unpatched vulnerability in a public issue or pull request.
|
|
8
|
+
|
|
9
|
+
## Supported versions
|
|
10
|
+
|
|
11
|
+
The latest published version is the primary supported version. Security fixes may not be backported to end-of-life versions.
|
|
12
|
+
|
|
13
|
+
## Deployment guidance
|
|
14
|
+
|
|
15
|
+
- Configure a unique high-entropy `AGENTSBLOOM_SECRET` for every merchant deployment, or provision per-agent credentials via `agentKeys` (with `revokedIdentifiers` for eviction) so one compromised agent cannot forge every other.
|
|
16
|
+
- Keep secrets in the deployment secret manager or environment, never in source control or browser bundles.
|
|
17
|
+
- Do not use `demoMode` or `disableSignatureAuth` for internet-facing production traffic.
|
|
18
|
+
- Configure `agentJwks` or `agentJwksUrl` explicitly: since v4 (0.3.0) there is no default JWKS and RFC 9421 verification fails closed without one. Serve `merchantJwks` if you publish the signatures directory endpoint (it fails closed rather than serving a placeholder).
|
|
19
|
+
- For production AP2, set `ap2.expectedAudience`, provide a trusted `ap2PublicKey`, enable `ap2.trustedIssuersOnly`, and pin `ap2.expectedCurrency`. Always return the handler-computed order total from your checkout handler — it is what the budget cap enforces against.
|
|
20
|
+
- Restrict origins with `corsOrigin` (string or exact-match array; the default is `*` and warns at startup), consider `allowedHosts` to pin discovery-URL derivation, and use `actionAccess`/`actionIdentities` to scope which verified identities may invoke high-value actions such as checkout.
|
|
21
|
+
- Use HTTPS, durable authorization, and a distributed rate/idempotency store for production systems; configure Upstash (`UPSTASH_REDIS_REST_URL`/`TOKEN`) so replay protection is cluster-wide rather than per-instance.
|
|
22
|
+
- Rotate any credential that has appeared in logs, chat, tickets, shell history, or a repository.
|
|
23
|
+
|
|
24
|
+
See `documentation/security/sdk-v4-hardening.md` for the full list of v4 findings, fixes, and residual risks.
|