@adcp/sdk 16.0.0-beta.3 → 16.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/auth/oauth/diagnose.js +3 -11
- package/dist/lib/auth/oauth/diagnose.mjs +4 -12
- package/dist/lib/auth/oauth/diagnostics.d.mts +2 -1
- package/dist/lib/auth/oauth/diagnostics.d.ts +2 -1
- package/dist/lib/auth/oauth/diagnostics.js +8 -10
- package/dist/lib/auth/oauth/diagnostics.mjs +7 -10
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.mjs +7 -1
- package/dist/lib/reporting/consumer-runtime.js +2 -1
- package/dist/lib/reporting/consumer-runtime.mjs +2 -1
- package/dist/lib/reporting/ledger/handler.js +50 -11
- package/dist/lib/reporting/ledger/handler.mjs +50 -12
- package/dist/lib/reporting/ledger/index.d.mts +17 -14
- package/dist/lib/reporting/ledger/index.d.ts +17 -14
- package/dist/lib/reporting/ledger/index.js +32 -20
- package/dist/lib/reporting/ledger/index.mjs +21 -10
- package/dist/lib/reporting/ledger/offering-validation.d.mts +9 -0
- package/dist/lib/reporting/ledger/offering-validation.d.ts +9 -0
- package/dist/lib/reporting/{gcs/bucket-policy.js → ledger/offering-validation.js} +9 -8
- package/dist/lib/reporting/ledger/offering-validation.mjs +8 -0
- package/dist/lib/reporting/ledger/receipts.d.mts +48 -0
- package/dist/lib/reporting/ledger/receipts.d.ts +48 -0
- package/dist/lib/reporting/ledger/receipts.js +186 -0
- package/dist/lib/reporting/ledger/receipts.mjs +161 -0
- package/dist/lib/reporting/ledger/status-ingest.js +3 -3
- package/dist/lib/reporting/ledger/status-ingest.mjs +4 -5
- package/dist/lib/reporting/ledger/types.d.mts +43 -0
- package/dist/lib/reporting/ledger/types.d.ts +43 -0
- package/dist/lib/reporting/ledger/types.js +31 -2
- package/dist/lib/reporting/ledger/types.mjs +26 -1
- package/dist/lib/reporting/pagination.d.mts +6 -0
- package/dist/lib/reporting/pagination.d.ts +6 -0
- package/dist/lib/reporting/{gcs/errors.js → pagination.js} +12 -17
- package/dist/lib/reporting/pagination.mjs +12 -0
- package/dist/lib/reporting/reconciliation.d.mts +1 -0
- package/dist/lib/reporting/reconciliation.d.ts +1 -0
- package/dist/lib/reporting/reconciliation.js +3 -2
- package/dist/lib/reporting/reconciliation.mjs +3 -2
- package/dist/lib/reporting/service/index.d.mts +79 -153
- package/dist/lib/reporting/service/index.d.ts +79 -153
- package/dist/lib/reporting/service/index.js +34 -491
- package/dist/lib/reporting/service/index.mjs +36 -510
- package/dist/lib/reporting/service/scheduler-support.d.mts +43 -0
- package/dist/lib/reporting/service/scheduler-support.d.ts +43 -0
- package/dist/lib/reporting/service/scheduler-support.js +125 -0
- package/dist/lib/reporting/service/scheduler-support.mjs +96 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/signing/canonicalize.d.mts +4 -0
- package/dist/lib/signing/canonicalize.d.ts +4 -0
- package/dist/lib/signing/canonicalize.js +14 -8
- package/dist/lib/signing/canonicalize.mjs +14 -8
- package/dist/lib/signing/content-digest.d.mts +8 -0
- package/dist/lib/signing/content-digest.d.ts +8 -0
- package/dist/lib/signing/content-digest.js +11 -5
- package/dist/lib/signing/content-digest.mjs +10 -5
- package/dist/lib/signing/signer.js +9 -6
- package/dist/lib/signing/signer.mjs +10 -7
- package/dist/lib/signing/web-bot-auth.js +103 -37
- package/dist/lib/signing/web-bot-auth.mjs +108 -37
- package/dist/lib/testing/storyboard/junit.js +16 -3
- package/dist/lib/testing/storyboard/junit.mjs +16 -3
- package/dist/lib/testing/storyboard/request-signing/builder.js +10 -9
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +10 -9
- package/dist/lib/testing/storyboard/runner.js +94 -25
- package/dist/lib/testing/storyboard/runner.mjs +94 -25
- package/dist/lib/testing/storyboard/types.d.mts +6 -0
- package/dist/lib/testing/storyboard/types.d.ts +6 -0
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/schemas.generated.d.ts +907 -60
- package/dist/lib/types/schemas.generated.js +7 -7
- package/dist/lib/types/schemas.generated.mjs +7 -7
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +23 -5
- package/docs/guides/REPORTING-GCS-FENCE.md +3 -3
- package/docs/guides/REPORTING-GCS-MANAGED.md +4 -4
- package/docs/guides/REPORTING-LEDGER-CUTOVER.md +7 -7
- package/docs/guides/REPORTING-LEDGER.md +107 -51
- package/docs/guides/REPORTING-OPERATIONS.md +66 -5
- package/docs/guides/REPORTING-STABILITY.md +36 -32
- package/docs/llms.txt +4 -3
- package/docs/migration-14.x-rc-worksheet.md +4 -7
- package/docs/migration-reporting-storage-package.md +186 -0
- package/examples/README.md +1 -1
- package/package.json +13 -78
- package/dist/lib/reporting/azure/index.d.mts +0 -31
- package/dist/lib/reporting/azure/index.d.ts +0 -31
- package/dist/lib/reporting/azure/index.js +0 -266
- package/dist/lib/reporting/azure/index.mjs +0 -249
- package/dist/lib/reporting/bigquery/index.d.mts +0 -246
- package/dist/lib/reporting/bigquery/index.d.ts +0 -246
- package/dist/lib/reporting/bigquery/index.js +0 -633
- package/dist/lib/reporting/bigquery/index.mjs +0 -594
- package/dist/lib/reporting/gcs/adapter.d.mts +0 -38
- package/dist/lib/reporting/gcs/adapter.d.ts +0 -38
- package/dist/lib/reporting/gcs/adapter.js +0 -342
- package/dist/lib/reporting/gcs/adapter.mjs +0 -325
- package/dist/lib/reporting/gcs/bucket-policy.d.mts +0 -3
- package/dist/lib/reporting/gcs/bucket-policy.d.ts +0 -3
- package/dist/lib/reporting/gcs/bucket-policy.mjs +0 -7
- package/dist/lib/reporting/gcs/errors.d.mts +0 -11
- package/dist/lib/reporting/gcs/errors.d.ts +0 -11
- package/dist/lib/reporting/gcs/errors.mjs +0 -16
- package/dist/lib/reporting/gcs/fence.d.mts +0 -41
- package/dist/lib/reporting/gcs/fence.d.ts +0 -41
- package/dist/lib/reporting/gcs/fence.js +0 -250
- package/dist/lib/reporting/gcs/fence.mjs +0 -230
- package/dist/lib/reporting/gcs/index.d.mts +0 -18
- package/dist/lib/reporting/gcs/index.d.ts +0 -18
- package/dist/lib/reporting/gcs/index.js +0 -44
- package/dist/lib/reporting/gcs/index.mjs +0 -14
- package/dist/lib/reporting/gcs/io.d.mts +0 -7
- package/dist/lib/reporting/gcs/io.d.ts +0 -7
- package/dist/lib/reporting/gcs/io.js +0 -95
- package/dist/lib/reporting/gcs/io.mjs +0 -69
- package/dist/lib/reporting/gcs/reader.d.mts +0 -67
- package/dist/lib/reporting/gcs/reader.d.ts +0 -67
- package/dist/lib/reporting/gcs/reader.js +0 -193
- package/dist/lib/reporting/gcs/reader.mjs +0 -169
- package/dist/lib/reporting/gcs/row-provider.d.mts +0 -39
- package/dist/lib/reporting/gcs/row-provider.d.ts +0 -39
- package/dist/lib/reporting/gcs/row-provider.js +0 -225
- package/dist/lib/reporting/gcs/row-provider.mjs +0 -208
- package/dist/lib/reporting/gcs/validation.d.mts +0 -5
- package/dist/lib/reporting/gcs/validation.d.ts +0 -5
- package/dist/lib/reporting/gcs/validation.js +0 -49
- package/dist/lib/reporting/gcs/validation.mjs +0 -25
- package/dist/lib/reporting/ledger/change-feed.d.mts +0 -69
- package/dist/lib/reporting/ledger/change-feed.d.ts +0 -69
- package/dist/lib/reporting/ledger/change-feed.js +0 -107
- package/dist/lib/reporting/ledger/change-feed.mjs +0 -80
- package/dist/lib/reporting/ledger/managed-postgres.d.mts +0 -293
- package/dist/lib/reporting/ledger/managed-postgres.d.ts +0 -293
- package/dist/lib/reporting/ledger/managed-postgres.js +0 -2346
- package/dist/lib/reporting/ledger/managed-postgres.mjs +0 -2332
- package/dist/lib/reporting/ledger/managed-router.d.mts +0 -148
- package/dist/lib/reporting/ledger/managed-router.d.ts +0 -148
- package/dist/lib/reporting/ledger/managed-router.js +0 -280
- package/dist/lib/reporting/ledger/managed-router.mjs +0 -258
- package/dist/lib/reporting/ledger/managed.d.mts +0 -535
- package/dist/lib/reporting/ledger/managed.d.ts +0 -535
- package/dist/lib/reporting/ledger/managed.js +0 -761
- package/dist/lib/reporting/ledger/managed.mjs +0 -729
- package/dist/lib/reporting/ledger/notification-activity.d.mts +0 -332
- package/dist/lib/reporting/ledger/notification-activity.d.ts +0 -332
- package/dist/lib/reporting/ledger/notification-activity.js +0 -1366
- package/dist/lib/reporting/ledger/notification-activity.mjs +0 -1337
- package/dist/lib/reporting/ledger/object-writes.d.mts +0 -128
- package/dist/lib/reporting/ledger/object-writes.d.ts +0 -128
- package/dist/lib/reporting/ledger/object-writes.js +0 -147
- package/dist/lib/reporting/ledger/object-writes.mjs +0 -114
- package/dist/lib/reporting/ledger/postgres.d.mts +0 -689
- package/dist/lib/reporting/ledger/postgres.d.ts +0 -689
- package/dist/lib/reporting/ledger/postgres.js +0 -4462
- package/dist/lib/reporting/ledger/postgres.mjs +0 -4462
- package/dist/lib/reporting/ledger/row-storage-migration.d.mts +0 -59
- package/dist/lib/reporting/ledger/row-storage-migration.d.ts +0 -59
- package/dist/lib/reporting/ledger/row-storage-migration.js +0 -365
- package/dist/lib/reporting/ledger/row-storage-migration.mjs +0 -339
- package/dist/lib/reporting/ledger/row-storage-object.d.mts +0 -203
- package/dist/lib/reporting/ledger/row-storage-object.d.ts +0 -203
- package/dist/lib/reporting/ledger/row-storage-object.js +0 -379
- package/dist/lib/reporting/ledger/row-storage-object.mjs +0 -335
- package/dist/lib/reporting/ledger/row-storage-provider-io.d.mts +0 -44
- package/dist/lib/reporting/ledger/row-storage-provider-io.d.ts +0 -44
- package/dist/lib/reporting/ledger/row-storage-provider-io.js +0 -142
- package/dist/lib/reporting/ledger/row-storage-provider-io.mjs +0 -111
- package/dist/lib/reporting/ledger/row-storage.d.mts +0 -316
- package/dist/lib/reporting/ledger/row-storage.d.ts +0 -316
- package/dist/lib/reporting/ledger/row-storage.js +0 -812
- package/dist/lib/reporting/ledger/row-storage.mjs +0 -802
- package/dist/lib/reporting/s3/index.d.mts +0 -34
- package/dist/lib/reporting/s3/index.d.ts +0 -34
- package/dist/lib/reporting/s3/index.js +0 -347
- package/dist/lib/reporting/s3/index.mjs +0 -340
- package/dist/lib/reporting/service/maintenance.d.mts +0 -148
- package/dist/lib/reporting/service/maintenance.d.ts +0 -148
- package/dist/lib/reporting/service/maintenance.js +0 -185
- package/dist/lib/reporting/service/maintenance.mjs +0 -159
- 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
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
return
|
|
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
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
return
|
|
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 =
|
|
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)(
|
|
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)(
|
|
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")
|
|
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
|
-
|
|
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")
|
|
5778
|
+
if (typeof token === "string") pushHeaderToken(token);
|
|
5754
5779
|
}
|
|
5755
5780
|
const kit = options.test_kit?.auth;
|
|
5756
|
-
if (typeof kit?.api_key === "string")
|
|
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
|
-
|
|
5785
|
+
pushUserPass(`${basic.username}:${basic.password}`);
|
|
5761
5786
|
}
|
|
5762
|
-
if (typeof basic?.credentials === "string")
|
|
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())
|
|
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
|
-
|
|
6034
|
-
|
|
6035
|
-
|
|
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
|
-
|
|
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
|
|
6099
|
-
const
|
|
6100
|
-
|
|
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,
|
|
6179
|
+
return (0, import_client.createTestClient)(agentUrl, protocol, {
|
|
6111
6180
|
...options,
|
|
6112
|
-
protocol
|
|
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 =
|
|
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(
|
|
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(
|
|
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")
|
|
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
|
-
|
|
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")
|
|
5801
|
+
if (typeof token === "string") pushHeaderToken(token);
|
|
5777
5802
|
}
|
|
5778
5803
|
const kit = options.test_kit?.auth;
|
|
5779
|
-
if (typeof kit?.api_key === "string")
|
|
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
|
-
|
|
5808
|
+
pushUserPass(`${basic.username}:${basic.password}`);
|
|
5784
5809
|
}
|
|
5785
|
-
if (typeof basic?.credentials === "string")
|
|
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())
|
|
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
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
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
|
-
|
|
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
|
|
6122
|
-
const
|
|
6123
|
-
|
|
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,
|
|
6202
|
+
return createTestClient(agentUrl, protocol, {
|
|
6134
6203
|
...options,
|
|
6135
|
-
protocol
|
|
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.
|
|
200
|
+
export declare const RUNNER_CAPABILITY_VERSION = "16.0.0-beta.5";
|
|
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.
|
|
200
|
+
export declare const RUNNER_CAPABILITY_VERSION = "16.0.0-beta.5";
|
|
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
|
/**
|