@adcp/sdk 17.0.0-beta.2 → 17.0.0-beta.4

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 (70) hide show
  1. package/dist/lib/adapters/version/index.d.mts +9 -0
  2. package/dist/lib/adapters/version/index.d.ts +9 -0
  3. package/dist/lib/adapters/version/index.js +20 -6
  4. package/dist/lib/adapters/version/index.mjs +15 -2
  5. package/dist/lib/identity-3.3/trust.js +9 -2
  6. package/dist/lib/identity-3.3/trust.mjs +9 -2
  7. package/dist/lib/server/a2a-adapter.js +2 -1
  8. package/dist/lib/server/a2a-adapter.mjs +2 -1
  9. package/dist/lib/server/account-response-identity.d.mts +4 -0
  10. package/dist/lib/server/account-response-identity.d.ts +4 -0
  11. package/dist/lib/server/account-response-identity.js +23 -0
  12. package/dist/lib/server/account-response-identity.mjs +22 -1
  13. package/dist/lib/server/auth-signature.d.mts +2 -2
  14. package/dist/lib/server/auth-signature.d.ts +2 -2
  15. package/dist/lib/server/auth-signature.js +3 -0
  16. package/dist/lib/server/auth-signature.mjs +3 -0
  17. package/dist/lib/server/create-adcp-server.d.mts +2 -2
  18. package/dist/lib/server/create-adcp-server.d.ts +2 -2
  19. package/dist/lib/server/create-adcp-server.js +25 -3
  20. package/dist/lib/server/create-adcp-server.mjs +25 -3
  21. package/dist/lib/server/decisioning/account.d.mts +2 -1
  22. package/dist/lib/server/decisioning/account.d.ts +2 -1
  23. package/dist/lib/server/decisioning/account.js +1 -0
  24. package/dist/lib/server/decisioning/account.mjs +5 -1
  25. package/dist/lib/server/responses.js +8 -4
  26. package/dist/lib/server/responses.mjs +13 -5
  27. package/dist/lib/server/serve.js +3 -1
  28. package/dist/lib/server/serve.mjs +3 -1
  29. package/dist/lib/server/signed-request-transport.d.mts +1 -0
  30. package/dist/lib/server/signed-request-transport.d.ts +1 -0
  31. package/dist/lib/server/signed-request-transport.js +46 -0
  32. package/dist/lib/server/signed-request-transport.mjs +20 -0
  33. package/dist/lib/server/test-controller.d.mts +1 -0
  34. package/dist/lib/server/test-controller.d.ts +1 -0
  35. package/dist/lib/server/test-controller.js +5 -1
  36. package/dist/lib/server/test-controller.mjs +5 -1
  37. package/dist/lib/testing/index.d.mts +1 -0
  38. package/dist/lib/testing/index.d.ts +1 -0
  39. package/dist/lib/testing/index.js +3 -0
  40. package/dist/lib/testing/index.mjs +2 -0
  41. package/dist/lib/testing/storyboard/canonical-format-satisfaction.js +1 -15
  42. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +1 -15
  43. package/dist/lib/testing/storyboard/index.d.mts +1 -0
  44. package/dist/lib/testing/storyboard/index.d.ts +1 -0
  45. package/dist/lib/testing/storyboard/index.js +3 -0
  46. package/dist/lib/testing/storyboard/index.mjs +2 -0
  47. package/dist/lib/testing/storyboard/loader.js +7 -0
  48. package/dist/lib/testing/storyboard/loader.mjs +7 -0
  49. package/dist/lib/testing/storyboard/request-builder.js +9 -6
  50. package/dist/lib/testing/storyboard/request-builder.mjs +9 -6
  51. package/dist/lib/testing/storyboard/runner.js +59 -6
  52. package/dist/lib/testing/storyboard/runner.mjs +59 -6
  53. package/dist/lib/testing/storyboard/types.d.mts +18 -0
  54. package/dist/lib/testing/storyboard/types.d.ts +18 -0
  55. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  56. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  57. package/dist/lib/testing/storyboard/web-bot-auth.d.mts +10 -0
  58. package/dist/lib/testing/storyboard/web-bot-auth.d.ts +10 -0
  59. package/dist/lib/testing/storyboard/web-bot-auth.js +80 -0
  60. package/dist/lib/testing/storyboard/web-bot-auth.mjs +56 -0
  61. package/dist/lib/version.d.mts +3 -3
  62. package/dist/lib/version.d.ts +3 -3
  63. package/dist/lib/version.js +3 -3
  64. package/dist/lib/version.mjs +3 -3
  65. package/docs/TYPE-SUMMARY.md +2 -2
  66. package/docs/llms.txt +2 -2
  67. package/docs/migration-14.x-rc-worksheet.md +4 -4
  68. package/docs/migration-16-to-17.md +27 -0
  69. package/docs/migration-agent-identity-3.3.md +106 -4
  70. package/package.json +15 -2
@@ -61,6 +61,9 @@ __export(runner_exports, {
61
61
  summarizeStrictValidation: () => summarizeStrictValidation
62
62
  });
63
63
  module.exports = __toCommonJS(runner_exports);
64
+ var import_web_bot_auth = require('./web-bot-auth.js');
65
+ var import_web_bot_auth2 = require('../../signing/web-bot-auth.js');
66
+ var import_agent_transport_fetch = require('../../net/agent-transport-fetch.js');
64
67
  var import_node_crypto = require("node:crypto");
65
68
  var import_node_fs = require("node:fs");
66
69
  var import_node_path = require("node:path");
@@ -2206,6 +2209,19 @@ function resolveBindingAccountScope(storyboard, options) {
2206
2209
  }
2207
2210
  function resolveBindingCredential(options, step) {
2208
2211
  const parts = [];
2212
+ if (options.web_bot_auth) {
2213
+ parts.push(`wba_target:${JSON.stringify(options.web_bot_auth.publicUrl ?? null)}`);
2214
+ for (const [name, identity] of Object.entries(options.web_bot_auth.identities).sort(
2215
+ ([a], [b]) => a < b ? -1 : a > b ? 1 : 0
2216
+ )) {
2217
+ try {
2218
+ const jwk = "privateKey" in identity.key ? identity.key.privateKey : identity.key.publicKey;
2219
+ parts.push(`wba_identity:${JSON.stringify([name, identity.origin, (0, import_web_bot_auth2.jwkThumbprint)(jwk)])}`);
2220
+ } catch {
2221
+ parts.push(`wba_identity:${JSON.stringify([name, "invalid"])}`);
2222
+ }
2223
+ }
2224
+ }
2209
2225
  if (step?.auth !== void 0) {
2210
2226
  parts.push(`step_auth:${JSON.stringify(describeStepAuthDirective(step.auth))}`);
2211
2227
  }
@@ -4867,7 +4883,7 @@ function buildStepRequest(step, effectiveStep, context, options, runnerVars) {
4867
4883
  const governedFixture = payloadBoundGovernance && effectiveStep.task !== "check_governance" && effectiveStep.task !== "report_plan_outcome" && (governedSource !== void 0 && Object.prototype.hasOwnProperty.call(governedSource, "governance_context") || contextGovernance);
4868
4884
  if (options.request) {
4869
4885
  request = (0, import_context.injectContext)({ ...options.request }, context, runnerVars);
4870
- } else if (step.expect_error && step.sample_request) {
4886
+ } else if (step.expect_error && step.sample_request && step.enrich_request !== true) {
4871
4887
  request = (0, import_context.injectContext)({ ...step.sample_request }, context, runnerVars);
4872
4888
  } else if (governedFixture) {
4873
4889
  request = (0, import_context.injectContext)({ ...step.sample_request ?? {} }, context, runnerVars);
@@ -5242,18 +5258,49 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
5242
5258
  const testsIdempotencyKeyOmission = (step.omit_idempotency_key === true || governedRequest && (typeof request.idempotency_key !== "string" || request.idempotency_key.length === 0)) && (0, import_idempotency.requestUsesIdempotency)(effectiveStep.task, request);
5243
5259
  const testsMissingAccount = effectiveStep.task === "create_media_buy" && (step.omit_account === true || governedRequest && !Object.prototype.hasOwnProperty.call(request, "account"));
5244
5260
  const testsSchemaInvalidRequest = step.expect_error === true && step.negative_path !== "payload_well_formed";
5245
- const useSdkAuthOverride = typeof step.auth === "object" && step.auth.type === "api_key" && step.auth.from_test_kit === true && step.auth.value_strategy === void 0 && step.expect_error !== true && !(step.validations ?? []).some((validation) => HTTP_PROBE_ONLY_CHECKS.has(validation.check));
5261
+ const useWebBotAuth = typeof step.auth === "object" && step.auth.type === "web_bot_auth";
5262
+ const useSdkAuthOverride = useWebBotAuth || typeof step.auth === "object" && step.auth.type === "api_key" && step.auth.from_test_kit === true && step.auth.value_strategy === void 0 && step.expect_error !== true && !(step.validations ?? []).some((validation) => HTTP_PROBE_ONLY_CHECKS.has(validation.check));
5246
5263
  let rawProbeHeaders;
5247
5264
  let authOverrideClient;
5248
5265
  try {
5249
5266
  rawProbeHeaders = step.auth !== void 0 ? authHeadersForStep(step.auth, options) : void 0;
5267
+ let signedFetch;
5268
+ if (typeof step.auth === "object" && step.auth.type === "web_bot_auth") {
5269
+ if ((step.validations ?? []).some((validation) => HTTP_PROBE_ONLY_CHECKS.has(validation.check)))
5270
+ throw new Error(
5271
+ "web_bot_auth steps require tool-response validations; HTTP probe assertions are not supported"
5272
+ );
5273
+ if (options.web_bot_auth?.publicUrl && options.protocol === "a2a")
5274
+ throw new Error("web_bot_auth.publicUrl loopback delivery supports MCP only; use HTTPS directly for A2A");
5275
+ if (!options.web_bot_auth?.publicUrl && new URL(runState.agentUrl).protocol !== "https:")
5276
+ throw new Error("web_bot_auth.publicUrl is required to sign for a non-HTTPS agent");
5277
+ const name = step.auth.identity;
5278
+ const identities = options.web_bot_auth?.identities;
5279
+ const identity = identities && Object.hasOwn(identities, name) ? identities[name] : void 0;
5280
+ if (!identity) throw new Error("web_bot_auth identity is not configured in options.web_bot_auth.identities");
5281
+ signedFetch = (0, import_web_bot_auth.createStoryboardWebBotAuthFetch)(
5282
+ (0, import_agent_transport_fetch.createAgentTransportFetch)(runState.agentUrl, {
5283
+ trustedFetchFn: options.transport?.trustedFetchFn,
5284
+ allowPrivateIp: options.transport?.allowPrivateIp
5285
+ }),
5286
+ identity.key,
5287
+ {
5288
+ agentUrl: runState.agentUrl,
5289
+ origin: identity.origin,
5290
+ ...options.web_bot_auth?.publicUrl && {
5291
+ target: { publicUrl: options.web_bot_auth.publicUrl, loopbackUrl: runState.agentUrl }
5292
+ }
5293
+ }
5294
+ );
5295
+ }
5250
5296
  if (useSdkAuthOverride) {
5251
5297
  if (rawProbeHeaders === void 0) throw new Error("Step auth override credentials were not resolved");
5252
5298
  authOverrideClient = createAuthOverrideClient(
5253
5299
  runState.agentUrl,
5254
5300
  options.protocol ?? "mcp",
5255
5301
  options,
5256
- rawProbeHeaders
5302
+ rawProbeHeaders,
5303
+ signedFetch
5257
5304
  );
5258
5305
  }
5259
5306
  } catch (err) {
@@ -5547,7 +5594,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
5547
5594
  runState.agentProfile?.raw_capabilities,
5548
5595
  "request_signing.required_for"
5549
5596
  );
5550
- if (taskResult?.adcp_error?.code === "request_signature_required" && Array.isArray(requiredForSigning) && requiredForSigning.includes(effectiveStep.task) && options.functional_request_signing === void 0 && runState.storyboardRequiresRequestSigner !== true) {
5597
+ if (taskResult?.adcp_error?.code === "request_signature_required" && Array.isArray(requiredForSigning) && requiredForSigning.includes(effectiveStep.task) && options.functional_request_signing === void 0 && !useWebBotAuth && runState.storyboardRequiresRequestSigner !== true) {
5551
5598
  const next2 = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
5552
5599
  const detail = `Agent declared request_signing.required_for includes "${effectiveStep.task}" and rejected the unsigned request with request_signature_required; storyboard "${storyboardId}" does not require request_signer.`;
5553
5600
  return {
@@ -7679,6 +7726,8 @@ function selectProtectedToolTarget(tools) {
7679
7726
  function sessionControlMechanismFor(auth) {
7680
7727
  if (auth === "none") return "any";
7681
7728
  switch (auth.type) {
7729
+ case "web_bot_auth":
7730
+ throw new Error("web_bot_auth is not supported by session probes");
7682
7731
  case "oauth_bearer":
7683
7732
  return "oauth_bearer";
7684
7733
  case "basic":
@@ -7704,6 +7753,9 @@ function planMcpSessionSentinel(step, options, client, agentUrl) {
7704
7753
  )
7705
7754
  };
7706
7755
  }
7756
+ if (typeof step.auth === "object" && step.auth.type === "web_bot_auth") {
7757
+ return { kind: "error", error: "web_bot_auth is not supported by MCP session probes; select an AdCP tool step" };
7758
+ }
7707
7759
  const signatureBound = signatureBoundTools(options);
7708
7760
  const candidates = protectedToolCandidates(options.agentTools);
7709
7761
  if (signatureBound === "unparseable") {
@@ -7763,7 +7815,7 @@ function planMcpSessionSentinel(step, options, client, agentUrl) {
7763
7815
  };
7764
7816
  }
7765
7817
  function authHeadersForStep(directive, options) {
7766
- if (directive === "none") return {};
7818
+ if (directive === "none" || directive.type === "web_bot_auth") return {};
7767
7819
  if (directive.type === "basic") return basicAuthHeadersForStep(directive, options);
7768
7820
  let value;
7769
7821
  if ("value" in directive && directive.value) {
@@ -7811,7 +7863,7 @@ function isCredentialHeaderName(name) {
7811
7863
  if (SESSION_PROBE_ROUTING_HEADERS.has(normalized)) return false;
7812
7864
  return AUTH_OVERRIDE_HEADER_NAMES.has(normalized) || AUTH_OVERRIDE_CREDENTIAL_HEADER_RE.test(normalized) || AUTH_OVERRIDE_COMPACT_CREDENTIAL_RE.test(normalized.replace(/[-_]/g, ""));
7813
7865
  }
7814
- function createAuthOverrideClient(agentUrl, protocol, options, authHeaders) {
7866
+ function createAuthOverrideClient(agentUrl, protocol, options, authHeaders, signedFetch) {
7815
7867
  const runSecrets = runCredentialValues(options);
7816
7868
  const headers = {};
7817
7869
  for (const [name, value] of Object.entries(options.headers ?? {})) {
@@ -7842,6 +7894,7 @@ function createAuthOverrideClient(agentUrl, protocol, options, authHeaders) {
7842
7894
  test_kit: void 0,
7843
7895
  _client: void 0,
7844
7896
  functional_request_signing: void 0,
7897
+ ...signedFetch && { transport: { ...options.transport, trustedFetchFn: signedFetch } },
7845
7898
  headers: Object.keys(headers).length > 0 ? headers : void 0
7846
7899
  });
7847
7900
  }
@@ -1,3 +1,6 @@
1
+ import { createStoryboardWebBotAuthFetch } from "./web-bot-auth.mjs";
2
+ import { jwkThumbprint } from "../../signing/web-bot-auth.mjs";
3
+ import { createAgentTransportFetch } from "../../net/agent-transport-fetch.mjs";
1
4
  import { createHash, createHmac } from "node:crypto";
2
5
  import { existsSync, readFileSync } from "node:fs";
3
6
  import { basename, join } from "node:path";
@@ -2248,6 +2251,19 @@ function resolveBindingAccountScope(storyboard, options) {
2248
2251
  }
2249
2252
  function resolveBindingCredential(options, step) {
2250
2253
  const parts = [];
2254
+ if (options.web_bot_auth) {
2255
+ parts.push(`wba_target:${JSON.stringify(options.web_bot_auth.publicUrl ?? null)}`);
2256
+ for (const [name, identity] of Object.entries(options.web_bot_auth.identities).sort(
2257
+ ([a], [b]) => a < b ? -1 : a > b ? 1 : 0
2258
+ )) {
2259
+ try {
2260
+ const jwk = "privateKey" in identity.key ? identity.key.privateKey : identity.key.publicKey;
2261
+ parts.push(`wba_identity:${JSON.stringify([name, identity.origin, jwkThumbprint(jwk)])}`);
2262
+ } catch {
2263
+ parts.push(`wba_identity:${JSON.stringify([name, "invalid"])}`);
2264
+ }
2265
+ }
2266
+ }
2251
2267
  if (step?.auth !== void 0) {
2252
2268
  parts.push(`step_auth:${JSON.stringify(describeStepAuthDirective(step.auth))}`);
2253
2269
  }
@@ -4909,7 +4925,7 @@ function buildStepRequest(step, effectiveStep, context, options, runnerVars) {
4909
4925
  const governedFixture = payloadBoundGovernance && effectiveStep.task !== "check_governance" && effectiveStep.task !== "report_plan_outcome" && (governedSource !== void 0 && Object.prototype.hasOwnProperty.call(governedSource, "governance_context") || contextGovernance);
4910
4926
  if (options.request) {
4911
4927
  request = injectContext({ ...options.request }, context, runnerVars);
4912
- } else if (step.expect_error && step.sample_request) {
4928
+ } else if (step.expect_error && step.sample_request && step.enrich_request !== true) {
4913
4929
  request = injectContext({ ...step.sample_request }, context, runnerVars);
4914
4930
  } else if (governedFixture) {
4915
4931
  request = injectContext({ ...step.sample_request ?? {} }, context, runnerVars);
@@ -5284,18 +5300,49 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
5284
5300
  const testsIdempotencyKeyOmission = (step.omit_idempotency_key === true || governedRequest && (typeof request.idempotency_key !== "string" || request.idempotency_key.length === 0)) && requestUsesIdempotency(effectiveStep.task, request);
5285
5301
  const testsMissingAccount = effectiveStep.task === "create_media_buy" && (step.omit_account === true || governedRequest && !Object.prototype.hasOwnProperty.call(request, "account"));
5286
5302
  const testsSchemaInvalidRequest = step.expect_error === true && step.negative_path !== "payload_well_formed";
5287
- const useSdkAuthOverride = typeof step.auth === "object" && step.auth.type === "api_key" && step.auth.from_test_kit === true && step.auth.value_strategy === void 0 && step.expect_error !== true && !(step.validations ?? []).some((validation) => HTTP_PROBE_ONLY_CHECKS.has(validation.check));
5303
+ const useWebBotAuth = typeof step.auth === "object" && step.auth.type === "web_bot_auth";
5304
+ const useSdkAuthOverride = useWebBotAuth || typeof step.auth === "object" && step.auth.type === "api_key" && step.auth.from_test_kit === true && step.auth.value_strategy === void 0 && step.expect_error !== true && !(step.validations ?? []).some((validation) => HTTP_PROBE_ONLY_CHECKS.has(validation.check));
5288
5305
  let rawProbeHeaders;
5289
5306
  let authOverrideClient;
5290
5307
  try {
5291
5308
  rawProbeHeaders = step.auth !== void 0 ? authHeadersForStep(step.auth, options) : void 0;
5309
+ let signedFetch;
5310
+ if (typeof step.auth === "object" && step.auth.type === "web_bot_auth") {
5311
+ if ((step.validations ?? []).some((validation) => HTTP_PROBE_ONLY_CHECKS.has(validation.check)))
5312
+ throw new Error(
5313
+ "web_bot_auth steps require tool-response validations; HTTP probe assertions are not supported"
5314
+ );
5315
+ if (options.web_bot_auth?.publicUrl && options.protocol === "a2a")
5316
+ throw new Error("web_bot_auth.publicUrl loopback delivery supports MCP only; use HTTPS directly for A2A");
5317
+ if (!options.web_bot_auth?.publicUrl && new URL(runState.agentUrl).protocol !== "https:")
5318
+ throw new Error("web_bot_auth.publicUrl is required to sign for a non-HTTPS agent");
5319
+ const name = step.auth.identity;
5320
+ const identities = options.web_bot_auth?.identities;
5321
+ const identity = identities && Object.hasOwn(identities, name) ? identities[name] : void 0;
5322
+ if (!identity) throw new Error("web_bot_auth identity is not configured in options.web_bot_auth.identities");
5323
+ signedFetch = createStoryboardWebBotAuthFetch(
5324
+ createAgentTransportFetch(runState.agentUrl, {
5325
+ trustedFetchFn: options.transport?.trustedFetchFn,
5326
+ allowPrivateIp: options.transport?.allowPrivateIp
5327
+ }),
5328
+ identity.key,
5329
+ {
5330
+ agentUrl: runState.agentUrl,
5331
+ origin: identity.origin,
5332
+ ...options.web_bot_auth?.publicUrl && {
5333
+ target: { publicUrl: options.web_bot_auth.publicUrl, loopbackUrl: runState.agentUrl }
5334
+ }
5335
+ }
5336
+ );
5337
+ }
5292
5338
  if (useSdkAuthOverride) {
5293
5339
  if (rawProbeHeaders === void 0) throw new Error("Step auth override credentials were not resolved");
5294
5340
  authOverrideClient = createAuthOverrideClient(
5295
5341
  runState.agentUrl,
5296
5342
  options.protocol ?? "mcp",
5297
5343
  options,
5298
- rawProbeHeaders
5344
+ rawProbeHeaders,
5345
+ signedFetch
5299
5346
  );
5300
5347
  }
5301
5348
  } catch (err) {
@@ -5589,7 +5636,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
5589
5636
  runState.agentProfile?.raw_capabilities,
5590
5637
  "request_signing.required_for"
5591
5638
  );
5592
- if (taskResult?.adcp_error?.code === "request_signature_required" && Array.isArray(requiredForSigning) && requiredForSigning.includes(effectiveStep.task) && options.functional_request_signing === void 0 && runState.storyboardRequiresRequestSigner !== true) {
5639
+ if (taskResult?.adcp_error?.code === "request_signature_required" && Array.isArray(requiredForSigning) && requiredForSigning.includes(effectiveStep.task) && options.functional_request_signing === void 0 && !useWebBotAuth && runState.storyboardRequiresRequestSigner !== true) {
5593
5640
  const next2 = getNextStepPreview(step.id, allSteps, context, runState.runnerVars);
5594
5641
  const detail = `Agent declared request_signing.required_for includes "${effectiveStep.task}" and rejected the unsigned request with request_signature_required; storyboard "${storyboardId}" does not require request_signer.`;
5595
5642
  return {
@@ -7721,6 +7768,8 @@ function selectProtectedToolTarget(tools) {
7721
7768
  function sessionControlMechanismFor(auth) {
7722
7769
  if (auth === "none") return "any";
7723
7770
  switch (auth.type) {
7771
+ case "web_bot_auth":
7772
+ throw new Error("web_bot_auth is not supported by session probes");
7724
7773
  case "oauth_bearer":
7725
7774
  return "oauth_bearer";
7726
7775
  case "basic":
@@ -7746,6 +7795,9 @@ function planMcpSessionSentinel(step, options, client, agentUrl) {
7746
7795
  )
7747
7796
  };
7748
7797
  }
7798
+ if (typeof step.auth === "object" && step.auth.type === "web_bot_auth") {
7799
+ return { kind: "error", error: "web_bot_auth is not supported by MCP session probes; select an AdCP tool step" };
7800
+ }
7749
7801
  const signatureBound = signatureBoundTools(options);
7750
7802
  const candidates = protectedToolCandidates(options.agentTools);
7751
7803
  if (signatureBound === "unparseable") {
@@ -7805,7 +7857,7 @@ function planMcpSessionSentinel(step, options, client, agentUrl) {
7805
7857
  };
7806
7858
  }
7807
7859
  function authHeadersForStep(directive, options) {
7808
- if (directive === "none") return {};
7860
+ if (directive === "none" || directive.type === "web_bot_auth") return {};
7809
7861
  if (directive.type === "basic") return basicAuthHeadersForStep(directive, options);
7810
7862
  let value;
7811
7863
  if ("value" in directive && directive.value) {
@@ -7853,7 +7905,7 @@ function isCredentialHeaderName(name) {
7853
7905
  if (SESSION_PROBE_ROUTING_HEADERS.has(normalized)) return false;
7854
7906
  return AUTH_OVERRIDE_HEADER_NAMES.has(normalized) || AUTH_OVERRIDE_CREDENTIAL_HEADER_RE.test(normalized) || AUTH_OVERRIDE_COMPACT_CREDENTIAL_RE.test(normalized.replace(/[-_]/g, ""));
7855
7907
  }
7856
- function createAuthOverrideClient(agentUrl, protocol, options, authHeaders) {
7908
+ function createAuthOverrideClient(agentUrl, protocol, options, authHeaders, signedFetch) {
7857
7909
  const runSecrets = runCredentialValues(options);
7858
7910
  const headers = {};
7859
7911
  for (const [name, value] of Object.entries(options.headers ?? {})) {
@@ -7884,6 +7936,7 @@ function createAuthOverrideClient(agentUrl, protocol, options, authHeaders) {
7884
7936
  test_kit: void 0,
7885
7937
  _client: void 0,
7886
7938
  functional_request_signing: void 0,
7939
+ ...signedFetch && { transport: { ...options.transport, trustedFetchFn: signedFetch } },
7887
7940
  headers: Object.keys(headers).length > 0 ? headers : void 0
7888
7941
  });
7889
7942
  }
@@ -704,6 +704,10 @@ export interface ContextInput {
704
704
  export type StepAuthDirective =
705
705
  /** Strip transport credentials entirely. The step MUST hit the agent unauthenticated. */
706
706
  'none' | {
707
+ type: 'web_bot_auth';
708
+ /** Name in the runner's runtime-only `web_bot_auth.identities` map. */
709
+ identity: string;
710
+ } | {
707
711
  type: 'api_key';
708
712
  /** Literal Bearer value sent as `Authorization: Bearer <value>`. */
709
713
  value?: string;
@@ -838,6 +842,11 @@ export interface StoryboardStep {
838
842
  * seller; schema validation remains enabled for `payload_well_formed`.
839
843
  */
840
844
  negative_path?: 'schema_invalid' | 'payload_well_formed';
845
+ /** Opt a schema-valid semantic rejection probe into normal request enrichment.
846
+ * Explicit fixture values remain authoritative. Invalid-input probes must
847
+ * retain the default, which sends the authored request without enrichment.
848
+ */
849
+ enrich_request?: true;
841
850
  /**
842
851
  * Per-step invariant opt-out. See `StepInvariantsObject`. Use when a
843
852
  * specific step deliberately trips a default invariant (e.g. a
@@ -1694,6 +1703,15 @@ export interface PrepareStoryboardFixturesOptions extends StoryboardRunOptions {
1694
1703
  prepared_fixtures_preparation_authorizer?: PreparedFixturesPreparationAuthorizer;
1695
1704
  }
1696
1705
  export interface StoryboardRunOptions extends TestOptions {
1706
+ /** Runtime signing keys; storyboard YAML contains only identity names. */
1707
+ web_bot_auth?: {
1708
+ identities: Record<string, {
1709
+ origin: string;
1710
+ key: import('../../signing/web-bot-auth.mjs').WebBotSigningKey;
1711
+ }>;
1712
+ /** Sign this public HTTPS endpoint, delivering to the loopback agent URL. */
1713
+ publicUrl?: string;
1714
+ };
1697
1715
  /** Compliance cache root for bundle-scoped fixtures and test vectors. */
1698
1716
  complianceDir?: string;
1699
1717
  /**
@@ -704,6 +704,10 @@ export interface ContextInput {
704
704
  export type StepAuthDirective =
705
705
  /** Strip transport credentials entirely. The step MUST hit the agent unauthenticated. */
706
706
  'none' | {
707
+ type: 'web_bot_auth';
708
+ /** Name in the runner's runtime-only `web_bot_auth.identities` map. */
709
+ identity: string;
710
+ } | {
707
711
  type: 'api_key';
708
712
  /** Literal Bearer value sent as `Authorization: Bearer <value>`. */
709
713
  value?: string;
@@ -838,6 +842,11 @@ export interface StoryboardStep {
838
842
  * seller; schema validation remains enabled for `payload_well_formed`.
839
843
  */
840
844
  negative_path?: 'schema_invalid' | 'payload_well_formed';
845
+ /** Opt a schema-valid semantic rejection probe into normal request enrichment.
846
+ * Explicit fixture values remain authoritative. Invalid-input probes must
847
+ * retain the default, which sends the authored request without enrichment.
848
+ */
849
+ enrich_request?: true;
841
850
  /**
842
851
  * Per-step invariant opt-out. See `StepInvariantsObject`. Use when a
843
852
  * specific step deliberately trips a default invariant (e.g. a
@@ -1694,6 +1703,15 @@ export interface PrepareStoryboardFixturesOptions extends StoryboardRunOptions {
1694
1703
  prepared_fixtures_preparation_authorizer?: PreparedFixturesPreparationAuthorizer;
1695
1704
  }
1696
1705
  export interface StoryboardRunOptions extends TestOptions {
1706
+ /** Runtime signing keys; storyboard YAML contains only identity names. */
1707
+ web_bot_auth?: {
1708
+ identities: Record<string, {
1709
+ origin: string;
1710
+ key: import('../../signing/web-bot-auth').WebBotSigningKey;
1711
+ }>;
1712
+ /** Sign this public HTTPS endpoint, delivering to the loopback agent URL. */
1713
+ publicUrl?: string;
1714
+ };
1697
1715
  /** Compliance cache root for bundle-scoped fixtures and test vectors. */
1698
1716
  complianceDir?: string;
1699
1717
  /**
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
197
197
  */
198
198
  export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
199
199
  /** Capability semver emitted in run summaries and used for advisory expiry. */
200
- export declare const RUNNER_CAPABILITY_VERSION = "17.0.0-beta.2";
200
+ export declare const RUNNER_CAPABILITY_VERSION = "17.0.0-beta.4";
201
201
  /** True when a failed validation contributes to the owning step's grade. */
202
202
  export declare function validationFailsStep(result: ValidationResult): boolean;
203
203
  /**
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
197
197
  */
198
198
  export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
199
199
  /** Capability semver emitted in run summaries and used for advisory expiry. */
200
- export declare const RUNNER_CAPABILITY_VERSION = "17.0.0-beta.2";
200
+ export declare const RUNNER_CAPABILITY_VERSION = "17.0.0-beta.4";
201
201
  /** True when a failed validation contributes to the owning step's grade. */
202
202
  export declare function validationFailsStep(result: ValidationResult): boolean;
203
203
  /**
@@ -0,0 +1,10 @@
1
+ import { type WebBotSigningKey, type WebBotSigningOptions } from '../../signing/web-bot-auth.mjs';
2
+ /** Sign the public HTTPS target while the official transport delivers to loopback. */
3
+ export declare function createStoryboardWebBotAuthFetch(upstream: typeof fetch, key: WebBotSigningKey, options: WebBotSigningOptions & {
4
+ /** Pin the destination origin for direct HTTPS delivery. */
5
+ agentUrl?: string;
6
+ target?: {
7
+ publicUrl: string;
8
+ loopbackUrl: string;
9
+ };
10
+ }): typeof fetch;
@@ -0,0 +1,10 @@
1
+ import { type WebBotSigningKey, type WebBotSigningOptions } from '../../signing/web-bot-auth';
2
+ /** Sign the public HTTPS target while the official transport delivers to loopback. */
3
+ export declare function createStoryboardWebBotAuthFetch(upstream: typeof fetch, key: WebBotSigningKey, options: WebBotSigningOptions & {
4
+ /** Pin the destination origin for direct HTTPS delivery. */
5
+ agentUrl?: string;
6
+ target?: {
7
+ publicUrl: string;
8
+ loopbackUrl: string;
9
+ };
10
+ }): typeof fetch;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var web_bot_auth_exports = {};
20
+ __export(web_bot_auth_exports, {
21
+ createStoryboardWebBotAuthFetch: () => createStoryboardWebBotAuthFetch
22
+ });
23
+ module.exports = __toCommonJS(web_bot_auth_exports);
24
+ var import_web_bot_auth = require('../../signing/web-bot-auth.js');
25
+ function createStoryboardWebBotAuthFetch(upstream, key, options) {
26
+ const deliver = async (input, init) => {
27
+ const response = await upstream(input, { ...init, redirect: "manual" });
28
+ if ([301, 302, 303, 307, 308].includes(response.status) && response.headers.has("location")) {
29
+ await response.body?.cancel();
30
+ throw new TypeError("Web Bot Auth storyboard requests do not follow HTTP redirects");
31
+ }
32
+ return response;
33
+ };
34
+ if (!options.target) {
35
+ if (!options.agentUrl) throw new TypeError("Direct Web Bot Auth storyboard signing requires agentUrl");
36
+ const agentUrl = new URL(options.agentUrl);
37
+ if (agentUrl.protocol !== "https:" || agentUrl.username || agentUrl.password || agentUrl.hash)
38
+ throw new TypeError(
39
+ "Direct Web Bot Auth storyboard signing requires an HTTPS agentUrl without credentials or fragments"
40
+ );
41
+ const signed2 = (0, import_web_bot_auth.createWebBotAuthFetch)(deliver, key, options);
42
+ return (input, init) => {
43
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
44
+ if (new URL(url).origin !== agentUrl.origin)
45
+ return Promise.reject(new TypeError("Web Bot Auth storyboard refused a different agent origin"));
46
+ return signed2(input, init);
47
+ };
48
+ }
49
+ const publicUrl = new URL(options.target.publicUrl);
50
+ const localUrl = new URL(options.target.loopbackUrl);
51
+ if (publicUrl.protocol !== "https:" || publicUrl.username || publicUrl.password || publicUrl.hash || publicUrl.search || !["http:", "https:"].includes(localUrl.protocol) || !["localhost", "127.0.0.1", "[::1]"].includes(localUrl.hostname) || localUrl.username || localUrl.password || localUrl.hash || localUrl.search)
52
+ throw new TypeError(
53
+ "Web Bot Auth test delivery requires a public HTTPS URL and a loopback URL without credentials, query or fragment"
54
+ );
55
+ const signed = (0, import_web_bot_auth.createWebBotAuthFetch)(
56
+ async (input, init) => {
57
+ const target = new URL(String(input));
58
+ if (target.origin !== publicUrl.origin || target.pathname !== publicUrl.pathname)
59
+ throw new TypeError("Web Bot Auth test delivery refused a different public endpoint");
60
+ const destination = new URL(localUrl);
61
+ destination.search = target.search;
62
+ return deliver(destination.href, init);
63
+ },
64
+ key,
65
+ options
66
+ );
67
+ return async (input, init) => {
68
+ if (input instanceof Request) throw new TypeError("Web Bot Auth test delivery requires a URL and init");
69
+ const source = new URL(String(input));
70
+ if (source.origin !== localUrl.origin || source.pathname !== localUrl.pathname)
71
+ throw new TypeError("Web Bot Auth test delivery refused a different loopback endpoint");
72
+ const target = new URL(publicUrl);
73
+ target.search = source.search;
74
+ return signed(target.href, init);
75
+ };
76
+ }
77
+ // Annotate the CommonJS export names for ESM import in node:
78
+ 0 && (module.exports = {
79
+ createStoryboardWebBotAuthFetch
80
+ });
@@ -0,0 +1,56 @@
1
+ import { createWebBotAuthFetch } from "../../signing/web-bot-auth.mjs";
2
+ function createStoryboardWebBotAuthFetch(upstream, key, options) {
3
+ const deliver = async (input, init) => {
4
+ const response = await upstream(input, { ...init, redirect: "manual" });
5
+ if ([301, 302, 303, 307, 308].includes(response.status) && response.headers.has("location")) {
6
+ await response.body?.cancel();
7
+ throw new TypeError("Web Bot Auth storyboard requests do not follow HTTP redirects");
8
+ }
9
+ return response;
10
+ };
11
+ if (!options.target) {
12
+ if (!options.agentUrl) throw new TypeError("Direct Web Bot Auth storyboard signing requires agentUrl");
13
+ const agentUrl = new URL(options.agentUrl);
14
+ if (agentUrl.protocol !== "https:" || agentUrl.username || agentUrl.password || agentUrl.hash)
15
+ throw new TypeError(
16
+ "Direct Web Bot Auth storyboard signing requires an HTTPS agentUrl without credentials or fragments"
17
+ );
18
+ const signed2 = createWebBotAuthFetch(deliver, key, options);
19
+ return (input, init) => {
20
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
21
+ if (new URL(url).origin !== agentUrl.origin)
22
+ return Promise.reject(new TypeError("Web Bot Auth storyboard refused a different agent origin"));
23
+ return signed2(input, init);
24
+ };
25
+ }
26
+ const publicUrl = new URL(options.target.publicUrl);
27
+ const localUrl = new URL(options.target.loopbackUrl);
28
+ if (publicUrl.protocol !== "https:" || publicUrl.username || publicUrl.password || publicUrl.hash || publicUrl.search || !["http:", "https:"].includes(localUrl.protocol) || !["localhost", "127.0.0.1", "[::1]"].includes(localUrl.hostname) || localUrl.username || localUrl.password || localUrl.hash || localUrl.search)
29
+ throw new TypeError(
30
+ "Web Bot Auth test delivery requires a public HTTPS URL and a loopback URL without credentials, query or fragment"
31
+ );
32
+ const signed = createWebBotAuthFetch(
33
+ async (input, init) => {
34
+ const target = new URL(String(input));
35
+ if (target.origin !== publicUrl.origin || target.pathname !== publicUrl.pathname)
36
+ throw new TypeError("Web Bot Auth test delivery refused a different public endpoint");
37
+ const destination = new URL(localUrl);
38
+ destination.search = target.search;
39
+ return deliver(destination.href, init);
40
+ },
41
+ key,
42
+ options
43
+ );
44
+ return async (input, init) => {
45
+ if (input instanceof Request) throw new TypeError("Web Bot Auth test delivery requires a URL and init");
46
+ const source = new URL(String(input));
47
+ if (source.origin !== localUrl.origin || source.pathname !== localUrl.pathname)
48
+ throw new TypeError("Web Bot Auth test delivery refused a different loopback endpoint");
49
+ const target = new URL(publicUrl);
50
+ target.search = source.search;
51
+ return signed(target.href, init);
52
+ };
53
+ }
54
+ export {
55
+ createStoryboardWebBotAuthFetch
56
+ };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "17.0.0-beta.2";
4
+ export declare const LIBRARY_VERSION = "17.0.0-beta.4";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
33
33
  * Full version information
34
34
  */
35
35
  export declare const VERSION_INFO: {
36
- readonly library: "17.0.0-beta.2";
36
+ readonly library: "17.0.0-beta.4";
37
37
  readonly adcp: "3.3.0-beta.0";
38
38
  readonly compatibleVersions: readonly ["v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.1.25", "3.1.26", "3.1.27", "3.1.28", "3.1.29", "3.2.1", "3.2", "3.2.2", "3.2.3", "3.2.4", "3.2.5", "3.2.6", "3.2.7", "3.3.0-beta.0", "3.3-beta.0"];
39
- readonly generatedAt: "2026-10-27T06:33:58.733Z";
39
+ readonly generatedAt: "2026-10-28T18:30:58.178Z";
40
40
  };
41
41
  /**
42
42
  * Get the AdCP specification version this library is built for
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "17.0.0-beta.2";
4
+ export declare const LIBRARY_VERSION = "17.0.0-beta.4";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
33
33
  * Full version information
34
34
  */
35
35
  export declare const VERSION_INFO: {
36
- readonly library: "17.0.0-beta.2";
36
+ readonly library: "17.0.0-beta.4";
37
37
  readonly adcp: "3.3.0-beta.0";
38
38
  readonly compatibleVersions: readonly ["v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.1.25", "3.1.26", "3.1.27", "3.1.28", "3.1.29", "3.2.1", "3.2", "3.2.2", "3.2.3", "3.2.4", "3.2.5", "3.2.6", "3.2.7", "3.3.0-beta.0", "3.3-beta.0"];
39
- readonly generatedAt: "2026-10-27T06:33:58.733Z";
39
+ readonly generatedAt: "2026-10-28T18:30:58.178Z";
40
40
  };
41
41
  /**
42
42
  * Get the AdCP specification version this library is built for
@@ -31,7 +31,7 @@ __export(version_exports, {
31
31
  toReleasePrecisionVersion: () => toReleasePrecisionVersion
32
32
  });
33
33
  module.exports = __toCommonJS(version_exports);
34
- const LIBRARY_VERSION = "17.0.0-beta.2";
34
+ const LIBRARY_VERSION = "17.0.0-beta.4";
35
35
  const ADCP_VERSION = "3.3.0-beta.0";
36
36
  const ADCP_MAJOR_VERSION = 3;
37
37
  const COMPATIBLE_ADCP_VERSIONS = [
@@ -106,10 +106,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
106
106
  "3.3-beta.0"
107
107
  ];
108
108
  const VERSION_INFO = {
109
- library: "17.0.0-beta.2",
109
+ library: "17.0.0-beta.4",
110
110
  adcp: "3.3.0-beta.0",
111
111
  compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
112
- generatedAt: "2026-10-27T06:33:58.733Z"
112
+ generatedAt: "2026-10-28T18:30:58.178Z"
113
113
  };
114
114
  function getAdcpVersion() {
115
115
  return ADCP_VERSION;
@@ -1,4 +1,4 @@
1
- const LIBRARY_VERSION = "17.0.0-beta.2";
1
+ const LIBRARY_VERSION = "17.0.0-beta.4";
2
2
  const ADCP_VERSION = "3.3.0-beta.0";
3
3
  const ADCP_MAJOR_VERSION = 3;
4
4
  const COMPATIBLE_ADCP_VERSIONS = [
@@ -73,10 +73,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
73
73
  "3.3-beta.0"
74
74
  ];
75
75
  const VERSION_INFO = {
76
- library: "17.0.0-beta.2",
76
+ library: "17.0.0-beta.4",
77
77
  adcp: "3.3.0-beta.0",
78
78
  compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
79
- generatedAt: "2026-10-27T06:33:58.733Z"
79
+ generatedAt: "2026-10-28T18:30:58.178Z"
80
80
  };
81
81
  function getAdcpVersion() {
82
82
  return ADCP_VERSION;
@@ -1,7 +1,7 @@
1
1
  # AdCP Type Summary
2
2
 
3
- > Generated at: 2026-10-27
4
- > @adcp/sdk v17.0.0-beta.2
3
+ > Generated at: 2026-10-28
4
+ > @adcp/sdk v17.0.0-beta.4
5
5
 
6
6
  Curated reference of the types that matter for using the AdCP client. For full generated types see `src/lib/types/tools.generated.ts` and `src/lib/types/core.generated.ts`.
7
7