@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 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
- <p align="center">
2
- <a href="https://agentsbloom.com">
3
- <img src="./assets/logo-mark.svg" alt="AgentsBloom lotus mark" width="96" height="96" />
4
- </a>
5
- </p>
6
-
7
- <h1 align="center">@agentsbloom/sdk</h1>
8
-
9
- <p align="center">
10
- <strong>One install makes your Express store agent-ready.</strong><br />
11
- Expose commerce actions to AI agents through open discovery surfaces and secure agent-commerce protocols.
12
- </p>
13
-
14
- <p align="center">
15
- <a href="https://docs.agentsbloom.com">Docs</a> ·
16
- <a href="https://agentsbloom.com">Marketing</a> ·
17
- <a href="https://blog.agentsbloom.com">Blog</a> ·
18
- <a href="https://github.com/AgentsBloom">AgentsBloom on GitHub</a>
19
- </p>
20
-
21
- <p align="center">
22
- <a href="https://www.npmjs.com/package/@agentsbloom/sdk"><img src="https://img.shields.io/npm/v/@agentsbloom/sdk?logo=npm&logoColor=white&label=npm" alt="npm version" /></a>
23
- <a href="https://github.com/AgentsBloom/sdk/actions/workflows/ci.yml"><img src="https://github.com/AgentsBloom/sdk/actions/workflows/ci.yml/badge.svg" alt="CI status" /></a>
24
- <a href="https://github.com/AgentsBloom/sdk/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-7c3aed.svg" alt="MIT license" /></a>
25
- </p>
26
-
27
- ## About AgentsBloom
28
-
29
- [AgentsBloom](https://agentsbloom.com) builds open infrastructure for commerce on the agentic web. We help teams make existing server-side commerce actions understandable and usable by software agents while keeping the store in control of its catalog, authorization, inventory, checkout, and payment logic.
30
-
31
- This SDK is the open-source Node.js/Express core: a small middleware layer that gives an existing Express store a clear path to agent-ready commerce.
32
-
33
- ## One install to make an Express store agent-ready
34
-
35
- ```sh
36
- npm install @agentsbloom/sdk express
37
- ```
38
-
39
- Then add the middleware and describe your store actions:
40
-
41
- ```js
42
- import express from "express";
43
- import { agentsbloom } from "@agentsbloom/sdk";
44
-
45
- const app = express();
46
-
47
- app.use(express.json({ limit: "1mb" }));
48
- app.use(agentsbloom({
49
- baseUrl: process.env.PUBLIC_STORE_URL,
50
- actions: {
51
- search: {
52
- method: "POST",
53
- description: "Search the product catalog.",
54
- params: { query: "string" },
55
- handler: async ({ query }) => ({
56
- query,
57
- items: await searchProducts(query)
58
- })
59
- }
60
- }
61
- }));
62
- ```
63
-
64
- Follow the [Express quickstart in the AgentsBloom documentation](https://docs.agentsbloom.com). You do not need to rewrite your storefront or move your commerce logic into a proprietary platform.
65
-
66
- ## What the SDK provides
67
-
68
- - Action discovery and machine-readable commerce metadata.
69
- - Express middleware for agent-facing store actions.
70
- - UCP, ACP, AP2, WebMCP, and Web Bot Auth building blocks.
71
- - RFC 9421-compatible HTTP Message Signature verification.
72
- - Legacy HMAC signatures with timestamp and nonce replay protection.
73
- - AP2 mandate creation and verification with budget, audience, lifetime, category, and replay checks.
74
- - Per-IP rate limiting and idempotency handling for protected writes.
75
- - Optional OpenTelemetry export with graceful fallback when exporters are unavailable.
76
- - HTML metadata and WebMCP injection for compatible responses.
77
-
78
- ## Authentication paths
79
-
80
- The SDK does not require an AgentsBloom account just to install or self-host the middleware. Choose the authentication model that fits your integration:
81
-
82
- - **Legacy HMAC writes:** configure a private merchant-generated `AGENTSBLOOM_SECRET` or `agentSecret`. This is required only for requests using the legacy `X-Agent-Signature` headers.
83
- - **RFC HTTP Message Signatures:** configure trusted agent public keys through `agentJwks` or `agentJwksUrl`; this path does not use `AGENTSBLOOM_SECRET`.
84
- - **AP2:** use the package's signed mandate helpers and verification path.
85
- - **Local demos:** `demoMode` can bypass signature authentication, but it must never be enabled for an internet-facing production deployment.
86
-
87
- An `AGENTSBLOOM_API_KEY` is a separate account/service-integration value. It is not the HMAC signing secret. Keep both values server-side and out of source control.
88
-
89
- ## Requirements
90
-
91
- - Node.js 20 or newer.
92
- - An Express 4 application.
93
- - A real `AGENTSBLOOM_SECRET` for protected legacy-signed write actions, or a configured RFC Message Signature trust path.
94
-
95
- ## Minimal production setup
96
-
97
- ```js
98
- import express from "express";
99
- import { agentsbloom, shutdown } from "@agentsbloom/sdk";
100
-
101
- const app = express();
102
- const agentSecret = process.env.AGENTSBLOOM_SECRET;
103
-
104
- if (!agentSecret) {
105
- throw new Error("AGENTSBLOOM_SECRET must be configured for legacy-signed writes");
106
- }
107
-
108
- app.use(express.json({ limit: "1mb" }));
109
- app.use(agentsbloom({
110
- apiKey: process.env.AGENTSBLOOM_API_KEY,
111
- agentSecret,
112
- baseUrl: process.env.PUBLIC_STORE_URL,
113
- name: "Example Store",
114
- description: "An example store for agent-driven commerce.",
115
- actions: {
116
- search: {
117
- method: "POST",
118
- description: "Search the product catalog.",
119
- params: { query: "string" },
120
- handler: async ({ query }) => ({ query, items: [] })
121
- }
122
- }
123
- }));
124
-
125
- const server = app.listen(process.env.PORT || 3000);
126
- const closeServer = () => new Promise((resolve, reject) => {
127
- if (!server.listening) return resolve();
128
- server.close((error) => error ? reject(error) : resolve());
129
- });
130
- const stop = async () => {
131
- try {
132
- await closeServer();
133
- } finally {
134
- await shutdown();
135
- }
136
- };
137
- process.once("SIGTERM", stop);
138
- process.once("SIGINT", stop);
139
- ```
140
-
141
- `baseUrl` should be the canonical public HTTPS origin of the store. Do not put API keys or signing secrets in source control, client-side code, logs, or package metadata.
142
-
143
- ## Configuration
144
-
145
- - `apiKey`: optional AgentsBloom account key used for attribution and service integrations.
146
- - `agentSecret`: 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.
147
- - `baseUrl`: canonical store origin used for discovery and audience binding.
148
- - `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`; declare `method: "GET"` explicitly for a read action.
149
- - `rateLimit`: optional `{ max, windowMs }` in-memory per-IP limits.
150
- - `idempotency`: optional `{ ttlMs }` for successful write responses keyed by `Idempotency-Key`.
151
- - `ap2`: optional AP2 settings including `expectedAudience`, `maxMandateLifetimeSec`, `requireJti`, and `requestedCategories`.
152
- - `merchantJwks`: merchant JWKS document served at the HTTP Message Signatures discovery endpoint.
153
- - `agentJwks`: optional inline trusted JWKS used to verify RFC HTTP Message Signatures.
154
- - `agentJwksUrl`: optional HTTPS URL for the trusted agent JWKS. A request cannot select an arbitrary remote JWKS URL.
155
- - `signature`: optional `{ maxAgeMs }` for legacy HMAC timestamp validation; the default is five minutes.
156
- - `demoMode`: explicit local/demo-only bypass for signature authentication. Never enable it in production.
157
- - `disableSignatureAuth`: explicit compatibility bypass. Do not enable it for an internet-facing deployment.
158
-
159
- The middleware does not replace application-level authorization, a distributed rate limiter, a durable idempotency store, TLS termination, or payment-provider verification.
160
-
161
- ## Legacy HMAC request signatures
162
-
163
- For a mutating action using `X-Agent-Signature`, send:
164
-
165
- - `X-Agent-Identifier`: printable agent identifier.
166
- - `X-Agent-Timestamp`: current Unix timestamp in seconds.
167
- - `X-Agent-Nonce`: unique printable nonce of at least 16 characters.
168
- - `X-Agent-Signature`: lowercase or uppercase hexadecimal HMAC-SHA-256.
169
-
170
- 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. Identifier-only signatures from older SDK revisions are intentionally rejected.
171
-
172
- ## RFC HTTP Message Signatures
173
-
174
- Protected writes using the RFC 9421-compatible path must sign `@method`, `@path`, and `content-digest`, and include `created`, `expires`, `nonce`, `keyid`, and `alg` parameters. The SDK validates the lifetime, rejects reused nonces, and recomputes `content-digest` from `req.rawBody` when present or the parsed request body otherwise.
175
-
176
- ## MCP message authentication
177
-
178
- The SSE connection at `/mcp` can advertise 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.
179
-
180
- ## AP2
181
-
182
- The package exports helpers for creating and verifying signed AP2 mandates:
183
-
184
- ```js
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
- - Use HTTPS, durable authorization, and a distributed rate/idempotency store for production systems.
19
- - Rotate any credential that has appeared in logs, chat, tickets, shell history, or a repository.
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.