@adcp/sdk 16.0.0-beta.3 → 16.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 (182) hide show
  1. package/dist/lib/auth/oauth/diagnose.js +3 -11
  2. package/dist/lib/auth/oauth/diagnose.mjs +4 -12
  3. package/dist/lib/auth/oauth/diagnostics.d.mts +2 -1
  4. package/dist/lib/auth/oauth/diagnostics.d.ts +2 -1
  5. package/dist/lib/auth/oauth/diagnostics.js +8 -10
  6. package/dist/lib/auth/oauth/diagnostics.mjs +7 -10
  7. package/dist/lib/index.d.mts +1 -1
  8. package/dist/lib/index.d.ts +1 -1
  9. package/dist/lib/index.js +2 -0
  10. package/dist/lib/index.mjs +7 -1
  11. package/dist/lib/reporting/consumer-runtime.js +2 -1
  12. package/dist/lib/reporting/consumer-runtime.mjs +2 -1
  13. package/dist/lib/reporting/ledger/handler.js +50 -11
  14. package/dist/lib/reporting/ledger/handler.mjs +50 -12
  15. package/dist/lib/reporting/ledger/index.d.mts +17 -14
  16. package/dist/lib/reporting/ledger/index.d.ts +17 -14
  17. package/dist/lib/reporting/ledger/index.js +32 -20
  18. package/dist/lib/reporting/ledger/index.mjs +21 -10
  19. package/dist/lib/reporting/ledger/offering-validation.d.mts +9 -0
  20. package/dist/lib/reporting/ledger/offering-validation.d.ts +9 -0
  21. package/dist/lib/reporting/{gcs/bucket-policy.js → ledger/offering-validation.js} +9 -8
  22. package/dist/lib/reporting/ledger/offering-validation.mjs +8 -0
  23. package/dist/lib/reporting/ledger/receipts.d.mts +48 -0
  24. package/dist/lib/reporting/ledger/receipts.d.ts +48 -0
  25. package/dist/lib/reporting/ledger/receipts.js +186 -0
  26. package/dist/lib/reporting/ledger/receipts.mjs +161 -0
  27. package/dist/lib/reporting/ledger/status-ingest.js +3 -3
  28. package/dist/lib/reporting/ledger/status-ingest.mjs +4 -5
  29. package/dist/lib/reporting/ledger/types.d.mts +43 -0
  30. package/dist/lib/reporting/ledger/types.d.ts +43 -0
  31. package/dist/lib/reporting/ledger/types.js +31 -2
  32. package/dist/lib/reporting/ledger/types.mjs +26 -1
  33. package/dist/lib/reporting/pagination.d.mts +6 -0
  34. package/dist/lib/reporting/pagination.d.ts +6 -0
  35. package/dist/lib/reporting/{gcs/errors.js → pagination.js} +12 -17
  36. package/dist/lib/reporting/pagination.mjs +12 -0
  37. package/dist/lib/reporting/reconciliation.d.mts +1 -0
  38. package/dist/lib/reporting/reconciliation.d.ts +1 -0
  39. package/dist/lib/reporting/reconciliation.js +3 -2
  40. package/dist/lib/reporting/reconciliation.mjs +3 -2
  41. package/dist/lib/reporting/service/index.d.mts +79 -153
  42. package/dist/lib/reporting/service/index.d.ts +79 -153
  43. package/dist/lib/reporting/service/index.js +34 -491
  44. package/dist/lib/reporting/service/index.mjs +36 -510
  45. package/dist/lib/reporting/service/scheduler-support.d.mts +43 -0
  46. package/dist/lib/reporting/service/scheduler-support.d.ts +43 -0
  47. package/dist/lib/reporting/service/scheduler-support.js +125 -0
  48. package/dist/lib/reporting/service/scheduler-support.mjs +96 -0
  49. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  50. package/dist/lib/signing/canonicalize.d.mts +4 -0
  51. package/dist/lib/signing/canonicalize.d.ts +4 -0
  52. package/dist/lib/signing/canonicalize.js +14 -8
  53. package/dist/lib/signing/canonicalize.mjs +14 -8
  54. package/dist/lib/signing/content-digest.d.mts +8 -0
  55. package/dist/lib/signing/content-digest.d.ts +8 -0
  56. package/dist/lib/signing/content-digest.js +11 -5
  57. package/dist/lib/signing/content-digest.mjs +10 -5
  58. package/dist/lib/signing/signer.js +9 -6
  59. package/dist/lib/signing/signer.mjs +10 -7
  60. package/dist/lib/signing/web-bot-auth.js +103 -37
  61. package/dist/lib/signing/web-bot-auth.mjs +108 -37
  62. package/dist/lib/testing/storyboard/junit.js +16 -3
  63. package/dist/lib/testing/storyboard/junit.mjs +16 -3
  64. package/dist/lib/testing/storyboard/request-signing/builder.js +10 -9
  65. package/dist/lib/testing/storyboard/request-signing/builder.mjs +10 -9
  66. package/dist/lib/testing/storyboard/runner.js +94 -25
  67. package/dist/lib/testing/storyboard/runner.mjs +94 -25
  68. package/dist/lib/testing/storyboard/types.d.mts +6 -0
  69. package/dist/lib/testing/storyboard/types.d.ts +6 -0
  70. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  71. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  72. package/dist/lib/version.d.mts +3 -3
  73. package/dist/lib/version.d.ts +3 -3
  74. package/dist/lib/version.js +3 -3
  75. package/dist/lib/version.mjs +3 -3
  76. package/docs/TYPE-SUMMARY.md +23 -5
  77. package/docs/guides/REPORTING-GCS-FENCE.md +3 -3
  78. package/docs/guides/REPORTING-GCS-MANAGED.md +4 -4
  79. package/docs/guides/REPORTING-LEDGER-CUTOVER.md +7 -7
  80. package/docs/guides/REPORTING-LEDGER.md +107 -51
  81. package/docs/guides/REPORTING-OPERATIONS.md +66 -5
  82. package/docs/guides/REPORTING-STABILITY.md +36 -32
  83. package/docs/llms.txt +4 -3
  84. package/docs/migration-14.x-rc-worksheet.md +4 -7
  85. package/docs/migration-reporting-storage-package.md +186 -0
  86. package/examples/README.md +1 -1
  87. package/package.json +13 -78
  88. package/dist/lib/reporting/azure/index.d.mts +0 -31
  89. package/dist/lib/reporting/azure/index.d.ts +0 -31
  90. package/dist/lib/reporting/azure/index.js +0 -266
  91. package/dist/lib/reporting/azure/index.mjs +0 -249
  92. package/dist/lib/reporting/bigquery/index.d.mts +0 -246
  93. package/dist/lib/reporting/bigquery/index.d.ts +0 -246
  94. package/dist/lib/reporting/bigquery/index.js +0 -633
  95. package/dist/lib/reporting/bigquery/index.mjs +0 -594
  96. package/dist/lib/reporting/gcs/adapter.d.mts +0 -38
  97. package/dist/lib/reporting/gcs/adapter.d.ts +0 -38
  98. package/dist/lib/reporting/gcs/adapter.js +0 -342
  99. package/dist/lib/reporting/gcs/adapter.mjs +0 -325
  100. package/dist/lib/reporting/gcs/bucket-policy.d.mts +0 -3
  101. package/dist/lib/reporting/gcs/bucket-policy.d.ts +0 -3
  102. package/dist/lib/reporting/gcs/bucket-policy.mjs +0 -7
  103. package/dist/lib/reporting/gcs/errors.d.mts +0 -11
  104. package/dist/lib/reporting/gcs/errors.d.ts +0 -11
  105. package/dist/lib/reporting/gcs/errors.mjs +0 -16
  106. package/dist/lib/reporting/gcs/fence.d.mts +0 -41
  107. package/dist/lib/reporting/gcs/fence.d.ts +0 -41
  108. package/dist/lib/reporting/gcs/fence.js +0 -250
  109. package/dist/lib/reporting/gcs/fence.mjs +0 -230
  110. package/dist/lib/reporting/gcs/index.d.mts +0 -18
  111. package/dist/lib/reporting/gcs/index.d.ts +0 -18
  112. package/dist/lib/reporting/gcs/index.js +0 -44
  113. package/dist/lib/reporting/gcs/index.mjs +0 -14
  114. package/dist/lib/reporting/gcs/io.d.mts +0 -7
  115. package/dist/lib/reporting/gcs/io.d.ts +0 -7
  116. package/dist/lib/reporting/gcs/io.js +0 -95
  117. package/dist/lib/reporting/gcs/io.mjs +0 -69
  118. package/dist/lib/reporting/gcs/reader.d.mts +0 -67
  119. package/dist/lib/reporting/gcs/reader.d.ts +0 -67
  120. package/dist/lib/reporting/gcs/reader.js +0 -193
  121. package/dist/lib/reporting/gcs/reader.mjs +0 -169
  122. package/dist/lib/reporting/gcs/row-provider.d.mts +0 -39
  123. package/dist/lib/reporting/gcs/row-provider.d.ts +0 -39
  124. package/dist/lib/reporting/gcs/row-provider.js +0 -225
  125. package/dist/lib/reporting/gcs/row-provider.mjs +0 -208
  126. package/dist/lib/reporting/gcs/validation.d.mts +0 -5
  127. package/dist/lib/reporting/gcs/validation.d.ts +0 -5
  128. package/dist/lib/reporting/gcs/validation.js +0 -49
  129. package/dist/lib/reporting/gcs/validation.mjs +0 -25
  130. package/dist/lib/reporting/ledger/change-feed.d.mts +0 -69
  131. package/dist/lib/reporting/ledger/change-feed.d.ts +0 -69
  132. package/dist/lib/reporting/ledger/change-feed.js +0 -107
  133. package/dist/lib/reporting/ledger/change-feed.mjs +0 -80
  134. package/dist/lib/reporting/ledger/managed-postgres.d.mts +0 -293
  135. package/dist/lib/reporting/ledger/managed-postgres.d.ts +0 -293
  136. package/dist/lib/reporting/ledger/managed-postgres.js +0 -2346
  137. package/dist/lib/reporting/ledger/managed-postgres.mjs +0 -2332
  138. package/dist/lib/reporting/ledger/managed-router.d.mts +0 -148
  139. package/dist/lib/reporting/ledger/managed-router.d.ts +0 -148
  140. package/dist/lib/reporting/ledger/managed-router.js +0 -280
  141. package/dist/lib/reporting/ledger/managed-router.mjs +0 -258
  142. package/dist/lib/reporting/ledger/managed.d.mts +0 -535
  143. package/dist/lib/reporting/ledger/managed.d.ts +0 -535
  144. package/dist/lib/reporting/ledger/managed.js +0 -761
  145. package/dist/lib/reporting/ledger/managed.mjs +0 -729
  146. package/dist/lib/reporting/ledger/notification-activity.d.mts +0 -332
  147. package/dist/lib/reporting/ledger/notification-activity.d.ts +0 -332
  148. package/dist/lib/reporting/ledger/notification-activity.js +0 -1366
  149. package/dist/lib/reporting/ledger/notification-activity.mjs +0 -1337
  150. package/dist/lib/reporting/ledger/object-writes.d.mts +0 -128
  151. package/dist/lib/reporting/ledger/object-writes.d.ts +0 -128
  152. package/dist/lib/reporting/ledger/object-writes.js +0 -147
  153. package/dist/lib/reporting/ledger/object-writes.mjs +0 -114
  154. package/dist/lib/reporting/ledger/postgres.d.mts +0 -689
  155. package/dist/lib/reporting/ledger/postgres.d.ts +0 -689
  156. package/dist/lib/reporting/ledger/postgres.js +0 -4462
  157. package/dist/lib/reporting/ledger/postgres.mjs +0 -4462
  158. package/dist/lib/reporting/ledger/row-storage-migration.d.mts +0 -59
  159. package/dist/lib/reporting/ledger/row-storage-migration.d.ts +0 -59
  160. package/dist/lib/reporting/ledger/row-storage-migration.js +0 -365
  161. package/dist/lib/reporting/ledger/row-storage-migration.mjs +0 -339
  162. package/dist/lib/reporting/ledger/row-storage-object.d.mts +0 -203
  163. package/dist/lib/reporting/ledger/row-storage-object.d.ts +0 -203
  164. package/dist/lib/reporting/ledger/row-storage-object.js +0 -379
  165. package/dist/lib/reporting/ledger/row-storage-object.mjs +0 -335
  166. package/dist/lib/reporting/ledger/row-storage-provider-io.d.mts +0 -44
  167. package/dist/lib/reporting/ledger/row-storage-provider-io.d.ts +0 -44
  168. package/dist/lib/reporting/ledger/row-storage-provider-io.js +0 -142
  169. package/dist/lib/reporting/ledger/row-storage-provider-io.mjs +0 -111
  170. package/dist/lib/reporting/ledger/row-storage.d.mts +0 -316
  171. package/dist/lib/reporting/ledger/row-storage.d.ts +0 -316
  172. package/dist/lib/reporting/ledger/row-storage.js +0 -812
  173. package/dist/lib/reporting/ledger/row-storage.mjs +0 -802
  174. package/dist/lib/reporting/s3/index.d.mts +0 -34
  175. package/dist/lib/reporting/s3/index.d.ts +0 -34
  176. package/dist/lib/reporting/s3/index.js +0 -347
  177. package/dist/lib/reporting/s3/index.mjs +0 -340
  178. package/dist/lib/reporting/service/maintenance.d.mts +0 -148
  179. package/dist/lib/reporting/service/maintenance.d.ts +0 -148
  180. package/dist/lib/reporting/service/maintenance.js +0 -185
  181. package/dist/lib/reporting/service/maintenance.mjs +0 -159
  182. package/examples/reliable-reporting-service/README.md +0 -169
@@ -24,6 +24,7 @@ __export(builder_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(builder_exports);
26
26
  var import_crypto = require("crypto");
27
+ var import_structured_headers = require("structured-headers");
27
28
  var import_crypto2 = require('../../../signing/crypto.js');
28
29
  var import_signing = require('../../../signing/index.js');
29
30
  var import_vector_loader = require('./vector-loader.js');
@@ -561,15 +562,15 @@ function refreshContentDigest(shaped, vector, shape) {
561
562
  });
562
563
  }
563
564
  function formatParamsWithOmissions(components, params, override) {
564
- const componentList = components.map((c) => `"${c}"`).join(" ");
565
- const pairs = [];
566
- pairs.push(`created=${params.created}`);
567
- if (!override.omitExpires) pairs.push(`expires=${params.expires}`);
568
- if (!override.omitNonce) pairs.push(`nonce="${params.nonce}"`);
569
- pairs.push(`keyid="${params.keyid}"`);
570
- pairs.push(`alg="${params.alg}"`);
571
- pairs.push(`tag="${params.tag}"`);
572
- return `(${componentList});${pairs.join(";")}`;
565
+ const omitted = /* @__PURE__ */ new Set([
566
+ ...override.omitExpires ? ["expires"] : [],
567
+ ...override.omitNonce ? ["nonce"] : []
568
+ ]);
569
+ const pairs = /* @__PURE__ */ new Map();
570
+ for (const key of ["created", "expires", "nonce", "keyid", "alg", "tag"]) {
571
+ if (!omitted.has(key) && params[key] !== void 0) pairs.set(key, params[key]);
572
+ }
573
+ return (0, import_structured_headers.serializeInnerList)([components.map((c) => [c, /* @__PURE__ */ new Map()]), pairs]);
573
574
  }
574
575
  function produceSignature(key, data) {
575
576
  return (0, import_crypto2.signWithPrivateJwk)(key.alg, key.privateKey, data);
@@ -1,4 +1,5 @@
1
1
  import { createHash, randomBytes, randomUUID } from "crypto";
2
+ import { serializeInnerList } from "structured-headers";
2
3
  import { signWithPrivateJwk } from "../../../signing/crypto.mjs";
3
4
  import {
4
5
  buildSignatureBase,
@@ -544,15 +545,15 @@ function refreshContentDigest(shaped, vector, shape) {
544
545
  });
545
546
  }
546
547
  function formatParamsWithOmissions(components, params, override) {
547
- const componentList = components.map((c) => `"${c}"`).join(" ");
548
- const pairs = [];
549
- pairs.push(`created=${params.created}`);
550
- if (!override.omitExpires) pairs.push(`expires=${params.expires}`);
551
- if (!override.omitNonce) pairs.push(`nonce="${params.nonce}"`);
552
- pairs.push(`keyid="${params.keyid}"`);
553
- pairs.push(`alg="${params.alg}"`);
554
- pairs.push(`tag="${params.tag}"`);
555
- return `(${componentList});${pairs.join(";")}`;
548
+ const omitted = /* @__PURE__ */ new Set([
549
+ ...override.omitExpires ? ["expires"] : [],
550
+ ...override.omitNonce ? ["nonce"] : []
551
+ ]);
552
+ const pairs = /* @__PURE__ */ new Map();
553
+ for (const key of ["created", "expires", "nonce", "keyid", "alg", "tag"]) {
554
+ if (!omitted.has(key) && params[key] !== void 0) pairs.set(key, params[key]);
555
+ }
556
+ return serializeInnerList([components.map((c) => [c, /* @__PURE__ */ new Map()]), pairs]);
556
557
  }
557
558
  function produceSignature(key, data) {
558
559
  return signWithPrivateJwk(key.alg, key.privateKey, data);
@@ -548,6 +548,7 @@ function applyBranchSetGrading(phases, phaseResults, branchSetByPhaseId, contrib
548
548
  step.skip = { reason: "peer_branch_taken", detail };
549
549
  delete step.error;
550
550
  delete step.adcp_error;
551
+ delete step.counts_toward_failure;
551
552
  skippedDelta++;
552
553
  regraded = true;
553
554
  }
@@ -2661,6 +2662,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2661
2662
  if (!phase.optional || (routingContext ? routedOauthPresent.has(assignment.instanceIndex) : presenceDetected)) {
2662
2663
  failedCount++;
2663
2664
  countedAsFailed.add(result2);
2665
+ } else if (!result2.validations.some((validation) => validation.check === "assertion" && !validation.passed)) {
2666
+ result2.counts_toward_failure = false;
2664
2667
  }
2665
2668
  if (step.stateful) {
2666
2669
  phaseStatefulCascades.set(phase.id, null);
@@ -3672,9 +3675,20 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
3672
3675
  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);
3673
3676
  const testsMissingAccount = effectiveStep.task === "create_media_buy" && (step.omit_account === true || governedRequest && !Object.prototype.hasOwnProperty.call(request, "account"));
3674
3677
  const testsSchemaInvalidRequest = step.expect_error === true && step.negative_path !== "payload_well_formed";
3678
+ 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));
3675
3679
  let rawProbeHeaders;
3680
+ let authOverrideClient;
3676
3681
  try {
3677
3682
  rawProbeHeaders = step.auth !== void 0 ? authHeadersForStep(step.auth, options) : void 0;
3683
+ if (useSdkAuthOverride) {
3684
+ if (rawProbeHeaders === void 0) throw new Error("Step auth override credentials were not resolved");
3685
+ authOverrideClient = createAuthOverrideClient(
3686
+ runState.agentUrl,
3687
+ options.protocol ?? "mcp",
3688
+ options,
3689
+ rawProbeHeaders
3690
+ );
3691
+ }
3678
3692
  } catch (err) {
3679
3693
  return {
3680
3694
  step_id: step.id,
@@ -3689,7 +3703,8 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
3689
3703
  extraction: { path: "none" }
3690
3704
  };
3691
3705
  }
3692
- const useRawProbe = rawProbeHeaders !== void 0;
3706
+ const useRawProbe = rawProbeHeaders !== void 0 && !useSdkAuthOverride;
3707
+ const stepClient = () => authOverrideClient ?? client;
3693
3708
  let taskResult;
3694
3709
  let stepResult;
3695
3710
  let caughtError;
@@ -3773,7 +3788,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
3773
3788
  const started = Date.now();
3774
3789
  try {
3775
3790
  if (options.protocol === "a2a") {
3776
- const probeClient = createA2AAuthOverrideClient(runState.agentUrl, options, rawProbeHeaders ?? {});
3791
+ const probeClient = createAuthOverrideClient(runState.agentUrl, "a2a", options, rawProbeHeaders ?? {});
3777
3792
  const captured = await (0, import_rawResponseCapture.withRawResponseCapture)(
3778
3793
  () => (0, import_client.runStep)(
3779
3794
  step.title,
@@ -3868,7 +3883,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
3868
3883
  let a2aCaptures;
3869
3884
  if (step.parallel_dispatch) {
3870
3885
  const started = Date.now();
3871
- crossResponses = await (0, import_parallel_dispatch.runParallelDispatches)(client, effectiveStep.task, request, {
3886
+ crossResponses = await (0, import_parallel_dispatch.runParallelDispatches)(stepClient(), effectiveStep.task, request, {
3872
3887
  spec: step.parallel_dispatch,
3873
3888
  keyMinter: import_idempotency.generateIdempotencyKey,
3874
3889
  correlationPrefix: step.id,
@@ -3905,7 +3920,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
3905
3920
  };
3906
3921
  }
3907
3922
  } else {
3908
- const dispatch = () => (0, import_task_map.executeStoryboardTask)(client, effectiveStep.task, request, {
3923
+ const dispatch = () => (0, import_task_map.executeStoryboardTask)(stepClient(), effectiveStep.task, request, {
3909
3924
  skipIdempotencyAutoInject: testsIdempotencyKeyOmission,
3910
3925
  skipAccountValidation: testsMissingAccount,
3911
3926
  skipRequestValidation: testsSchemaInvalidRequest,
@@ -5714,8 +5729,10 @@ function defaultAuthHeadersForRawProbe(options) {
5714
5729
  }
5715
5730
  function sessionProbeRoutingHeaders(options) {
5716
5731
  const headers = {};
5732
+ const runSecrets = runCredentialValues(options);
5717
5733
  for (const [name, value] of Object.entries(options.headers ?? {})) {
5718
5734
  if (!SESSION_PROBE_ROUTING_HEADERS.has(name.toLowerCase())) continue;
5735
+ if (runSecrets.some((secret) => value.includes(secret))) continue;
5719
5736
  try {
5720
5737
  assertSafeAuthHeaderPart(value, `options.headers.${name}`);
5721
5738
  } catch {
@@ -5740,35 +5757,62 @@ function setHeaderIfAbsent(headers, name, value, label) {
5740
5757
  }
5741
5758
  function runCredentialValues(options) {
5742
5759
  const values = [];
5760
+ const pushHeaderToken = (value) => {
5761
+ values.push(value, value.replace(/^[\t ]+|[\t ]+$/g, ""));
5762
+ };
5763
+ const pushUserPass = (userpass) => {
5764
+ values.push(userpass, Buffer.from(userpass).toString("base64"));
5765
+ const separator = userpass.indexOf(":");
5766
+ if (separator >= 0) values.push(userpass.slice(separator + 1));
5767
+ };
5743
5768
  const auth = options.auth;
5744
- if (auth?.type === "bearer" && typeof auth.token === "string") values.push(auth.token);
5769
+ if (auth?.type === "bearer" && typeof auth.token === "string") pushHeaderToken(auth.token);
5745
5770
  if (auth?.type === "basic") {
5746
5771
  if (typeof auth.password === "string") values.push(auth.password);
5747
5772
  if (typeof auth.username === "string" && typeof auth.password === "string") {
5748
- values.push(`${auth.username}:${auth.password}`);
5773
+ pushUserPass(`${auth.username}:${auth.password}`);
5749
5774
  }
5750
5775
  }
5751
5776
  if (auth?.type === "oauth" || auth?.type === "oauth_client_credentials") {
5752
5777
  const token = auth.tokens?.access_token;
5753
- if (typeof token === "string") values.push(token);
5778
+ if (typeof token === "string") pushHeaderToken(token);
5754
5779
  }
5755
5780
  const kit = options.test_kit?.auth;
5756
- if (typeof kit?.api_key === "string") values.push(kit.api_key);
5781
+ if (typeof kit?.api_key === "string") pushHeaderToken(kit.api_key);
5757
5782
  const basic = kit?.basic;
5758
5783
  if (typeof basic?.password === "string") values.push(basic.password);
5759
5784
  if (typeof basic?.username === "string" && typeof basic?.password === "string") {
5760
- values.push(`${basic.username}:${basic.password}`);
5785
+ pushUserPass(`${basic.username}:${basic.password}`);
5761
5786
  }
5762
- if (typeof basic?.credentials === "string") values.push(basic.credentials);
5787
+ if (typeof basic?.credentials === "string") pushUserPass(basic.credentials);
5763
5788
  for (const [name, value] of Object.entries(options.headers ?? {})) {
5764
5789
  if (typeof value !== "string" || value.length === 0) continue;
5765
- if (AUTH_OVERRIDE_HEADER_NAMES.has(name.toLowerCase()) || isCredentialHeaderName(name)) values.push(value);
5790
+ if (!AUTH_OVERRIDE_HEADER_NAMES.has(name.toLowerCase()) && !isCredentialHeaderName(name)) continue;
5791
+ pushHeaderToken(value);
5792
+ const scheme = /^(Bearer|Basic|Token|ApiKey)\s+(.+)$/i.exec(value.trim());
5793
+ if (scheme?.[1] !== void 0 && scheme[2] !== void 0) {
5794
+ const payload = scheme[2].trim();
5795
+ values.push(payload);
5796
+ if (/^Basic$/i.test(scheme[1]) && /^[A-Za-z0-9+/]+={0,2}$/.test(payload)) {
5797
+ const bytes = Buffer.from(payload, "base64");
5798
+ const decoded = bytes.toString("utf8");
5799
+ if (bytes.toString("base64").replace(/=+$/, "") === payload.replace(/=+$/, "") && Buffer.from(decoded, "utf8").equals(bytes) && !/[\x00-\x1f\x7f]/.test(decoded) && decoded.includes(":")) {
5800
+ pushUserPass(decoded);
5801
+ }
5802
+ }
5803
+ }
5766
5804
  }
5767
5805
  return values.filter((value) => value.trim().length > 0);
5768
5806
  }
5769
5807
  const SESSION_PROBE_ROUTING_HEADERS = /* @__PURE__ */ new Set([
5770
5808
  "x-tenant-id",
5771
5809
  "x-tenant",
5810
+ // AdCP's own tenant-routing header (`src/lib/testing/types.ts` names it as
5811
+ // the canonical example). Omitting it meant a run that routes on it had the
5812
+ // header classified as unknown: dropped from session probes, and — once the
5813
+ // isolated-client value test landed — silently strippable on a credential
5814
+ // collision, which reroutes the step to another tenant.
5815
+ "x-adcp-tenant",
5772
5816
  "x-account",
5773
5817
  "x-account-id",
5774
5818
  "x-routing-key",
@@ -5787,16 +5831,17 @@ function unroutableProbeHeader(options) {
5787
5831
  for (const [name, value] of Object.entries(options.headers ?? {})) {
5788
5832
  const lower = name.toLowerCase();
5789
5833
  if (SESSION_PROBE_ROUTING_HEADERS.has(lower)) {
5834
+ if (runSecrets.some((secret) => value.includes(secret))) return { name, reason: "credential_collision" };
5790
5835
  try {
5791
5836
  assertSafeAuthHeaderPart(value, `options.headers.${name}`);
5792
5837
  } catch {
5793
- return name;
5838
+ return { name, reason: "malformed" };
5794
5839
  }
5795
5840
  continue;
5796
5841
  }
5797
5842
  if (AUTH_OVERRIDE_HEADER_NAMES.has(lower)) continue;
5798
5843
  if (runSecrets.some((secret) => value.includes(secret))) continue;
5799
- return name;
5844
+ return { name, reason: "unknown" };
5800
5845
  }
5801
5846
  return void 0;
5802
5847
  }
@@ -6030,11 +6075,9 @@ function planMcpSessionSentinel(step, options, client, agentUrl) {
6030
6075
  }
6031
6076
  const unroutable = unroutableProbeHeader(options);
6032
6077
  if (unroutable !== void 0) {
6033
- return {
6034
- kind: "skip",
6035
- reason: "session_probe_ungradable",
6036
- detail: `The runner cannot classify run header "${escapeControlChars(unroutable.slice(0, 64))}", and both answers are unsafe \u2014 forwarding it could make the unauthenticated probe authenticated, dropping it could send the probe to a different tenant than the rest of this run. Nothing was graded, and this is a property of the run, not of the agent. Three ways forward: rename it to a recognised routing header (${[...SESSION_PROBE_ROUTING_HEADERS].join(", ")}); drop it from this run if the probe does not need it; or, if it carries a credential, move that into \`options.auth\` / \`test_kit.auth\` where the runner owns it.`
6037
- };
6078
+ const name = escapeControlChars(unroutable.name.slice(0, 64));
6079
+ const detail = unroutable.reason === "credential_collision" ? `Routing header "${name}" has a value containing a credential this run holds. Nothing was graded: forwarding it could authenticate the unauthenticated probe, and dropping it could change tenants. Choose a routing value or suite credential that does not collide.` : unroutable.reason === "malformed" ? `Routing header "${name}" contains invalid header characters. Nothing was graded because dropping it could change tenants. Correct this run header before retrying the probe.` : `The runner cannot classify run header "${name}", and both answers are unsafe \u2014 forwarding it could make the unauthenticated probe authenticated, dropping it could send the probe to a different tenant than the rest of this run. Nothing was graded, and this is a property of the run, not of the agent. Three ways forward: rename it to a recognised routing header (${[...SESSION_PROBE_ROUTING_HEADERS].join(", ")}); drop it from this run if the probe does not need it; or, if it carries a credential, move that into \`options.auth\` / \`test_kit.auth\` where the runner owns it.`;
6080
+ return { kind: "skip", reason: "session_probe_ungradable", detail };
6038
6081
  }
6039
6082
  const routing = sessionProbeRoutingHeaders(options);
6040
6083
  let headers;
@@ -6067,6 +6110,11 @@ function authHeadersForStep(directive, options) {
6067
6110
  if ("value" in directive && directive.value) {
6068
6111
  value = directive.value;
6069
6112
  } else if ("from_test_kit" in directive && directive.from_test_kit) {
6113
+ if (typeof directive.from_test_kit === "string") {
6114
+ throw new Error(
6115
+ "Named test-kit API-key paths are not supported; use from_test_kit: true only for the primary key."
6116
+ );
6117
+ }
6070
6118
  value = options.test_kit?.auth?.api_key;
6071
6119
  if (!value) {
6072
6120
  throw new Error(
@@ -6083,6 +6131,13 @@ function authHeadersForStep(directive, options) {
6083
6131
  }
6084
6132
  return { authorization: `Bearer ${value}` };
6085
6133
  }
6134
+ const HTTP_PROBE_ONLY_CHECKS = /* @__PURE__ */ new Set([
6135
+ "http_status",
6136
+ "http_status_in",
6137
+ "probe_passed",
6138
+ "on_401_require_header",
6139
+ "resource_equals_agent_url"
6140
+ ]);
6086
6141
  const AUTH_OVERRIDE_HEADER_NAMES = /* @__PURE__ */ new Set([
6087
6142
  "authorization",
6088
6143
  "proxy-authorization",
@@ -6091,14 +6146,28 @@ const AUTH_OVERRIDE_HEADER_NAMES = /* @__PURE__ */ new Set([
6091
6146
  "x-api-key"
6092
6147
  ]);
6093
6148
  const AUTH_OVERRIDE_CREDENTIAL_HEADER_RE = /(^|[-_])(auth(?:entication|orization)?|credentials?|secrets?|tokens?|keys?|api[-_]?keys?|access[-_]?keys?|private[-_]?keys?|password|passwd|signatures?|cert(?:ificate)?s?)([-_]|$)/i;
6149
+ const AUTH_OVERRIDE_COMPACT_CREDENTIAL_RE = /(auth(?:entication|orization)?|credentials?|secrets?|tokens?|passwords?|passwd|signatures?|certificates?|bearer|(?:api|access|private|session|auth|secret|client|app|master|signing|shared|subscription)keys?|(?:client|tls|ssl)certs?)$/i;
6094
6150
  function isCredentialHeaderName(name) {
6095
6151
  const normalized = name.toLowerCase();
6096
- return AUTH_OVERRIDE_HEADER_NAMES.has(normalized) || AUTH_OVERRIDE_CREDENTIAL_HEADER_RE.test(normalized);
6152
+ if (SESSION_PROBE_ROUTING_HEADERS.has(normalized)) return false;
6153
+ return AUTH_OVERRIDE_HEADER_NAMES.has(normalized) || AUTH_OVERRIDE_CREDENTIAL_HEADER_RE.test(normalized) || AUTH_OVERRIDE_COMPACT_CREDENTIAL_RE.test(normalized.replace(/[-_]/g, ""));
6097
6154
  }
6098
- function createA2AAuthOverrideClient(agentUrl, options, authHeaders) {
6099
- const headers = Object.fromEntries(
6100
- Object.entries(options.headers ?? {}).filter(([name]) => !isCredentialHeaderName(name))
6101
- );
6155
+ function createAuthOverrideClient(agentUrl, protocol, options, authHeaders) {
6156
+ const runSecrets = runCredentialValues(options);
6157
+ const headers = {};
6158
+ for (const [name, value] of Object.entries(options.headers ?? {})) {
6159
+ const isRouting = SESSION_PROBE_ROUTING_HEADERS.has(name.toLowerCase());
6160
+ if (!isRouting && isCredentialHeaderName(name)) continue;
6161
+ if (typeof value === "string" && runSecrets.some((secret) => value.includes(secret))) {
6162
+ if (isRouting) {
6163
+ throw new Error(
6164
+ `options.headers.${name} is a routing header but its value contains a credential this run holds; an isolated step cannot both route correctly and withhold the suite principal. Choose a routing value or suite credential that does not collide.`
6165
+ );
6166
+ }
6167
+ continue;
6168
+ }
6169
+ headers[name] = value;
6170
+ }
6102
6171
  let auth;
6103
6172
  for (const [name, value] of Object.entries(authHeaders)) {
6104
6173
  if (name.toLowerCase() === "authorization" && value.startsWith("Bearer ")) {
@@ -6107,9 +6176,9 @@ function createA2AAuthOverrideClient(agentUrl, options, authHeaders) {
6107
6176
  headers[name] = value;
6108
6177
  }
6109
6178
  }
6110
- return (0, import_client.createTestClient)(agentUrl, "a2a", {
6179
+ return (0, import_client.createTestClient)(agentUrl, protocol, {
6111
6180
  ...options,
6112
- protocol: "a2a",
6181
+ protocol,
6113
6182
  auth,
6114
6183
  test_kit: void 0,
6115
6184
  _client: void 0,
@@ -571,6 +571,7 @@ function applyBranchSetGrading(phases, phaseResults, branchSetByPhaseId, contrib
571
571
  step.skip = { reason: "peer_branch_taken", detail };
572
572
  delete step.error;
573
573
  delete step.adcp_error;
574
+ delete step.counts_toward_failure;
574
575
  skippedDelta++;
575
576
  regraded = true;
576
577
  }
@@ -2684,6 +2685,8 @@ async function executeStoryboardPass(agentUrls, storyboard, options, dispatchOff
2684
2685
  if (!phase.optional || (routingContext ? routedOauthPresent.has(assignment.instanceIndex) : presenceDetected)) {
2685
2686
  failedCount++;
2686
2687
  countedAsFailed.add(result2);
2688
+ } else if (!result2.validations.some((validation) => validation.check === "assertion" && !validation.passed)) {
2689
+ result2.counts_toward_failure = false;
2687
2690
  }
2688
2691
  if (step.stateful) {
2689
2692
  phaseStatefulCascades.set(phase.id, null);
@@ -3695,9 +3698,20 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
3695
3698
  const testsIdempotencyKeyOmission = (step.omit_idempotency_key === true || governedRequest && (typeof request.idempotency_key !== "string" || request.idempotency_key.length === 0)) && requestUsesIdempotency(effectiveStep.task, request);
3696
3699
  const testsMissingAccount = effectiveStep.task === "create_media_buy" && (step.omit_account === true || governedRequest && !Object.prototype.hasOwnProperty.call(request, "account"));
3697
3700
  const testsSchemaInvalidRequest = step.expect_error === true && step.negative_path !== "payload_well_formed";
3701
+ 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));
3698
3702
  let rawProbeHeaders;
3703
+ let authOverrideClient;
3699
3704
  try {
3700
3705
  rawProbeHeaders = step.auth !== void 0 ? authHeadersForStep(step.auth, options) : void 0;
3706
+ if (useSdkAuthOverride) {
3707
+ if (rawProbeHeaders === void 0) throw new Error("Step auth override credentials were not resolved");
3708
+ authOverrideClient = createAuthOverrideClient(
3709
+ runState.agentUrl,
3710
+ options.protocol ?? "mcp",
3711
+ options,
3712
+ rawProbeHeaders
3713
+ );
3714
+ }
3701
3715
  } catch (err) {
3702
3716
  return {
3703
3717
  step_id: step.id,
@@ -3712,7 +3726,8 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
3712
3726
  extraction: { path: "none" }
3713
3727
  };
3714
3728
  }
3715
- const useRawProbe = rawProbeHeaders !== void 0;
3729
+ const useRawProbe = rawProbeHeaders !== void 0 && !useSdkAuthOverride;
3730
+ const stepClient = () => authOverrideClient ?? client;
3716
3731
  let taskResult;
3717
3732
  let stepResult;
3718
3733
  let caughtError;
@@ -3796,7 +3811,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
3796
3811
  const started = Date.now();
3797
3812
  try {
3798
3813
  if (options.protocol === "a2a") {
3799
- const probeClient = createA2AAuthOverrideClient(runState.agentUrl, options, rawProbeHeaders ?? {});
3814
+ const probeClient = createAuthOverrideClient(runState.agentUrl, "a2a", options, rawProbeHeaders ?? {});
3800
3815
  const captured = await withRawResponseCapture(
3801
3816
  () => runStep(
3802
3817
  step.title,
@@ -3891,7 +3906,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
3891
3906
  let a2aCaptures;
3892
3907
  if (step.parallel_dispatch) {
3893
3908
  const started = Date.now();
3894
- crossResponses = await runParallelDispatches(client, effectiveStep.task, request, {
3909
+ crossResponses = await runParallelDispatches(stepClient(), effectiveStep.task, request, {
3895
3910
  spec: step.parallel_dispatch,
3896
3911
  keyMinter: generateIdempotencyKey,
3897
3912
  correlationPrefix: step.id,
@@ -3928,7 +3943,7 @@ async function executeStep(client, step, storyboardId, phaseId, context, allStep
3928
3943
  };
3929
3944
  }
3930
3945
  } else {
3931
- const dispatch = () => executeStoryboardTask(client, effectiveStep.task, request, {
3946
+ const dispatch = () => executeStoryboardTask(stepClient(), effectiveStep.task, request, {
3932
3947
  skipIdempotencyAutoInject: testsIdempotencyKeyOmission,
3933
3948
  skipAccountValidation: testsMissingAccount,
3934
3949
  skipRequestValidation: testsSchemaInvalidRequest,
@@ -5737,8 +5752,10 @@ function defaultAuthHeadersForRawProbe(options) {
5737
5752
  }
5738
5753
  function sessionProbeRoutingHeaders(options) {
5739
5754
  const headers = {};
5755
+ const runSecrets = runCredentialValues(options);
5740
5756
  for (const [name, value] of Object.entries(options.headers ?? {})) {
5741
5757
  if (!SESSION_PROBE_ROUTING_HEADERS.has(name.toLowerCase())) continue;
5758
+ if (runSecrets.some((secret) => value.includes(secret))) continue;
5742
5759
  try {
5743
5760
  assertSafeAuthHeaderPart(value, `options.headers.${name}`);
5744
5761
  } catch {
@@ -5763,35 +5780,62 @@ function setHeaderIfAbsent(headers, name, value, label) {
5763
5780
  }
5764
5781
  function runCredentialValues(options) {
5765
5782
  const values = [];
5783
+ const pushHeaderToken = (value) => {
5784
+ values.push(value, value.replace(/^[\t ]+|[\t ]+$/g, ""));
5785
+ };
5786
+ const pushUserPass = (userpass) => {
5787
+ values.push(userpass, Buffer.from(userpass).toString("base64"));
5788
+ const separator = userpass.indexOf(":");
5789
+ if (separator >= 0) values.push(userpass.slice(separator + 1));
5790
+ };
5766
5791
  const auth = options.auth;
5767
- if (auth?.type === "bearer" && typeof auth.token === "string") values.push(auth.token);
5792
+ if (auth?.type === "bearer" && typeof auth.token === "string") pushHeaderToken(auth.token);
5768
5793
  if (auth?.type === "basic") {
5769
5794
  if (typeof auth.password === "string") values.push(auth.password);
5770
5795
  if (typeof auth.username === "string" && typeof auth.password === "string") {
5771
- values.push(`${auth.username}:${auth.password}`);
5796
+ pushUserPass(`${auth.username}:${auth.password}`);
5772
5797
  }
5773
5798
  }
5774
5799
  if (auth?.type === "oauth" || auth?.type === "oauth_client_credentials") {
5775
5800
  const token = auth.tokens?.access_token;
5776
- if (typeof token === "string") values.push(token);
5801
+ if (typeof token === "string") pushHeaderToken(token);
5777
5802
  }
5778
5803
  const kit = options.test_kit?.auth;
5779
- if (typeof kit?.api_key === "string") values.push(kit.api_key);
5804
+ if (typeof kit?.api_key === "string") pushHeaderToken(kit.api_key);
5780
5805
  const basic = kit?.basic;
5781
5806
  if (typeof basic?.password === "string") values.push(basic.password);
5782
5807
  if (typeof basic?.username === "string" && typeof basic?.password === "string") {
5783
- values.push(`${basic.username}:${basic.password}`);
5808
+ pushUserPass(`${basic.username}:${basic.password}`);
5784
5809
  }
5785
- if (typeof basic?.credentials === "string") values.push(basic.credentials);
5810
+ if (typeof basic?.credentials === "string") pushUserPass(basic.credentials);
5786
5811
  for (const [name, value] of Object.entries(options.headers ?? {})) {
5787
5812
  if (typeof value !== "string" || value.length === 0) continue;
5788
- if (AUTH_OVERRIDE_HEADER_NAMES.has(name.toLowerCase()) || isCredentialHeaderName(name)) values.push(value);
5813
+ if (!AUTH_OVERRIDE_HEADER_NAMES.has(name.toLowerCase()) && !isCredentialHeaderName(name)) continue;
5814
+ pushHeaderToken(value);
5815
+ const scheme = /^(Bearer|Basic|Token|ApiKey)\s+(.+)$/i.exec(value.trim());
5816
+ if (scheme?.[1] !== void 0 && scheme[2] !== void 0) {
5817
+ const payload = scheme[2].trim();
5818
+ values.push(payload);
5819
+ if (/^Basic$/i.test(scheme[1]) && /^[A-Za-z0-9+/]+={0,2}$/.test(payload)) {
5820
+ const bytes = Buffer.from(payload, "base64");
5821
+ const decoded = bytes.toString("utf8");
5822
+ if (bytes.toString("base64").replace(/=+$/, "") === payload.replace(/=+$/, "") && Buffer.from(decoded, "utf8").equals(bytes) && !/[\x00-\x1f\x7f]/.test(decoded) && decoded.includes(":")) {
5823
+ pushUserPass(decoded);
5824
+ }
5825
+ }
5826
+ }
5789
5827
  }
5790
5828
  return values.filter((value) => value.trim().length > 0);
5791
5829
  }
5792
5830
  const SESSION_PROBE_ROUTING_HEADERS = /* @__PURE__ */ new Set([
5793
5831
  "x-tenant-id",
5794
5832
  "x-tenant",
5833
+ // AdCP's own tenant-routing header (`src/lib/testing/types.ts` names it as
5834
+ // the canonical example). Omitting it meant a run that routes on it had the
5835
+ // header classified as unknown: dropped from session probes, and — once the
5836
+ // isolated-client value test landed — silently strippable on a credential
5837
+ // collision, which reroutes the step to another tenant.
5838
+ "x-adcp-tenant",
5795
5839
  "x-account",
5796
5840
  "x-account-id",
5797
5841
  "x-routing-key",
@@ -5810,16 +5854,17 @@ function unroutableProbeHeader(options) {
5810
5854
  for (const [name, value] of Object.entries(options.headers ?? {})) {
5811
5855
  const lower = name.toLowerCase();
5812
5856
  if (SESSION_PROBE_ROUTING_HEADERS.has(lower)) {
5857
+ if (runSecrets.some((secret) => value.includes(secret))) return { name, reason: "credential_collision" };
5813
5858
  try {
5814
5859
  assertSafeAuthHeaderPart(value, `options.headers.${name}`);
5815
5860
  } catch {
5816
- return name;
5861
+ return { name, reason: "malformed" };
5817
5862
  }
5818
5863
  continue;
5819
5864
  }
5820
5865
  if (AUTH_OVERRIDE_HEADER_NAMES.has(lower)) continue;
5821
5866
  if (runSecrets.some((secret) => value.includes(secret))) continue;
5822
- return name;
5867
+ return { name, reason: "unknown" };
5823
5868
  }
5824
5869
  return void 0;
5825
5870
  }
@@ -6053,11 +6098,9 @@ function planMcpSessionSentinel(step, options, client, agentUrl) {
6053
6098
  }
6054
6099
  const unroutable = unroutableProbeHeader(options);
6055
6100
  if (unroutable !== void 0) {
6056
- return {
6057
- kind: "skip",
6058
- reason: "session_probe_ungradable",
6059
- detail: `The runner cannot classify run header "${escapeControlChars(unroutable.slice(0, 64))}", and both answers are unsafe \u2014 forwarding it could make the unauthenticated probe authenticated, dropping it could send the probe to a different tenant than the rest of this run. Nothing was graded, and this is a property of the run, not of the agent. Three ways forward: rename it to a recognised routing header (${[...SESSION_PROBE_ROUTING_HEADERS].join(", ")}); drop it from this run if the probe does not need it; or, if it carries a credential, move that into \`options.auth\` / \`test_kit.auth\` where the runner owns it.`
6060
- };
6101
+ const name = escapeControlChars(unroutable.name.slice(0, 64));
6102
+ const detail = unroutable.reason === "credential_collision" ? `Routing header "${name}" has a value containing a credential this run holds. Nothing was graded: forwarding it could authenticate the unauthenticated probe, and dropping it could change tenants. Choose a routing value or suite credential that does not collide.` : unroutable.reason === "malformed" ? `Routing header "${name}" contains invalid header characters. Nothing was graded because dropping it could change tenants. Correct this run header before retrying the probe.` : `The runner cannot classify run header "${name}", and both answers are unsafe \u2014 forwarding it could make the unauthenticated probe authenticated, dropping it could send the probe to a different tenant than the rest of this run. Nothing was graded, and this is a property of the run, not of the agent. Three ways forward: rename it to a recognised routing header (${[...SESSION_PROBE_ROUTING_HEADERS].join(", ")}); drop it from this run if the probe does not need it; or, if it carries a credential, move that into \`options.auth\` / \`test_kit.auth\` where the runner owns it.`;
6103
+ return { kind: "skip", reason: "session_probe_ungradable", detail };
6061
6104
  }
6062
6105
  const routing = sessionProbeRoutingHeaders(options);
6063
6106
  let headers;
@@ -6090,6 +6133,11 @@ function authHeadersForStep(directive, options) {
6090
6133
  if ("value" in directive && directive.value) {
6091
6134
  value = directive.value;
6092
6135
  } else if ("from_test_kit" in directive && directive.from_test_kit) {
6136
+ if (typeof directive.from_test_kit === "string") {
6137
+ throw new Error(
6138
+ "Named test-kit API-key paths are not supported; use from_test_kit: true only for the primary key."
6139
+ );
6140
+ }
6093
6141
  value = options.test_kit?.auth?.api_key;
6094
6142
  if (!value) {
6095
6143
  throw new Error(
@@ -6106,6 +6154,13 @@ function authHeadersForStep(directive, options) {
6106
6154
  }
6107
6155
  return { authorization: `Bearer ${value}` };
6108
6156
  }
6157
+ const HTTP_PROBE_ONLY_CHECKS = /* @__PURE__ */ new Set([
6158
+ "http_status",
6159
+ "http_status_in",
6160
+ "probe_passed",
6161
+ "on_401_require_header",
6162
+ "resource_equals_agent_url"
6163
+ ]);
6109
6164
  const AUTH_OVERRIDE_HEADER_NAMES = /* @__PURE__ */ new Set([
6110
6165
  "authorization",
6111
6166
  "proxy-authorization",
@@ -6114,14 +6169,28 @@ const AUTH_OVERRIDE_HEADER_NAMES = /* @__PURE__ */ new Set([
6114
6169
  "x-api-key"
6115
6170
  ]);
6116
6171
  const AUTH_OVERRIDE_CREDENTIAL_HEADER_RE = /(^|[-_])(auth(?:entication|orization)?|credentials?|secrets?|tokens?|keys?|api[-_]?keys?|access[-_]?keys?|private[-_]?keys?|password|passwd|signatures?|cert(?:ificate)?s?)([-_]|$)/i;
6172
+ const AUTH_OVERRIDE_COMPACT_CREDENTIAL_RE = /(auth(?:entication|orization)?|credentials?|secrets?|tokens?|passwords?|passwd|signatures?|certificates?|bearer|(?:api|access|private|session|auth|secret|client|app|master|signing|shared|subscription)keys?|(?:client|tls|ssl)certs?)$/i;
6117
6173
  function isCredentialHeaderName(name) {
6118
6174
  const normalized = name.toLowerCase();
6119
- return AUTH_OVERRIDE_HEADER_NAMES.has(normalized) || AUTH_OVERRIDE_CREDENTIAL_HEADER_RE.test(normalized);
6175
+ if (SESSION_PROBE_ROUTING_HEADERS.has(normalized)) return false;
6176
+ return AUTH_OVERRIDE_HEADER_NAMES.has(normalized) || AUTH_OVERRIDE_CREDENTIAL_HEADER_RE.test(normalized) || AUTH_OVERRIDE_COMPACT_CREDENTIAL_RE.test(normalized.replace(/[-_]/g, ""));
6120
6177
  }
6121
- function createA2AAuthOverrideClient(agentUrl, options, authHeaders) {
6122
- const headers = Object.fromEntries(
6123
- Object.entries(options.headers ?? {}).filter(([name]) => !isCredentialHeaderName(name))
6124
- );
6178
+ function createAuthOverrideClient(agentUrl, protocol, options, authHeaders) {
6179
+ const runSecrets = runCredentialValues(options);
6180
+ const headers = {};
6181
+ for (const [name, value] of Object.entries(options.headers ?? {})) {
6182
+ const isRouting = SESSION_PROBE_ROUTING_HEADERS.has(name.toLowerCase());
6183
+ if (!isRouting && isCredentialHeaderName(name)) continue;
6184
+ if (typeof value === "string" && runSecrets.some((secret) => value.includes(secret))) {
6185
+ if (isRouting) {
6186
+ throw new Error(
6187
+ `options.headers.${name} is a routing header but its value contains a credential this run holds; an isolated step cannot both route correctly and withhold the suite principal. Choose a routing value or suite credential that does not collide.`
6188
+ );
6189
+ }
6190
+ continue;
6191
+ }
6192
+ headers[name] = value;
6193
+ }
6125
6194
  let auth;
6126
6195
  for (const [name, value] of Object.entries(authHeaders)) {
6127
6196
  if (name.toLowerCase() === "authorization" && value.startsWith("Bearer ")) {
@@ -6130,9 +6199,9 @@ function createA2AAuthOverrideClient(agentUrl, options, authHeaders) {
6130
6199
  headers[name] = value;
6131
6200
  }
6132
6201
  }
6133
- return createTestClient(agentUrl, "a2a", {
6202
+ return createTestClient(agentUrl, protocol, {
6134
6203
  ...options,
6135
- protocol: "a2a",
6204
+ protocol,
6136
6205
  auth,
6137
6206
  test_kit: void 0,
6138
6207
  _client: void 0,
@@ -2395,6 +2395,12 @@ export interface StoryboardStepResult {
2395
2395
  title: string;
2396
2396
  task: string;
2397
2397
  passed: boolean;
2398
+ /**
2399
+ * False when a failed step is diagnostic only and does not count toward
2400
+ * the storyboard verdict (for example, an optional discovery phase).
2401
+ * Absent on ordinary failures, including mandatory OAuth and invariant checks.
2402
+ */
2403
+ counts_toward_failure?: boolean;
2398
2404
  /** True when the step was not executed */
2399
2405
  skipped?: boolean;
2400
2406
  /**
@@ -2395,6 +2395,12 @@ export interface StoryboardStepResult {
2395
2395
  title: string;
2396
2396
  task: string;
2397
2397
  passed: boolean;
2398
+ /**
2399
+ * False when a failed step is diagnostic only and does not count toward
2400
+ * the storyboard verdict (for example, an optional discovery phase).
2401
+ * Absent on ordinary failures, including mandatory OAuth and invariant checks.
2402
+ */
2403
+ counts_toward_failure?: boolean;
2398
2404
  /** True when the step was not executed */
2399
2405
  skipped?: boolean;
2400
2406
  /**
@@ -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 = "16.0.0-beta.3";
200
+ export declare const RUNNER_CAPABILITY_VERSION = "16.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 = "16.0.0-beta.3";
200
+ export declare const RUNNER_CAPABILITY_VERSION = "16.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
  /**