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

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 (60) 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/auth-signature.d.mts +2 -2
  10. package/dist/lib/server/auth-signature.d.ts +2 -2
  11. package/dist/lib/server/auth-signature.js +3 -0
  12. package/dist/lib/server/auth-signature.mjs +3 -0
  13. package/dist/lib/server/create-adcp-server.d.mts +2 -2
  14. package/dist/lib/server/create-adcp-server.d.ts +2 -2
  15. package/dist/lib/server/create-adcp-server.js +25 -3
  16. package/dist/lib/server/create-adcp-server.mjs +25 -3
  17. package/dist/lib/server/serve.js +3 -1
  18. package/dist/lib/server/serve.mjs +3 -1
  19. package/dist/lib/server/signed-request-transport.d.mts +1 -0
  20. package/dist/lib/server/signed-request-transport.d.ts +1 -0
  21. package/dist/lib/server/signed-request-transport.js +46 -0
  22. package/dist/lib/server/signed-request-transport.mjs +20 -0
  23. package/dist/lib/server/test-controller.d.mts +1 -0
  24. package/dist/lib/server/test-controller.d.ts +1 -0
  25. package/dist/lib/server/test-controller.js +5 -1
  26. package/dist/lib/server/test-controller.mjs +5 -1
  27. package/dist/lib/testing/index.d.mts +1 -0
  28. package/dist/lib/testing/index.d.ts +1 -0
  29. package/dist/lib/testing/index.js +3 -0
  30. package/dist/lib/testing/index.mjs +2 -0
  31. package/dist/lib/testing/storyboard/canonical-format-satisfaction.js +1 -15
  32. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +1 -15
  33. package/dist/lib/testing/storyboard/index.d.mts +1 -0
  34. package/dist/lib/testing/storyboard/index.d.ts +1 -0
  35. package/dist/lib/testing/storyboard/index.js +3 -0
  36. package/dist/lib/testing/storyboard/index.mjs +2 -0
  37. package/dist/lib/testing/storyboard/loader.js +7 -0
  38. package/dist/lib/testing/storyboard/loader.mjs +7 -0
  39. package/dist/lib/testing/storyboard/request-builder.js +9 -6
  40. package/dist/lib/testing/storyboard/request-builder.mjs +9 -6
  41. package/dist/lib/testing/storyboard/runner.js +59 -6
  42. package/dist/lib/testing/storyboard/runner.mjs +59 -6
  43. package/dist/lib/testing/storyboard/types.d.mts +18 -0
  44. package/dist/lib/testing/storyboard/types.d.ts +18 -0
  45. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  46. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  47. package/dist/lib/testing/storyboard/web-bot-auth.d.mts +10 -0
  48. package/dist/lib/testing/storyboard/web-bot-auth.d.ts +10 -0
  49. package/dist/lib/testing/storyboard/web-bot-auth.js +80 -0
  50. package/dist/lib/testing/storyboard/web-bot-auth.mjs +56 -0
  51. package/dist/lib/version.d.mts +3 -3
  52. package/dist/lib/version.d.ts +3 -3
  53. package/dist/lib/version.js +3 -3
  54. package/dist/lib/version.mjs +3 -3
  55. package/docs/TYPE-SUMMARY.md +2 -2
  56. package/docs/llms.txt +2 -2
  57. package/docs/migration-14.x-rc-worksheet.md +4 -4
  58. package/docs/migration-16-to-17.md +27 -0
  59. package/docs/migration-agent-identity-3.3.md +106 -4
  60. package/package.json +15 -2
@@ -23,3 +23,4 @@ export { COLLECTION_DIAGNOSTIC_LIMIT, COLLECTION_PAIR_LIMIT, COLLECTION_TARGETIN
23
23
  export type { CollectionNormalizationCode, CollectionNormalizationFailure, CollectionNormalizationResult, CrossPublisherCollectionRelation, CollectionPair, CollectionSelectionEvaluation, CollectionSelectionSelector, CollectionSelectionWitness, CollectionSelectorObject, CollectionWitnessKind, CollectionWitnessReadResult, FixtureContextOutput, NormalizedCollectionSelectors, PreparedFixtureBinding, PreparedFixtureSelection, PreparedFixturesAuthorizer, PreparedFixturesDecision, PreparedFixturesDisposition, PreparedFixturesLookup, PreparedFixturesPreparationLookup, PreparedFixturesPreparationAuthorizer, PreparedFixturesRefusal, PreparedFixturesRefusalCode, PreparedFixturesReference, PreparedSchemaArtifact, ProtectedContextViolationCode, ResolvedCollectionSelectionSelector, } from './storyboard';
24
24
  export { resolveCreativeBuildProbe, validateCreativeBuildProbeSpec } from './storyboard';
25
25
  export type { CreativeBuildProbeSpec, CreativeBuildProbeInputFixture, CreativeBuildProbeResolution, } from './storyboard';
26
+ export { createStoryboardWebBotAuthFetch } from './storyboard/web-bot-auth';
@@ -67,6 +67,7 @@ __export(testing_exports, {
67
67
  comply: () => import_compliance.comply,
68
68
  createComplyController: () => import_comply_controller.createComplyController,
69
69
  createSeedFixtureCache: () => import_test_controller.createSeedFixtureCache,
70
+ createStoryboardWebBotAuthFetch: () => import_web_bot_auth.createStoryboardWebBotAuthFetch,
70
71
  createTestAgent: () => import_test_helpers.createTestAgent,
71
72
  createTestClient: () => import_agent_tester.createTestClient,
72
73
  creativeAgent: () => import_test_helpers.creativeAgent,
@@ -234,6 +235,7 @@ var import_validation = require('../validation/index.js');
234
235
  var import_storyboard = require('./storyboard/index.js');
235
236
  var import_storyboard2 = require('./storyboard/index.js');
236
237
  var import_storyboard3 = require('./storyboard/index.js');
238
+ var import_web_bot_auth = require('./storyboard/web-bot-auth.js');
237
239
  // Annotate the CommonJS export names for ESM import in node:
238
240
  0 && (module.exports = {
239
241
  AdagentsJsonSchema,
@@ -285,6 +287,7 @@ var import_storyboard3 = require('./storyboard/index.js');
285
287
  comply,
286
288
  createComplyController,
287
289
  createSeedFixtureCache,
290
+ createStoryboardWebBotAuthFetch,
288
291
  createTestAgent,
289
292
  createTestClient,
290
293
  creativeAgent,
@@ -212,6 +212,7 @@ import {
212
212
  withPreparedFixtures
213
213
  } from "./storyboard/index.mjs";
214
214
  import { resolveCreativeBuildProbe, validateCreativeBuildProbeSpec } from "./storyboard/index.mjs";
215
+ import { createStoryboardWebBotAuthFetch } from "./storyboard/web-bot-auth.mjs";
215
216
  export {
216
217
  AdagentsJsonSchema,
217
218
  BrandJsonSchema,
@@ -262,6 +263,7 @@ export {
262
263
  comply,
263
264
  createComplyController,
264
265
  createSeedFixtureCache,
266
+ createStoryboardWebBotAuthFetch,
265
267
  createTestAgent,
266
268
  createTestClient,
267
269
  creativeAgent,
@@ -47,13 +47,6 @@ const HANDLED_CANONICAL_PARAM_KEYS = /* @__PURE__ */ new Set([
47
47
  "duration_ms_range"
48
48
  ]);
49
49
  const ARRAY_SUBSET_PARAM_KEYS = /* @__PURE__ */ new Set(["video_codecs", "audio_codecs", "mime_types", "file_types", "formats"]);
50
- const OMITTABLE_DECLARATION_PARAMS = /* @__PURE__ */ new Set([
51
- "asset_source",
52
- "buyer_asset_acceptance",
53
- "composition_model",
54
- "slots",
55
- "ssl_required"
56
- ]);
57
50
  function validateCanonicalFormatSatisfaction(validation, request, context, taskResult) {
58
51
  if (typeof validation.value !== "boolean") {
59
52
  return {
@@ -484,14 +477,7 @@ function requireRemainingParamContainment(productParams, requestParams) {
484
477
  for (const [key, productValue] of Object.entries(productParams)) {
485
478
  if (HANDLED_CANONICAL_PARAM_KEYS.has(key) || productValue === void 0) continue;
486
479
  if (Array.isArray(productValue) && productValue.length === 0) continue;
487
- if (requestParams[key] === void 0) {
488
- if (OMITTABLE_DECLARATION_PARAMS.has(key)) continue;
489
- return {
490
- ok: false,
491
- bug_class: "directionality",
492
- detail: `Under-specified selector: product constrains params.${key}, but the request selector omits ${key}`
493
- };
494
- }
480
+ if (requestParams[key] === void 0) continue;
495
481
  const requestValue = requestParams[key];
496
482
  if (ARRAY_SUBSET_PARAM_KEYS.has(key)) {
497
483
  const subset = requireArraySubset(key, productValue, requestValue);
@@ -23,13 +23,6 @@ const HANDLED_CANONICAL_PARAM_KEYS = /* @__PURE__ */ new Set([
23
23
  "duration_ms_range"
24
24
  ]);
25
25
  const ARRAY_SUBSET_PARAM_KEYS = /* @__PURE__ */ new Set(["video_codecs", "audio_codecs", "mime_types", "file_types", "formats"]);
26
- const OMITTABLE_DECLARATION_PARAMS = /* @__PURE__ */ new Set([
27
- "asset_source",
28
- "buyer_asset_acceptance",
29
- "composition_model",
30
- "slots",
31
- "ssl_required"
32
- ]);
33
26
  function validateCanonicalFormatSatisfaction(validation, request, context, taskResult) {
34
27
  if (typeof validation.value !== "boolean") {
35
28
  return {
@@ -460,14 +453,7 @@ function requireRemainingParamContainment(productParams, requestParams) {
460
453
  for (const [key, productValue] of Object.entries(productParams)) {
461
454
  if (HANDLED_CANONICAL_PARAM_KEYS.has(key) || productValue === void 0) continue;
462
455
  if (Array.isArray(productValue) && productValue.length === 0) continue;
463
- if (requestParams[key] === void 0) {
464
- if (OMITTABLE_DECLARATION_PARAMS.has(key)) continue;
465
- return {
466
- ok: false,
467
- bug_class: "directionality",
468
- detail: `Under-specified selector: product constrains params.${key}, but the request selector omits ${key}`
469
- };
470
- }
456
+ if (requestParams[key] === void 0) continue;
471
457
  const requestValue = requestParams[key];
472
458
  if (ARRAY_SUBSET_PARAM_KEYS.has(key)) {
473
459
  const subset = requireArraySubset(key, productValue, requestValue);
@@ -6,6 +6,7 @@
6
6
  * The canonical storyboard set lives in the AdCP compliance tarball
7
7
  * and is pulled into `compliance/cache/{version}/` via `npm run sync-schemas`.
8
8
  */
9
+ export { createStoryboardWebBotAuthFetch } from './web-bot-auth.mjs';
9
10
  export type { A2ATaskEnvelope, AgentEntry, Storyboard, StoryboardFixtureResolution, FixtureResolutionStrategy, FixtureMatchOperator, FixtureMatchClause, FixtureResolutionDeclaration, ProductFixtureResolutionDeclaration, PricingOptionFixtureResolutionDeclaration, FixtureResolutionStatus, FixtureResolutionRecord, FixtureResolutionAttempt, FixtureResolutionEvidence, FixtureResolutionCoverageGap, StoryboardInvariants, StoryboardInvariantsObject, StepInvariantsObject, StoryboardPhase, StoryboardStep, RateLimitTripSpec, StoryboardValidation, StoryboardValidationCheck, WebhookFilterSpec, WebhookRetryTriggerSpec, WebhookAssertionErrorCode, ContextOutput, ContextInput, ContextProvenanceEntry, ContextValueRejectedHint, ShapeDriftHint, MissingRequiredFieldHint, FormatMismatchHint, MonotonicViolationHint, ImpairmentCoherenceHint, ImpairmentCoherenceNotApplicableHint, StoryboardContext, StoryboardRunOptions, PrepareStoryboardFixturesOptions, TrustedMatchContextProviderEndpoint, TrustedMatchContextRegistrationContext, TrustedMatchContextRouterRunnerOptions, TrustedMatchPublisherAuthOperation, TrustedMatchPublisherCredentialState, TrustedMatchPublisherAuthTls, TrustedMatchPublisherAuthProbeConfiguration, TrustedMatchPublisherAuthRunner, ValidationResult, StoryboardStepPreview, StoryboardStepResult, StoryboardStepHint, StoryboardStepHintBase, StoryboardPhaseResult, StoryboardResult, AssertionResult, StrictValidationSummary, StrictValidationVerdict, UpstreamTrafficPayloadMatch, RunnerNotice, NoticeCode, NoticeSeverity, } from './types.mjs';
10
11
  export { WEBHOOK_IDEMPOTENCY_KEY_PATTERN } from './types.mjs';
11
12
  export { MCP_SESSION_PROBE_TASK } from './types.mjs';
@@ -6,6 +6,7 @@
6
6
  * The canonical storyboard set lives in the AdCP compliance tarball
7
7
  * and is pulled into `compliance/cache/{version}/` via `npm run sync-schemas`.
8
8
  */
9
+ export { createStoryboardWebBotAuthFetch } from './web-bot-auth';
9
10
  export type { A2ATaskEnvelope, AgentEntry, Storyboard, StoryboardFixtureResolution, FixtureResolutionStrategy, FixtureMatchOperator, FixtureMatchClause, FixtureResolutionDeclaration, ProductFixtureResolutionDeclaration, PricingOptionFixtureResolutionDeclaration, FixtureResolutionStatus, FixtureResolutionRecord, FixtureResolutionAttempt, FixtureResolutionEvidence, FixtureResolutionCoverageGap, StoryboardInvariants, StoryboardInvariantsObject, StepInvariantsObject, StoryboardPhase, StoryboardStep, RateLimitTripSpec, StoryboardValidation, StoryboardValidationCheck, WebhookFilterSpec, WebhookRetryTriggerSpec, WebhookAssertionErrorCode, ContextOutput, ContextInput, ContextProvenanceEntry, ContextValueRejectedHint, ShapeDriftHint, MissingRequiredFieldHint, FormatMismatchHint, MonotonicViolationHint, ImpairmentCoherenceHint, ImpairmentCoherenceNotApplicableHint, StoryboardContext, StoryboardRunOptions, PrepareStoryboardFixturesOptions, TrustedMatchContextProviderEndpoint, TrustedMatchContextRegistrationContext, TrustedMatchContextRouterRunnerOptions, TrustedMatchPublisherAuthOperation, TrustedMatchPublisherCredentialState, TrustedMatchPublisherAuthTls, TrustedMatchPublisherAuthProbeConfiguration, TrustedMatchPublisherAuthRunner, ValidationResult, StoryboardStepPreview, StoryboardStepResult, StoryboardStepHint, StoryboardStepHintBase, StoryboardPhaseResult, StoryboardResult, AssertionResult, StrictValidationSummary, StrictValidationVerdict, UpstreamTrafficPayloadMatch, RunnerNotice, NoticeCode, NoticeSeverity, } from './types';
10
11
  export { WEBHOOK_IDEMPOTENCY_KEY_PATTERN } from './types';
11
12
  export { MCP_SESSION_PROBE_TASK } from './types';
@@ -60,6 +60,7 @@ __export(storyboard_exports, {
60
60
  clearSandboxCache: () => import_sandbox_entities.clearSandboxCache,
61
61
  compareCollectionPairs: () => import_collection_selection.compareCollectionPairs,
62
62
  createRunnerVariables: () => import_context.createRunnerVariables,
63
+ createStoryboardWebBotAuthFetch: () => import_web_bot_auth.createStoryboardWebBotAuthFetch,
63
64
  createWebhookReceiver: () => import_webhook_receiver.createWebhookReceiver,
64
65
  describeStoryboardCapabilityGates: () => import_runner.describeStoryboardCapabilityGates,
65
66
  detectContextRejectionHints: () => import_rejection_hints.detectContextRejectionHints,
@@ -136,6 +137,7 @@ __export(storyboard_exports, {
136
137
  });
137
138
  module.exports = __toCommonJS(storyboard_exports);
138
139
  var import_default_invariants = require('./default-invariants.js');
140
+ var import_web_bot_auth = require('./web-bot-auth.js');
139
141
  var import_types = require('./types.js');
140
142
  var import_types2 = require('./types.js');
141
143
  var import_assertions = require('./assertions.js');
@@ -207,6 +209,7 @@ var import_creative_build_probe = require('./creative-build-probe.js');
207
209
  clearSandboxCache,
208
210
  compareCollectionPairs,
209
211
  createRunnerVariables,
212
+ createStoryboardWebBotAuthFetch,
210
213
  createWebhookReceiver,
211
214
  describeStoryboardCapabilityGates,
212
215
  detectContextRejectionHints,
@@ -1,5 +1,6 @@
1
1
  import { registerDefaultInvariants } from "./default-invariants.mjs";
2
2
  registerDefaultInvariants();
3
+ import { createStoryboardWebBotAuthFetch } from "./web-bot-auth.mjs";
3
4
  import { WEBHOOK_IDEMPOTENCY_KEY_PATTERN } from "./types.mjs";
4
5
  import { MCP_SESSION_PROBE_TASK } from "./types.mjs";
5
6
  import {
@@ -164,6 +165,7 @@ export {
164
165
  clearSandboxCache,
165
166
  compareCollectionPairs,
166
167
  createRunnerVariables,
168
+ createStoryboardWebBotAuthFetch,
167
169
  createWebhookReceiver,
168
170
  describeStoryboardCapabilityGates,
169
171
  detectContextRejectionHints,
@@ -96,6 +96,13 @@ function validateStoryboardShape(storyboard) {
96
96
  validateBranchSet(storyboard.id, phase);
97
97
  if (!phase.steps) continue;
98
98
  for (const step of phase.steps) {
99
+ if (step.enrich_request !== void 0 && (step.enrich_request !== true || !step.expect_error || step.negative_path !== "payload_well_formed")) {
100
+ throw new Error(
101
+ `[${storyboard.id}] ${step.id}: enrich_request requires expect_error: true and negative_path: payload_well_formed`
102
+ );
103
+ }
104
+ if (typeof step.auth === "object" && step.auth.type === "web_bot_auth" && (typeof step.auth.identity !== "string" || step.auth.identity.trim().length === 0))
105
+ throw new Error(`[${storyboard.id}] ${step.id}: web_bot_auth requires an identity name`);
99
106
  const rawStep = step;
100
107
  if (rawStep.task === void 0) {
101
108
  if (!Array.isArray(rawStep.validations) || rawStep.validations.length === 0) {
@@ -68,6 +68,13 @@ function validateStoryboardShape(storyboard) {
68
68
  validateBranchSet(storyboard.id, phase);
69
69
  if (!phase.steps) continue;
70
70
  for (const step of phase.steps) {
71
+ if (step.enrich_request !== void 0 && (step.enrich_request !== true || !step.expect_error || step.negative_path !== "payload_well_formed")) {
72
+ throw new Error(
73
+ `[${storyboard.id}] ${step.id}: enrich_request requires expect_error: true and negative_path: payload_well_formed`
74
+ );
75
+ }
76
+ if (typeof step.auth === "object" && step.auth.type === "web_bot_auth" && (typeof step.auth.identity !== "string" || step.auth.identity.trim().length === 0))
77
+ throw new Error(`[${storyboard.id}] ${step.id}: web_bot_auth requires an identity name`);
71
78
  const rawStep = step;
72
79
  if (rawStep.task === void 0) {
73
80
  if (!Array.isArray(rawStep.validations) || rawStep.validations.length === 0) {
@@ -248,12 +248,15 @@ const REQUEST_ENRICHERS = {
248
248
  budget: (typeof baseSample.budget === "number" ? baseSample.budget : void 0) ?? options.budget ?? Math.max(1e3, pricingOption?.min_spend_per_package ?? 1e3),
249
249
  pricing_option_id: fixturePricingOptionId ?? pricingOption?.pricing_option_id ?? context.pricing_option_id ?? "test-pricing"
250
250
  };
251
- const sentPricingOption = fixtureProductId === void 0 && fixturePricingOptionId === void 0 ? pricingOption : findPricingOption(context, firstPkg.product_id, firstPkg.pricing_option_id);
252
- if (baseSample.bid_price === void 0 && baseSample.bidding === void 0 && step.sample_request?.bidding === void 0 && sentPricingOption?.pricing_model === "cpm" && !(0, import_pricing_adapter.isFixedPricing)(sentPricingOption)) {
253
- const floor = Number(sentPricingOption.floor_price) || 5;
254
- firstPkg.bid_price = Math.round(floor * 1.5 * 100) / 100;
255
- }
256
251
  const additionalPkgs = samplePackages.slice(1).map((p) => (0, import_context.injectContext)({ ...p }, context));
252
+ const packages = [firstPkg, ...additionalPkgs];
253
+ for (const pkg of packages) {
254
+ const sentPricingOption = pkg === firstPkg && fixtureProductId === void 0 && fixturePricingOptionId === void 0 ? pricingOption : findPricingOption(context, pkg.product_id, pkg.pricing_option_id);
255
+ if (pkg.bid_price === void 0 && pkg.bidding === void 0 && step.sample_request?.bidding === void 0 && sentPricingOption?.pricing_model === "cpm" && !(0, import_pricing_adapter.isFixedPricing)(sentPricingOption)) {
256
+ const floor = Number(sentPricingOption.floor_price) || 5;
257
+ pkg.bid_price = Math.round(floor * 1.5 * 100) / 100;
258
+ }
259
+ }
257
260
  const fixture = step.sample_request !== void 0 ? (0, import_context.injectContext)({ ...step.sample_request }, context) : {};
258
261
  const fixtureBody = omitEnvelopeFields(fixture);
259
262
  const fixtureHasPackages = Array.isArray(fixture.packages) && fixture.packages.length > 0;
@@ -275,7 +278,7 @@ const REQUEST_ENRICHERS = {
275
278
  brand: (0, import_client.resolveBrand)(options),
276
279
  start_time: startTime,
277
280
  end_time: endTime,
278
- packages: [firstPkg, ...additionalPkgs]
281
+ packages
279
282
  };
280
283
  },
281
284
  update_media_buy(step, context, options) {
@@ -222,12 +222,15 @@ const REQUEST_ENRICHERS = {
222
222
  budget: (typeof baseSample.budget === "number" ? baseSample.budget : void 0) ?? options.budget ?? Math.max(1e3, pricingOption?.min_spend_per_package ?? 1e3),
223
223
  pricing_option_id: fixturePricingOptionId ?? pricingOption?.pricing_option_id ?? context.pricing_option_id ?? "test-pricing"
224
224
  };
225
- const sentPricingOption = fixtureProductId === void 0 && fixturePricingOptionId === void 0 ? pricingOption : findPricingOption(context, firstPkg.product_id, firstPkg.pricing_option_id);
226
- if (baseSample.bid_price === void 0 && baseSample.bidding === void 0 && step.sample_request?.bidding === void 0 && sentPricingOption?.pricing_model === "cpm" && !isFixedPricing(sentPricingOption)) {
227
- const floor = Number(sentPricingOption.floor_price) || 5;
228
- firstPkg.bid_price = Math.round(floor * 1.5 * 100) / 100;
229
- }
230
225
  const additionalPkgs = samplePackages.slice(1).map((p) => injectContext({ ...p }, context));
226
+ const packages = [firstPkg, ...additionalPkgs];
227
+ for (const pkg of packages) {
228
+ const sentPricingOption = pkg === firstPkg && fixtureProductId === void 0 && fixturePricingOptionId === void 0 ? pricingOption : findPricingOption(context, pkg.product_id, pkg.pricing_option_id);
229
+ if (pkg.bid_price === void 0 && pkg.bidding === void 0 && step.sample_request?.bidding === void 0 && sentPricingOption?.pricing_model === "cpm" && !isFixedPricing(sentPricingOption)) {
230
+ const floor = Number(sentPricingOption.floor_price) || 5;
231
+ pkg.bid_price = Math.round(floor * 1.5 * 100) / 100;
232
+ }
233
+ }
231
234
  const fixture = step.sample_request !== void 0 ? injectContext({ ...step.sample_request }, context) : {};
232
235
  const fixtureBody = omitEnvelopeFields(fixture);
233
236
  const fixtureHasPackages = Array.isArray(fixture.packages) && fixture.packages.length > 0;
@@ -249,7 +252,7 @@ const REQUEST_ENRICHERS = {
249
252
  brand: resolveBrand(options),
250
253
  start_time: startTime,
251
254
  end_time: endTime,
252
- packages: [firstPkg, ...additionalPkgs]
255
+ packages
253
256
  };
254
257
  },
255
258
  update_media_buy(step, context, options) {
@@ -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.3";
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
  /**