@adcp/sdk 14.0.0-beta.11 → 14.0.0-beta.13
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/bin/adcp-storyboard-sandbox.js +16 -0
- package/bin/adcp.js +28 -30
- package/dist/lib/index.d.mts +3 -3
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +3 -1
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/schemas/index.d.mts +385 -1
- package/dist/lib/schemas/index.d.ts +385 -1
- package/dist/lib/schemas/index.d.ts.map +1 -1
- package/dist/lib/schemas/index.js +13 -0
- package/dist/lib/schemas/index.js.map +1 -1
- package/dist/lib/schemas/index.mjs +11 -0
- package/dist/lib/schemas/index.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +2 -2
- package/dist/lib/server/create-adcp-server.d.ts +2 -2
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +6 -1
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +6 -1
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.d.mts +3 -3
- package/dist/lib/server/decisioning/index.d.ts +3 -3
- package/dist/lib/server/decisioning/index.d.ts.map +1 -1
- package/dist/lib/server/decisioning/index.js.map +1 -1
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.mts +24 -17
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +24 -17
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +71 -42
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +75 -43
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.mts +15 -21
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts +15 -21
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +100 -30
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +100 -30
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.d.mts +30 -16
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts +30 -16
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.js +40 -20
- package/dist/lib/server/decisioning/runtime/task-registry.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/task-registry.mjs +38 -19
- package/dist/lib/server/decisioning/runtime/task-registry.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.d.mts +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.d.ts +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.js +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/to-context.mjs +2 -2
- package/dist/lib/server/decisioning/runtime/to-context.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.mts +3 -2
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts +3 -2
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative-ad-server.js.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative.d.mts +10 -10
- package/dist/lib/server/decisioning/specialisms/creative.d.ts +10 -10
- package/dist/lib/server/decisioning/specialisms/creative.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/creative.js.map +1 -1
- package/dist/lib/server/index.d.mts +1 -1
- package/dist/lib/server/index.d.ts +1 -1
- package/dist/lib/server/index.d.ts.map +1 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/index.mjs.map +1 -1
- package/dist/lib/signing/agent-context.d.mts +1 -0
- package/dist/lib/signing/agent-context.d.ts +1 -0
- package/dist/lib/signing/agent-context.d.ts.map +1 -1
- package/dist/lib/signing/agent-context.js +37 -2
- package/dist/lib/signing/agent-context.js.map +1 -1
- package/dist/lib/signing/agent-context.mjs +38 -3
- package/dist/lib/signing/agent-context.mjs.map +1 -1
- package/dist/lib/signing/agent-fetch.d.mts +1 -2
- package/dist/lib/signing/agent-fetch.d.ts +1 -2
- package/dist/lib/signing/agent-fetch.d.ts.map +1 -1
- package/dist/lib/signing/agent-fetch.js +2 -0
- package/dist/lib/signing/agent-fetch.js.map +1 -1
- package/dist/lib/signing/agent-fetch.mjs +2 -0
- package/dist/lib/signing/agent-fetch.mjs.map +1 -1
- package/dist/lib/signing/agent-resolver/etld.js.map +1 -1
- package/dist/lib/signing/agent-resolver/etld.mjs.map +1 -1
- package/dist/lib/testing/client.d.mts +6 -0
- package/dist/lib/testing/client.d.ts +6 -0
- package/dist/lib/testing/client.d.ts.map +1 -1
- package/dist/lib/testing/client.js +76 -4
- package/dist/lib/testing/client.js.map +1 -1
- package/dist/lib/testing/client.mjs +75 -4
- package/dist/lib/testing/client.mjs.map +1 -1
- package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
- package/dist/lib/testing/compliance/comply.js +6 -0
- package/dist/lib/testing/compliance/comply.js.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +7 -1
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.js +11 -2
- package/dist/lib/testing/storyboard/default-invariants.js.map +1 -1
- package/dist/lib/testing/storyboard/default-invariants.mjs +11 -2
- package/dist/lib/testing/storyboard/default-invariants.mjs.map +1 -1
- package/dist/lib/testing/storyboard/index.d.mts +1 -1
- package/dist/lib/testing/storyboard/index.d.ts +1 -1
- package/dist/lib/testing/storyboard/index.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/index.js.map +1 -1
- package/dist/lib/testing/storyboard/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/loader.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/loader.js +14 -0
- package/dist/lib/testing/storyboard/loader.js.map +1 -1
- package/dist/lib/testing/storyboard/loader.mjs +14 -0
- package/dist/lib/testing/storyboard/loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/phase-condition.d.mts +41 -0
- package/dist/lib/testing/storyboard/phase-condition.d.ts +42 -0
- package/dist/lib/testing/storyboard/phase-condition.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/phase-condition.js +215 -0
- package/dist/lib/testing/storyboard/phase-condition.js.map +1 -0
- package/dist/lib/testing/storyboard/phase-condition.mjs +189 -0
- package/dist/lib/testing/storyboard/phase-condition.mjs.map +1 -0
- package/dist/lib/testing/storyboard/request-builder.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.js +15 -2
- package/dist/lib/testing/storyboard/request-builder.js.map +1 -1
- package/dist/lib/testing/storyboard/request-builder.mjs +15 -2
- package/dist/lib/testing/storyboard/request-builder.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.d.mts +15 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.d.ts +16 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.d.ts.map +1 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.js +106 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.js.map +1 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.mjs +82 -0
- package/dist/lib/testing/storyboard/request-signing/functional-dispatch.mjs.map +1 -0
- package/dist/lib/testing/storyboard/request-signing/test-kit.d.mts +15 -0
- package/dist/lib/testing/storyboard/request-signing/test-kit.d.ts +15 -0
- package/dist/lib/testing/storyboard/request-signing/test-kit.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/test-kit.js +58 -0
- package/dist/lib/testing/storyboard/request-signing/test-kit.js.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs +58 -0
- package/dist/lib/testing/storyboard/request-signing/test-kit.mjs.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.d.mts +2 -0
- package/dist/lib/testing/storyboard/request-signing/vector-loader.d.ts +2 -0
- package/dist/lib/testing/storyboard/request-signing/vector-loader.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.js +7 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.js.map +1 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +6 -1
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs.map +1 -1
- package/dist/lib/testing/storyboard/runner.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/runner.js +67 -24
- package/dist/lib/testing/storyboard/runner.js.map +1 -1
- package/dist/lib/testing/storyboard/runner.mjs +67 -24
- package/dist/lib/testing/storyboard/runner.mjs.map +1 -1
- package/dist/lib/testing/storyboard/task-map.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/task-map.js +6 -2
- package/dist/lib/testing/storyboard/task-map.js.map +1 -1
- package/dist/lib/testing/storyboard/task-map.mjs +6 -2
- package/dist/lib/testing/storyboard/task-map.mjs.map +1 -1
- package/dist/lib/testing/storyboard/types.d.mts +5 -4
- package/dist/lib/testing/storyboard/types.d.ts +5 -4
- package/dist/lib/testing/storyboard/types.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/types.js.map +1 -1
- package/dist/lib/testing/storyboard/types.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.js +60 -4
- package/dist/lib/testing/storyboard/webhook-assertions.js.map +1 -1
- package/dist/lib/testing/storyboard/webhook-assertions.mjs +60 -4
- package/dist/lib/testing/storyboard/webhook-assertions.mjs.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.d.mts +15 -0
- package/dist/lib/testing/storyboard/webhook-receiver.d.ts +15 -0
- package/dist/lib/testing/storyboard/webhook-receiver.d.ts.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.js +57 -6
- package/dist/lib/testing/storyboard/webhook-receiver.js.map +1 -1
- package/dist/lib/testing/storyboard/webhook-receiver.mjs +57 -6
- package/dist/lib/testing/storyboard/webhook-receiver.mjs.map +1 -1
- package/dist/lib/testing/types.d.mts +12 -0
- package/dist/lib/testing/types.d.ts +12 -0
- package/dist/lib/testing/types.d.ts.map +1 -1
- package/dist/lib/testing/types.js.map +1 -1
- package/dist/lib/types/comply-test-controller.d.ts +1 -14
- package/dist/lib/types/core.generated.d.mts +6 -3
- package/dist/lib/types/core.generated.d.ts +6 -3
- package/dist/lib/types/core.generated.d.ts.map +1 -1
- package/dist/lib/types/core.generated.js.map +1 -1
- package/dist/lib/types/get-products.d.ts +1 -14
- package/dist/lib/types/index.d.mts +1 -1
- package/dist/lib/types/index.d.ts +1 -1
- package/dist/lib/types/index.d.ts.map +1 -1
- package/dist/lib/types/index.js.map +1 -1
- package/dist/lib/types/index.mjs.map +1 -1
- package/dist/lib/types/list-transformers.d.ts +9 -5
- package/dist/lib/types/schemas.generated.d.ts +23 -352
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +7 -4
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +6 -4
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/server-payload-aliases.d.mts +2 -1
- package/dist/lib/types/server-payload-aliases.d.ts +2 -1
- package/dist/lib/types/server-payload-aliases.d.ts.map +1 -1
- package/dist/lib/types/server-payload-aliases.js.map +1 -1
- package/dist/lib/types/tools.generated.d.mts +6 -3
- package/dist/lib/types/tools.generated.d.ts +6 -3
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/types/tools.generated.js.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.d.mts +5 -1
- package/dist/lib/utils/build-creative-return-builders.d.ts +5 -1
- package/dist/lib/utils/build-creative-return-builders.d.ts.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.js +9 -3
- package/dist/lib/utils/build-creative-return-builders.js.map +1 -1
- package/dist/lib/utils/build-creative-return-builders.mjs +7 -2
- package/dist/lib/utils/build-creative-return-builders.mjs.map +1 -1
- package/dist/lib/utils/response-unwrapper.js +1 -1
- package/dist/lib/utils/response-unwrapper.js.map +1 -1
- package/dist/lib/utils/response-unwrapper.mjs +1 -1
- package/dist/lib/utils/response-unwrapper.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.d.ts.map +1 -1
- package/dist/lib/validation/schema-loader.js +16 -7
- package/dist/lib/validation/schema-loader.js.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +16 -7
- package/dist/lib/validation/schema-loader.mjs.map +1 -1
- 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.js.map +1 -1
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/version.mjs.map +1 -1
- package/docs/llms.txt +2 -2
- package/docs/migration-5.x-to-6.x.md +3 -2
- package/docs/migration-task-registry-scoping.md +61 -0
- package/examples/hello_seller_adapter_guaranteed.ts +1 -1
- package/package.json +5 -5
- package/skills/build-decisioning-creative-template/SKILL.md +2 -2
- package/skills/build-decisioning-platform/SKILL.md +4 -2
- package/skills/build-decisioning-platform/advanced/REFERENCE.md +7 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/storyboard/default-invariants.ts"],"sourcesContent":["/**\n * Default assertion registrations for invariant ids that upstream storyboards\n * reference but that every SDK consumer would otherwise have to implement\n * themselves. Importing this module side-registers the ids below, so\n * `resolveAssertions` doesn't throw on fresh `@adcp/sdk` installs.\n *\n * The implementations aim for the spec's stated intent, not byte-perfect\n * fidelity with the upstream reference. Consumers can override a default by\n * calling `registerAssertion(spec, { override: true })` with a stricter\n * implementation of their own.\n *\n * Registered ids:\n * - `idempotency.conflict_no_payload_leak` — when a mutating step returns\n * `IDEMPOTENCY_CONFLICT`, the error envelope must carry only allowlisted\n * keys. Any other top-level property is flagged as a potential payload\n * leak (stolen-key read oracle).\n * - `context.no_secret_echo` — response bodies (not just `.context`) MUST\n * NOT contain bearer tokens, API keys, auth header values, or any leaf\n * string extracted from the caller-supplied `auth` union. Walks the\n * whole body, matches on suspect property names at any depth, and\n * catches bearer-token literals via regex.\n * - `governance.denial_blocks_mutation` — once a plan is denied by a\n * governance signal (GOVERNANCE_DENIED, CAMPAIGN_SUSPENDED, etc., or\n * `check_governance` returning `status: \"denied\"`), no subsequent step\n * in the run may acquire a resource for that plan. Plan-scoped via\n * `plan_id`; runs without a denial signal are a silent pass.\n * - `status.monotonic` — across the steps of a run, no observed resource's\n * `status` (or creative `approval_status`) may transition along an edge\n * that is not in the spec-published lifecycle graph for its resource\n * type. Catches regressions like `active → pending_creatives` that\n * per-step validations miss. Scoped by `(resource_type, resource_id)`\n * so unrelated resources don't interfere. Tables below cite the spec\n * enum schemas in `static/schemas/source/enums/*-status.json`.\n * - `impairment.coherence` — cross-resource invariant: every entry in\n * `media_buy.impairments[]` MUST reference a resource the seller has\n * reported in an offline state (forward); any resource the run\n * transitioned to an offline state AND that the buy references MUST\n * appear in `impairments[]` while the buy is non-terminal (inverse);\n * `health == \"impaired\"` iff `impairments[]` is non-empty. See\n * adcontextprotocol/adcp#2859 for the originating spec issue.\n */\n\nimport { ADCP_VERSION } from '../../version';\nimport { CONFLICT_ADCP_ERROR_ALLOWLIST } from '../../server/envelope-allowlist';\nimport { STANDARD_ERROR_CODES } from '../../types/error-codes';\nimport {\n CREATIVE_ASSET_TRANSITIONS as CREATIVE_ASSET_TRANSITIONS_TYPED,\n MEDIA_BUY_TRANSITIONS as MEDIA_BUY_TRANSITIONS_TYPED,\n} from '../../server/state-machine';\nimport { registerAssertion } from './assertions';\n\n// Register only once per process. `registerAssertion` throws on duplicates —\n// consumers who import `@adcp/sdk/testing` multiple times would hit that.\nconst REGISTERED = new Set<string>();\n\nfunction registerOnce(id: string, spec: Parameters<typeof registerAssertion>[0]): void {\n if (REGISTERED.has(id)) return;\n REGISTERED.add(id);\n registerAssertion(spec);\n}\n\n/**\n * Register the default invariant assertions into the shared registry.\n *\n * Idempotent (guarded by `REGISTERED`), so the storyboard runner and the\n * compliance harness can both call it. Invoked explicitly by those entry\n * points rather than through a bare `import './default-invariants'` for side\n * effect: a side-effect-only import is fragile — ESM extension rewriting and\n * bundler tree-shaking can silently drop it, leaving the assertion registry\n * empty and `resolveAssertions` throwing.\n */\nexport function registerDefaultInvariants(): void {\n registerOnce('idempotency.conflict_no_payload_leak', {\n id: 'idempotency.conflict_no_payload_leak',\n default: true,\n description:\n 'IDEMPOTENCY_CONFLICT errors MUST NOT echo the prior request payload or response (stolen-key read oracle).',\n onStep: (_ctx, stepResult) => {\n const err = extractAdcpError(stepResult);\n if (!err) return [];\n if (err.code !== 'IDEMPOTENCY_CONFLICT') return [];\n\n const description = 'IDEMPOTENCY_CONFLICT error redacts prior payload';\n const leaked: string[] = [];\n for (const key of Object.keys(err.details)) {\n if (!CONFLICT_ADCP_ERROR_ALLOWLIST.has(key)) leaked.push(key);\n }\n const expectedRecovery = STANDARD_ERROR_CODES.IDEMPOTENCY_CONFLICT.recovery;\n if ('recovery' in err.details && err.details.recovery !== expectedRecovery) {\n return [\n {\n passed: false,\n description,\n step_id: stepResult.step_id,\n error:\n `IDEMPOTENCY_CONFLICT error envelope carried non-standard recovery metadata: ` +\n `expected ${JSON.stringify(expectedRecovery)}.`,\n },\n ];\n }\n if (leaked.length === 0) {\n return [{ passed: true, description, step_id: stepResult.step_id }];\n }\n return [\n {\n passed: false,\n description,\n step_id: stepResult.step_id,\n error:\n `IDEMPOTENCY_CONFLICT error envelope leaked non-allowlisted field(s): ${leaked.sort().join(', ')}. ` +\n `Allowed envelope keys (ADCP_ERROR_FIELD_ALLOWLIST.IDEMPOTENCY_CONFLICT): ` +\n `${[...CONFLICT_ADCP_ERROR_ALLOWLIST].join(', ')}.`,\n },\n ];\n },\n });\n\n /**\n * Bearer-token literal pattern. Matches the wire form a seller might echo\n * from `Authorization: Bearer <token>` — case-insensitive `bearer` keyword\n * followed by a token body of at least 10 characters of base64url / JWT\n * vocabulary. Kept strict on length to avoid false positives on prose like\n * \"bearer of bad news\".\n */\n const BEARER_TOKEN_PATTERN = /\\bbearer\\s+[A-Za-z0-9._~+/=-]{10,}/i;\n\n /**\n * Property names that MUST NOT appear on a response body — a seller that\n * serializes `Authorization` / `api_key` / `x-api-key` headers or fields\n * into the response is almost certainly leaking credentials, regardless of\n * whether the scanner picks up the value verbatim (header normalization,\n * whitespace differences, etc. can mask verbatim matches). Case-insensitive.\n */\n const SUSPECT_PROPERTY_NAMES = new Set(['authorization', 'api_key', 'apikey', 'bearer', 'x-api-key']);\n\n /**\n * Minimum length for a caller-supplied secret to be hunted for verbatim.\n * Set to 16 because real OAuth access tokens, refresh tokens, and signing\n * secrets are ≥20 chars by convention (opaque UUIDs, JWTs, HMAC hex). A\n * shorter floor would false-positive on benign identifiers (short\n * usernames, environment names, 8-char hex prefixes, ISO timestamps).\n * Hand-coded fixture keys like `\"test-key\"` below this bar are not caught\n * — that's the right tradeoff: a real agent echoing such a value is an\n * obvious leak a human reviewer would spot, and the collision cost of\n * matching short strings against every response body is too high to\n * justify the coverage.\n */\n const SECRET_MIN_LENGTH = 16;\n\n registerOnce('context.no_secret_echo', {\n id: 'context.no_secret_echo',\n default: true,\n description: 'Response bodies MUST NOT echo bearer tokens, API keys, or auth header values back to the caller.',\n onStart: ctx => {\n // Stash caller-supplied secrets worth hunting verbatim. `auth` is the\n // structured discriminated union from TestOptions — we walk it and\n // extract leaf strings so `String.includes(obj)` can't silently no-op.\n // test_kit api_key pickup matches what storyboards typically stage;\n // options.secrets is a consumer hook for custom credentials.\n const secrets = new Set<string>();\n const optAny = ctx.options as unknown as {\n auth_token?: string;\n auth?: unknown;\n secrets?: string[];\n test_kit?: { auth?: { api_key?: string; basic?: unknown } };\n };\n addIfSecret(secrets, optAny.auth_token);\n for (const s of extractAuthSecrets(optAny.auth)) addIfSecret(secrets, s);\n for (const s of optAny.secrets ?? []) addIfSecret(secrets, s);\n addIfSecret(secrets, optAny.test_kit?.auth?.api_key);\n for (const s of extractBasicSecrets(optAny.test_kit?.auth?.basic)) addIfSecret(secrets, s);\n ctx.state.secrets = secrets;\n },\n onStep: (ctx, stepResult) => {\n const body = (stepResult as unknown as { response?: unknown }).response;\n if (body === undefined || body === null) return [];\n\n const secrets = (ctx.state.secrets as Set<string> | undefined) ?? new Set<string>();\n const description = 'Response omits caller-supplied secrets and credential-shaped fields';\n\n const hit = findSecretEcho(body, secrets);\n if (hit) {\n return [\n {\n passed: false,\n description,\n step_id: stepResult.step_id,\n error: `step \"${stepResult.step_id}\" response ${hit}`,\n },\n ];\n }\n return [{ passed: true, description, step_id: stepResult.step_id }];\n },\n });\n\n /**\n * Recursively walk `value` hunting for (a) suspect property names at any\n * depth, (b) bearer-token literals in any string value, and (c) verbatim\n * copies of caller-supplied secrets. First hit wins; the caller turns the\n * reason into a human-readable error message.\n */\n function findSecretEcho(value: unknown, secrets: Set<string>): string | null {\n const stack: unknown[] = [value];\n while (stack.length > 0) {\n const v = stack.pop();\n if (typeof v === 'string') {\n if (BEARER_TOKEN_PATTERN.test(v)) return 'contains a bearer-token literal';\n for (const s of secrets) {\n if (v.includes(s)) return 'contains a caller-supplied secret value verbatim';\n }\n continue;\n }\n if (Array.isArray(v)) {\n for (const item of v) stack.push(item);\n continue;\n }\n if (v !== null && typeof v === 'object') {\n for (const [key, inner] of Object.entries(v as Record<string, unknown>)) {\n // Name-based dragnet. The SUSPECT_PROPERTY_NAMES set catches the\n // \"bare token on a credential-named field\" leak shape that the\n // BEARER_TOKEN_PATTERN value-scan misses (a JWT without `Bearer `\n // prefix won't match the regex). But the dragnet over-rejects\n // when the field's VALUE is a structured object or array — those\n // are spec-legitimate config payloads, not credential echoes.\n // `compliance/cache/{version}/property/validation-result.json`\n // declares an `authorization` object field carrying authorization-\n // validation metadata, not a token; sellers extending\n // `sync_accounts` via the schema's `additionalProperties: true`\n // may carry their own structured `authorization` posture. Both\n // are spec-conformant.\n //\n // Gate the name-based fail on `typeof inner === 'string'` and\n // non-empty so structured values pass through to the recursive\n // walk below. The recursion still scans nested string values, so\n // a `Bearer xyz...` literal embedded in a structured object is\n // still caught by the regex at the top of this loop.\n // Spec: adcp-client#1713 / adcp#4419.\n if (SUSPECT_PROPERTY_NAMES.has(key.toLowerCase()) && typeof inner === 'string' && inner.length > 0) {\n return `contains suspect property name \"${key}\" with string value`;\n }\n stack.push(inner);\n }\n }\n }\n return null;\n }\n\n // ────────────────────────────────────────────────────────────\n // governance.denial_blocks_mutation\n // ────────────────────────────────────────────────────────────\n\n /**\n * Error codes that signal a seller-side refusal with plan scope. Grounded\n * in `ErrorCodeSchema` in `src/lib/types/schemas.generated.ts`. Excludes\n * transient (`GOVERNANCE_UNAVAILABLE` — no decision rendered) and\n * account-state (`ACCOUNT_SUSPENDED`) codes — those aren't plan denials.\n */\n const GOVERNANCE_DENIAL_CODES = new Set([\n 'GOVERNANCE_DENIED',\n 'CAMPAIGN_SUSPENDED',\n 'PERMISSION_DENIED',\n 'POLICY_VIOLATION',\n 'TERMS_REJECTED',\n 'COMPLIANCE_UNSATISFIED',\n ]);\n\n /**\n * Write-class tasks whose successful response carries a server-minted\n * resource id at the top level. Read tasks (`get_*`, `list_*`,\n * `check_governance`) can echo ids without having created anything; they\n * are excluded so the assertion doesn't false-positive on lookups after\n * a denial. Sync-batch tasks (`sync_*`) are excluded until per-item\n * acquisition detection lands — see follow-up in the spec repo.\n */\n const GOVERNANCE_WRITE_TASKS = new Set([\n 'create_media_buy',\n 'update_media_buy',\n 'activate_signal',\n 'create_property_list',\n 'update_property_list',\n 'delete_property_list',\n 'create_collection_list',\n 'update_collection_list',\n 'delete_collection_list',\n 'acquire_rights',\n ]);\n\n const GOVERNANCE_ACQUIRED_STATUSES = new Set(['pending_creatives', 'pending_start', 'active', 'paused', 'completed']);\n\n const GOVERNANCE_RESOURCE_ID_FIELDS = [\n 'media_buy_id',\n 'plan_id',\n 'creative_id',\n 'audience_id',\n 'catalog_id',\n 'activation_id',\n 'property_list_id',\n 'collection_list_id',\n 'acquisition_id',\n 'operation_id',\n ];\n\n interface GovernanceDenialAnchor {\n stepId: string;\n signal: string;\n }\n\n registerOnce('governance.denial_blocks_mutation', {\n id: 'governance.denial_blocks_mutation',\n default: true,\n description:\n 'Once a governance signal denies a plan, no subsequent step in the run may acquire a resource for that plan.',\n onStart: ctx => {\n ctx.state.deniedPlans = new Map<string, GovernanceDenialAnchor>();\n ctx.state.runDenial = undefined;\n },\n onStep: (ctx, stepResult) => {\n const state = ctx.state as {\n deniedPlans: Map<string, GovernanceDenialAnchor>;\n runDenial?: GovernanceDenialAnchor;\n };\n const planId = extractGovernancePlanId(stepResult);\n\n // Denial observation is never itself a failure — record and return.\n const denial = detectGovernanceDenial(stepResult);\n if (denial) {\n // A step marked `expect_error: true` is the storyboard author explicitly\n // acknowledging the denial. Subsequent mutations in the same run are a\n // recovery path, not a silent bypass — don't anchor. The invariant still\n // catches silent denials (check_governance 200 `status: denied`, or\n // adcp_error responses the author did not expect).\n if (stepResult.expect_error) return [];\n const anchor: GovernanceDenialAnchor = { stepId: stepResult.step_id, signal: denial };\n if (planId) {\n if (!state.deniedPlans.has(planId)) state.deniedPlans.set(planId, anchor);\n } else if (!state.runDenial) {\n state.runDenial = anchor;\n }\n return [];\n }\n\n const acquired = detectGovernanceAcquisition(stepResult);\n if (!acquired) return [];\n\n const anchor = (planId && state.deniedPlans.get(planId)) ?? state.runDenial;\n if (!anchor) return [];\n\n // Always surface the step-level escape hatch — it's the one hint that\n // works for both wire-error denials and `check_governance` 200\n // `status: denied`. Names the step, names the field, shows the YAML so\n // the author doesn't have to re-derive the escape from source.\n const escapeHint =\n `. If the denial at step \"${anchor.stepId}\" is an intentional recovery-path setup, add to that step:\\n` +\n ` invariants:\\n` +\n ` disable: [governance.denial_blocks_mutation]`;\n\n return [\n {\n passed: false,\n description: 'Mutation acquired a resource after a governance denial',\n step_id: stepResult.step_id,\n error:\n `step \"${anchor.stepId}\" returned ${anchor.signal}` +\n (planId ? ` for plan_id=${planId}` : ' (run-wide)') +\n `; subsequent step \"${stepResult.step_id}\" (task=${stepResult.task}) ` +\n `acquired ${acquired.field}=${acquired.id}` +\n (planId ? ' for the same plan' : '') +\n escapeHint,\n },\n ];\n },\n });\n\n function detectGovernanceDenial(step: import('./types').StoryboardStepResult): string | undefined {\n const err = extractAdcpError(step);\n if (err && GOVERNANCE_DENIAL_CODES.has(err.code)) return err.code;\n // `check_governance` decides-no via a 200 response with `status: \"denied\"`\n // (see static/schemas/source/governance/check-governance-response.json in\n // the spec repo). The body isn't wrapped in `adcp_error`.\n if (step.task === 'check_governance') {\n const body = (step as unknown as { response?: unknown }).response;\n if (body && typeof body === 'object') {\n const status = (body as Record<string, unknown>).status;\n if (status === 'denied') return 'CHECK_GOVERNANCE_DENIED';\n }\n }\n return undefined;\n }\n\n function extractGovernancePlanId(step: import('./types').StoryboardStepResult): string | undefined {\n const body = (step as unknown as { response?: unknown }).response;\n if (body && typeof body === 'object') {\n const rec = body as Record<string, unknown>;\n if (typeof rec.plan_id === 'string' && rec.plan_id) return rec.plan_id;\n }\n // The runner records the outgoing payload on `stepResult.request` — read\n // from there rather than accumulated step context to avoid stale plan_id\n // bleed from earlier unrelated steps.\n const req = (step as unknown as { request?: { payload?: unknown } }).request;\n if (req && typeof req.payload === 'object' && req.payload !== null) {\n const payload = req.payload as Record<string, unknown>;\n if (typeof payload.plan_id === 'string' && payload.plan_id) return payload.plan_id;\n }\n return undefined;\n }\n\n function detectGovernanceAcquisition(\n step: import('./types').StoryboardStepResult\n ): { field: string; id: string } | undefined {\n if (step.expect_error) return undefined;\n if (!step.passed) return undefined;\n if (!GOVERNANCE_WRITE_TASKS.has(step.task)) return undefined;\n\n const body = (step as unknown as { response?: unknown }).response;\n if (!body || typeof body !== 'object') return undefined;\n const record = body as Record<string, unknown>;\n\n if (step.task === 'create_media_buy' || step.task === 'update_media_buy') {\n const status = record.status;\n if (typeof status === 'string' && !GOVERNANCE_ACQUIRED_STATUSES.has(status)) return undefined;\n }\n\n for (const field of GOVERNANCE_RESOURCE_ID_FIELDS) {\n const val = record[field];\n if (typeof val === 'string' && val.length > 0) return { field, id: val };\n }\n return undefined;\n }\n\n // ────────────────────────────────────────────────────────────\n // Helpers\n // ────────────────────────────────────────────────────────────\n\n interface AdcpErrorShape {\n code: string;\n details: Record<string, unknown>;\n }\n\n function extractAdcpError(step: import('./types').StoryboardStepResult): AdcpErrorShape | null {\n const resp = (step as unknown as { response?: unknown }).response;\n if (!resp || typeof resp !== 'object') return null;\n const envelope = (resp as { adcp_error?: unknown }).adcp_error;\n if (!envelope || typeof envelope !== 'object') return null;\n const code = (envelope as { code?: unknown }).code;\n if (typeof code !== 'string') return null;\n return { code, details: envelope as Record<string, unknown> };\n }\n\n /**\n * Add a value to the secrets set if it is a non-empty string of at least\n * `SECRET_MIN_LENGTH` chars. Centralises the length guard so every source\n * (structured auth, `auth_token`, `secrets[]`, `test_kit.auth.api_key`)\n * gets the same floor.\n */\n function addIfSecret(out: Set<string>, value: unknown): void {\n if (typeof value !== 'string') return;\n if (value.length < SECRET_MIN_LENGTH) return;\n out.add(value);\n }\n\n const ENV_REFERENCE_PREFIX = '$ENV:';\n\n /**\n * Resolve a possibly `$ENV:VAR`-prefixed credential value to the literal it\n * references at runtime. Mirrors the auth-layer `resolveSecret` in\n * `src/lib/auth/oauth/secret-resolver.ts`, but swallows missing / empty\n * variables instead of throwing — the assertion must never break a\n * storyboard run just because it can't resolve a ref.\n *\n * Returns `undefined` if the value is not an env reference, or if the\n * referenced variable is unset / empty. Callers should skip `undefined`\n * results. The literal `$ENV:FOO` string itself is never returned because\n * it is a reference, not a secret, and cannot appear in an agent response.\n */\n function resolveEnvReference(value: string): string | undefined {\n if (!value.startsWith(ENV_REFERENCE_PREFIX)) return undefined;\n const envVar = value.slice(ENV_REFERENCE_PREFIX.length).trim();\n if (!envVar) return undefined;\n const resolved = process.env[envVar];\n if (!resolved) return undefined;\n return resolved;\n }\n\n /**\n * Push a credential-field string onto `out`, resolving `$ENV:VAR` references\n * to their literal runtime value. Literal values pass through unchanged.\n * `$ENV:` references only contribute the resolved value — the reference\n * string itself is not a secret.\n */\n function pushCredentialValue(out: string[], value: unknown): void {\n if (typeof value !== 'string' || !value) return;\n if (value.startsWith(ENV_REFERENCE_PREFIX)) {\n const resolved = resolveEnvReference(value);\n if (resolved) out.push(resolved);\n return;\n }\n out.push(value);\n }\n\n /**\n * Extract every leaf string secret from a structured `TestOptions.auth` value.\n * Mirrors the four variants in `src/lib/testing/types.ts`:\n * - bearer → `token`\n * - basic → `password` and, when both credentials are\n * present, the `base64(user:pass)` blob an\n * `Authorization: Basic` header carries.\n * Username alone is NOT extracted — it's a\n * public identifier (welcome messages, audit\n * logs, \"last login by X\" echoes legitimately).\n * - oauth → `tokens.access_token`, `tokens.refresh_token`,\n * `client.client_secret` (if confidential)\n * - oauth_client_credentials → `credentials.client_secret` (may be a\n * `$ENV:VAR` reference, resolved at runtime),\n * `tokens.access_token`, `tokens.refresh_token`.\n * `client_id` is NOT extracted — RFC 6749 §2.2\n * is explicit that the client identifier is\n * public and legitimately echoed in token\n * responses, introspection payloads, audit\n * logs, and error bodies.\n *\n * Returns an empty list for anything we can't recognise — the goal is a best-\n * effort extraction, not schema validation. The SECRET_MIN_LENGTH guard is\n * applied by the caller via `addIfSecret`.\n */\n function extractAuthSecrets(auth: unknown): string[] {\n if (!auth || typeof auth !== 'object') return [];\n const a = auth as Record<string, unknown>;\n const out: string[] = [];\n pushCredentialValue(out, a.token); // bearer\n\n // basic: the password is the secret; the base64 blob catches echoes of the\n // full Authorization: Basic header, including RFC 7617-valid empty passwords.\n // Username alone is not a secret.\n if (typeof a.password === 'string') {\n if (a.password) out.push(a.password);\n if (typeof a.username === 'string' && a.username) {\n out.push(Buffer.from(`${a.username}:${a.password}`, 'utf8').toString('base64'));\n }\n }\n\n if (a.tokens && typeof a.tokens === 'object') {\n const t = a.tokens as Record<string, unknown>;\n if (typeof t.access_token === 'string' && t.access_token) out.push(t.access_token);\n if (typeof t.refresh_token === 'string' && t.refresh_token) out.push(t.refresh_token);\n }\n if (a.client && typeof a.client === 'object') {\n const c = a.client as Record<string, unknown>;\n if (typeof c.client_secret === 'string' && c.client_secret) out.push(c.client_secret);\n }\n if (a.credentials && typeof a.credentials === 'object') {\n const c = a.credentials as Record<string, unknown>;\n // client_secret on AgentOAuthClientCredentials may be a `$ENV:VAR`\n // reference — resolve so the assertion compares the real runtime value\n // the AS sees, not the reference string. client_id is NOT extracted\n // (RFC 6749 §2.2 — public identifier).\n pushCredentialValue(out, c.client_secret);\n }\n return out;\n }\n\n function extractBasicSecrets(basic: unknown): string[] {\n if (!basic || typeof basic !== 'object') return [];\n const b = basic as Record<string, unknown>;\n const out: string[] = [];\n if (typeof b.credentials === 'string' && b.credentials) {\n const colonIndex = b.credentials.indexOf(':');\n if (colonIndex > 0) {\n const password = b.credentials.slice(colonIndex + 1);\n if (password) out.push(password);\n out.push(Buffer.from(b.credentials, 'utf8').toString('base64'));\n }\n return out;\n }\n if (typeof b.password === 'string') {\n if (b.password) out.push(b.password);\n if (typeof b.username === 'string' && b.username) {\n out.push(Buffer.from(`${b.username}:${b.password}`, 'utf8').toString('base64'));\n }\n }\n return out;\n }\n\n // ────────────────────────────────────────────────────────────\n // status.monotonic\n // ────────────────────────────────────────────────────────────\n\n /**\n * Per-resource-type lifecycle transition graphs. Each inner map is\n * `from → Set<to>`. An observed transition `prev → curr` is legal iff\n * `TRANSITIONS[type].get(prev)?.has(curr)` (self-edges `prev === curr`\n * are always legal and skipped). The tables are hand-written from the\n * spec enum schemas in `static/schemas/source/enums/*-status.json` and\n * the narrative transitions documented there. When an enum gains a\n * value this module needs an update alongside the schema change — that's\n * the right coupling, visible in PR review.\n *\n * Bidirectional edges are listed in both directions explicitly (no\n * auto-mirroring) so one-way edges like `rejected → processing` for\n * creative assets don't accidentally become reversible.\n */\n interface TransitionGraph {\n readonly transitions: ReadonlyMap<string, ReadonlySet<string>>;\n /**\n * Filename of the canonical enum schema this graph mirrors, relative to\n * `/schemas/<adcp-version>/enums/`. Used to render a deep-link in the\n * assertion failure message so implementors can jump straight to the\n * spec's lifecycle doc instead of grep-searching for it.\n */\n readonly enumFile: string;\n }\n\n const SCHEMA_URL_BASE = 'https://adcontextprotocol.org';\n\n function buildEnumSchemaUrl(enumFile: string): string {\n return `${SCHEMA_URL_BASE}/schemas/${ADCP_VERSION}/enums/${enumFile}`;\n }\n\n // Source of truth for both graphs lives in `server/state-machine.ts` so\n // production sellers and the runner enforce identical edges. Wrap the typed\n // maps in `TransitionGraph` for the runner's string-keyed extractors.\n const MEDIA_BUY_TRANSITIONS: TransitionGraph = {\n transitions: MEDIA_BUY_TRANSITIONS_TYPED as ReadonlyMap<string, ReadonlySet<string>>,\n enumFile: 'media-buy-status.json',\n };\n\n const CREATIVE_ASSET_TRANSITIONS: TransitionGraph = {\n transitions: CREATIVE_ASSET_TRANSITIONS_TYPED as ReadonlyMap<string, ReadonlySet<string>>,\n enumFile: 'creative-status.json',\n };\n\n const CREATIVE_APPROVAL_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/creative-approval-status.json`.\n // Per-assignment approval state on a package. `rejected → pending_review`\n // is allowed on re-sync.\n transitions: new Map<string, ReadonlySet<string>>([\n ['pending_review', new Set(['approved', 'rejected'])],\n ['approved', new Set(['rejected'])],\n ['rejected', new Set(['pending_review'])],\n ]),\n enumFile: 'creative-approval-status.json',\n };\n\n const ACCOUNT_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/account-status.json`. `active ↔\n // suspended` and `active ↔ payment_required` are both reversible.\n // `suspended → payment_required` covers the legitimate case where a\n // suspended account's credit lapses during the suspension window.\n // `rejected | closed` are terminal.\n transitions: new Map<string, ReadonlySet<string>>([\n ['pending_approval', new Set(['active', 'rejected'])],\n ['active', new Set(['suspended', 'payment_required', 'closed'])],\n ['suspended', new Set(['active', 'payment_required', 'closed'])],\n ['payment_required', new Set(['active', 'suspended', 'closed'])],\n ['rejected', new Set()],\n ['closed', new Set()],\n ]),\n enumFile: 'account-status.json',\n };\n\n const SI_SESSION_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/si-session-status.json`.\n // `complete | terminated` are terminal.\n transitions: new Map<string, ReadonlySet<string>>([\n ['active', new Set(['pending_handoff', 'complete', 'terminated'])],\n ['pending_handoff', new Set(['complete', 'terminated'])],\n ['complete', new Set()],\n ['terminated', new Set()],\n ]),\n enumFile: 'si-session-status.json',\n };\n\n const CATALOG_ITEM_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/catalog-item-status.json`. `approved ↔\n // warning` is reversible (seller flags a warning, then clears it).\n // `rejected → pending` is allowed on re-sync. No terminals.\n transitions: new Map<string, ReadonlySet<string>>([\n ['pending', new Set(['approved', 'rejected', 'warning'])],\n ['approved', new Set(['warning', 'rejected'])],\n ['warning', new Set(['approved', 'rejected'])],\n ['rejected', new Set(['pending'])],\n ]),\n enumFile: 'catalog-item-status.json',\n };\n\n const PROPOSAL_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/proposal-status.json`. One-way.\n transitions: new Map<string, ReadonlySet<string>>([\n ['draft', new Set(['committed'])],\n ['committed', new Set()],\n ]),\n enumFile: 'proposal-status.json',\n };\n\n const AUDIENCE_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/audience-status.json`. Fully bidirectional\n // across the three states — sellers MAY re-enter `processing` on re-sync\n // from `ready` or `too_small`, and `ready ↔ too_small` can happen as\n // member counts cross `minimum_size` (spec hedges this as MAY, not MUST).\n // No terminals: delete / fail omit `status` entirely via the envelope's\n // `action` field, so there's nothing to record for them.\n transitions: new Map<string, ReadonlySet<string>>([\n ['processing', new Set(['ready', 'too_small'])],\n ['ready', new Set(['processing', 'too_small'])],\n ['too_small', new Set(['processing', 'ready'])],\n ]),\n enumFile: 'audience-status.json',\n };\n\n /**\n * Extractor record per resource type. For each response shape we recognize,\n * describe how to walk the body and emit `(resource_id, status)` pairs.\n * The runner hands us `stepResult.response` — we look at the shape and\n * the task name to disambiguate (e.g. `get_media_buys` vs `sync_creatives`).\n */\n interface StatusObservation {\n resource_type: string;\n resource_id: string;\n status: string;\n graph: TransitionGraph;\n }\n\n /**\n * Task-aware extractors. Each knows the response shape for its task family\n * and walks arrays where present. Unknown tasks produce no observations —\n * the assertion is silent on tasks it doesn't recognize.\n */\n function extractStatusObservations(task: string, body: Record<string, unknown>): StatusObservation[] {\n const obs: StatusObservation[] = [];\n\n // Media-buy: create/update_media_buy return top-level status + packages\n // with per-creative approval_status. get_media_buys returns media_buys[].\n if (task === 'create_media_buy' || task === 'update_media_buy') {\n pushMediaBuy(obs, body);\n } else if (task === 'get_media_buys') {\n for (const mb of asArray(body.media_buys)) {\n if (isObject(mb)) pushMediaBuy(obs, mb);\n }\n }\n\n // Creative asset lifecycle: sync_creatives and list_creatives.\n if (task === 'sync_creatives' || task === 'list_creatives') {\n for (const c of asArray(body.creatives)) {\n if (isObject(c)) pushCreative(obs, c);\n }\n }\n\n // Account: sync_accounts and list_accounts. Embedded `account` objects on\n // media-buy responses do not carry a lifecycle status — they're just\n // references (brand, operator) — so we don't read them here.\n if (task === 'sync_accounts' || task === 'list_accounts') {\n for (const a of asArray(body.accounts)) {\n if (isObject(a)) pushAccount(obs, a);\n }\n }\n\n // SI session: si_initiate_session / si_send_message return top-level\n // `session_id` + `status`.\n if (task === 'si_initiate_session' || task === 'si_send_message' || task === 'si_terminate_session') {\n pushSiSession(obs, body);\n }\n\n // Catalog items: sync_catalogs / list_catalogs return `items[]` per catalog.\n if (task === 'sync_catalogs' || task === 'list_catalogs') {\n for (const cat of asArray(body.catalogs)) {\n if (!isObject(cat)) continue;\n for (const item of asArray(cat.items)) {\n if (isObject(item)) pushCatalogItem(obs, item);\n }\n }\n for (const item of asArray(body.items)) {\n if (isObject(item)) pushCatalogItem(obs, item);\n }\n }\n\n // Proposal: get_products may return a `proposal` object when the\n // caller is refining toward commitment.\n if (task === 'get_products' && isObject(body.proposal)) {\n pushProposal(obs, body.proposal);\n }\n\n // Audience lifecycle: sync_audiences is both the write and discovery path\n // (discovery-only calls omit the request `audiences` array but still return\n // `audiences[]`). No separate list_audiences task exists.\n if (task === 'sync_audiences') {\n for (const a of asArray(body.audiences)) {\n if (isObject(a)) pushAudience(obs, a);\n }\n }\n\n return obs;\n }\n\n function pushMediaBuy(obs: StatusObservation[], record: Record<string, unknown>): void {\n const id = asString(record.media_buy_id);\n // 3.1+: `media_buy_status` (body) carries MediaBuyStatus; top-level\n // `status` (envelope) carries TaskStatus. Pre-3.1 + nested fields on\n // `get_media_buys` / `get_media_buy_delivery`: `status` still carries\n // MediaBuyStatus. Read the canonical 3.1 field first, fall back to\n // legacy. Refs adcontextprotocol/adcp#4895 (3.1 additive-deprecate),\n // #4906 (3.2 legacy removal), #4905 (4.0 nested cascade).\n const status = asString(record.media_buy_status) ?? asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'media_buy',\n resource_id: id,\n status,\n graph: MEDIA_BUY_TRANSITIONS,\n });\n }\n // Each media_buy carries packages; each package can list creative_approvals\n // with per-creative approval_status. Track those against the approval graph.\n for (const pkg of asArray(record.packages)) {\n if (!isObject(pkg)) continue;\n for (const ca of asArray(pkg.creative_approvals)) {\n if (!isObject(ca)) continue;\n const cid = asString(ca.creative_id);\n const astatus = asString(ca.approval_status);\n if (cid && astatus) {\n obs.push({\n resource_type: 'creative_approval',\n resource_id: cid,\n status: astatus,\n graph: CREATIVE_APPROVAL_TRANSITIONS,\n });\n }\n }\n }\n }\n\n function pushCreative(obs: StatusObservation[], record: Record<string, unknown>): void {\n const id = asString(record.creative_id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'creative',\n resource_id: id,\n status,\n graph: CREATIVE_ASSET_TRANSITIONS,\n });\n }\n }\n\n function pushAccount(obs: StatusObservation[], record: Record<string, unknown>): void {\n const id = asString(record.account_id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'account',\n resource_id: id,\n status,\n graph: ACCOUNT_TRANSITIONS,\n });\n }\n }\n\n function pushSiSession(obs: StatusObservation[], record: Record<string, unknown>): void {\n const id = asString(record.session_id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'si_session',\n resource_id: id,\n status,\n graph: SI_SESSION_TRANSITIONS,\n });\n }\n }\n\n function pushCatalogItem(obs: StatusObservation[], record: Record<string, unknown>): void {\n // Catalog items are heterogeneous across catalog types. Prefer `item_id`\n // (spec-canonical on sync/list responses), then domain-specific\n // `offering_id` (SI) and `sku` (retail), then a generic `id` as last\n // resort. The fallback chain silently mis-identifies if a seller echoes\n // a non-canonical id — the resulting history splits per id shape rather\n // than emitting an error. Acceptable tradeoff given schema churn; enum\n // drift stays under `response_schema`'s purview.\n const id = asString(record.item_id) ?? asString(record.offering_id) ?? asString(record.sku) ?? asString(record.id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'catalog_item',\n resource_id: id,\n status,\n graph: CATALOG_ITEM_TRANSITIONS,\n });\n }\n }\n\n function pushProposal(obs: StatusObservation[], record: Record<string, unknown>): void {\n const id = asString(record.proposal_id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'proposal',\n resource_id: id,\n status,\n graph: PROPOSAL_TRANSITIONS,\n });\n }\n }\n\n function pushAudience(obs: StatusObservation[], record: Record<string, unknown>): void {\n // `status` is absent when `action` is `deleted` or `failed` — spec\n // envelope intentionally omits the field rather than emitting a terminal\n // value. The `&& status` guard below makes those observations silent.\n const id = asString(record.audience_id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'audience',\n resource_id: id,\n status,\n graph: AUDIENCE_TRANSITIONS,\n });\n }\n }\n\n interface MonotonicState {\n stepId: string;\n status: string;\n }\n\n registerOnce('status.monotonic', {\n id: 'status.monotonic',\n default: true,\n description:\n 'Observed resource statuses (media_buy, creative, account, si_session, catalog_item, proposal, creative_approval, audience) MUST only transition along edges in the spec lifecycle graph.',\n onStart: ctx => {\n // `${resource_type}:${resource_id}` → last-observed state. Tuple key\n // disambiguates the unlikely `media_buy_id` / `creative_id` collision.\n ctx.state.history = new Map<string, MonotonicState>();\n ctx.state.statusMonotonicEligibleStepCount = 0;\n },\n onStep: (ctx, stepResult) => {\n // Skip error / skipped / negative-path steps. An errored read doesn't\n // observe a new state; `expect_error: true` runs are probing error\n // codes, not transitions.\n if (stepResult.skipped) return [];\n if (stepResult.expect_error) return [];\n if (!stepResult.passed) return [];\n const body = (stepResult as unknown as { response?: unknown }).response;\n if (!body || typeof body !== 'object') return [];\n if (extractAdcpError(stepResult)) return [];\n ctx.state.statusMonotonicEligibleStepCount =\n ((ctx.state.statusMonotonicEligibleStepCount as number | undefined) ?? 0) + 1;\n\n const history = ctx.state.history as Map<string, MonotonicState>;\n const observations = extractStatusObservations(stepResult.task, body as Record<string, unknown>);\n const description = 'Resource statuses transition only along spec lifecycle edges';\n\n for (const ob of observations) {\n const key = `${ob.resource_type}:${ob.resource_id}`;\n const prev = history.get(key);\n if (!prev) {\n history.set(key, { stepId: stepResult.step_id, status: ob.status });\n continue;\n }\n if (prev.status === ob.status) {\n // No-op observation (replay, re-read of unchanged state). Don't emit,\n // don't advance the anchor step — the earlier stepId stays useful for\n // diagnostics if a later backward edge appears.\n continue;\n }\n const allowedTargets = ob.graph.transitions.get(prev.status);\n if (!allowedTargets) {\n // Unknown previous status (enum drift or we missed a state in the\n // table). Don't fail — `response_schema` catches enum violations;\n // reset the anchor so downstream transitions still get checked.\n history.set(key, { stepId: stepResult.step_id, status: ob.status });\n continue;\n }\n if (!allowedTargets.has(ob.status)) {\n // Surface the legal next states + a canonical enum URL so implementors\n // can self-diagnose without grepping the SDK source for the\n // lifecycle table. `allowedTargets` is empty for terminal states\n // (completed / rejected / canceled / etc.) — call that out explicitly\n // rather than rendering an empty list that reads as \"any target is\n // fine, just not this one\".\n const legalTargets = [...allowedTargets].sort();\n const legalDescription =\n legalTargets.length > 0 ? legalTargets.map(t => `\"${t}\"`).join(', ') : '(none — terminal state)';\n const enumUrl = buildEnumSchemaUrl(ob.graph.enumFile);\n const errorMessage =\n `${ob.resource_type} ${ob.resource_id}: ${prev.status} → ${ob.status} ` +\n `(step \"${prev.stepId}\" → step \"${stepResult.step_id}\") is not in the lifecycle graph. ` +\n `Legal next states from \"${prev.status}\": ${legalDescription}. ` +\n `See ${enumUrl} for the canonical lifecycle.`;\n return [\n {\n passed: false,\n description,\n step_id: stepResult.step_id,\n error: errorMessage,\n // Issue #935: structured `MonotonicViolationHint` mirrored into\n // the owning step's `hints[]` so renderers can branch on the\n // discriminator and render the legal-target set in a per-kind\n // template instead of regex-parsing the prose error string.\n hint: {\n kind: 'monotonic_violation',\n message: errorMessage,\n resource_type: ob.resource_type,\n resource_id: ob.resource_id,\n from_status: prev.status,\n to_status: ob.status,\n from_step_id: prev.stepId,\n legal_next_states: legalTargets,\n enum_url: enumUrl,\n },\n },\n ];\n }\n history.set(key, { stepId: stepResult.step_id, status: ob.status });\n }\n\n if (observations.length === 0) return [];\n return [{ passed: true, description, step_id: stepResult.step_id }];\n },\n // Emit a run-level summary so the track rollup can distinguish\n // \"wired and exercised\" (history.size > 0) from \"wired but never\n // observed a lifecycle resource\" (history.size === 0). The latter\n // demotes the track to TrackStatus: 'silent' even though every step\n // and every per-step assertion record passed. Companion to\n // adcontextprotocol/adcp#2834.\n onEnd: ctx => {\n if (((ctx.state.statusMonotonicEligibleStepCount as number | undefined) ?? 0) === 0) return [];\n const history = ctx.state.history as Map<string, MonotonicState> | undefined;\n const observation_count = history?.size ?? 0;\n return [\n {\n passed: true,\n description: 'Resource statuses transition only along spec lifecycle edges',\n observation_count,\n status: observation_count === 0 ? ('silent' as const) : ('pass' as const),\n },\n ];\n },\n });\n\n // Tiny type-safety helpers for the extractors above.\n function isObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v);\n }\n\n function asArray(v: unknown): unknown[] {\n return Array.isArray(v) ? v : [];\n }\n\n function asString(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n }\n\n // ────────────────────────────────────────────────────────────\n // impairment.coherence\n // ────────────────────────────────────────────────────────────\n\n /**\n * Per-resource-type offline status sets. An impairment entry referencing\n * `(resource_type, resource_id)` is coherent when the runner's last\n * observation for that resource matches one of these values.\n *\n * Sourced from spec issue #2859 plus the resource-status enum schemas:\n * - audience: `suspended` (audience-status.json)\n * - creative: `rejected` (creative-status.json — terminal)\n * - catalog_item: `withdrawn` (catalog-item-status.json)\n * - event_source: `insufficient` (assessment-status.json, on\n * event-source-health.status)\n *\n * `property` is intentionally absent — offline state is sourced from\n * `brand.json` / `adagents.json` depublishing, not from a status enum on\n * the wire. The runner has no observation hook for that transition today,\n * so property-typed impairments grade silent rather than emitting a forward\n * pass / fail. The spec issue calls this out explicitly.\n */\n const IMPAIRMENT_OFFLINE_STATUS: ReadonlyMap<string, ReadonlySet<string>> = new Map([\n ['audience', new Set(['suspended'])],\n ['creative', new Set(['rejected'])],\n ['catalog_item', new Set(['withdrawn'])],\n ['event_source', new Set(['insufficient'])],\n ]);\n\n /**\n * Media-buy statuses that are non-terminal — the inverse rule only applies\n * while the buy is still serving (or about to). The spec issue carves out\n * `completed`, `canceled`, `rejected` as the terminal set that MAY remain\n * unreported because the buy is no longer accruing impressions.\n */\n const NON_TERMINAL_MEDIA_BUY_STATUSES: ReadonlySet<string> = new Set([\n 'pending_creatives',\n 'pending_start',\n 'active',\n 'paused',\n ]);\n\n interface ImpairmentEntry {\n resource_type: string;\n resource_id: string;\n }\n\n interface BuySnapshot {\n media_buy_id: string;\n status: string | undefined;\n health: string | undefined;\n impairments: ImpairmentEntry[];\n referencedCreativeIds: Set<string>;\n referencedAudienceIds: Set<string>;\n stepId: string;\n }\n\n interface ResourceObservation {\n status: string;\n stepId: string;\n }\n\n /**\n * Resource families the inverse rule does NOT yet grade — the buy-side\n * reference shape for these in `media_buy.packages` isn't stable in the\n * cached schema, so we can't reliably tell which buys reference which\n * resources. Listed here so the onEnd summary can emit a runtime\n * \"partial inverse coverage\" signal when the run actually observed\n * offline resources in one of these families — making the deferral\n * visible to storyboard authors and reviewers rather than burying it in\n * PR prose and JSDoc.\n *\n * `audience` is graded — the buy-side reference lives at\n * `packages[*].targeting_overlay.audience_include[]` and is extracted in\n * `readBuySnapshot`. `catalog_item` and `event_source` are deferred: a\n * buy doesn't reference catalog_items or event_sources by stable id in\n * the cached schema, so the runner can't traverse buy → resource.\n */\n const INVERSE_DEFERRED_FAMILIES: ReadonlySet<string> = new Set(['catalog_item', 'event_source']);\n\n /**\n * Private per-run scratch state. Namespaced under\n * `ctx.state.impairmentCoherence` so generic field names (`offlineResources`,\n * `observedTransition`) can't collide with another assertion that lands\n * later and pokes the same shared `ctx.state` bag.\n */\n interface ImpairmentCoherenceState {\n /** `${resource_type}:${resource_id}` → last observation, offline or not. */\n resourceStatus: Map<string, ResourceObservation>;\n /** `${resource_type}:${resource_id}` for entries currently in an offline status. */\n offlineResources: Map<string, ResourceObservation>;\n /** Run actually observed at least one resource status transition. */\n observedTransition: boolean;\n /** Run actually observed at least one media-buy snapshot read. */\n observedBuySnapshot: boolean;\n /**\n * Per-family count of offline observations the run saw, used by the\n * onEnd summary to flag deferred inverse-rule coverage. A non-zero\n * count for any family in `INVERSE_DEFERRED_FAMILIES` means the run\n * exercised the cross-resource path for a family the runner can't yet\n * grade — surfaced so reviewers see the gap at run-time.\n */\n offlineObservationsByFamily: Map<string, number>;\n /** Successful non-error steps on which lifecycle state could be observed. */\n eligibleStepCount: number;\n }\n\n const IMPAIRMENT_STATE_KEY = 'impairmentCoherence';\n\n function getImpairmentState(ctx: import('./assertions').AssertionContext): ImpairmentCoherenceState {\n // onStart populates the namespaced slot; the cast is safe because no other\n // assertion writes there.\n return ctx.state[IMPAIRMENT_STATE_KEY] as ImpairmentCoherenceState;\n }\n\n registerOnce('impairment.coherence', {\n id: 'impairment.coherence',\n default: true,\n description:\n 'media_buy.impairments[] MUST reference currently-offline resources (forward); any offline resource referenced by a non-terminal buy MUST appear in impairments[] (inverse); health == \"impaired\" iff impairments[] is non-empty.',\n onStart: ctx => {\n const state: ImpairmentCoherenceState = {\n resourceStatus: new Map(),\n offlineResources: new Map(),\n observedTransition: false,\n observedBuySnapshot: false,\n offlineObservationsByFamily: new Map(),\n eligibleStepCount: 0,\n };\n ctx.state[IMPAIRMENT_STATE_KEY] = state;\n },\n onStep: (ctx, stepResult) => {\n if (stepResult.skipped) return [];\n if (stepResult.expect_error) return [];\n if (!stepResult.passed) return [];\n const body = (stepResult as unknown as { response?: unknown }).response;\n if (!body || typeof body !== 'object') return [];\n if (extractAdcpError(stepResult)) return [];\n\n const state = getImpairmentState(ctx);\n state.eligibleStepCount += 1;\n\n type CoherenceResult = {\n passed: boolean;\n description: string;\n step_id: string;\n error?: string;\n status?: 'not_applicable';\n hint?: import('./types').ImpairmentCoherenceHint | import('./types').ImpairmentCoherenceNotApplicableHint;\n };\n const deferredCoverageResults: CoherenceResult[] = [];\n\n // Direct, dedicated extractor for the four families this invariant cares\n // about. NOT routed through `extractStatusObservations` (which is bound\n // to the `status.monotonic` transition graphs and therefore excludes\n // the new offline values `suspended` / `withdrawn` / `insufficient`):\n // monotonic's graphs intentionally enumerate only spec-stable enum\n // values, but those new offline states are exactly what this invariant\n // needs to observe.\n for (const ob of extractImpairmentObservations(stepResult.task, body as Record<string, unknown>)) {\n const key = `${ob.resource_type}:${ob.resource_id}`;\n state.resourceStatus.set(key, { status: ob.status, stepId: stepResult.step_id });\n const offline = IMPAIRMENT_OFFLINE_STATUS.get(ob.resource_type);\n if (offline?.has(ob.status)) {\n const wasOffline = state.offlineResources.has(key);\n state.offlineResources.set(key, { status: ob.status, stepId: stepResult.step_id });\n state.observedTransition = true;\n state.offlineObservationsByFamily.set(\n ob.resource_type,\n (state.offlineObservationsByFamily.get(ob.resource_type) ?? 0) + 1\n );\n\n // Issue #1806: surface deferred inverse-rule coverage at the\n // transition step. When a resource family the runner can't yet\n // reverse-traverse (`catalog_item` / `event_source`) enters an\n // offline state for the first time in this run, emit a\n // `not_applicable` step-level result so reviewers see the gap in\n // run output instead of having to read PR prose. One emission per\n // (resource_type, resource_id) per run — re-syncs of an already\n // offline resource don't re-fire. Only catalog_item and event_source\n // surface here; audience is graded via the inverse rule using refs\n // from packages[*].targeting_overlay.audience_include[].\n if (!wasOffline && (ob.resource_type === 'catalog_item' || ob.resource_type === 'event_source')) {\n const message =\n `inverse-rule coverage for ${ob.resource_type} ${ob.resource_id} ` +\n `(status=\"${ob.status}\", step \"${stepResult.step_id}\") is deferred — ` +\n `buy → resource traversal not yet implemented for this family.`;\n deferredCoverageResults.push({\n passed: true,\n status: 'not_applicable',\n description:\n 'inverse-rule coverage deferred for non-creative offline resource (resource_traversal_deferred)',\n step_id: stepResult.step_id,\n hint: {\n kind: 'impairment_coherence_not_applicable',\n violation: 'inverse',\n reason: 'resource_traversal_deferred',\n message,\n resource_type: ob.resource_type,\n resource_id: ob.resource_id,\n resource_status: ob.status,\n resource_step_id: stepResult.step_id,\n },\n });\n }\n } else {\n // Resource recovered from offline → drop the entry so the inverse\n // rule no longer expects it in impairments[].\n state.offlineResources.delete(key);\n }\n }\n\n // Extract media-buy snapshots and run the three coherence checks.\n const snapshots = extractBuySnapshots(stepResult.task, body as Record<string, unknown>, stepResult.step_id);\n if (snapshots.length === 0) return deferredCoverageResults;\n state.observedBuySnapshot = true;\n\n const description = 'media_buy.impairments[] coheres with resource state and buy health';\n const results: CoherenceResult[] = [];\n\n for (const snap of snapshots) {\n const isTerminal = Boolean(snap.status && !NON_TERMINAL_MEDIA_BUY_STATUSES.has(snap.status));\n\n // Health-iff-impairments check. The spec ties the two together — a\n // buy with non-empty impairments[] MUST report `health: \"impaired\"`,\n // and an `impaired` health MUST have at least one impairment entry.\n // Skip on terminal buys (the spec's terminal carve-out lets the\n // seller stop tracking impairments, which makes the biconditional\n // moot) and on snapshots that omit `health` entirely (sellers\n // without health scoring grade silent).\n if (!isTerminal && snap.health !== undefined) {\n const hasImpairments = snap.impairments.length > 0;\n const isImpaired = snap.health === 'impaired';\n if (hasImpairments !== isImpaired) {\n const message =\n `media_buy ${snap.media_buy_id} health=\"${snap.health}\" but impairments[] has ` +\n `${snap.impairments.length} entries. ` +\n `Spec: health MUST be \"impaired\" iff impairments[] is non-empty (adcp#2859).`;\n results.push({\n passed: false,\n description,\n step_id: stepResult.step_id,\n error: message,\n hint: {\n kind: 'impairment_coherence_violation',\n violation: 'health',\n message,\n media_buy_id: snap.media_buy_id,\n buy_step_id: snap.stepId,\n buy_health: snap.health,\n impairments_count: snap.impairments.length,\n },\n });\n }\n }\n\n // Forward check. Every impairment entry must reference a resource the\n // runner has observed in an offline state. If we have an observation\n // and it's NOT offline, the seller is reporting a phantom impairment;\n // if we have no observation at all, grade silent (can't disprove).\n for (const entry of snap.impairments) {\n const key = `${entry.resource_type}:${entry.resource_id}`;\n const offline = IMPAIRMENT_OFFLINE_STATUS.get(entry.resource_type);\n if (!offline) continue; // property or unknown family — skip silently\n if (state.offlineResources.has(key)) continue; // ok, we agree it's offline\n\n const lastStatus = state.resourceStatus.get(key);\n if (!lastStatus) continue; // never observed — can't grade\n\n const offlineList = [...offline].sort().join(', ');\n const message =\n `media_buy ${snap.media_buy_id} impairments[] references ${entry.resource_type} ` +\n `${entry.resource_id}, but its last observed status is \"${lastStatus.status}\" (step \"${lastStatus.stepId}\"). ` +\n `Offline statuses for ${entry.resource_type}: ${offlineList}.`;\n results.push({\n passed: false,\n description,\n step_id: stepResult.step_id,\n error: message,\n hint: {\n kind: 'impairment_coherence_violation',\n violation: 'forward',\n message,\n media_buy_id: snap.media_buy_id,\n buy_step_id: snap.stepId,\n resource_type: entry.resource_type,\n resource_id: entry.resource_id,\n resource_status: lastStatus.status,\n resource_step_id: lastStatus.stepId,\n impairments_count: snap.impairments.length,\n },\n });\n }\n\n // Inverse check. For each resource the buy references — creatives\n // via `packages[].creative_assignments[].creative_id`, audiences via\n // `packages[].targeting_overlay.audience_include[]` — if the runner\n // has it in the offline set AND the buy is non-terminal AND the\n // impairments[] list doesn't mention it, the seller failed to\n // propagate the resource state into the buy. `catalog_item` and\n // `event_source` inverse coverage is still deferred: their buy-side\n // reference shape isn't yet stable enough in the cached schema to\n // extract without ambiguity.\n if (isTerminal) continue;\n\n for (const [resourceType, referencedIds] of [\n ['creative', snap.referencedCreativeIds] as const,\n ['audience', snap.referencedAudienceIds] as const,\n ]) {\n const impairedIds = new Set(\n snap.impairments.filter(e => e.resource_type === resourceType).map(e => e.resource_id)\n );\n for (const resourceId of referencedIds) {\n const key = `${resourceType}:${resourceId}`;\n const offline = state.offlineResources.get(key);\n if (!offline) continue;\n if (impairedIds.has(resourceId)) continue;\n const message =\n `media_buy ${snap.media_buy_id} (status=\"${snap.status ?? 'unknown'}\") references ${resourceType} ` +\n `${resourceId} which is offline (status=\"${offline.status}\", step \"${offline.stepId}\"), ` +\n `but impairments[] does not list it. Spec: any offline resource referenced by a ` +\n `non-terminal buy MUST appear in impairments[] (adcp#2859).`;\n results.push({\n passed: false,\n description,\n step_id: stepResult.step_id,\n error: message,\n hint: {\n kind: 'impairment_coherence_violation',\n violation: 'inverse',\n message,\n media_buy_id: snap.media_buy_id,\n buy_step_id: snap.stepId,\n resource_type: resourceType,\n resource_id: resourceId,\n resource_status: offline.status,\n resource_step_id: offline.stepId,\n impairments_count: snap.impairments.length,\n },\n });\n }\n }\n }\n\n if (results.length === 0) {\n return [...deferredCoverageResults, { passed: true, description, step_id: stepResult.step_id }];\n }\n return [...deferredCoverageResults, ...results];\n },\n // Emit a run-level summary so the track rollup can distinguish\n // \"wired and exercised\" from \"wired but neither side observed\". When\n // either side is missing the assertion is functionally NA — the spec\n // issue explicitly carves out that case rather than treating it as a\n // silent pass with false confidence.\n onEnd: ctx => {\n const state = ctx.state[IMPAIRMENT_STATE_KEY] as ImpairmentCoherenceState | undefined;\n if (!state || state.eligibleStepCount === 0) return [];\n const exercised = Boolean(state?.observedTransition && state?.observedBuySnapshot);\n const results: Omit<import('./types').AssertionResult, 'assertion_id' | 'scope'>[] = [\n {\n passed: true,\n description: 'media_buy.impairments[] coheres with resource state and buy health',\n observation_count: exercised ? 1 : 0,\n status: exercised ? ('pass' as const) : ('silent' as const),\n },\n ];\n\n // Surface partial inverse-rule coverage. If the run observed at least\n // one offline resource in a deferred family (audience, catalog_item,\n // event_source), the inverse rule's silence on those families is\n // material to this run — naming the gap loudly at the end of the run\n // beats burying it in PR prose and JSDoc.\n if (state) {\n const deferredCounts: { family: string; count: number }[] = [];\n for (const family of INVERSE_DEFERRED_FAMILIES) {\n const count = state.offlineObservationsByFamily.get(family) ?? 0;\n if (count > 0) deferredCounts.push({ family, count });\n }\n if (deferredCounts.length > 0) {\n const summary = deferredCounts.map(d => `${d.family} (${d.count})`).join(', ');\n results.push({\n passed: true,\n description:\n 'inverse coverage gap: offline resources observed for families the runner does not yet grade ' +\n 'on the inverse rule (creative and audience are graded; catalog_item and event_source are forward-only). ' +\n `Observed: ${summary}.`,\n observation_count: 0,\n });\n }\n }\n\n return results;\n },\n });\n\n /**\n * Dedicated status extractor for the resource families this invariant\n * grades. Returns `(resource_type, resource_id, status)` triples for every\n * shape the spec carries an offline value on. Independent of\n * `status.monotonic`'s `extractStatusObservations` so the new offline\n * statuses (`suspended`, `withdrawn`, `insufficient`) — which monotonic's\n * graphs intentionally don't enumerate — are still observable here.\n */\n function extractImpairmentObservations(\n task: string,\n body: Record<string, unknown>\n ): { resource_type: string; resource_id: string; status: string }[] {\n const out: { resource_type: string; resource_id: string; status: string }[] = [];\n if (task === 'sync_creatives' || task === 'list_creatives') {\n for (const c of asArray(body.creatives)) {\n if (!isObject(c)) continue;\n const id = asString(c.creative_id);\n const status = asString(c.status);\n if (id && status) out.push({ resource_type: 'creative', resource_id: id, status });\n }\n } else if (task === 'sync_audiences') {\n for (const a of asArray(body.audiences)) {\n if (!isObject(a)) continue;\n const id = asString(a.audience_id);\n const status = asString(a.status);\n if (id && status) out.push({ resource_type: 'audience', resource_id: id, status });\n }\n } else if (task === 'sync_catalogs' || task === 'list_catalogs') {\n // Two response shapes: catalogs[].items[] (nested) or items[] (flat).\n // Heterogeneous item ids — prefer `item_id` (spec-canonical), then\n // `offering_id` (SI), `sku` (retail), else `id`. Matches the fallback\n // chain in `pushCatalogItem`.\n const collect = (item: Record<string, unknown>) => {\n const id = asString(item.item_id) ?? asString(item.offering_id) ?? asString(item.sku) ?? asString(item.id);\n const status = asString(item.status);\n if (id && status) out.push({ resource_type: 'catalog_item', resource_id: id, status });\n };\n for (const cat of asArray(body.catalogs)) {\n if (!isObject(cat)) continue;\n for (const item of asArray(cat.items)) if (isObject(item)) collect(item);\n }\n for (const item of asArray(body.items)) if (isObject(item)) collect(item);\n } else if (task === 'sync_event_sources') {\n for (const es of asArray(body.event_sources)) {\n if (!isObject(es)) continue;\n const id = asString(es.event_source_id);\n // event_source health lives under `health.status` per\n // `core/event-source-health.json`; the top-level enum is\n // `assessment-status.json` (`insufficient | minimum | good | excellent`).\n const health = isObject(es.health) ? es.health : undefined;\n const status = health ? asString(health.status) : undefined;\n if (id && status) out.push({ resource_type: 'event_source', resource_id: id, status });\n }\n }\n return out;\n }\n\n /**\n * Extract every media-buy snapshot present on a step response. Walks\n * `create_media_buy` / `update_media_buy` (top-level buy object) and\n * `get_media_buys` (`media_buys[]` array). Returns each snapshot's\n * impairments[], health, status, the set of `creative_id`s the buy\n * references through `packages[].creative_assignments[]`, and the set of\n * `audience_id`s referenced through `packages[].targeting_overlay.audience_include[]`.\n * Both reference sets feed the inverse rule. `audience_exclude` is not\n * collected as a hard dependency for the inverse rule: an offline exclude\n * does not prevent the buy from serving, so it isn't a \"buy can't function\"\n * signal. Note this is a serviceability framing, not a safety framing —\n * an offline exclude can still silently break the suppression promise,\n * which is a separate (forward-looking) signal class.\n */\n function extractBuySnapshots(task: string, body: Record<string, unknown>, stepId: string): BuySnapshot[] {\n const out: BuySnapshot[] = [];\n if (task === 'create_media_buy' || task === 'update_media_buy') {\n const snap = readBuySnapshot(body, stepId);\n if (snap) out.push(snap);\n } else if (task === 'get_media_buys') {\n for (const mb of asArray(body.media_buys)) {\n if (!isObject(mb)) continue;\n const snap = readBuySnapshot(mb, stepId);\n if (snap) out.push(snap);\n }\n }\n return out;\n }\n\n function readBuySnapshot(record: Record<string, unknown>, stepId: string): BuySnapshot | undefined {\n const media_buy_id = asString(record.media_buy_id);\n if (!media_buy_id) return undefined;\n const status = asString(record.status);\n const health = asString(record.health);\n const impairments: ImpairmentEntry[] = [];\n for (const entry of asArray(record.impairments)) {\n if (!isObject(entry)) continue;\n const resource_type = asString(entry.resource_type);\n const resource_id = asString(entry.resource_id);\n if (!resource_type || !resource_id) continue;\n impairments.push({ resource_type, resource_id });\n }\n const referencedCreativeIds = new Set<string>();\n const referencedAudienceIds = new Set<string>();\n for (const pkg of asArray(record.packages)) {\n if (!isObject(pkg)) continue;\n // Creative refs appear in two shapes on the wire:\n // - `core/package.json` → `creative_assignments[].creative_id` (used on\n // create_media_buy request/response, update_media_buy)\n // - `get-media-buys-response.json` → `creative_approvals[].creative_id`\n // (the snapshot shape — `creative_approvals` carries per-assignment\n // approval_status alongside the id)\n // Walk both — sellers conformant to either schema surface the references\n // we need for the inverse rule.\n for (const ca of asArray(pkg.creative_assignments)) {\n if (!isObject(ca)) continue;\n const cid = asString(ca.creative_id);\n if (cid) referencedCreativeIds.add(cid);\n }\n for (const ca of asArray(pkg.creative_approvals)) {\n if (!isObject(ca)) continue;\n const cid = asString(ca.creative_id);\n if (cid) referencedCreativeIds.add(cid);\n }\n // Audience refs: only `audience_include` counts as a hard dependency\n // for the inverse rule. `audience_exclude` is omitted on serviceability\n // grounds — a suspended exclude doesn't keep the buy from serving — not\n // on safety grounds. An offline exclude can still silently break the\n // suppression promise; that's a separate signal class (see extractBuySnapshots).\n const overlay = isObject(pkg.targeting_overlay) ? pkg.targeting_overlay : undefined;\n if (overlay) {\n for (const aid of asArray(overlay.audience_include)) {\n if (typeof aid === 'string' && aid.length > 0) referencedAudienceIds.add(aid);\n }\n }\n }\n return {\n media_buy_id,\n status,\n health,\n impairments,\n referencedCreativeIds,\n referencedAudienceIds,\n stepId,\n };\n }\n}\n\n// Register on module load too, so merely importing this module (or a direct\n// `require('.../default-invariants')`) still registers the defaults —\n// preserving the historical side-effect-on-import behaviour. Idempotent via\n// the `REGISTERED` guard, so the explicit calls from the storyboard and\n// compliance entry points are harmless repeats.\nregisterDefaultInvariants();\n"],"mappings":"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","names":["anchor"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/storyboard/default-invariants.ts"],"sourcesContent":["/**\n * Default assertion registrations for invariant ids that upstream storyboards\n * reference but that every SDK consumer would otherwise have to implement\n * themselves. Importing this module side-registers the ids below, so\n * `resolveAssertions` doesn't throw on fresh `@adcp/sdk` installs.\n *\n * The implementations aim for the spec's stated intent, not byte-perfect\n * fidelity with the upstream reference. Consumers can override a default by\n * calling `registerAssertion(spec, { override: true })` with a stricter\n * implementation of their own.\n *\n * Registered ids:\n * - `idempotency.conflict_no_payload_leak` — when a mutating step returns\n * `IDEMPOTENCY_CONFLICT`, the error envelope must carry only allowlisted\n * keys. Any other top-level property is flagged as a potential payload\n * leak (stolen-key read oracle).\n * - `context.no_secret_echo` — response bodies (not just `.context`) MUST\n * NOT contain bearer tokens, API keys, auth header values, or any leaf\n * string extracted from the caller-supplied `auth` union. Walks the\n * whole body, matches on suspect property names at any depth, and\n * catches bearer-token literals via regex.\n * - `governance.denial_blocks_mutation` — once a plan is denied by a\n * governance signal (GOVERNANCE_DENIED, CAMPAIGN_SUSPENDED, etc., or\n * `check_governance` returning `status: \"denied\"`), no subsequent step\n * in the run may acquire a resource for that plan. Plan-scoped via\n * `plan_id`; runs without a denial signal are a silent pass.\n * - `status.monotonic` — across the steps of a run, no observed resource's\n * `status` (or creative `approval_status`) may transition along an edge\n * that is not in the spec-published lifecycle graph for its resource\n * type. Catches regressions like `active → pending_creatives` that\n * per-step validations miss. Scoped by `(resource_type, resource_id)`\n * so unrelated resources don't interfere. Tables below cite the spec\n * enum schemas in `static/schemas/source/enums/*-status.json`.\n * - `impairment.coherence` — cross-resource invariant: every entry in\n * `media_buy.impairments[]` MUST reference a resource the seller has\n * reported in an offline state (forward); any resource the run\n * transitioned to an offline state AND that the buy references MUST\n * appear in `impairments[]` while the buy is non-terminal (inverse);\n * `health == \"impaired\"` iff `impairments[]` is non-empty. See\n * adcontextprotocol/adcp#2859 for the originating spec issue.\n */\n\nimport { ADCP_VERSION } from '../../version';\nimport { CONFLICT_ADCP_ERROR_ALLOWLIST } from '../../server/envelope-allowlist';\nimport { STANDARD_ERROR_CODES } from '../../types/error-codes';\nimport {\n CREATIVE_ASSET_TRANSITIONS as CREATIVE_ASSET_TRANSITIONS_TYPED,\n MEDIA_BUY_TRANSITIONS as MEDIA_BUY_TRANSITIONS_TYPED,\n} from '../../server/state-machine';\nimport { registerAssertion } from './assertions';\n\n// Register only once per process. `registerAssertion` throws on duplicates —\n// consumers who import `@adcp/sdk/testing` multiple times would hit that.\nconst REGISTERED = new Set<string>();\n\nfunction registerOnce(id: string, spec: Parameters<typeof registerAssertion>[0]): void {\n if (REGISTERED.has(id)) return;\n REGISTERED.add(id);\n registerAssertion(spec);\n}\n\n/**\n * Register the default invariant assertions into the shared registry.\n *\n * Idempotent (guarded by `REGISTERED`), so the storyboard runner and the\n * compliance harness can both call it. Invoked explicitly by those entry\n * points rather than through a bare `import './default-invariants'` for side\n * effect: a side-effect-only import is fragile — ESM extension rewriting and\n * bundler tree-shaking can silently drop it, leaving the assertion registry\n * empty and `resolveAssertions` throwing.\n */\nexport function registerDefaultInvariants(): void {\n registerOnce('idempotency.conflict_no_payload_leak', {\n id: 'idempotency.conflict_no_payload_leak',\n default: true,\n description:\n 'IDEMPOTENCY_CONFLICT errors MUST NOT echo the prior request payload or response (stolen-key read oracle).',\n onStep: (_ctx, stepResult) => {\n const err = extractAdcpError(stepResult);\n if (!err) return [];\n if (err.code !== 'IDEMPOTENCY_CONFLICT') return [];\n\n const description = 'IDEMPOTENCY_CONFLICT error redacts prior payload';\n const leaked: string[] = [];\n for (const key of Object.keys(err.details)) {\n if (!CONFLICT_ADCP_ERROR_ALLOWLIST.has(key)) leaked.push(key);\n }\n const expectedRecovery = STANDARD_ERROR_CODES.IDEMPOTENCY_CONFLICT.recovery;\n if ('recovery' in err.details && err.details.recovery !== expectedRecovery) {\n return [\n {\n passed: false,\n description,\n step_id: stepResult.step_id,\n error:\n `IDEMPOTENCY_CONFLICT error envelope carried non-standard recovery metadata: ` +\n `expected ${JSON.stringify(expectedRecovery)}.`,\n },\n ];\n }\n if (leaked.length === 0) {\n return [{ passed: true, description, step_id: stepResult.step_id }];\n }\n return [\n {\n passed: false,\n description,\n step_id: stepResult.step_id,\n error:\n `IDEMPOTENCY_CONFLICT error envelope leaked non-allowlisted field(s): ${leaked.sort().join(', ')}. ` +\n `Allowed envelope keys (ADCP_ERROR_FIELD_ALLOWLIST.IDEMPOTENCY_CONFLICT): ` +\n `${[...CONFLICT_ADCP_ERROR_ALLOWLIST].join(', ')}.`,\n },\n ];\n },\n });\n\n /**\n * Bearer-token literal pattern. Matches the wire form a seller might echo\n * from `Authorization: Bearer <token>` — case-insensitive `bearer` keyword\n * followed by a token body of at least 10 characters of base64url / JWT\n * vocabulary. Kept strict on length to avoid false positives on prose like\n * \"bearer of bad news\".\n */\n const BEARER_TOKEN_PATTERN = /\\bbearer\\s+[A-Za-z0-9._~+/=-]{10,}/i;\n\n /**\n * Property names that MUST NOT appear on a response body — a seller that\n * serializes `Authorization` / `api_key` / `x-api-key` headers or fields\n * into the response is almost certainly leaking credentials, regardless of\n * whether the scanner picks up the value verbatim (header normalization,\n * whitespace differences, etc. can mask verbatim matches). Case-insensitive.\n */\n const SUSPECT_PROPERTY_NAMES = new Set(['authorization', 'api_key', 'apikey', 'bearer', 'x-api-key']);\n\n /**\n * Minimum length for a caller-supplied secret to be hunted for verbatim.\n * Set to 16 because real OAuth access tokens, refresh tokens, and signing\n * secrets are ≥20 chars by convention (opaque UUIDs, JWTs, HMAC hex). A\n * shorter floor would false-positive on benign identifiers (short\n * usernames, environment names, 8-char hex prefixes, ISO timestamps).\n * Hand-coded fixture keys like `\"test-key\"` below this bar are not caught\n * — that's the right tradeoff: a real agent echoing such a value is an\n * obvious leak a human reviewer would spot, and the collision cost of\n * matching short strings against every response body is too high to\n * justify the coverage.\n */\n const SECRET_MIN_LENGTH = 16;\n\n registerOnce('context.no_secret_echo', {\n id: 'context.no_secret_echo',\n default: true,\n description: 'Response bodies MUST NOT echo bearer tokens, API keys, or auth header values back to the caller.',\n onStart: ctx => {\n // Stash caller-supplied secrets worth hunting verbatim. `auth` is the\n // structured discriminated union from TestOptions — we walk it and\n // extract leaf strings so `String.includes(obj)` can't silently no-op.\n // test_kit api_key pickup matches what storyboards typically stage;\n // options.secrets is a consumer hook for custom credentials.\n const secrets = new Set<string>();\n const optAny = ctx.options as unknown as {\n auth_token?: string;\n auth?: unknown;\n secrets?: string[];\n test_kit?: { auth?: { api_key?: string; basic?: unknown } };\n };\n addIfSecret(secrets, optAny.auth_token);\n for (const s of extractAuthSecrets(optAny.auth)) addIfSecret(secrets, s);\n for (const s of optAny.secrets ?? []) addIfSecret(secrets, s);\n addIfSecret(secrets, optAny.test_kit?.auth?.api_key);\n for (const s of extractBasicSecrets(optAny.test_kit?.auth?.basic)) addIfSecret(secrets, s);\n ctx.state.secrets = secrets;\n },\n onStep: (ctx, stepResult) => {\n const body = (stepResult as unknown as { response?: unknown }).response;\n if (body === undefined || body === null) return [];\n\n const secrets = (ctx.state.secrets as Set<string> | undefined) ?? new Set<string>();\n const description = 'Response omits caller-supplied secrets and credential-shaped fields';\n\n const hit = findSecretEcho(body, secrets);\n if (hit) {\n return [\n {\n passed: false,\n description,\n step_id: stepResult.step_id,\n error: `step \"${stepResult.step_id}\" response ${hit}`,\n },\n ];\n }\n return [{ passed: true, description, step_id: stepResult.step_id }];\n },\n });\n\n /**\n * Recursively walk `value` hunting for (a) suspect property names at any\n * depth, (b) bearer-token literals in any string value, and (c) verbatim\n * copies of caller-supplied secrets. First hit wins; the caller turns the\n * reason into a human-readable error message.\n */\n function findSecretEcho(value: unknown, secrets: Set<string>): string | null {\n const stack: unknown[] = [value];\n while (stack.length > 0) {\n const v = stack.pop();\n if (typeof v === 'string') {\n if (BEARER_TOKEN_PATTERN.test(v)) return 'contains a bearer-token literal';\n for (const s of secrets) {\n if (v.includes(s)) return 'contains a caller-supplied secret value verbatim';\n }\n continue;\n }\n if (Array.isArray(v)) {\n for (const item of v) stack.push(item);\n continue;\n }\n if (v !== null && typeof v === 'object') {\n for (const [key, inner] of Object.entries(v as Record<string, unknown>)) {\n // Name-based dragnet. The SUSPECT_PROPERTY_NAMES set catches the\n // \"bare token on a credential-named field\" leak shape that the\n // BEARER_TOKEN_PATTERN value-scan misses (a JWT without `Bearer `\n // prefix won't match the regex). But the dragnet over-rejects\n // when the field's VALUE is a structured object or array — those\n // are spec-legitimate config payloads, not credential echoes.\n // `compliance/cache/{version}/property/validation-result.json`\n // declares an `authorization` object field carrying authorization-\n // validation metadata, not a token; sellers extending\n // `sync_accounts` via the schema's `additionalProperties: true`\n // may carry their own structured `authorization` posture. Both\n // are spec-conformant.\n //\n // Gate the name-based fail on `typeof inner === 'string'` and\n // non-empty so structured values pass through to the recursive\n // walk below. The recursion still scans nested string values, so\n // a `Bearer xyz...` literal embedded in a structured object is\n // still caught by the regex at the top of this loop.\n // Spec: adcp-client#1713 / adcp#4419.\n if (SUSPECT_PROPERTY_NAMES.has(key.toLowerCase()) && typeof inner === 'string' && inner.length > 0) {\n return `contains suspect property name \"${key}\" with string value`;\n }\n stack.push(inner);\n }\n }\n }\n return null;\n }\n\n // ────────────────────────────────────────────────────────────\n // governance.denial_blocks_mutation\n // ────────────────────────────────────────────────────────────\n\n /**\n * Error codes that signal a seller-side refusal with plan scope. Grounded\n * in `ErrorCodeSchema` in `src/lib/types/schemas.generated.ts`. Excludes\n * transient (`GOVERNANCE_UNAVAILABLE` — no decision rendered) and\n * account-state (`ACCOUNT_SUSPENDED`) codes — those aren't plan denials.\n */\n const GOVERNANCE_DENIAL_CODES = new Set([\n 'GOVERNANCE_DENIED',\n 'CAMPAIGN_SUSPENDED',\n 'PERMISSION_DENIED',\n 'POLICY_VIOLATION',\n 'TERMS_REJECTED',\n 'COMPLIANCE_UNSATISFIED',\n ]);\n\n /**\n * Write-class tasks whose successful response carries a server-minted\n * resource id at the top level. Read tasks (`get_*`, `list_*`,\n * `check_governance`) can echo ids without having created anything; they\n * are excluded so the assertion doesn't false-positive on lookups after\n * a denial. Sync-batch tasks (`sync_*`) are excluded until per-item\n * acquisition detection lands — see follow-up in the spec repo.\n */\n const GOVERNANCE_WRITE_TASKS = new Set([\n 'create_media_buy',\n 'update_media_buy',\n 'activate_signal',\n 'create_property_list',\n 'update_property_list',\n 'delete_property_list',\n 'create_collection_list',\n 'update_collection_list',\n 'delete_collection_list',\n 'acquire_rights',\n ]);\n\n const GOVERNANCE_ACQUIRED_STATUSES = new Set(['pending_creatives', 'pending_start', 'active', 'paused', 'completed']);\n\n const GOVERNANCE_RESOURCE_ID_FIELDS = [\n 'media_buy_id',\n 'plan_id',\n 'creative_id',\n 'audience_id',\n 'catalog_id',\n 'activation_id',\n 'property_list_id',\n 'collection_list_id',\n 'acquisition_id',\n 'operation_id',\n ];\n\n interface GovernanceDenialAnchor {\n stepId: string;\n signal: string;\n }\n\n registerOnce('governance.denial_blocks_mutation', {\n id: 'governance.denial_blocks_mutation',\n default: true,\n description:\n 'Once a governance signal denies a plan, no subsequent step in the run may acquire a resource for that plan.',\n onStart: ctx => {\n ctx.state.deniedPlans = new Map<string, GovernanceDenialAnchor>();\n ctx.state.runDenial = undefined;\n },\n onStep: (ctx, stepResult) => {\n const state = ctx.state as {\n deniedPlans: Map<string, GovernanceDenialAnchor>;\n runDenial?: GovernanceDenialAnchor;\n };\n const planId = extractGovernancePlanId(stepResult);\n\n // Denial observation is never itself a failure — record and return.\n const denial = detectGovernanceDenial(stepResult);\n if (denial) {\n // A step marked `expect_error: true` is the storyboard author explicitly\n // acknowledging the denial. Subsequent mutations in the same run are a\n // recovery path, not a silent bypass — don't anchor. The invariant still\n // catches silent denials (check_governance 200 `status: denied`, or\n // adcp_error responses the author did not expect).\n if (stepResult.expect_error) return [];\n const anchor: GovernanceDenialAnchor = { stepId: stepResult.step_id, signal: denial };\n if (planId) {\n if (!state.deniedPlans.has(planId)) state.deniedPlans.set(planId, anchor);\n } else if (!state.runDenial) {\n state.runDenial = anchor;\n }\n return [];\n }\n\n const acquired = detectGovernanceAcquisition(stepResult);\n if (!acquired) return [];\n\n const anchor = (planId && state.deniedPlans.get(planId)) ?? state.runDenial;\n if (!anchor) return [];\n\n // Always surface the step-level escape hatch — it's the one hint that\n // works for both wire-error denials and `check_governance` 200\n // `status: denied`. Names the step, names the field, shows the YAML so\n // the author doesn't have to re-derive the escape from source.\n const escapeHint =\n `. If the denial at step \"${anchor.stepId}\" is an intentional recovery-path setup, add to that step:\\n` +\n ` invariants:\\n` +\n ` disable: [governance.denial_blocks_mutation]`;\n\n return [\n {\n passed: false,\n description: 'Mutation acquired a resource after a governance denial',\n step_id: stepResult.step_id,\n error:\n `step \"${anchor.stepId}\" returned ${anchor.signal}` +\n (planId ? ` for plan_id=${planId}` : ' (run-wide)') +\n `; subsequent step \"${stepResult.step_id}\" (task=${stepResult.task}) ` +\n `acquired ${acquired.field}=${acquired.id}` +\n (planId ? ' for the same plan' : '') +\n escapeHint,\n },\n ];\n },\n });\n\n function detectGovernanceDenial(step: import('./types').StoryboardStepResult): string | undefined {\n const err = extractAdcpError(step);\n if (err && GOVERNANCE_DENIAL_CODES.has(err.code)) return err.code;\n // `check_governance` decides-no via a 200 response with `status: \"denied\"`\n // (see static/schemas/source/governance/check-governance-response.json in\n // the spec repo). The body isn't wrapped in `adcp_error`.\n if (step.task === 'check_governance') {\n const body = (step as unknown as { response?: unknown }).response;\n if (body && typeof body === 'object') {\n const status = (body as Record<string, unknown>).status;\n if (status === 'denied') return 'CHECK_GOVERNANCE_DENIED';\n }\n }\n return undefined;\n }\n\n function extractGovernancePlanId(step: import('./types').StoryboardStepResult): string | undefined {\n const body = (step as unknown as { response?: unknown }).response;\n if (body && typeof body === 'object') {\n const rec = body as Record<string, unknown>;\n if (typeof rec.plan_id === 'string' && rec.plan_id) return rec.plan_id;\n }\n // The runner records the outgoing payload on `stepResult.request` — read\n // from there rather than accumulated step context to avoid stale plan_id\n // bleed from earlier unrelated steps.\n const req = (step as unknown as { request?: { payload?: unknown } }).request;\n if (req && typeof req.payload === 'object' && req.payload !== null) {\n const payload = req.payload as Record<string, unknown>;\n if (typeof payload.plan_id === 'string' && payload.plan_id) return payload.plan_id;\n }\n return undefined;\n }\n\n function detectGovernanceAcquisition(\n step: import('./types').StoryboardStepResult\n ): { field: string; id: string } | undefined {\n if (step.expect_error) return undefined;\n if (!step.passed) return undefined;\n if (!GOVERNANCE_WRITE_TASKS.has(step.task)) return undefined;\n\n const body = (step as unknown as { response?: unknown }).response;\n if (!body || typeof body !== 'object') return undefined;\n const record = body as Record<string, unknown>;\n\n if (step.task === 'create_media_buy' || step.task === 'update_media_buy') {\n const status = record.status;\n if (typeof status === 'string' && !GOVERNANCE_ACQUIRED_STATUSES.has(status)) return undefined;\n }\n\n for (const field of GOVERNANCE_RESOURCE_ID_FIELDS) {\n const val = record[field];\n if (typeof val === 'string' && val.length > 0) return { field, id: val };\n }\n return undefined;\n }\n\n // ────────────────────────────────────────────────────────────\n // Helpers\n // ────────────────────────────────────────────────────────────\n\n interface AdcpErrorShape {\n code: string;\n details: Record<string, unknown>;\n }\n\n function extractAdcpError(step: import('./types').StoryboardStepResult): AdcpErrorShape | null {\n const resp = (step as unknown as { response?: unknown }).response;\n if (!resp || typeof resp !== 'object') return null;\n const envelope = (resp as { adcp_error?: unknown }).adcp_error;\n if (!envelope || typeof envelope !== 'object') return null;\n const code = (envelope as { code?: unknown }).code;\n if (typeof code !== 'string') return null;\n return { code, details: envelope as Record<string, unknown> };\n }\n\n /**\n * Add a value to the secrets set if it is a non-empty string of at least\n * `SECRET_MIN_LENGTH` chars. Centralises the length guard so every source\n * (structured auth, `auth_token`, `secrets[]`, `test_kit.auth.api_key`)\n * gets the same floor.\n */\n function addIfSecret(out: Set<string>, value: unknown): void {\n if (typeof value !== 'string') return;\n if (value.length < SECRET_MIN_LENGTH) return;\n out.add(value);\n }\n\n const ENV_REFERENCE_PREFIX = '$ENV:';\n\n /**\n * Resolve a possibly `$ENV:VAR`-prefixed credential value to the literal it\n * references at runtime. Mirrors the auth-layer `resolveSecret` in\n * `src/lib/auth/oauth/secret-resolver.ts`, but swallows missing / empty\n * variables instead of throwing — the assertion must never break a\n * storyboard run just because it can't resolve a ref.\n *\n * Returns `undefined` if the value is not an env reference, or if the\n * referenced variable is unset / empty. Callers should skip `undefined`\n * results. The literal `$ENV:FOO` string itself is never returned because\n * it is a reference, not a secret, and cannot appear in an agent response.\n */\n function resolveEnvReference(value: string): string | undefined {\n if (!value.startsWith(ENV_REFERENCE_PREFIX)) return undefined;\n const envVar = value.slice(ENV_REFERENCE_PREFIX.length).trim();\n if (!envVar) return undefined;\n const resolved = process.env[envVar];\n if (!resolved) return undefined;\n return resolved;\n }\n\n /**\n * Push a credential-field string onto `out`, resolving `$ENV:VAR` references\n * to their literal runtime value. Literal values pass through unchanged.\n * `$ENV:` references only contribute the resolved value — the reference\n * string itself is not a secret.\n */\n function pushCredentialValue(out: string[], value: unknown): void {\n if (typeof value !== 'string' || !value) return;\n if (value.startsWith(ENV_REFERENCE_PREFIX)) {\n const resolved = resolveEnvReference(value);\n if (resolved) out.push(resolved);\n return;\n }\n out.push(value);\n }\n\n /**\n * Extract every leaf string secret from a structured `TestOptions.auth` value.\n * Mirrors the four variants in `src/lib/testing/types.ts`:\n * - bearer → `token`\n * - basic → `password` and, when both credentials are\n * present, the `base64(user:pass)` blob an\n * `Authorization: Basic` header carries.\n * Username alone is NOT extracted — it's a\n * public identifier (welcome messages, audit\n * logs, \"last login by X\" echoes legitimately).\n * - oauth → `tokens.access_token`, `tokens.refresh_token`,\n * `client.client_secret` (if confidential)\n * - oauth_client_credentials → `credentials.client_secret` (may be a\n * `$ENV:VAR` reference, resolved at runtime),\n * `tokens.access_token`, `tokens.refresh_token`.\n * `client_id` is NOT extracted — RFC 6749 §2.2\n * is explicit that the client identifier is\n * public and legitimately echoed in token\n * responses, introspection payloads, audit\n * logs, and error bodies.\n *\n * Returns an empty list for anything we can't recognise — the goal is a best-\n * effort extraction, not schema validation. The SECRET_MIN_LENGTH guard is\n * applied by the caller via `addIfSecret`.\n */\n function extractAuthSecrets(auth: unknown): string[] {\n if (!auth || typeof auth !== 'object') return [];\n const a = auth as Record<string, unknown>;\n const out: string[] = [];\n pushCredentialValue(out, a.token); // bearer\n\n // basic: the password is the secret; the base64 blob catches echoes of the\n // full Authorization: Basic header, including RFC 7617-valid empty passwords.\n // Username alone is not a secret.\n if (typeof a.password === 'string') {\n if (a.password) out.push(a.password);\n if (typeof a.username === 'string' && a.username) {\n out.push(Buffer.from(`${a.username}:${a.password}`, 'utf8').toString('base64'));\n }\n }\n\n if (a.tokens && typeof a.tokens === 'object') {\n const t = a.tokens as Record<string, unknown>;\n if (typeof t.access_token === 'string' && t.access_token) out.push(t.access_token);\n if (typeof t.refresh_token === 'string' && t.refresh_token) out.push(t.refresh_token);\n }\n if (a.client && typeof a.client === 'object') {\n const c = a.client as Record<string, unknown>;\n if (typeof c.client_secret === 'string' && c.client_secret) out.push(c.client_secret);\n }\n if (a.credentials && typeof a.credentials === 'object') {\n const c = a.credentials as Record<string, unknown>;\n // client_secret on AgentOAuthClientCredentials may be a `$ENV:VAR`\n // reference — resolve so the assertion compares the real runtime value\n // the AS sees, not the reference string. client_id is NOT extracted\n // (RFC 6749 §2.2 — public identifier).\n pushCredentialValue(out, c.client_secret);\n }\n return out;\n }\n\n function extractBasicSecrets(basic: unknown): string[] {\n if (!basic || typeof basic !== 'object') return [];\n const b = basic as Record<string, unknown>;\n const out: string[] = [];\n if (typeof b.credentials === 'string' && b.credentials) {\n const colonIndex = b.credentials.indexOf(':');\n if (colonIndex > 0) {\n const password = b.credentials.slice(colonIndex + 1);\n if (password) out.push(password);\n out.push(Buffer.from(b.credentials, 'utf8').toString('base64'));\n }\n return out;\n }\n if (typeof b.password === 'string') {\n if (b.password) out.push(b.password);\n if (typeof b.username === 'string' && b.username) {\n out.push(Buffer.from(`${b.username}:${b.password}`, 'utf8').toString('base64'));\n }\n }\n return out;\n }\n\n // ────────────────────────────────────────────────────────────\n // status.monotonic\n // ────────────────────────────────────────────────────────────\n\n /**\n * Per-resource-type lifecycle transition graphs. Each inner map is\n * `from → Set<to>`. An observed transition `prev → curr` is legal iff\n * `TRANSITIONS[type].get(prev)?.has(curr)` (self-edges `prev === curr`\n * are always legal and skipped). The tables are hand-written from the\n * spec enum schemas in `static/schemas/source/enums/*-status.json` and\n * the narrative transitions documented there. When an enum gains a\n * value this module needs an update alongside the schema change — that's\n * the right coupling, visible in PR review.\n *\n * Bidirectional edges are listed in both directions explicitly (no\n * auto-mirroring) so one-way edges like `rejected → processing` for\n * creative assets don't accidentally become reversible.\n */\n interface TransitionGraph {\n readonly transitions: ReadonlyMap<string, ReadonlySet<string>>;\n /**\n * Filename of the canonical enum schema this graph mirrors, relative to\n * `/schemas/<adcp-version>/enums/`. Used to render a deep-link in the\n * assertion failure message so implementors can jump straight to the\n * spec's lifecycle doc instead of grep-searching for it.\n */\n readonly enumFile: string;\n }\n\n const SCHEMA_URL_BASE = 'https://adcontextprotocol.org';\n\n function buildEnumSchemaUrl(enumFile: string): string {\n return `${SCHEMA_URL_BASE}/schemas/${ADCP_VERSION}/enums/${enumFile}`;\n }\n\n // Source of truth for both graphs lives in `server/state-machine.ts` so\n // production sellers and the runner enforce identical edges. Wrap the typed\n // maps in `TransitionGraph` for the runner's string-keyed extractors.\n const MEDIA_BUY_TRANSITIONS: TransitionGraph = {\n transitions: MEDIA_BUY_TRANSITIONS_TYPED as ReadonlyMap<string, ReadonlySet<string>>,\n enumFile: 'media-buy-status.json',\n };\n\n const CREATIVE_ASSET_TRANSITIONS: TransitionGraph = {\n transitions: CREATIVE_ASSET_TRANSITIONS_TYPED as ReadonlyMap<string, ReadonlySet<string>>,\n enumFile: 'creative-status.json',\n };\n\n const CREATIVE_APPROVAL_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/creative-approval-status.json`.\n // Per-assignment approval state on a package. `rejected → pending_review`\n // is allowed on re-sync.\n transitions: new Map<string, ReadonlySet<string>>([\n ['pending_review', new Set(['approved', 'rejected'])],\n ['approved', new Set(['rejected'])],\n ['rejected', new Set(['pending_review'])],\n ]),\n enumFile: 'creative-approval-status.json',\n };\n\n const ACCOUNT_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/account-status.json`. `active ↔\n // suspended` and `active ↔ payment_required` are both reversible.\n // `suspended → payment_required` covers the legitimate case where a\n // suspended account's credit lapses during the suspension window.\n // `rejected | closed` are terminal.\n transitions: new Map<string, ReadonlySet<string>>([\n ['pending_approval', new Set(['active', 'rejected'])],\n ['active', new Set(['suspended', 'payment_required', 'closed'])],\n ['suspended', new Set(['active', 'payment_required', 'closed'])],\n ['payment_required', new Set(['active', 'suspended', 'closed'])],\n ['rejected', new Set()],\n ['closed', new Set()],\n ]),\n enumFile: 'account-status.json',\n };\n\n const SI_SESSION_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/si-session-status.json`.\n // `complete | terminated` are terminal.\n transitions: new Map<string, ReadonlySet<string>>([\n ['active', new Set(['pending_handoff', 'complete', 'terminated'])],\n ['pending_handoff', new Set(['complete', 'terminated'])],\n ['complete', new Set()],\n ['terminated', new Set()],\n ]),\n enumFile: 'si-session-status.json',\n };\n\n const CATALOG_ITEM_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/catalog-item-status.json`. `approved ↔\n // warning` is reversible (seller flags a warning, then clears it).\n // `rejected → pending` is allowed on re-sync. No terminals.\n transitions: new Map<string, ReadonlySet<string>>([\n ['pending', new Set(['approved', 'rejected', 'warning'])],\n ['approved', new Set(['warning', 'rejected'])],\n ['warning', new Set(['approved', 'rejected'])],\n ['rejected', new Set(['pending'])],\n ]),\n enumFile: 'catalog-item-status.json',\n };\n\n const PROPOSAL_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/proposal-status.json`. One-way.\n transitions: new Map<string, ReadonlySet<string>>([\n ['draft', new Set(['committed'])],\n ['committed', new Set()],\n ]),\n enumFile: 'proposal-status.json',\n };\n\n const AUDIENCE_TRANSITIONS: TransitionGraph = {\n // See `static/schemas/source/enums/audience-status.json`. Fully bidirectional\n // across the three states — sellers MAY re-enter `processing` on re-sync\n // from `ready` or `too_small`, and `ready ↔ too_small` can happen as\n // member counts cross `minimum_size` (spec hedges this as MAY, not MUST).\n // No terminals: delete / fail omit `status` entirely via the envelope's\n // `action` field, so there's nothing to record for them.\n transitions: new Map<string, ReadonlySet<string>>([\n ['processing', new Set(['ready', 'too_small'])],\n ['ready', new Set(['processing', 'too_small'])],\n ['too_small', new Set(['processing', 'ready'])],\n ]),\n enumFile: 'audience-status.json',\n };\n\n /**\n * Extractor record per resource type. For each response shape we recognize,\n * describe how to walk the body and emit `(resource_id, status)` pairs.\n * The runner hands us `stepResult.response` — we look at the shape and\n * the task name to disambiguate (e.g. `get_media_buys` vs `sync_creatives`).\n */\n interface StatusObservation {\n resource_type: string;\n resource_id: string;\n status: string;\n graph: TransitionGraph;\n }\n\n /**\n * Task-aware extractors. Each knows the response shape for its task family\n * and walks arrays where present. Unknown tasks produce no observations —\n * the assertion is silent on tasks it doesn't recognize.\n */\n function extractStatusObservations(task: string, body: Record<string, unknown>): StatusObservation[] {\n const obs: StatusObservation[] = [];\n\n // Media-buy: create/update_media_buy return top-level status + packages\n // with per-creative approval_status. get_media_buys returns media_buys[].\n if (task === 'create_media_buy' || task === 'update_media_buy') {\n pushMediaBuy(obs, body);\n } else if (task === 'get_media_buys') {\n for (const mb of asArray(body.media_buys)) {\n if (isObject(mb)) pushMediaBuy(obs, mb);\n }\n }\n\n // Creative asset lifecycle: sync_creatives and list_creatives.\n if (task === 'sync_creatives' || task === 'list_creatives') {\n for (const c of asArray(body.creatives)) {\n if (isObject(c)) pushCreative(obs, c);\n }\n }\n\n // Account: sync_accounts and list_accounts. Embedded `account` objects on\n // media-buy responses do not carry a lifecycle status — they're just\n // references (brand, operator) — so we don't read them here.\n if (task === 'sync_accounts' || task === 'list_accounts') {\n for (const a of asArray(body.accounts)) {\n if (isObject(a)) pushAccount(obs, a);\n }\n }\n\n // SI session: si_initiate_session / si_send_message return top-level\n // `session_id` + `status`.\n if (task === 'si_initiate_session' || task === 'si_send_message' || task === 'si_terminate_session') {\n pushSiSession(obs, body);\n }\n\n // Catalog items: sync_catalogs / list_catalogs return `items[]` per catalog.\n if (task === 'sync_catalogs' || task === 'list_catalogs') {\n for (const cat of asArray(body.catalogs)) {\n if (!isObject(cat)) continue;\n for (const item of asArray(cat.items)) {\n if (isObject(item)) pushCatalogItem(obs, item);\n }\n }\n for (const item of asArray(body.items)) {\n if (isObject(item)) pushCatalogItem(obs, item);\n }\n }\n\n // Proposal: get_products may return a `proposal` object when the\n // caller is refining toward commitment.\n if (task === 'get_products' && isObject(body.proposal)) {\n pushProposal(obs, body.proposal);\n }\n\n // Audience lifecycle: sync_audiences is both the write and discovery path\n // (discovery-only calls omit the request `audiences` array but still return\n // `audiences[]`). No separate list_audiences task exists.\n if (task === 'sync_audiences') {\n for (const a of asArray(body.audiences)) {\n if (isObject(a)) pushAudience(obs, a);\n }\n }\n\n return obs;\n }\n\n function pushMediaBuy(obs: StatusObservation[], record: Record<string, unknown>): void {\n const id = asString(record.media_buy_id);\n // 3.1+: `media_buy_status` (body) carries MediaBuyStatus; top-level\n // `status` (envelope) carries TaskStatus. Pre-3.1 + nested fields on\n // `get_media_buys` / `get_media_buy_delivery`: `status` still carries\n // MediaBuyStatus. Read the canonical 3.1 field first, fall back to\n // legacy. Refs adcontextprotocol/adcp#4895 (3.1 additive-deprecate),\n // #4906 (3.2 legacy removal), #4905 (4.0 nested cascade).\n const status = asString(record.media_buy_status) ?? asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'media_buy',\n resource_id: id,\n status,\n graph: MEDIA_BUY_TRANSITIONS,\n });\n }\n // Each media_buy carries packages; each package can list creative_approvals\n // with per-creative approval_status. Track those against the approval graph.\n for (const pkg of asArray(record.packages)) {\n if (!isObject(pkg)) continue;\n for (const ca of asArray(pkg.creative_approvals)) {\n if (!isObject(ca)) continue;\n const cid = asString(ca.creative_id);\n const astatus = asString(ca.approval_status);\n if (cid && astatus) {\n obs.push({\n resource_type: 'creative_approval',\n resource_id: cid,\n status: astatus,\n graph: CREATIVE_APPROVAL_TRANSITIONS,\n });\n }\n }\n }\n }\n\n function pushCreative(obs: StatusObservation[], record: Record<string, unknown>): void {\n const id = asString(record.creative_id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'creative',\n resource_id: id,\n status,\n graph: CREATIVE_ASSET_TRANSITIONS,\n });\n }\n }\n\n function pushAccount(obs: StatusObservation[], record: Record<string, unknown>): void {\n const id = asString(record.account_id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'account',\n resource_id: id,\n status,\n graph: ACCOUNT_TRANSITIONS,\n });\n }\n }\n\n function pushSiSession(obs: StatusObservation[], record: Record<string, unknown>): void {\n const id = asString(record.session_id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'si_session',\n resource_id: id,\n status,\n graph: SI_SESSION_TRANSITIONS,\n });\n }\n }\n\n function pushCatalogItem(obs: StatusObservation[], record: Record<string, unknown>): void {\n // Catalog items are heterogeneous across catalog types. Prefer `item_id`\n // (spec-canonical on sync/list responses), then domain-specific\n // `offering_id` (SI) and `sku` (retail), then a generic `id` as last\n // resort. The fallback chain silently mis-identifies if a seller echoes\n // a non-canonical id — the resulting history splits per id shape rather\n // than emitting an error. Acceptable tradeoff given schema churn; enum\n // drift stays under `response_schema`'s purview.\n const id = asString(record.item_id) ?? asString(record.offering_id) ?? asString(record.sku) ?? asString(record.id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'catalog_item',\n resource_id: id,\n status,\n graph: CATALOG_ITEM_TRANSITIONS,\n });\n }\n }\n\n function pushProposal(obs: StatusObservation[], record: Record<string, unknown>): void {\n const id = asString(record.proposal_id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'proposal',\n resource_id: id,\n status,\n graph: PROPOSAL_TRANSITIONS,\n });\n }\n }\n\n function pushAudience(obs: StatusObservation[], record: Record<string, unknown>): void {\n // `status` is absent when `action` is `deleted` or `failed` — spec\n // envelope intentionally omits the field rather than emitting a terminal\n // value. The `&& status` guard below makes those observations silent.\n const id = asString(record.audience_id);\n const status = asString(record.status);\n if (id && status) {\n obs.push({\n resource_type: 'audience',\n resource_id: id,\n status,\n graph: AUDIENCE_TRANSITIONS,\n });\n }\n }\n\n interface MonotonicState {\n stepId: string;\n status: string;\n }\n\n registerOnce('status.monotonic', {\n id: 'status.monotonic',\n default: true,\n description:\n 'Observed resource statuses (media_buy, creative, account, si_session, catalog_item, proposal, creative_approval, audience) MUST only transition along edges in the spec lifecycle graph.',\n onStart: ctx => {\n // `${resource_type}:${resource_id}` → last-observed state. Tuple key\n // disambiguates the unlikely `media_buy_id` / `creative_id` collision.\n ctx.state.history = new Map<string, MonotonicState>();\n ctx.state.statusMonotonicEligibleStepCount = 0;\n },\n onStep: (ctx, stepResult) => {\n // Skip error / skipped / negative-path steps. An errored read doesn't\n // observe a new state; `expect_error: true` runs are probing error\n // codes, not transitions.\n if (stepResult.skipped) return [];\n if (stepResult.expect_error) return [];\n if (!stepResult.passed) return [];\n const body = (stepResult as unknown as { response?: unknown }).response;\n if (!body || typeof body !== 'object') return [];\n if (extractAdcpError(stepResult)) return [];\n ctx.state.statusMonotonicEligibleStepCount =\n ((ctx.state.statusMonotonicEligibleStepCount as number | undefined) ?? 0) + 1;\n\n const history = ctx.state.history as Map<string, MonotonicState>;\n const observations = extractStatusObservations(stepResult.task, body as Record<string, unknown>);\n const description = 'Resource statuses transition only along spec lifecycle edges';\n\n for (const ob of observations) {\n const key = `${ob.resource_type}:${ob.resource_id}`;\n const prev = history.get(key);\n if (!prev) {\n history.set(key, { stepId: stepResult.step_id, status: ob.status });\n continue;\n }\n if (prev.status === ob.status) {\n // No-op observation (replay, re-read of unchanged state). Don't emit,\n // don't advance the anchor step — the earlier stepId stays useful for\n // diagnostics if a later backward edge appears.\n continue;\n }\n const allowedTargets = ob.graph.transitions.get(prev.status);\n if (!allowedTargets) {\n // Unknown previous status (enum drift or we missed a state in the\n // table). Don't fail — `response_schema` catches enum violations;\n // reset the anchor so downstream transitions still get checked.\n history.set(key, { stepId: stepResult.step_id, status: ob.status });\n continue;\n }\n if (!allowedTargets.has(ob.status)) {\n // Surface the legal next states + a canonical enum URL so implementors\n // can self-diagnose without grepping the SDK source for the\n // lifecycle table. `allowedTargets` is empty for terminal states\n // (completed / rejected / canceled / etc.) — call that out explicitly\n // rather than rendering an empty list that reads as \"any target is\n // fine, just not this one\".\n const legalTargets = [...allowedTargets].sort();\n const legalDescription =\n legalTargets.length > 0 ? legalTargets.map(t => `\"${t}\"`).join(', ') : '(none — terminal state)';\n const enumUrl = buildEnumSchemaUrl(ob.graph.enumFile);\n const errorMessage =\n `${ob.resource_type} ${ob.resource_id}: ${prev.status} → ${ob.status} ` +\n `(step \"${prev.stepId}\" → step \"${stepResult.step_id}\") is not in the lifecycle graph. ` +\n `Legal next states from \"${prev.status}\": ${legalDescription}. ` +\n `See ${enumUrl} for the canonical lifecycle.`;\n return [\n {\n passed: false,\n description,\n step_id: stepResult.step_id,\n error: errorMessage,\n // Issue #935: structured `MonotonicViolationHint` mirrored into\n // the owning step's `hints[]` so renderers can branch on the\n // discriminator and render the legal-target set in a per-kind\n // template instead of regex-parsing the prose error string.\n hint: {\n kind: 'monotonic_violation',\n message: errorMessage,\n resource_type: ob.resource_type,\n resource_id: ob.resource_id,\n from_status: prev.status,\n to_status: ob.status,\n from_step_id: prev.stepId,\n legal_next_states: legalTargets,\n enum_url: enumUrl,\n },\n },\n ];\n }\n history.set(key, { stepId: stepResult.step_id, status: ob.status });\n }\n\n if (observations.length === 0) return [];\n return [{ passed: true, description, step_id: stepResult.step_id }];\n },\n // Emit a run-level summary so the track rollup can distinguish\n // \"wired and exercised\" (history.size > 0) from \"wired but never\n // observed a lifecycle resource\" (history.size === 0). The latter\n // demotes the track to TrackStatus: 'silent' even though every step\n // and every per-step assertion record passed. Companion to\n // adcontextprotocol/adcp#2834.\n onEnd: ctx => {\n if (((ctx.state.statusMonotonicEligibleStepCount as number | undefined) ?? 0) === 0) return [];\n const history = ctx.state.history as Map<string, MonotonicState> | undefined;\n const observation_count = history?.size ?? 0;\n return [\n {\n passed: true,\n description: 'Resource statuses transition only along spec lifecycle edges',\n observation_count,\n status: observation_count === 0 ? ('silent' as const) : ('pass' as const),\n },\n ];\n },\n });\n\n // Tiny type-safety helpers for the extractors above.\n function isObject(v: unknown): v is Record<string, unknown> {\n return v !== null && typeof v === 'object' && !Array.isArray(v);\n }\n\n function asArray(v: unknown): unknown[] {\n return Array.isArray(v) ? v : [];\n }\n\n function asString(v: unknown): string | undefined {\n return typeof v === 'string' && v.length > 0 ? v : undefined;\n }\n\n // ────────────────────────────────────────────────────────────\n // impairment.coherence\n // ────────────────────────────────────────────────────────────\n\n /**\n * Per-resource-type offline status sets. An impairment entry referencing\n * `(resource_type, resource_id)` is coherent when the runner's last\n * observation for that resource matches one of these values.\n *\n * Sourced from spec issue #2859 plus the resource-status enum schemas:\n * - audience: `suspended` (audience-status.json)\n * - creative: `rejected` (creative-status.json — terminal)\n * - catalog_item: `withdrawn` (catalog-item-status.json)\n * - event_source: `insufficient` (assessment-status.json, on\n * event-source-health.status)\n *\n * `property` is intentionally absent — offline state is sourced from\n * `brand.json` / `adagents.json` depublishing, not from a status enum on\n * the wire. The runner has no observation hook for that transition today,\n * so property-typed impairments grade silent rather than emitting a forward\n * pass / fail. The spec issue calls this out explicitly.\n */\n const IMPAIRMENT_OFFLINE_STATUS: ReadonlyMap<string, ReadonlySet<string>> = new Map([\n ['audience', new Set(['suspended'])],\n ['creative', new Set(['rejected'])],\n ['catalog_item', new Set(['withdrawn'])],\n ['event_source', new Set(['insufficient'])],\n ]);\n\n /**\n * Media-buy statuses that are non-terminal — the inverse rule only applies\n * while the buy is still serving (or about to). The spec issue carves out\n * `completed`, `canceled`, `rejected` as the terminal set that MAY remain\n * unreported because the buy is no longer accruing impressions.\n */\n const NON_TERMINAL_MEDIA_BUY_STATUSES: ReadonlySet<string> = new Set([\n 'pending_creatives',\n 'pending_start',\n 'active',\n 'paused',\n ]);\n\n interface ImpairmentEntry {\n resource_type: string;\n resource_id: string;\n }\n\n interface BuySnapshot {\n media_buy_id: string;\n status: string | undefined;\n health: string | undefined;\n impairments: ImpairmentEntry[];\n referencedCreativeIds: Set<string>;\n referencedAudienceIds: Set<string>;\n stepId: string;\n }\n\n interface ResourceObservation {\n status: string;\n stepId: string;\n }\n\n /**\n * Resource families the inverse rule does NOT yet grade — the buy-side\n * reference shape for these in `media_buy.packages` isn't stable in the\n * cached schema, so we can't reliably tell which buys reference which\n * resources. Listed here so the onEnd summary can emit a runtime\n * \"partial inverse coverage\" signal when the run actually observed\n * offline resources in one of these families — making the deferral\n * visible to storyboard authors and reviewers rather than burying it in\n * PR prose and JSDoc.\n *\n * `audience` is graded — the buy-side reference lives at\n * `packages[*].targeting_overlay.audience_include[]` and is extracted in\n * `readBuySnapshot`. `catalog_item` and `event_source` are deferred: a\n * buy doesn't reference catalog_items or event_sources by stable id in\n * the cached schema, so the runner can't traverse buy → resource.\n */\n const INVERSE_DEFERRED_FAMILIES: ReadonlySet<string> = new Set(['catalog_item', 'event_source']);\n\n /**\n * Private per-run scratch state. Namespaced under\n * `ctx.state.impairmentCoherence` so generic field names (`offlineResources`,\n * `observedTransition`) can't collide with another assertion that lands\n * later and pokes the same shared `ctx.state` bag.\n */\n interface ImpairmentCoherenceState {\n /** `${resource_type}:${resource_id}` → last observation, offline or not. */\n resourceStatus: Map<string, ResourceObservation>;\n /** `${resource_type}:${resource_id}` for entries currently in an offline status. */\n offlineResources: Map<string, ResourceObservation>;\n /** Run actually observed at least one resource status transition. */\n observedTransition: boolean;\n /** Run actually observed at least one media-buy snapshot read. */\n observedBuySnapshot: boolean;\n /**\n * Per-family count of offline observations the run saw, used by the\n * onEnd summary to flag deferred inverse-rule coverage. A non-zero\n * count for any family in `INVERSE_DEFERRED_FAMILIES` means the run\n * exercised the cross-resource path for a family the runner can't yet\n * grade — surfaced so reviewers see the gap at run-time.\n */\n offlineObservationsByFamily: Map<string, number>;\n /** Successful non-error steps on which lifecycle state could be observed. */\n eligibleStepCount: number;\n }\n\n const IMPAIRMENT_STATE_KEY = 'impairmentCoherence';\n\n function getImpairmentState(ctx: import('./assertions').AssertionContext): ImpairmentCoherenceState {\n // onStart populates the namespaced slot; the cast is safe because no other\n // assertion writes there.\n return ctx.state[IMPAIRMENT_STATE_KEY] as ImpairmentCoherenceState;\n }\n\n registerOnce('impairment.coherence', {\n id: 'impairment.coherence',\n default: true,\n description:\n 'media_buy.impairments[] MUST reference currently-offline resources (forward); any offline resource referenced by a non-terminal buy MUST appear in impairments[] (inverse); health == \"impaired\" iff impairments[] is non-empty.',\n onStart: ctx => {\n const state: ImpairmentCoherenceState = {\n resourceStatus: new Map(),\n offlineResources: new Map(),\n observedTransition: false,\n observedBuySnapshot: false,\n offlineObservationsByFamily: new Map(),\n eligibleStepCount: 0,\n };\n ctx.state[IMPAIRMENT_STATE_KEY] = state;\n },\n onStep: (ctx, stepResult) => {\n if (stepResult.skipped) return [];\n if (stepResult.expect_error) return [];\n if (!stepResult.passed) return [];\n const body = (stepResult as unknown as { response?: unknown }).response;\n if (!body || typeof body !== 'object') return [];\n if (extractAdcpError(stepResult)) return [];\n\n const state = getImpairmentState(ctx);\n state.eligibleStepCount += 1;\n\n type CoherenceResult = {\n passed: boolean;\n description: string;\n step_id: string;\n error?: string;\n status?: 'not_applicable';\n hint?: import('./types').ImpairmentCoherenceHint | import('./types').ImpairmentCoherenceNotApplicableHint;\n };\n const deferredCoverageResults: CoherenceResult[] = [];\n\n // Direct, dedicated extractor for the four families this invariant cares\n // about. NOT routed through `extractStatusObservations` (which is bound\n // to the `status.monotonic` transition graphs and therefore excludes\n // the new offline values `suspended` / `withdrawn` / `insufficient`):\n // monotonic's graphs intentionally enumerate only spec-stable enum\n // values, but those new offline states are exactly what this invariant\n // needs to observe.\n for (const ob of extractImpairmentObservations(\n stepResult.task,\n body as Record<string, unknown>,\n stepResult.request?.payload\n )) {\n const key = `${ob.resource_type}:${ob.resource_id}`;\n state.resourceStatus.set(key, { status: ob.status, stepId: stepResult.step_id });\n const offline = IMPAIRMENT_OFFLINE_STATUS.get(ob.resource_type);\n if (offline?.has(ob.status)) {\n const wasOffline = state.offlineResources.has(key);\n state.offlineResources.set(key, { status: ob.status, stepId: stepResult.step_id });\n state.observedTransition = true;\n state.offlineObservationsByFamily.set(\n ob.resource_type,\n (state.offlineObservationsByFamily.get(ob.resource_type) ?? 0) + 1\n );\n\n // Issue #1806: surface deferred inverse-rule coverage at the\n // transition step. When a resource family the runner can't yet\n // reverse-traverse (`catalog_item` / `event_source`) enters an\n // offline state for the first time in this run, emit a\n // `not_applicable` step-level result so reviewers see the gap in\n // run output instead of having to read PR prose. One emission per\n // (resource_type, resource_id) per run — re-syncs of an already\n // offline resource don't re-fire. Only catalog_item and event_source\n // surface here; audience is graded via the inverse rule using refs\n // from packages[*].targeting_overlay.audience_include[].\n if (!wasOffline && (ob.resource_type === 'catalog_item' || ob.resource_type === 'event_source')) {\n const message =\n `inverse-rule coverage for ${ob.resource_type} ${ob.resource_id} ` +\n `(status=\"${ob.status}\", step \"${stepResult.step_id}\") is deferred — ` +\n `buy → resource traversal not yet implemented for this family.`;\n deferredCoverageResults.push({\n passed: true,\n status: 'not_applicable',\n description:\n 'inverse-rule coverage deferred for non-creative offline resource (resource_traversal_deferred)',\n step_id: stepResult.step_id,\n hint: {\n kind: 'impairment_coherence_not_applicable',\n violation: 'inverse',\n reason: 'resource_traversal_deferred',\n message,\n resource_type: ob.resource_type,\n resource_id: ob.resource_id,\n resource_status: ob.status,\n resource_step_id: stepResult.step_id,\n },\n });\n }\n } else {\n // Resource recovered from offline → drop the entry so the inverse\n // rule no longer expects it in impairments[].\n state.offlineResources.delete(key);\n }\n }\n\n // Extract media-buy snapshots and run the three coherence checks.\n const snapshots = extractBuySnapshots(stepResult.task, body as Record<string, unknown>, stepResult.step_id);\n if (snapshots.length === 0) return deferredCoverageResults;\n state.observedBuySnapshot = true;\n\n const description = 'media_buy.impairments[] coheres with resource state and buy health';\n const results: CoherenceResult[] = [];\n\n for (const snap of snapshots) {\n const isTerminal = Boolean(snap.status && !NON_TERMINAL_MEDIA_BUY_STATUSES.has(snap.status));\n\n // Health-iff-impairments check. The spec ties the two together — a\n // buy with non-empty impairments[] MUST report `health: \"impaired\"`,\n // and an `impaired` health MUST have at least one impairment entry.\n // Skip on terminal buys (the spec's terminal carve-out lets the\n // seller stop tracking impairments, which makes the biconditional\n // moot) and on snapshots that omit `health` entirely (sellers\n // without health scoring grade silent).\n if (!isTerminal && snap.health !== undefined) {\n const hasImpairments = snap.impairments.length > 0;\n const isImpaired = snap.health === 'impaired';\n if (hasImpairments !== isImpaired) {\n const message =\n `media_buy ${snap.media_buy_id} health=\"${snap.health}\" but impairments[] has ` +\n `${snap.impairments.length} entries. ` +\n `Spec: health MUST be \"impaired\" iff impairments[] is non-empty (adcp#2859).`;\n results.push({\n passed: false,\n description,\n step_id: stepResult.step_id,\n error: message,\n hint: {\n kind: 'impairment_coherence_violation',\n violation: 'health',\n message,\n media_buy_id: snap.media_buy_id,\n buy_step_id: snap.stepId,\n buy_health: snap.health,\n impairments_count: snap.impairments.length,\n },\n });\n }\n }\n\n // Forward check. Every impairment entry must reference a resource the\n // runner has observed in an offline state. If we have an observation\n // and it's NOT offline, the seller is reporting a phantom impairment;\n // if we have no observation at all, grade silent (can't disprove).\n for (const entry of snap.impairments) {\n const key = `${entry.resource_type}:${entry.resource_id}`;\n const offline = IMPAIRMENT_OFFLINE_STATUS.get(entry.resource_type);\n if (!offline) continue; // property or unknown family — skip silently\n if (state.offlineResources.has(key)) continue; // ok, we agree it's offline\n\n const lastStatus = state.resourceStatus.get(key);\n if (!lastStatus) continue; // never observed — can't grade\n\n const offlineList = [...offline].sort().join(', ');\n const message =\n `media_buy ${snap.media_buy_id} impairments[] references ${entry.resource_type} ` +\n `${entry.resource_id}, but its last observed status is \"${lastStatus.status}\" (step \"${lastStatus.stepId}\"). ` +\n `Offline statuses for ${entry.resource_type}: ${offlineList}.`;\n results.push({\n passed: false,\n description,\n step_id: stepResult.step_id,\n error: message,\n hint: {\n kind: 'impairment_coherence_violation',\n violation: 'forward',\n message,\n media_buy_id: snap.media_buy_id,\n buy_step_id: snap.stepId,\n resource_type: entry.resource_type,\n resource_id: entry.resource_id,\n resource_status: lastStatus.status,\n resource_step_id: lastStatus.stepId,\n impairments_count: snap.impairments.length,\n },\n });\n }\n\n // Inverse check. For each resource the buy references — creatives\n // via `packages[].creative_assignments[].creative_id`, audiences via\n // `packages[].targeting_overlay.audience_include[]` — if the runner\n // has it in the offline set AND the buy is non-terminal AND the\n // impairments[] list doesn't mention it, the seller failed to\n // propagate the resource state into the buy. `catalog_item` and\n // `event_source` inverse coverage is still deferred: their buy-side\n // reference shape isn't yet stable enough in the cached schema to\n // extract without ambiguity.\n if (isTerminal) continue;\n\n for (const [resourceType, referencedIds] of [\n ['creative', snap.referencedCreativeIds] as const,\n ['audience', snap.referencedAudienceIds] as const,\n ]) {\n const impairedIds = new Set(\n snap.impairments.filter(e => e.resource_type === resourceType).map(e => e.resource_id)\n );\n for (const resourceId of referencedIds) {\n const key = `${resourceType}:${resourceId}`;\n const offline = state.offlineResources.get(key);\n if (!offline) continue;\n if (impairedIds.has(resourceId)) continue;\n const message =\n `media_buy ${snap.media_buy_id} (status=\"${snap.status ?? 'unknown'}\") references ${resourceType} ` +\n `${resourceId} which is offline (status=\"${offline.status}\", step \"${offline.stepId}\"), ` +\n `but impairments[] does not list it. Spec: any offline resource referenced by a ` +\n `non-terminal buy MUST appear in impairments[] (adcp#2859).`;\n results.push({\n passed: false,\n description,\n step_id: stepResult.step_id,\n error: message,\n hint: {\n kind: 'impairment_coherence_violation',\n violation: 'inverse',\n message,\n media_buy_id: snap.media_buy_id,\n buy_step_id: snap.stepId,\n resource_type: resourceType,\n resource_id: resourceId,\n resource_status: offline.status,\n resource_step_id: offline.stepId,\n impairments_count: snap.impairments.length,\n },\n });\n }\n }\n }\n\n if (results.length === 0) {\n return [...deferredCoverageResults, { passed: true, description, step_id: stepResult.step_id }];\n }\n return [...deferredCoverageResults, ...results];\n },\n // Emit a run-level summary so the track rollup can distinguish\n // \"wired and exercised\" from \"wired but neither side observed\". When\n // either side is missing the assertion is functionally NA — the spec\n // issue explicitly carves out that case rather than treating it as a\n // silent pass with false confidence.\n onEnd: ctx => {\n const state = ctx.state[IMPAIRMENT_STATE_KEY] as ImpairmentCoherenceState | undefined;\n if (!state || state.eligibleStepCount === 0) return [];\n const exercised = Boolean(state?.observedTransition && state?.observedBuySnapshot);\n const results: Omit<import('./types').AssertionResult, 'assertion_id' | 'scope'>[] = [\n {\n passed: true,\n description: 'media_buy.impairments[] coheres with resource state and buy health',\n observation_count: exercised ? 1 : 0,\n status: exercised ? ('pass' as const) : ('silent' as const),\n },\n ];\n\n // Surface partial inverse-rule coverage. If the run observed at least\n // one offline resource in a deferred family (audience, catalog_item,\n // event_source), the inverse rule's silence on those families is\n // material to this run — naming the gap loudly at the end of the run\n // beats burying it in PR prose and JSDoc.\n if (state) {\n const deferredCounts: { family: string; count: number }[] = [];\n for (const family of INVERSE_DEFERRED_FAMILIES) {\n const count = state.offlineObservationsByFamily.get(family) ?? 0;\n if (count > 0) deferredCounts.push({ family, count });\n }\n if (deferredCounts.length > 0) {\n const summary = deferredCounts.map(d => `${d.family} (${d.count})`).join(', ');\n results.push({\n passed: true,\n description:\n 'inverse coverage gap: offline resources observed for families the runner does not yet grade ' +\n 'on the inverse rule (creative and audience are graded; catalog_item and event_source are forward-only). ' +\n `Observed: ${summary}.`,\n observation_count: 0,\n });\n }\n }\n\n return results;\n },\n });\n\n /**\n * Dedicated status extractor for the resource families this invariant\n * grades. Returns `(resource_type, resource_id, status)` triples for every\n * shape the spec carries an offline value on. Independent of\n * `status.monotonic`'s `extractStatusObservations` so the new offline\n * statuses (`suspended`, `withdrawn`, `insufficient`) — which monotonic's\n * graphs intentionally don't enumerate — are still observable here.\n */\n function extractImpairmentObservations(\n task: string,\n body: Record<string, unknown>,\n requestPayload?: unknown\n ): { resource_type: string; resource_id: string; status: string }[] {\n const out: { resource_type: string; resource_id: string; status: string }[] = [];\n if (task === 'sync_creatives' || task === 'list_creatives') {\n for (const c of asArray(body.creatives)) {\n if (!isObject(c)) continue;\n const id = asString(c.creative_id);\n const status = asString(c.status);\n if (id && status) out.push({ resource_type: 'creative', resource_id: id, status });\n }\n } else if (task === 'sync_audiences') {\n for (const a of asArray(body.audiences)) {\n if (!isObject(a)) continue;\n const id = asString(a.audience_id);\n const status = asString(a.status);\n if (id && status) out.push({ resource_type: 'audience', resource_id: id, status });\n }\n } else if (task === 'sync_catalogs' || task === 'list_catalogs') {\n // Two response shapes: catalogs[].items[] (nested) or items[] (flat).\n // Heterogeneous item ids — prefer `item_id` (spec-canonical), then\n // `offering_id` (SI), `sku` (retail), else `id`. Matches the fallback\n // chain in `pushCatalogItem`.\n const collect = (item: Record<string, unknown>) => {\n const id = asString(item.item_id) ?? asString(item.offering_id) ?? asString(item.sku) ?? asString(item.id);\n const status = asString(item.status);\n if (id && status) out.push({ resource_type: 'catalog_item', resource_id: id, status });\n };\n for (const cat of asArray(body.catalogs)) {\n if (!isObject(cat)) continue;\n for (const item of asArray(cat.items)) if (isObject(item)) collect(item);\n }\n for (const item of asArray(body.items)) if (isObject(item)) collect(item);\n } else if (task === 'sync_event_sources') {\n for (const es of asArray(body.event_sources)) {\n if (!isObject(es)) continue;\n const id = asString(es.event_source_id);\n // event_source health lives under `health.status` per\n // `core/event-source-health.json`; the top-level enum is\n // `assessment-status.json` (`insufficient | minimum | good | excellent`).\n const health = isObject(es.health) ? es.health : undefined;\n const status = health ? asString(health.status) : undefined;\n if (id && status) out.push({ resource_type: 'event_source', resource_id: id, status });\n }\n } else if (task === 'comply_test_controller' && body.success === true && isObject(requestPayload)) {\n // `force_audience_status` is the deterministic compliance surface for\n // seller-initiated audience transitions. The transition response is a\n // StateTransitionSuccess, so the authoritative status is\n // `current_state`; the entity id remains in the request params. Pair\n // the runner's recorded request and response instead of inventing a\n // protocol-visible audience read task solely for grading.\n if (requestPayload.scenario !== 'force_audience_status' || !isObject(requestPayload.params)) return out;\n const id = asString(requestPayload.params.audience_id);\n const status = asString(body.current_state);\n if (id && status) out.push({ resource_type: 'audience', resource_id: id, status });\n }\n return out;\n }\n\n /**\n * Extract every media-buy snapshot present on a step response. Walks\n * `create_media_buy` / `update_media_buy` (top-level buy object) and\n * `get_media_buys` (`media_buys[]` array). Returns each snapshot's\n * impairments[], health, status, the set of `creative_id`s the buy\n * references through `packages[].creative_assignments[]`, and the set of\n * `audience_id`s referenced through `packages[].targeting_overlay.audience_include[]`.\n * Both reference sets feed the inverse rule. `audience_exclude` is not\n * collected as a hard dependency for the inverse rule: an offline exclude\n * does not prevent the buy from serving, so it isn't a \"buy can't function\"\n * signal. Note this is a serviceability framing, not a safety framing —\n * an offline exclude can still silently break the suppression promise,\n * which is a separate (forward-looking) signal class.\n */\n function extractBuySnapshots(task: string, body: Record<string, unknown>, stepId: string): BuySnapshot[] {\n const out: BuySnapshot[] = [];\n if (task === 'create_media_buy' || task === 'update_media_buy') {\n const snap = readBuySnapshot(body, stepId);\n if (snap) out.push(snap);\n } else if (task === 'get_media_buys') {\n for (const mb of asArray(body.media_buys)) {\n if (!isObject(mb)) continue;\n const snap = readBuySnapshot(mb, stepId);\n if (snap) out.push(snap);\n }\n }\n return out;\n }\n\n function readBuySnapshot(record: Record<string, unknown>, stepId: string): BuySnapshot | undefined {\n const media_buy_id = asString(record.media_buy_id);\n if (!media_buy_id) return undefined;\n const status = asString(record.status);\n const health = asString(record.health);\n const impairments: ImpairmentEntry[] = [];\n for (const entry of asArray(record.impairments)) {\n if (!isObject(entry)) continue;\n const resource_type = asString(entry.resource_type);\n const resource_id = asString(entry.resource_id);\n if (!resource_type || !resource_id) continue;\n impairments.push({ resource_type, resource_id });\n }\n const referencedCreativeIds = new Set<string>();\n const referencedAudienceIds = new Set<string>();\n for (const pkg of asArray(record.packages)) {\n if (!isObject(pkg)) continue;\n // Creative refs appear in two shapes on the wire:\n // - `core/package.json` → `creative_assignments[].creative_id` (used on\n // create_media_buy request/response, update_media_buy)\n // - `get-media-buys-response.json` → `creative_approvals[].creative_id`\n // (the snapshot shape — `creative_approvals` carries per-assignment\n // approval_status alongside the id)\n // Walk both — sellers conformant to either schema surface the references\n // we need for the inverse rule.\n for (const ca of asArray(pkg.creative_assignments)) {\n if (!isObject(ca)) continue;\n const cid = asString(ca.creative_id);\n if (cid) referencedCreativeIds.add(cid);\n }\n for (const ca of asArray(pkg.creative_approvals)) {\n if (!isObject(ca)) continue;\n const cid = asString(ca.creative_id);\n if (cid) referencedCreativeIds.add(cid);\n }\n // Audience refs: only `audience_include` counts as a hard dependency\n // for the inverse rule. `audience_exclude` is omitted on serviceability\n // grounds — a suspended exclude doesn't keep the buy from serving — not\n // on safety grounds. An offline exclude can still silently break the\n // suppression promise; that's a separate signal class (see extractBuySnapshots).\n const overlay = isObject(pkg.targeting_overlay) ? pkg.targeting_overlay : undefined;\n if (overlay) {\n for (const aid of asArray(overlay.audience_include)) {\n if (typeof aid === 'string' && aid.length > 0) referencedAudienceIds.add(aid);\n }\n }\n }\n return {\n media_buy_id,\n status,\n health,\n impairments,\n referencedCreativeIds,\n referencedAudienceIds,\n stepId,\n };\n }\n}\n\n// Register on module load too, so merely importing this module (or a direct\n// `require('.../default-invariants')`) still registers the defaults —\n// preserving the historical side-effect-on-import behaviour. Idempotent via\n// the `REGISTERED` guard, so the explicit calls from the storyboard and\n// compliance entry points are harmless repeats.\nregisterDefaultInvariants();\n"],"mappings":"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","names":["anchor"]}
|
|
@@ -11,7 +11,7 @@ export { WEBHOOK_IDEMPOTENCY_KEY_PATTERN } from './types.mjs';
|
|
|
11
11
|
export { registerAssertion, getAssertion, listAssertions, listDefaultAssertions, clearAssertionRegistry, resolveAssertions, } from './assertions.mjs';
|
|
12
12
|
export type { AssertionSpec, AssertionContext, RegisterAssertionOptions } from './assertions.mjs';
|
|
13
13
|
export { createWebhookReceiver } from './webhook-receiver.mjs';
|
|
14
|
-
export type { CapturedWebhook, CreateWebhookReceiverOptions, RetryReplayPolicy, WebhookFilter, WebhookReceiver, WebhookWaitResult, } from './webhook-receiver.mjs';
|
|
14
|
+
export type { CapturedWebhook, CapturedWebhookChallenge, CreateWebhookReceiverOptions, RetryReplayPolicy, WebhookFilter, WebhookReceiver, WebhookWaitResult, } from './webhook-receiver.mjs';
|
|
15
15
|
export { createRunnerVariables } from './context.mjs';
|
|
16
16
|
export type { RunnerVariables } from './context.mjs';
|
|
17
17
|
export { WEBHOOK_ASSERTION_TASKS } from './webhook-assertions.mjs';
|
|
@@ -11,7 +11,7 @@ export { WEBHOOK_IDEMPOTENCY_KEY_PATTERN } from './types';
|
|
|
11
11
|
export { registerAssertion, getAssertion, listAssertions, listDefaultAssertions, clearAssertionRegistry, resolveAssertions, } from './assertions';
|
|
12
12
|
export type { AssertionSpec, AssertionContext, RegisterAssertionOptions } from './assertions';
|
|
13
13
|
export { createWebhookReceiver } from './webhook-receiver';
|
|
14
|
-
export type { CapturedWebhook, CreateWebhookReceiverOptions, RetryReplayPolicy, WebhookFilter, WebhookReceiver, WebhookWaitResult, } from './webhook-receiver';
|
|
14
|
+
export type { CapturedWebhook, CapturedWebhookChallenge, CreateWebhookReceiverOptions, RetryReplayPolicy, WebhookFilter, WebhookReceiver, WebhookWaitResult, } from './webhook-receiver';
|
|
15
15
|
export { createRunnerVariables } from './context';
|
|
16
16
|
export type { RunnerVariables } from './context';
|
|
17
17
|
export { WEBHOOK_ASSERTION_TASKS } from './webhook-assertions';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/testing/storyboard/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/testing/storyboard/index.ts"],"sourcesContent":["/**\n * Storyboard-driven testing for AdCP agents.\n *\n * Storyboards are YAML-defined workflows that map directly to\n * SingleAgentClient methods, enabling step-by-step agent testing.\n * The canonical storyboard set lives in the AdCP compliance tarball\n * and is pulled into `compliance/cache/{version}/` via `npm run sync-schemas`.\n */\n\n// Side-effect import: registers the default cross-step assertions that\n// upstream storyboards reference by id (idempotency.conflict_no_payload_leak,\n// context.no_secret_echo, governance.denial_blocks_mutation). Without this\n// registration here, any `runStoryboard` call against a storyboard declaring\n// `invariants: [...]` would throw at start on unresolved ids. Consumers who\n// want to replace the defaults can `clearAssertionRegistry()` first.\nimport { registerDefaultInvariants } from './default-invariants';\n\nregisterDefaultInvariants();\n\n// Types\nexport type {\n A2ATaskEnvelope,\n AgentEntry,\n Storyboard,\n StoryboardFixtureResolution,\n FixtureResolutionStrategy,\n FixtureMatchOperator,\n FixtureMatchClause,\n FixtureResolutionDeclaration,\n ProductFixtureResolutionDeclaration,\n PricingOptionFixtureResolutionDeclaration,\n FixtureResolutionStatus,\n FixtureResolutionRecord,\n FixtureResolutionAttempt,\n FixtureResolutionEvidence,\n FixtureResolutionCoverageGap,\n StoryboardInvariants,\n StoryboardInvariantsObject,\n StepInvariantsObject,\n StoryboardPhase,\n StoryboardStep,\n RateLimitTripSpec,\n StoryboardValidation,\n StoryboardValidationCheck,\n WebhookFilterSpec,\n WebhookRetryTriggerSpec,\n WebhookAssertionErrorCode,\n ContextOutput,\n ContextInput,\n ContextProvenanceEntry,\n ContextValueRejectedHint,\n ShapeDriftHint,\n MissingRequiredFieldHint,\n FormatMismatchHint,\n MonotonicViolationHint,\n ImpairmentCoherenceHint,\n ImpairmentCoherenceNotApplicableHint,\n StoryboardContext,\n StoryboardRunOptions,\n TrustedMatchContextProviderEndpoint,\n TrustedMatchContextRegistrationContext,\n TrustedMatchContextRouterRunnerOptions,\n TrustedMatchPublisherAuthOperation,\n TrustedMatchPublisherCredentialState,\n TrustedMatchPublisherAuthTls,\n TrustedMatchPublisherAuthProbeConfiguration,\n TrustedMatchPublisherAuthRunner,\n ValidationResult,\n StoryboardStepPreview,\n StoryboardStepResult,\n StoryboardStepHint,\n StoryboardStepHintBase,\n StoryboardPhaseResult,\n StoryboardResult,\n AssertionResult,\n StrictValidationSummary,\n StrictValidationVerdict,\n UpstreamTrafficPayloadMatch,\n RunnerNotice,\n NoticeCode,\n NoticeSeverity,\n} from './types';\nexport { WEBHOOK_IDEMPOTENCY_KEY_PATTERN } from './types';\n\n// Cross-step assertion registry (adcontextprotocol/adcp#2639)\nexport {\n registerAssertion,\n getAssertion,\n listAssertions,\n listDefaultAssertions,\n clearAssertionRegistry,\n resolveAssertions,\n} from './assertions';\nexport type { AssertionSpec, AssertionContext, RegisterAssertionOptions } from './assertions';\n\n// Webhook receiver (outbound-webhook conformance testing per adcontextprotocol/adcp#2431)\nexport { createWebhookReceiver } from './webhook-receiver';\nexport type {\n CapturedWebhook,\n CreateWebhookReceiverOptions,\n RetryReplayPolicy,\n WebhookFilter,\n WebhookReceiver,\n WebhookWaitResult,\n} from './webhook-receiver';\n\n// Runner-variable substitution (`{{runner.*}}` / `{{prior_step.*.operation_id}}`)\nexport { createRunnerVariables } from './context';\nexport type { RunnerVariables } from './context';\n\n// Webhook-assertion pseudo-tasks\nexport { WEBHOOK_ASSERTION_TASKS } from './webhook-assertions';\n\n// Runner\nexport {\n runStoryboard,\n runStoryboardStep,\n applyAdcpVersionRunOptions,\n applyStoryboardVersionOptions,\n getFirstStepPreview,\n summarizeStrictValidation,\n listStrictOnlyFailures,\n resolveCapabilityPath,\n evaluateCapabilityPredicate,\n describeStoryboardCapabilityGates,\n buildDiscoveryFailedResult,\n} from './runner';\n\n// Parser (single-file load for spec evolution / targeted testing)\nexport { parseStoryboard, loadStoryboardFile } from './loader';\n\n// AdCP 3.2 fixture-handle resolution\nexport {\n applyFixtureBindingsToRequest,\n buildFixtureResolutionSpecs,\n FixtureBindingRegistry,\n matchesFixtureRequirements,\n normalizeFixtureMatchExpression,\n validateFixtureResolutionDeclarations,\n} from './fixture-resolution';\n\n// Compliance cache: capability-driven resolution\nexport {\n getComplianceCacheDir,\n getExternalSchemaRootForCompliance,\n loadComplianceIndex,\n listBundles,\n loadBundleStoryboards,\n listAllComplianceStoryboards,\n getComplianceStoryboardById,\n findBundleById,\n resolveBundleOrStoryboard,\n resolveStoryboardsForCapabilities,\n isComplianceVersionSupported,\n loadSpecialismDetail,\n listSpecialisms,\n CapabilityResolutionError,\n PROTOCOL_TO_PATH,\n UNBASELINED_SUPPORTED_PROTOCOLS,\n} from './compliance';\nexport type {\n AgentCapabilities,\n BundleKind,\n BundleRef,\n CapabilityResolutionCode,\n ComplianceIndex,\n ComplianceIndexProtocol,\n ComplianceIndexSpecialism,\n NotApplicableStoryboard,\n ResolveOptions,\n ResolvedBundle,\n ResolvedStoryboards,\n SpecialismDetail,\n} from './compliance';\n\n// Task mapping\nexport { TASK_TO_METHOD, executeStoryboardTask } from './task-map';\n\n// Storyboard-only creative asset directives\nexport { expandCreativeAssetDirectives, findUnresolvedCreativeAssetDirectives } from './creative-assets';\n\n// Path utilities\nexport { parsePath, resolvePath, setPath } from './path';\n\n// Context\nexport {\n CONTEXT_EXTRACTORS,\n extractContext,\n extractContextWithProvenance,\n injectContext,\n applyContextOutputs,\n applyContextOutputsWithProvenance,\n applyContextInputs,\n} from './context';\nexport type { ContextWriteResult } from './context';\n\n// Rejection-hint detection (issue #870)\nexport { detectContextRejectionHints } from './rejection-hints';\n\n// Request builder\nexport { buildRequest, hasRequestBuilder } from './request-builder';\n\n// Validations\nexport { runValidations } from './validations';\nexport {\n gradeOAuthMetadataGraph,\n gradeOAuthMetadataGraphVector,\n loadOAuthMetadataGraphVectors,\n buildAuthorizationServerMetadataUrl,\n buildProtectedResourceMetadataUrl,\n normalizeOAuthResourceForComparison,\n redactOAuthUrlForOutput,\n} from './oauth-metadata-graph';\nexport type {\n GradeOAuthMetadataGraphOptions,\n OAuthMetadataFetchResponse,\n OAuthMetadataFetchTransport,\n OAuthMetadataGraphErrorCode,\n OAuthMetadataGraphFinding,\n OAuthMetadataGraphGrade,\n OAuthMetadataGraphObservation,\n OAuthMetadataGraphVector,\n OAuthMetadataGraphVectorCorpus,\n} from './oauth-metadata-graph';\nexport {\n RateLimitTripObserver,\n RATE_LIMIT_TRIP_CONTRACT,\n RATE_LIMIT_TRIP_DEFAULT_REPLAY_MAX_WAIT_SECONDS,\n RATE_LIMIT_TRIP_MAX_ATTEMPTS_MAX,\n RATE_LIMIT_TRIP_MAX_ATTEMPTS_MIN,\n extractTaskAdcpError,\n validateRateLimitTripSpec,\n type RateLimitTripFailureCode,\n type RateLimitTripClient,\n type RateLimitTripObservation,\n type RateLimitTripObserverOptions,\n type RateLimitTripResponseSnapshot,\n type RateLimitTripStructuredResult,\n type RateLimitTripTaskOptions,\n} from './rate-limit-trip';\n\n// `./junit` is deliberately NOT re-exported. The CLI requires it\n// directly from `dist/lib/testing/storyboard/junit.js` and the function\n// is marked `@internal` (stripped from the generated `.d.ts`). Add a\n// re-export here only if/when we promote it to a public API surface.\n\n// Test-kit schema validation\nexport { validateTestKit, TestKitValidationError, PROBE_TASK_ALLOWLIST } from './test-kit';\n\n// Sandbox entities\nexport type { SandboxBrand, SandboxAgent, SandboxEntities, BrandJson } from './sandbox-entities';\nexport { BrandJsonSchema, AdagentsJsonSchema } from '../../types/wellknown-schemas.generated';\nexport type { AdagentsJson } from '../../types/wellknown-schemas.generated';\nexport {\n getSandboxEntities,\n getSandboxBrands,\n getSandboxBrand,\n isSandboxDomain,\n clearSandboxCache,\n} from './sandbox-entities';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeA,gCAA0C;AAmE1C,mBAAgD;AAGhD,wBAOO;AAIP,8BAAsC;
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/testing/storyboard/index.ts"],"sourcesContent":["/**\n * Storyboard-driven testing for AdCP agents.\n *\n * Storyboards are YAML-defined workflows that map directly to\n * SingleAgentClient methods, enabling step-by-step agent testing.\n * The canonical storyboard set lives in the AdCP compliance tarball\n * and is pulled into `compliance/cache/{version}/` via `npm run sync-schemas`.\n */\n\n// Side-effect import: registers the default cross-step assertions that\n// upstream storyboards reference by id (idempotency.conflict_no_payload_leak,\n// context.no_secret_echo, governance.denial_blocks_mutation). Without this\n// registration here, any `runStoryboard` call against a storyboard declaring\n// `invariants: [...]` would throw at start on unresolved ids. Consumers who\n// want to replace the defaults can `clearAssertionRegistry()` first.\nimport { registerDefaultInvariants } from './default-invariants';\n\nregisterDefaultInvariants();\n\n// Types\nexport type {\n A2ATaskEnvelope,\n AgentEntry,\n Storyboard,\n StoryboardFixtureResolution,\n FixtureResolutionStrategy,\n FixtureMatchOperator,\n FixtureMatchClause,\n FixtureResolutionDeclaration,\n ProductFixtureResolutionDeclaration,\n PricingOptionFixtureResolutionDeclaration,\n FixtureResolutionStatus,\n FixtureResolutionRecord,\n FixtureResolutionAttempt,\n FixtureResolutionEvidence,\n FixtureResolutionCoverageGap,\n StoryboardInvariants,\n StoryboardInvariantsObject,\n StepInvariantsObject,\n StoryboardPhase,\n StoryboardStep,\n RateLimitTripSpec,\n StoryboardValidation,\n StoryboardValidationCheck,\n WebhookFilterSpec,\n WebhookRetryTriggerSpec,\n WebhookAssertionErrorCode,\n ContextOutput,\n ContextInput,\n ContextProvenanceEntry,\n ContextValueRejectedHint,\n ShapeDriftHint,\n MissingRequiredFieldHint,\n FormatMismatchHint,\n MonotonicViolationHint,\n ImpairmentCoherenceHint,\n ImpairmentCoherenceNotApplicableHint,\n StoryboardContext,\n StoryboardRunOptions,\n TrustedMatchContextProviderEndpoint,\n TrustedMatchContextRegistrationContext,\n TrustedMatchContextRouterRunnerOptions,\n TrustedMatchPublisherAuthOperation,\n TrustedMatchPublisherCredentialState,\n TrustedMatchPublisherAuthTls,\n TrustedMatchPublisherAuthProbeConfiguration,\n TrustedMatchPublisherAuthRunner,\n ValidationResult,\n StoryboardStepPreview,\n StoryboardStepResult,\n StoryboardStepHint,\n StoryboardStepHintBase,\n StoryboardPhaseResult,\n StoryboardResult,\n AssertionResult,\n StrictValidationSummary,\n StrictValidationVerdict,\n UpstreamTrafficPayloadMatch,\n RunnerNotice,\n NoticeCode,\n NoticeSeverity,\n} from './types';\nexport { WEBHOOK_IDEMPOTENCY_KEY_PATTERN } from './types';\n\n// Cross-step assertion registry (adcontextprotocol/adcp#2639)\nexport {\n registerAssertion,\n getAssertion,\n listAssertions,\n listDefaultAssertions,\n clearAssertionRegistry,\n resolveAssertions,\n} from './assertions';\nexport type { AssertionSpec, AssertionContext, RegisterAssertionOptions } from './assertions';\n\n// Webhook receiver (outbound-webhook conformance testing per adcontextprotocol/adcp#2431)\nexport { createWebhookReceiver } from './webhook-receiver';\nexport type {\n CapturedWebhook,\n CapturedWebhookChallenge,\n CreateWebhookReceiverOptions,\n RetryReplayPolicy,\n WebhookFilter,\n WebhookReceiver,\n WebhookWaitResult,\n} from './webhook-receiver';\n\n// Runner-variable substitution (`{{runner.*}}` / `{{prior_step.*.operation_id}}`)\nexport { createRunnerVariables } from './context';\nexport type { RunnerVariables } from './context';\n\n// Webhook-assertion pseudo-tasks\nexport { WEBHOOK_ASSERTION_TASKS } from './webhook-assertions';\n\n// Runner\nexport {\n runStoryboard,\n runStoryboardStep,\n applyAdcpVersionRunOptions,\n applyStoryboardVersionOptions,\n getFirstStepPreview,\n summarizeStrictValidation,\n listStrictOnlyFailures,\n resolveCapabilityPath,\n evaluateCapabilityPredicate,\n describeStoryboardCapabilityGates,\n buildDiscoveryFailedResult,\n} from './runner';\n\n// Parser (single-file load for spec evolution / targeted testing)\nexport { parseStoryboard, loadStoryboardFile } from './loader';\n\n// AdCP 3.2 fixture-handle resolution\nexport {\n applyFixtureBindingsToRequest,\n buildFixtureResolutionSpecs,\n FixtureBindingRegistry,\n matchesFixtureRequirements,\n normalizeFixtureMatchExpression,\n validateFixtureResolutionDeclarations,\n} from './fixture-resolution';\n\n// Compliance cache: capability-driven resolution\nexport {\n getComplianceCacheDir,\n getExternalSchemaRootForCompliance,\n loadComplianceIndex,\n listBundles,\n loadBundleStoryboards,\n listAllComplianceStoryboards,\n getComplianceStoryboardById,\n findBundleById,\n resolveBundleOrStoryboard,\n resolveStoryboardsForCapabilities,\n isComplianceVersionSupported,\n loadSpecialismDetail,\n listSpecialisms,\n CapabilityResolutionError,\n PROTOCOL_TO_PATH,\n UNBASELINED_SUPPORTED_PROTOCOLS,\n} from './compliance';\nexport type {\n AgentCapabilities,\n BundleKind,\n BundleRef,\n CapabilityResolutionCode,\n ComplianceIndex,\n ComplianceIndexProtocol,\n ComplianceIndexSpecialism,\n NotApplicableStoryboard,\n ResolveOptions,\n ResolvedBundle,\n ResolvedStoryboards,\n SpecialismDetail,\n} from './compliance';\n\n// Task mapping\nexport { TASK_TO_METHOD, executeStoryboardTask } from './task-map';\n\n// Storyboard-only creative asset directives\nexport { expandCreativeAssetDirectives, findUnresolvedCreativeAssetDirectives } from './creative-assets';\n\n// Path utilities\nexport { parsePath, resolvePath, setPath } from './path';\n\n// Context\nexport {\n CONTEXT_EXTRACTORS,\n extractContext,\n extractContextWithProvenance,\n injectContext,\n applyContextOutputs,\n applyContextOutputsWithProvenance,\n applyContextInputs,\n} from './context';\nexport type { ContextWriteResult } from './context';\n\n// Rejection-hint detection (issue #870)\nexport { detectContextRejectionHints } from './rejection-hints';\n\n// Request builder\nexport { buildRequest, hasRequestBuilder } from './request-builder';\n\n// Validations\nexport { runValidations } from './validations';\nexport {\n gradeOAuthMetadataGraph,\n gradeOAuthMetadataGraphVector,\n loadOAuthMetadataGraphVectors,\n buildAuthorizationServerMetadataUrl,\n buildProtectedResourceMetadataUrl,\n normalizeOAuthResourceForComparison,\n redactOAuthUrlForOutput,\n} from './oauth-metadata-graph';\nexport type {\n GradeOAuthMetadataGraphOptions,\n OAuthMetadataFetchResponse,\n OAuthMetadataFetchTransport,\n OAuthMetadataGraphErrorCode,\n OAuthMetadataGraphFinding,\n OAuthMetadataGraphGrade,\n OAuthMetadataGraphObservation,\n OAuthMetadataGraphVector,\n OAuthMetadataGraphVectorCorpus,\n} from './oauth-metadata-graph';\nexport {\n RateLimitTripObserver,\n RATE_LIMIT_TRIP_CONTRACT,\n RATE_LIMIT_TRIP_DEFAULT_REPLAY_MAX_WAIT_SECONDS,\n RATE_LIMIT_TRIP_MAX_ATTEMPTS_MAX,\n RATE_LIMIT_TRIP_MAX_ATTEMPTS_MIN,\n extractTaskAdcpError,\n validateRateLimitTripSpec,\n type RateLimitTripFailureCode,\n type RateLimitTripClient,\n type RateLimitTripObservation,\n type RateLimitTripObserverOptions,\n type RateLimitTripResponseSnapshot,\n type RateLimitTripStructuredResult,\n type RateLimitTripTaskOptions,\n} from './rate-limit-trip';\n\n// `./junit` is deliberately NOT re-exported. The CLI requires it\n// directly from `dist/lib/testing/storyboard/junit.js` and the function\n// is marked `@internal` (stripped from the generated `.d.ts`). Add a\n// re-export here only if/when we promote it to a public API surface.\n\n// Test-kit schema validation\nexport { validateTestKit, TestKitValidationError, PROBE_TASK_ALLOWLIST } from './test-kit';\n\n// Sandbox entities\nexport type { SandboxBrand, SandboxAgent, SandboxEntities, BrandJson } from './sandbox-entities';\nexport { BrandJsonSchema, AdagentsJsonSchema } from '../../types/wellknown-schemas.generated';\nexport type { AdagentsJson } from '../../types/wellknown-schemas.generated';\nexport {\n getSandboxEntities,\n getSandboxBrands,\n getSandboxBrand,\n isSandboxDomain,\n clearSandboxCache,\n} from './sandbox-entities';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAeA,gCAA0C;AAmE1C,mBAAgD;AAGhD,wBAOO;AAIP,8BAAsC;AAYtC,qBAAsC;AAItC,gCAAwC;AAGxC,oBAYO;AAGP,oBAAoD;AAGpD,gCAOO;AAGP,wBAiBO;AAiBP,sBAAsD;AAGtD,6BAAqF;AAGrF,kBAAgD;AAGhD,IAAAA,kBAQO;AAIP,6BAA4C;AAG5C,6BAAgD;AAGhD,yBAA+B;AAC/B,kCAQO;AAYP,6BAeO;AAQP,sBAA8E;AAI9E,+BAAoD;AAEpD,8BAMO;AAAA,IAnPP,qDAA0B;","names":["import_context"]}
|