@astrasyncai/verification-gateway 2.4.12 → 2.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.
Files changed (91) hide show
  1. package/dist/adapter-interface/interface.d.mts +2 -2
  2. package/dist/adapter-interface/interface.d.ts +2 -2
  3. package/dist/adapters/express.d.mts +2 -2
  4. package/dist/adapters/express.d.ts +2 -2
  5. package/dist/adapters/express.js +224 -42
  6. package/dist/adapters/express.js.map +1 -1
  7. package/dist/adapters/express.mjs +224 -42
  8. package/dist/adapters/express.mjs.map +1 -1
  9. package/dist/adapters/mcp.d.mts +101 -57
  10. package/dist/adapters/mcp.d.ts +101 -57
  11. package/dist/adapters/mcp.js +215 -44
  12. package/dist/adapters/mcp.js.map +1 -1
  13. package/dist/adapters/mcp.mjs +215 -44
  14. package/dist/adapters/mcp.mjs.map +1 -1
  15. package/dist/adapters/nextjs.d.mts +2 -2
  16. package/dist/adapters/nextjs.d.ts +2 -2
  17. package/dist/adapters/nextjs.js +87 -34
  18. package/dist/adapters/nextjs.js.map +1 -1
  19. package/dist/adapters/nextjs.mjs +87 -34
  20. package/dist/adapters/nextjs.mjs.map +1 -1
  21. package/dist/adapters/sdk.d.mts +2 -2
  22. package/dist/adapters/sdk.d.ts +2 -2
  23. package/dist/adapters/sdk.js +61 -28
  24. package/dist/adapters/sdk.js.map +1 -1
  25. package/dist/adapters/sdk.mjs +61 -28
  26. package/dist/adapters/sdk.mjs.map +1 -1
  27. package/dist/agent/index.d.mts +2 -2
  28. package/dist/agent/index.d.ts +2 -2
  29. package/dist/agent/index.js +29 -0
  30. package/dist/agent/index.js.map +1 -1
  31. package/dist/agent/index.mjs +29 -0
  32. package/dist/agent/index.mjs.map +1 -1
  33. package/dist/browser/background.js +102 -30
  34. package/dist/browser/background.js.map +1 -1
  35. package/dist/browser/background.mjs +102 -30
  36. package/dist/browser/background.mjs.map +1 -1
  37. package/dist/browser/browser-adapter.d.mts +2 -2
  38. package/dist/browser/browser-adapter.d.ts +2 -2
  39. package/dist/cli/index.d.mts +2 -2
  40. package/dist/cli/index.d.ts +2 -2
  41. package/dist/cursor/cursor-adapter.d.mts +2 -2
  42. package/dist/cursor/cursor-adapter.d.ts +2 -2
  43. package/dist/cursor/extension.d.mts +2 -2
  44. package/dist/cursor/extension.d.ts +2 -2
  45. package/dist/cursor/extension.js +102 -30
  46. package/dist/cursor/extension.js.map +1 -1
  47. package/dist/cursor/extension.mjs +102 -30
  48. package/dist/cursor/extension.mjs.map +1 -1
  49. package/dist/{express-C1ePFB7n.d.ts → express-CrfwoNAR.d.ts} +1 -1
  50. package/dist/{express-4WStX3PV.d.mts → express-ienhAXps.d.mts} +1 -1
  51. package/dist/gateway/gateway.d.mts +2 -2
  52. package/dist/gateway/gateway.d.ts +2 -2
  53. package/dist/gateway/gateway.js +102 -30
  54. package/dist/gateway/gateway.js.map +1 -1
  55. package/dist/gateway/gateway.mjs +102 -30
  56. package/dist/gateway/gateway.mjs.map +1 -1
  57. package/dist/git-trigger/git-hooks.d.mts +2 -2
  58. package/dist/git-trigger/git-hooks.d.ts +2 -2
  59. package/dist/{index-ChPX4WHl.d.mts → index-B5e2IDWU.d.mts} +1 -1
  60. package/dist/{index-CzJMCgEy.d.ts → index-CCdZxvAr.d.ts} +71 -6
  61. package/dist/{index-D8IEntil.d.mts → index-CEg_WG6y.d.mts} +71 -6
  62. package/dist/{index-Cjm-zBeZ.d.ts → index-DC5f8eoQ.d.ts} +1 -1
  63. package/dist/index.d.mts +39 -9
  64. package/dist/index.d.ts +39 -9
  65. package/dist/index.js +500 -94
  66. package/dist/index.js.map +1 -1
  67. package/dist/index.mjs +497 -94
  68. package/dist/index.mjs.map +1 -1
  69. package/dist/local-evaluator/evaluator.d.mts +2 -2
  70. package/dist/local-evaluator/evaluator.d.ts +2 -2
  71. package/dist/local-evaluator/evaluator.js +12 -2
  72. package/dist/local-evaluator/evaluator.js.map +1 -1
  73. package/dist/local-evaluator/evaluator.mjs +12 -2
  74. package/dist/local-evaluator/evaluator.mjs.map +1 -1
  75. package/dist/{nextjs-BIORS__0.d.ts → nextjs-66R1KW8e.d.ts} +1 -1
  76. package/dist/{nextjs-CjzHdaXA.d.mts → nextjs-DSpisQst.d.mts} +1 -1
  77. package/dist/{sdk-Chhz-FcT.d.mts → sdk-5U_CBRpr.d.mts} +1 -1
  78. package/dist/{sdk-CqTEQAc6.d.ts → sdk-Bm8np66n.d.ts} +1 -1
  79. package/dist/transport/index.d.mts +2 -2
  80. package/dist/transport/index.d.ts +2 -2
  81. package/dist/transport/index.js +146 -28
  82. package/dist/transport/index.js.map +1 -1
  83. package/dist/transport/index.mjs +146 -28
  84. package/dist/transport/index.mjs.map +1 -1
  85. package/dist/{types-L15pYd2c.d.mts → types-B3USs-Kx.d.mts} +42 -1
  86. package/dist/{types-L15pYd2c.d.ts → types-B3USs-Kx.d.ts} +42 -1
  87. package/dist/{types-DNK2BgIf.d.mts → types-CgDCUfo8.d.mts} +1 -1
  88. package/dist/{types-DoWIuzfj.d.ts → types-R5N4ET6x.d.ts} +1 -1
  89. package/dist/ui/index.d.mts +1 -1
  90. package/dist/ui/index.d.ts +1 -1
  91. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { Request, Response, RequestHandler } from 'express';
2
- import { A as AccessLevel, G as GatewayConfig, i as VerificationResult } from '../types-L15pYd2c.mjs';
2
+ import { A as AccessLevel, G as GatewayConfig, i as VerificationResult } from '../types-B3USs-Kx.mjs';
3
3
 
4
4
  /**
5
5
  * MCP server-side helpers — companion to `transport/mcp.ts` (which handles the
@@ -85,7 +85,7 @@ interface ParsedMcpRequest {
85
85
  * (canonical SDK location) OR `params.arguments.purpose` (legacy /
86
86
  * conventional callers). The discriminator is on `purposeSourceFromBody`.
87
87
  * Adapter combines this with the `X-Astra-Purpose` header (header wins)
88
- * before mapping; final fallback at `mcpToPdlss` is `'mcp_invoke'`.
88
+ * before mapping; final fallback at `mcpToPdlss` is `undefined`.
89
89
  */
90
90
  purposeFromBody?: string;
91
91
  /** Which body location resolved `purposeFromBody`. */
@@ -120,60 +120,45 @@ declare function parseMcpJsonRpc(body: unknown): ParsedMcpRequest | null;
120
120
  /**
121
121
  * PDLSS mapping for an MCP request. The platform's PDLSS taxonomy is
122
122
  * `purpose / action / resource`; for MCP traffic the audit-useful dimensions
123
- * are the JSON-RPC method and (for `tools/call`) the tool name. Doc-stable so
124
- * dashboards and audits can correlate consistently across cohort-3 partners.
123
+ * are the JSON-RPC method and (for `tools/call`) the tool name.
125
124
  *
126
- * Rules:
127
- * - `purpose` is always `mcp_invoke` for MCP traffic sets the high-level
128
- * PDLSS bucket.
129
- * - `action` is the JSON-RPC method, optionally `:tool_name` suffixed for
130
- * `tools/call`. Lets PDLSS allowlist specific tools.
131
- * - `resource` is `mcp:tool/<name>` for `tools/call`, `mcp:method/<method>`
132
- * otherwise. Lets PDLSS scope on tool identity.
125
+ * v2.5.0 rules:
126
+ * - `resource` defaults to the HTTP request path (e.g. `/mcp`). Per-tool
127
+ * overrides via `toolGates` config let merchants map tools to specific
128
+ * backend resources (e.g. `/api/catalog`).
129
+ * - `purpose` defaults to `undefined` (backend evaluator applies
130
+ * skip-when-undefined). Per-tool overrides via `toolGates` config let
131
+ * merchants declare the semantic purpose each tool fulfils.
132
+ * - `action` is the bare tool name for `tools/call`, the JSON-RPC method
133
+ * otherwise. Header/body overrides available.
133
134
  */
134
135
  interface McpPdlssMapping {
135
- purpose: string;
136
+ purpose: string | undefined;
136
137
  action: string;
137
138
  resource: string;
138
- /**
139
- * Round-13 (R13-1 / R13-2): the resolution channel for purpose and
140
- * action — disjoint enums sharing the same structure per
141
- * `feedback_symmetric_fallbacks_for_symmetric_concepts.md`. Adapters
142
- * log both at debug level so partners can confirm header / body
143
- * pass-through, support can triage tickets, and we can watch the
144
- * `default_*` / `transport_layer` decay over time as integrations
145
- * mature.
146
- *
147
- * Round-12 (F19) used a narrower `purposeSource: 'header' |
148
- * 'tool_argument' | 'default_mcp_invoke'` — round-13 widens to also
149
- * carry the `_meta` source distinct from `tool_argument`, so the round-13
150
- * R13-1 fallback (which now reads both `_meta.astrasync.purpose` AND
151
- * `params.arguments.purpose`) can report WHICH body location resolved.
152
- */
153
- purposeSource: 'header' | 'meta' | 'tool_argument' | 'default_mcp_invoke';
139
+ purposeSource: 'header' | 'meta' | 'tool_argument' | 'tool_gate' | undefined;
154
140
  actionSource: 'header' | 'meta' | 'tool_argument' | 'transport_layer';
155
141
  }
156
142
  /**
157
- * Round-13 (R13-1 + R13-2) canonical precedence chain documented ONCE,
158
- * applied identically to both purpose and action. Per
159
- * `feedback_symmetric_fallbacks_for_symmetric_concepts.md` — drift
160
- * between two paired concepts generates the same support-ticket class
161
- * repeatedly, so the resolution order is:
143
+ * v2.5.0 PDLSS field derivation for MCP requests.
144
+ *
145
+ * Purpose precedence:
146
+ * - If `toolGate.purpose` is provided, it is authoritative (header/body ignored).
147
+ * - Otherwise: header body `_meta` → body `arguments` → `undefined`.
148
+ *
149
+ * Resource precedence:
150
+ * - `toolGate.resource` if provided, else `requestPath`.
162
151
  *
163
- * 1. `X-Astra-<concept>` HTTP header (caller's explicit override)
164
- * 2. `params._meta.astrasync.<concept>` body field (canonical SDK location)
165
- * 3. `params.arguments.<concept>` body field (legacy / conventional)
166
- * 4. Transport-layer default:
167
- * purpose → 'mcp_invoke'
168
- * action → '<method>:<toolName>' (or just '<method>')
152
+ * Action precedence (unchanged from v2.4.14):
153
+ * - header → body `_meta` body `arguments` bare tool name / method.
169
154
  *
170
- * The header tier is the adapter's job (it has `req.headers` access);
171
- * this function takes the resolved `headerPurpose` / `headerAction`
172
- * inputs and combines them with the body extraction already done in
173
- * `parseMcpJsonRpc`. The discriminator is reported on `purposeSource` /
174
- * `actionSource` for debug logging.
155
+ * @param requestPath The HTTP request path (e.g. '/mcp'). Required.
156
+ * @param toolGate Resolved per-tool config from `toolGates`, if present.
175
157
  */
176
- declare function mcpToPdlss(parsed: ParsedMcpRequest, headerPurpose?: string, headerAction?: string): McpPdlssMapping;
158
+ declare function mcpToPdlss(parsed: ParsedMcpRequest, requestPath: string, headerPurpose?: string, headerAction?: string, toolGate?: {
159
+ purpose?: string;
160
+ resource?: string;
161
+ }): McpPdlssMapping;
177
162
  /**
178
163
  * Recommended minimum access level per method type. The MCP middleware uses
179
164
  * this to split low-risk handshake / introspection traffic from high-risk
@@ -200,10 +185,9 @@ declare function mcpRiskTier(parsed: ParsedMcpRequest): AccessLevel;
200
185
  * from `tools/call start_checkout` (high risk). This middleware peels
201
186
  * the JSON-RPC body and applies a per-method risk tier.
202
187
  *
203
- * (b) **PDLSS mapping**. Forwards `purpose=mcp_invoke`,
204
- * `action=method[:tool]`, `resource=mcp:tool/<name>` so audit traces
205
- * are stable across cohort-3 partners. See `transport/mcp-server.ts`
206
- * for the exact mapping.
188
+ * (b) **PDLSS mapping**. Derives purpose, action, and resource from
189
+ * `toolGates` config and request context. See `transport/mcp-server.ts`
190
+ * `mcpToPdlss()` for the exact mapping.
207
191
  *
208
192
  * (c) **Inner-hop dedupe**. Outbound responses set
209
193
  * `X-Astra-Verified-Hop` so a downstream REST endpoint that the tool
@@ -249,13 +233,51 @@ declare global {
249
233
  }
250
234
  }
251
235
  }
236
+ /**
237
+ * Extended per-tool gate with optional PDLSS purpose + resource overrides.
238
+ *
239
+ * When `purpose` is set, it is authoritative for that tool — the agent's
240
+ * `X-Astra-Purpose` header is ignored. This lets the merchant declare what
241
+ * semantic purpose each tool fulfils rather than trusting agent self-declaration.
242
+ *
243
+ * When `resource` is set, it overrides the default (`req.path`) for that
244
+ * tool's verify-access call — e.g. mapping `list_products` to `/api/catalog`.
245
+ */
246
+ interface ToolGateConfig {
247
+ minAccessLevel: AccessLevel;
248
+ purpose?: string;
249
+ resource?: string;
250
+ }
252
251
  interface McpMiddlewareOptions extends GatewayConfig {
253
252
  /**
254
- * Per-tool override for the minimum access level. Tools not listed inherit
255
- * the default tier from `mcpRiskTier` (`tools/call` → `'standard'`). Use
256
- * for high-risk tools that demand `'full'` or low-risk read-only tools.
253
+ * Per-tool gating for `tools/call` invocations. Tools not listed inherit
254
+ * the default tier from `mcpRiskTier` (`tools/call` → `'standard'`).
255
+ *
256
+ * Accepts both the shorthand access-level string and the full object shape:
257
+ * ```typescript
258
+ * toolGates: {
259
+ * browse_catalog: 'read-only', // shorthand
260
+ * list_products: { minAccessLevel: 'none', // full shape
261
+ * purpose: 'shopping.search',
262
+ * resource: '/api/catalog' },
263
+ * start_checkout: { minAccessLevel: 'standard',
264
+ * purpose: 'shopping.purchase',
265
+ * resource: '/api/checkout/*' },
266
+ * }
267
+ * ```
268
+ *
269
+ * When `tools/call` arrives for a tool not declared in `toolGates`, the SDK
270
+ * falls back to a risk-tier default based on the method classification
271
+ * (`mcpRiskTier`). For `tools/call` the fallback is `'standard'`. Best
272
+ * practice: declare every tool you expose explicitly.
273
+ *
274
+ * The action axis for non-tools/call MCP methods (`tools/list`,
275
+ * `resources/list`, `prompts/list`, etc.) is the literal JSON-RPC method
276
+ * name (e.g. `'tools/list'`). Merchants gating MCP traffic by action should
277
+ * declare per-tool gates in `toolGates`, not endpoint-level `allowedActions`
278
+ * — the latter applies to REST-style action values, not MCP method strings.
257
279
  */
258
- toolGates?: Record<string, AccessLevel>;
280
+ toolGates?: Record<string, AccessLevel | ToolGateConfig>;
259
281
  /**
260
282
  * Per-method override (e.g. tighten `tools/list` to `'read-only'` if you
261
283
  * don't want unregistered probes seeing your tool catalogue). Matches by
@@ -280,9 +302,22 @@ interface McpMiddlewareOptions extends GatewayConfig {
280
302
  /** Custom denied handler. Defaults to a structured JSON-RPC error response. */
281
303
  onDenied?: (result: VerificationResult, req: Request, res: Response) => void;
282
304
  /**
283
- * If `false`, don't trust an inbound `X-Astra-Verified-Hop` header (always
284
- * call verify-access). Default `true` recommended for inner-hop endpoints
285
- * called by your own MCP tools.
305
+ * If `true`, trust an inbound `X-Astra-Verified-Hop` header to skip
306
+ * verify-access when it carries a recent marker for the resolved agent.
307
+ *
308
+ * **DEFAULT FLIPPED TO `false` in SDK 2.4.13** (audit F-A1-01). The marker
309
+ * is plaintext semicolon-delimited with no HMAC, so any client that sets
310
+ * the header (with the right format + fresh timestamp + matching ASTRA-id)
311
+ * skipped verify-access entirely. The per-process verify-access result
312
+ * cache already dedupes legitimate repeat calls — this optimization
313
+ * provided no additional savings, only a bypass surface.
314
+ *
315
+ * Set this to `true` ONLY if you control every upstream MCP hop that sets
316
+ * the header AND you trust the network path between hops (mTLS, internal
317
+ * VPC, etc.). For most installs, leave at the safe default.
318
+ *
319
+ * Future SDK release will either remove this option entirely OR add HMAC
320
+ * signing to the marker. Tracked as round-19+ work.
286
321
  */
287
322
  trustVerifiedHop?: boolean;
288
323
  /** Window for accepting an upstream verified-hop marker. Default 60_000ms. */
@@ -294,6 +329,15 @@ interface McpMiddlewareOptions extends GatewayConfig {
294
329
  recordDecisions?: boolean;
295
330
  /** Forward runtime challenge (default `true`). */
296
331
  enableRuntimeChallenge?: boolean;
332
+ /**
333
+ * Posture when the MCP middleware itself throws an internal error.
334
+ * Default `'open'` for backward compatibility in SDK 2.4.13. Shadow logs
335
+ * record what WOULD be denied with `failOnError: 'closed'` so merchants
336
+ * can grep correlationId for impact analysis during the 1-week
337
+ * observation window. Default flips to `'closed'` in a follow-up release.
338
+ * Audit F-A1-06.
339
+ */
340
+ failOnError?: 'open' | 'closed';
297
341
  }
298
342
  /**
299
343
  * Create the MCP middleware. Attach AFTER `express.json()` — the body must
@@ -301,4 +345,4 @@ interface McpMiddlewareOptions extends GatewayConfig {
301
345
  */
302
346
  declare function createMcpMiddleware(options: McpMiddlewareOptions): RequestHandler;
303
347
 
304
- export { MCP_VERIFIED_HOP_HEADER, type McpMiddlewareOptions, type ParsedMcpRequest, createMcpMiddleware, isVerifiedHopValidFor, mcpRiskTier, mcpToPdlss, parseMcpJsonRpc, parseVerifiedHop, serializeVerifiedHop };
348
+ export { MCP_VERIFIED_HOP_HEADER, type McpMiddlewareOptions, type ParsedMcpRequest, type ToolGateConfig, createMcpMiddleware, isVerifiedHopValidFor, mcpRiskTier, mcpToPdlss, parseMcpJsonRpc, parseVerifiedHop, serializeVerifiedHop };
@@ -1,5 +1,5 @@
1
1
  import { Request, Response, RequestHandler } from 'express';
2
- import { A as AccessLevel, G as GatewayConfig, i as VerificationResult } from '../types-L15pYd2c.js';
2
+ import { A as AccessLevel, G as GatewayConfig, i as VerificationResult } from '../types-B3USs-Kx.js';
3
3
 
4
4
  /**
5
5
  * MCP server-side helpers — companion to `transport/mcp.ts` (which handles the
@@ -85,7 +85,7 @@ interface ParsedMcpRequest {
85
85
  * (canonical SDK location) OR `params.arguments.purpose` (legacy /
86
86
  * conventional callers). The discriminator is on `purposeSourceFromBody`.
87
87
  * Adapter combines this with the `X-Astra-Purpose` header (header wins)
88
- * before mapping; final fallback at `mcpToPdlss` is `'mcp_invoke'`.
88
+ * before mapping; final fallback at `mcpToPdlss` is `undefined`.
89
89
  */
90
90
  purposeFromBody?: string;
91
91
  /** Which body location resolved `purposeFromBody`. */
@@ -120,60 +120,45 @@ declare function parseMcpJsonRpc(body: unknown): ParsedMcpRequest | null;
120
120
  /**
121
121
  * PDLSS mapping for an MCP request. The platform's PDLSS taxonomy is
122
122
  * `purpose / action / resource`; for MCP traffic the audit-useful dimensions
123
- * are the JSON-RPC method and (for `tools/call`) the tool name. Doc-stable so
124
- * dashboards and audits can correlate consistently across cohort-3 partners.
123
+ * are the JSON-RPC method and (for `tools/call`) the tool name.
125
124
  *
126
- * Rules:
127
- * - `purpose` is always `mcp_invoke` for MCP traffic sets the high-level
128
- * PDLSS bucket.
129
- * - `action` is the JSON-RPC method, optionally `:tool_name` suffixed for
130
- * `tools/call`. Lets PDLSS allowlist specific tools.
131
- * - `resource` is `mcp:tool/<name>` for `tools/call`, `mcp:method/<method>`
132
- * otherwise. Lets PDLSS scope on tool identity.
125
+ * v2.5.0 rules:
126
+ * - `resource` defaults to the HTTP request path (e.g. `/mcp`). Per-tool
127
+ * overrides via `toolGates` config let merchants map tools to specific
128
+ * backend resources (e.g. `/api/catalog`).
129
+ * - `purpose` defaults to `undefined` (backend evaluator applies
130
+ * skip-when-undefined). Per-tool overrides via `toolGates` config let
131
+ * merchants declare the semantic purpose each tool fulfils.
132
+ * - `action` is the bare tool name for `tools/call`, the JSON-RPC method
133
+ * otherwise. Header/body overrides available.
133
134
  */
134
135
  interface McpPdlssMapping {
135
- purpose: string;
136
+ purpose: string | undefined;
136
137
  action: string;
137
138
  resource: string;
138
- /**
139
- * Round-13 (R13-1 / R13-2): the resolution channel for purpose and
140
- * action — disjoint enums sharing the same structure per
141
- * `feedback_symmetric_fallbacks_for_symmetric_concepts.md`. Adapters
142
- * log both at debug level so partners can confirm header / body
143
- * pass-through, support can triage tickets, and we can watch the
144
- * `default_*` / `transport_layer` decay over time as integrations
145
- * mature.
146
- *
147
- * Round-12 (F19) used a narrower `purposeSource: 'header' |
148
- * 'tool_argument' | 'default_mcp_invoke'` — round-13 widens to also
149
- * carry the `_meta` source distinct from `tool_argument`, so the round-13
150
- * R13-1 fallback (which now reads both `_meta.astrasync.purpose` AND
151
- * `params.arguments.purpose`) can report WHICH body location resolved.
152
- */
153
- purposeSource: 'header' | 'meta' | 'tool_argument' | 'default_mcp_invoke';
139
+ purposeSource: 'header' | 'meta' | 'tool_argument' | 'tool_gate' | undefined;
154
140
  actionSource: 'header' | 'meta' | 'tool_argument' | 'transport_layer';
155
141
  }
156
142
  /**
157
- * Round-13 (R13-1 + R13-2) canonical precedence chain documented ONCE,
158
- * applied identically to both purpose and action. Per
159
- * `feedback_symmetric_fallbacks_for_symmetric_concepts.md` — drift
160
- * between two paired concepts generates the same support-ticket class
161
- * repeatedly, so the resolution order is:
143
+ * v2.5.0 PDLSS field derivation for MCP requests.
144
+ *
145
+ * Purpose precedence:
146
+ * - If `toolGate.purpose` is provided, it is authoritative (header/body ignored).
147
+ * - Otherwise: header body `_meta` → body `arguments` → `undefined`.
148
+ *
149
+ * Resource precedence:
150
+ * - `toolGate.resource` if provided, else `requestPath`.
162
151
  *
163
- * 1. `X-Astra-<concept>` HTTP header (caller's explicit override)
164
- * 2. `params._meta.astrasync.<concept>` body field (canonical SDK location)
165
- * 3. `params.arguments.<concept>` body field (legacy / conventional)
166
- * 4. Transport-layer default:
167
- * purpose → 'mcp_invoke'
168
- * action → '<method>:<toolName>' (or just '<method>')
152
+ * Action precedence (unchanged from v2.4.14):
153
+ * - header → body `_meta` body `arguments` bare tool name / method.
169
154
  *
170
- * The header tier is the adapter's job (it has `req.headers` access);
171
- * this function takes the resolved `headerPurpose` / `headerAction`
172
- * inputs and combines them with the body extraction already done in
173
- * `parseMcpJsonRpc`. The discriminator is reported on `purposeSource` /
174
- * `actionSource` for debug logging.
155
+ * @param requestPath The HTTP request path (e.g. '/mcp'). Required.
156
+ * @param toolGate Resolved per-tool config from `toolGates`, if present.
175
157
  */
176
- declare function mcpToPdlss(parsed: ParsedMcpRequest, headerPurpose?: string, headerAction?: string): McpPdlssMapping;
158
+ declare function mcpToPdlss(parsed: ParsedMcpRequest, requestPath: string, headerPurpose?: string, headerAction?: string, toolGate?: {
159
+ purpose?: string;
160
+ resource?: string;
161
+ }): McpPdlssMapping;
177
162
  /**
178
163
  * Recommended minimum access level per method type. The MCP middleware uses
179
164
  * this to split low-risk handshake / introspection traffic from high-risk
@@ -200,10 +185,9 @@ declare function mcpRiskTier(parsed: ParsedMcpRequest): AccessLevel;
200
185
  * from `tools/call start_checkout` (high risk). This middleware peels
201
186
  * the JSON-RPC body and applies a per-method risk tier.
202
187
  *
203
- * (b) **PDLSS mapping**. Forwards `purpose=mcp_invoke`,
204
- * `action=method[:tool]`, `resource=mcp:tool/<name>` so audit traces
205
- * are stable across cohort-3 partners. See `transport/mcp-server.ts`
206
- * for the exact mapping.
188
+ * (b) **PDLSS mapping**. Derives purpose, action, and resource from
189
+ * `toolGates` config and request context. See `transport/mcp-server.ts`
190
+ * `mcpToPdlss()` for the exact mapping.
207
191
  *
208
192
  * (c) **Inner-hop dedupe**. Outbound responses set
209
193
  * `X-Astra-Verified-Hop` so a downstream REST endpoint that the tool
@@ -249,13 +233,51 @@ declare global {
249
233
  }
250
234
  }
251
235
  }
236
+ /**
237
+ * Extended per-tool gate with optional PDLSS purpose + resource overrides.
238
+ *
239
+ * When `purpose` is set, it is authoritative for that tool — the agent's
240
+ * `X-Astra-Purpose` header is ignored. This lets the merchant declare what
241
+ * semantic purpose each tool fulfils rather than trusting agent self-declaration.
242
+ *
243
+ * When `resource` is set, it overrides the default (`req.path`) for that
244
+ * tool's verify-access call — e.g. mapping `list_products` to `/api/catalog`.
245
+ */
246
+ interface ToolGateConfig {
247
+ minAccessLevel: AccessLevel;
248
+ purpose?: string;
249
+ resource?: string;
250
+ }
252
251
  interface McpMiddlewareOptions extends GatewayConfig {
253
252
  /**
254
- * Per-tool override for the minimum access level. Tools not listed inherit
255
- * the default tier from `mcpRiskTier` (`tools/call` → `'standard'`). Use
256
- * for high-risk tools that demand `'full'` or low-risk read-only tools.
253
+ * Per-tool gating for `tools/call` invocations. Tools not listed inherit
254
+ * the default tier from `mcpRiskTier` (`tools/call` → `'standard'`).
255
+ *
256
+ * Accepts both the shorthand access-level string and the full object shape:
257
+ * ```typescript
258
+ * toolGates: {
259
+ * browse_catalog: 'read-only', // shorthand
260
+ * list_products: { minAccessLevel: 'none', // full shape
261
+ * purpose: 'shopping.search',
262
+ * resource: '/api/catalog' },
263
+ * start_checkout: { minAccessLevel: 'standard',
264
+ * purpose: 'shopping.purchase',
265
+ * resource: '/api/checkout/*' },
266
+ * }
267
+ * ```
268
+ *
269
+ * When `tools/call` arrives for a tool not declared in `toolGates`, the SDK
270
+ * falls back to a risk-tier default based on the method classification
271
+ * (`mcpRiskTier`). For `tools/call` the fallback is `'standard'`. Best
272
+ * practice: declare every tool you expose explicitly.
273
+ *
274
+ * The action axis for non-tools/call MCP methods (`tools/list`,
275
+ * `resources/list`, `prompts/list`, etc.) is the literal JSON-RPC method
276
+ * name (e.g. `'tools/list'`). Merchants gating MCP traffic by action should
277
+ * declare per-tool gates in `toolGates`, not endpoint-level `allowedActions`
278
+ * — the latter applies to REST-style action values, not MCP method strings.
257
279
  */
258
- toolGates?: Record<string, AccessLevel>;
280
+ toolGates?: Record<string, AccessLevel | ToolGateConfig>;
259
281
  /**
260
282
  * Per-method override (e.g. tighten `tools/list` to `'read-only'` if you
261
283
  * don't want unregistered probes seeing your tool catalogue). Matches by
@@ -280,9 +302,22 @@ interface McpMiddlewareOptions extends GatewayConfig {
280
302
  /** Custom denied handler. Defaults to a structured JSON-RPC error response. */
281
303
  onDenied?: (result: VerificationResult, req: Request, res: Response) => void;
282
304
  /**
283
- * If `false`, don't trust an inbound `X-Astra-Verified-Hop` header (always
284
- * call verify-access). Default `true` recommended for inner-hop endpoints
285
- * called by your own MCP tools.
305
+ * If `true`, trust an inbound `X-Astra-Verified-Hop` header to skip
306
+ * verify-access when it carries a recent marker for the resolved agent.
307
+ *
308
+ * **DEFAULT FLIPPED TO `false` in SDK 2.4.13** (audit F-A1-01). The marker
309
+ * is plaintext semicolon-delimited with no HMAC, so any client that sets
310
+ * the header (with the right format + fresh timestamp + matching ASTRA-id)
311
+ * skipped verify-access entirely. The per-process verify-access result
312
+ * cache already dedupes legitimate repeat calls — this optimization
313
+ * provided no additional savings, only a bypass surface.
314
+ *
315
+ * Set this to `true` ONLY if you control every upstream MCP hop that sets
316
+ * the header AND you trust the network path between hops (mTLS, internal
317
+ * VPC, etc.). For most installs, leave at the safe default.
318
+ *
319
+ * Future SDK release will either remove this option entirely OR add HMAC
320
+ * signing to the marker. Tracked as round-19+ work.
286
321
  */
287
322
  trustVerifiedHop?: boolean;
288
323
  /** Window for accepting an upstream verified-hop marker. Default 60_000ms. */
@@ -294,6 +329,15 @@ interface McpMiddlewareOptions extends GatewayConfig {
294
329
  recordDecisions?: boolean;
295
330
  /** Forward runtime challenge (default `true`). */
296
331
  enableRuntimeChallenge?: boolean;
332
+ /**
333
+ * Posture when the MCP middleware itself throws an internal error.
334
+ * Default `'open'` for backward compatibility in SDK 2.4.13. Shadow logs
335
+ * record what WOULD be denied with `failOnError: 'closed'` so merchants
336
+ * can grep correlationId for impact analysis during the 1-week
337
+ * observation window. Default flips to `'closed'` in a follow-up release.
338
+ * Audit F-A1-06.
339
+ */
340
+ failOnError?: 'open' | 'closed';
297
341
  }
298
342
  /**
299
343
  * Create the MCP middleware. Attach AFTER `express.json()` — the body must
@@ -301,4 +345,4 @@ interface McpMiddlewareOptions extends GatewayConfig {
301
345
  */
302
346
  declare function createMcpMiddleware(options: McpMiddlewareOptions): RequestHandler;
303
347
 
304
- export { MCP_VERIFIED_HOP_HEADER, type McpMiddlewareOptions, type ParsedMcpRequest, createMcpMiddleware, isVerifiedHopValidFor, mcpRiskTier, mcpToPdlss, parseMcpJsonRpc, parseVerifiedHop, serializeVerifiedHop };
348
+ export { MCP_VERIFIED_HOP_HEADER, type McpMiddlewareOptions, type ParsedMcpRequest, type ToolGateConfig, createMcpMiddleware, isVerifiedHopValidFor, mcpRiskTier, mcpToPdlss, parseMcpJsonRpc, parseVerifiedHop, serializeVerifiedHop };