@adcp/sdk 17.0.0-beta.1 → 17.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/adapters/keyed-account-store.js +1 -1
- package/dist/lib/adapters/keyed-account-store.mjs +1 -1
- package/dist/lib/adapters/version/3.0/brand-fields.d.mts +7 -1
- package/dist/lib/adapters/version/3.0/brand-fields.d.ts +7 -1
- package/dist/lib/adapters/version/3.0/brand-fields.js +139 -3
- package/dist/lib/adapters/version/3.0/brand-fields.mjs +136 -2
- package/dist/lib/adapters/version/3.0/index.js +6 -0
- package/dist/lib/adapters/version/3.0/index.mjs +7 -1
- package/dist/lib/adapters/version/types.d.mts +5 -0
- package/dist/lib/adapters/version/types.d.ts +5 -0
- package/dist/lib/canonical-references/index.js +2 -0
- package/dist/lib/canonical-references/index.mjs +2 -0
- package/dist/lib/client/account-changes.d.mts +3 -1
- package/dist/lib/client/account-changes.d.ts +3 -1
- package/dist/lib/client/account-changes.js +22 -2
- package/dist/lib/client/account-changes.mjs +22 -2
- package/dist/lib/conformance/oracle.js +3 -2
- package/dist/lib/conformance/oracle.mjs +3 -2
- package/dist/lib/core/AgentClient.d.mts +165 -1
- package/dist/lib/core/AgentClient.d.ts +165 -1
- package/dist/lib/core/AgentClient.js +446 -8
- package/dist/lib/core/AgentClient.mjs +446 -8
- package/dist/lib/core/ConversationTypes.d.mts +8 -0
- package/dist/lib/core/ConversationTypes.d.ts +8 -0
- package/dist/lib/core/ProtocolResponseParser.d.mts +1 -1
- package/dist/lib/core/ProtocolResponseParser.d.ts +1 -1
- package/dist/lib/core/ProtocolResponseParser.js +28 -18
- package/dist/lib/core/ProtocolResponseParser.mjs +11 -1
- package/dist/lib/core/SingleAgentClient.d.mts +115 -2
- package/dist/lib/core/SingleAgentClient.d.ts +115 -2
- package/dist/lib/core/SingleAgentClient.js +547 -67
- package/dist/lib/core/SingleAgentClient.mjs +534 -54
- package/dist/lib/core/TaskExecutor.d.mts +7 -0
- package/dist/lib/core/TaskExecutor.d.ts +7 -0
- package/dist/lib/core/TaskExecutor.js +18 -5
- package/dist/lib/core/TaskExecutor.mjs +18 -5
- package/dist/lib/core/task-status.d.mts +2 -0
- package/dist/lib/core/task-status.d.ts +2 -0
- package/dist/lib/core/task-status.js +11 -2
- package/dist/lib/core/task-status.mjs +9 -1
- package/dist/lib/identity-3.3/trust.d.mts +1 -4
- package/dist/lib/identity-3.3/trust.d.ts +1 -4
- package/dist/lib/identity-3.3/trust.js +34 -21
- package/dist/lib/identity-3.3/trust.mjs +34 -21
- package/dist/lib/identity-3.3/validation.js +5 -3
- package/dist/lib/identity-3.3/validation.mjs +6 -4
- package/dist/lib/index.d.mts +6 -52
- package/dist/lib/index.d.ts +6 -52
- package/dist/lib/index.js +11 -0
- package/dist/lib/index.mjs +7 -0
- package/dist/lib/media-buy/compatibility.js +6 -1
- package/dist/lib/media-buy/compatibility.mjs +6 -1
- package/dist/lib/protocols/mcp-scope.d.mts +3 -0
- package/dist/lib/protocols/mcp-scope.d.ts +3 -0
- package/dist/lib/protocols/mcp-scope.js +8 -3
- package/dist/lib/protocols/mcp-scope.mjs +8 -3
- package/dist/lib/reporting/inspection.js +1 -0
- package/dist/lib/reporting/inspection.mjs +1 -0
- package/dist/lib/reporting/ledger/coverage.d.mts +5 -0
- package/dist/lib/reporting/ledger/coverage.d.ts +5 -0
- package/dist/lib/reporting/ledger/coverage.js +37 -3
- package/dist/lib/reporting/ledger/coverage.mjs +36 -3
- package/dist/lib/reporting/ledger/handler.js +7 -4
- package/dist/lib/reporting/ledger/handler.mjs +7 -4
- package/dist/lib/reporting/ledger/producer.js +215 -69
- package/dist/lib/reporting/ledger/producer.mjs +217 -70
- package/dist/lib/reporting/ledger/schedule.d.mts +2 -2
- package/dist/lib/reporting/ledger/schedule.d.ts +2 -2
- package/dist/lib/reporting/ledger/schedule.js +8 -5
- package/dist/lib/reporting/ledger/schedule.mjs +8 -5
- package/dist/lib/reporting/ledger/status-ingest.d.mts +1 -1
- package/dist/lib/reporting/ledger/status-ingest.d.ts +1 -1
- package/dist/lib/reporting/ledger/status-ingest.js +4 -3
- package/dist/lib/reporting/ledger/status-ingest.mjs +4 -3
- package/dist/lib/reporting/ledger/types.d.mts +36 -1
- package/dist/lib/reporting/ledger/types.d.ts +36 -1
- package/dist/lib/reporting/service/index.d.mts +14 -1
- package/dist/lib/reporting/service/index.d.ts +14 -1
- package/dist/lib/reporting/service/index.js +24 -12
- package/dist/lib/reporting/service/index.mjs +24 -12
- package/dist/lib/schemas/browser.d.mts +2 -0
- package/dist/lib/schemas/browser.d.ts +2 -0
- package/dist/lib/schemas/browser.js +3 -0
- package/dist/lib/schemas/browser.mjs +2 -0
- package/dist/lib/schemas/index.d.mts +5 -3
- package/dist/lib/schemas/index.d.ts +5 -3
- package/dist/lib/schemas/index.js +5 -0
- package/dist/lib/schemas/index.mjs +4 -0
- package/dist/lib/server/account-response-identity.d.mts +17 -0
- package/dist/lib/server/account-response-identity.d.ts +17 -0
- package/dist/lib/server/account-response-identity.js +52 -0
- package/dist/lib/server/account-response-identity.mjs +28 -0
- package/dist/lib/server/account-sync-contract.js +2 -2
- package/dist/lib/server/account-sync-contract.mjs +2 -2
- package/dist/lib/server/create-adcp-server.js +33 -20
- package/dist/lib/server/create-adcp-server.mjs +36 -12
- package/dist/lib/server/decisioning/account.d.mts +36 -10
- package/dist/lib/server/decisioning/account.d.ts +36 -10
- package/dist/lib/server/decisioning/account.js +33 -14
- package/dist/lib/server/decisioning/account.mjs +33 -14
- package/dist/lib/server/decisioning/runtime/from-platform.d.mts +5 -5
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +5 -5
- package/dist/lib/server/decisioning/runtime/from-platform.js +4 -4
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +4 -4
- package/dist/lib/server/media-buy-store.d.mts +26 -12
- package/dist/lib/server/media-buy-store.d.ts +26 -12
- package/dist/lib/server/media-buy-store.js +69 -21
- package/dist/lib/server/media-buy-store.mjs +69 -21
- package/dist/lib/server/notification-subscriptions/runtime.d.mts +1 -1
- package/dist/lib/server/notification-subscriptions/runtime.d.ts +1 -1
- package/dist/lib/server/notification-subscriptions/runtime.js +4 -0
- package/dist/lib/server/notification-subscriptions/runtime.mjs +4 -0
- package/dist/lib/server/responses.js +9 -1
- package/dist/lib/server/responses.mjs +9 -1
- package/dist/lib/signing/agent-fetch.d.mts +1 -1
- package/dist/lib/signing/agent-fetch.d.ts +1 -1
- package/dist/lib/signing/agent-fetch.js +3 -3
- package/dist/lib/signing/agent-fetch.mjs +3 -3
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.js +60 -14
- package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +60 -14
- package/dist/lib/testing/storyboard/compliance.d.mts +2 -5
- package/dist/lib/testing/storyboard/compliance.d.ts +2 -5
- package/dist/lib/testing/storyboard/compliance.js +62 -13
- package/dist/lib/testing/storyboard/compliance.mjs +63 -14
- 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.js +11 -0
- package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +10 -0
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/accept-proposal.d.ts +20 -28
- package/dist/lib/types/asset-instances.d.mts +1 -1
- package/dist/lib/types/asset-instances.d.ts +1 -1
- package/dist/lib/types/buy-products.d.ts +20 -28
- package/dist/lib/types/check-governance.d.ts +20 -28
- package/dist/lib/types/comply-test-controller.d.ts +20 -28
- package/dist/lib/types/control-media-buy.d.ts +20 -28
- package/dist/lib/types/core.generated.d.mts +273 -184
- package/dist/lib/types/core.generated.d.ts +273 -184
- package/dist/lib/types/create-media-buy.d.ts +20 -28
- package/dist/lib/types/get-media-buys.d.ts +20 -28
- package/dist/lib/types/get-products.d.ts +20 -28
- package/dist/lib/types/index.d.mts +6 -1
- package/dist/lib/types/index.d.ts +6 -1
- package/dist/lib/types/index.js +6 -1
- package/dist/lib/types/index.mjs +4 -1
- package/dist/lib/types/inline-enums.generated.d.mts +30 -4
- package/dist/lib/types/inline-enums.generated.d.ts +30 -4
- package/dist/lib/types/inline-enums.generated.js +41 -2
- package/dist/lib/types/inline-enums.generated.mjs +28 -2
- package/dist/lib/types/list-products.d.ts +20 -28
- package/dist/lib/types/list-proposals.d.ts +20 -28
- package/dist/lib/types/media-buy-delivery-report.d.mts +6 -0
- package/dist/lib/types/media-buy-delivery-report.d.ts +6 -0
- package/dist/lib/types/media-buy-delivery-report.js +16 -0
- package/dist/lib/types/media-buy-delivery-report.mjs +0 -0
- package/dist/lib/types/refine-proposals.d.ts +20 -28
- package/dist/lib/types/request-proposals.d.ts +20 -28
- package/dist/lib/types/schemas.generated.d.ts +63113 -127273
- package/dist/lib/types/schemas.generated.js +759 -770
- package/dist/lib/types/schemas.generated.mjs +759 -770
- package/dist/lib/types/targeting-keys.generated.d.mts +4 -0
- package/dist/lib/types/targeting-keys.generated.d.ts +4 -0
- package/dist/lib/types/targeting-keys.generated.js +109 -0
- package/dist/lib/types/targeting-keys.generated.mjs +84 -0
- package/dist/lib/types/tools.generated.d.mts +2 -68
- package/dist/lib/types/tools.generated.d.ts +2 -68
- package/dist/lib/types/update-media-buy.d.ts +20 -28
- package/dist/lib/utils/adcp-version-config.js +5 -2
- package/dist/lib/utils/adcp-version-config.mjs +5 -2
- package/dist/lib/utils/response-unwrapper.js +6 -1
- package/dist/lib/utils/response-unwrapper.mjs +6 -1
- package/dist/lib/v2/format-schema/resolver.js +1 -1
- package/dist/lib/v2/format-schema/resolver.mjs +1 -1
- package/dist/lib/v2/projection/creative-delivery.js +104 -29
- package/dist/lib/v2/projection/creative-delivery.mjs +108 -29
- package/dist/lib/v2/projection/index.d.mts +1 -0
- package/dist/lib/v2/projection/index.d.ts +1 -0
- package/dist/lib/v2/projection/index.js +3 -0
- package/dist/lib/v2/projection/index.mjs +2 -0
- package/dist/lib/v2/projection/legacy-metadata.d.mts +19 -0
- package/dist/lib/v2/projection/legacy-metadata.d.ts +19 -0
- package/dist/lib/v2/projection/legacy-metadata.js +91 -0
- package/dist/lib/v2/projection/legacy-metadata.mjs +86 -0
- package/dist/lib/v2/projection/v1-to-v2.d.mts +1 -1
- package/dist/lib/v2/projection/v1-to-v2.d.ts +1 -1
- package/dist/lib/v2/projection/v1-to-v2.js +12 -9
- package/dist/lib/v2/projection/v1-to-v2.mjs +12 -9
- package/dist/lib/validation/budget-allocation.d.mts +3 -3
- package/dist/lib/validation/budget-allocation.d.ts +3 -3
- package/dist/lib/validation/compact-schema.d.mts +27 -0
- package/dist/lib/validation/compact-schema.d.ts +27 -0
- package/dist/lib/validation/compact-schema.js +276 -0
- package/dist/lib/validation/compact-schema.mjs +250 -0
- package/dist/lib/validation/media-buy-delivery-report.d.mts +8 -0
- package/dist/lib/validation/media-buy-delivery-report.d.ts +8 -0
- package/dist/lib/validation/media-buy-delivery-report.js +31 -0
- package/dist/lib/validation/media-buy-delivery-report.mjs +7 -0
- package/dist/lib/validation/nonempty-array.d.mts +15 -0
- package/dist/lib/validation/nonempty-array.d.ts +15 -0
- package/dist/lib/validation/nonempty-array.js +41 -0
- package/dist/lib/validation/nonempty-array.mjs +7 -0
- package/dist/lib/validation/schema-diagnostic-origins.d.mts +21 -0
- package/dist/lib/validation/schema-diagnostic-origins.d.ts +21 -0
- package/dist/lib/validation/schema-diagnostic-origins.js +193 -0
- package/dist/lib/validation/schema-diagnostic-origins.mjs +169 -0
- package/dist/lib/validation/schema-loader.js +86 -16
- package/dist/lib/validation/schema-loader.mjs +82 -16
- package/dist/lib/validation/schema-validator.d.mts +10 -19
- package/dist/lib/validation/schema-validator.d.ts +10 -19
- package/dist/lib/validation/schema-validator.js +135 -42
- package/dist/lib/validation/schema-validator.mjs +139 -43
- package/dist/lib/validation/sync-creatives.d.mts +22 -22
- package/dist/lib/validation/sync-creatives.d.ts +22 -22
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/webhooks/index.d.mts +3 -0
- package/dist/lib/webhooks/index.d.ts +3 -0
- package/dist/lib/webhooks/index.js +3 -0
- package/dist/lib/webhooks/index.mjs +2 -0
- package/dist/lib/webhooks/media-buy-delivery.d.mts +43 -0
- package/dist/lib/webhooks/media-buy-delivery.d.ts +43 -0
- package/dist/lib/webhooks/media-buy-delivery.js +119 -0
- package/dist/lib/webhooks/media-buy-delivery.mjs +94 -0
- package/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/DELIVERY-WEBHOOK-PARSING.md +142 -0
- package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +15 -0
- package/docs/guides/REPORTING-LEDGER.md +93 -0
- package/docs/guides/REPORTING-STABILITY.md +1 -1
- package/docs/guides/TYPED-CLIENT-TOOLS.md +49 -0
- package/docs/llms.txt +2 -2
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/docs/migration-16-to-17.md +191 -14
- package/docs/migration-6.6-to-6.7.md +14 -0
- package/docs/migration-account-change-feed.md +15 -0
- package/docs/recipes/verifying-inbound-webhooks.md +18 -2
- package/package.json +2 -2
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import { applyTargetingInput, resolveTargetingInput } from "../media-buy/targeting-input.mjs";
|
|
2
2
|
import { scopedStore } from "./state-store.mjs";
|
|
3
3
|
const DEFAULT_MEDIA_BUY_STORE_COLLECTION = "media_buys_targeting";
|
|
4
|
+
const PACKAGE_IDENTITY_FIELDS = ["package_id", "product_id", "buyer_ref"];
|
|
5
|
+
function compatibleIdentity(left, right) {
|
|
6
|
+
if (!left || !right) return false;
|
|
7
|
+
return PACKAGE_IDENTITY_FIELDS.every((key) => !left[key] || !right[key] || left[key] === right[key]);
|
|
8
|
+
}
|
|
9
|
+
function sharesIdentity(left, right) {
|
|
10
|
+
if (!left || !right) return false;
|
|
11
|
+
return compatibleIdentity(left, right) && PACKAGE_IDENTITY_FIELDS.some((key) => left[key] && left[key] === right[key]);
|
|
12
|
+
}
|
|
13
|
+
function matchContextPackage(requests, responses, index) {
|
|
14
|
+
const matches = requests.filter((request) => sharesIdentity(request, responses[index]));
|
|
15
|
+
if (matches.length === 1 && responses.filter((response) => sharesIdentity(matches[0], response)).length === 1) {
|
|
16
|
+
return matches[0];
|
|
17
|
+
}
|
|
18
|
+
if (requests.length === responses.length && requests.every((request, i) => compatibleIdentity(request, responses[i]))) {
|
|
19
|
+
return requests[index];
|
|
20
|
+
}
|
|
21
|
+
return void 0;
|
|
22
|
+
}
|
|
4
23
|
function createMediaBuyStore(options) {
|
|
5
24
|
const collection = options.collection ?? DEFAULT_MEDIA_BUY_STORE_COLLECTION;
|
|
6
25
|
function viewFor(accountId) {
|
|
@@ -18,8 +37,9 @@ function createMediaBuyStore(options) {
|
|
|
18
37
|
async persistFromCreate(accountId, request, result) {
|
|
19
38
|
const requestPackages = request.packages ?? [];
|
|
20
39
|
const responsePackages = result.packages ?? [];
|
|
21
|
-
if (
|
|
22
|
-
const
|
|
40
|
+
if (!result.media_buy_id) return;
|
|
41
|
+
const prior = await loadRecord(accountId, result.media_buy_id);
|
|
42
|
+
const byId = new Map((prior?.packages ?? []).map((pkg) => [pkg.package_id, { ...pkg }]));
|
|
23
43
|
for (let i = 0; i < requestPackages.length; i++) {
|
|
24
44
|
const reqPkg = requestPackages[i];
|
|
25
45
|
if (!reqPkg?.targeting_overlay) continue;
|
|
@@ -30,12 +50,26 @@ function createMediaBuyStore(options) {
|
|
|
30
50
|
if (!packageId) continue;
|
|
31
51
|
const persistedOverlay = respPkg?.targeting_overlay ?? resolveTargetingInput(reqPkg.targeting_overlay);
|
|
32
52
|
if (!persistedOverlay) continue;
|
|
33
|
-
|
|
53
|
+
byId.set(packageId, { ...byId.get(packageId), package_id: packageId, targeting_overlay: persistedOverlay });
|
|
34
54
|
}
|
|
35
|
-
|
|
55
|
+
for (const [index, response] of responsePackages.entries()) {
|
|
56
|
+
if (!response.package_id) continue;
|
|
57
|
+
const context2 = matchContextPackage(requestPackages, responsePackages, index)?.context ?? response.context;
|
|
58
|
+
const stored = byId.get(response.package_id);
|
|
59
|
+
if (context2 !== void 0 && stored?.context === void 0) {
|
|
60
|
+
byId.set(response.package_id, {
|
|
61
|
+
...stored,
|
|
62
|
+
package_id: response.package_id,
|
|
63
|
+
context: structuredClone(context2)
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const context = prior?.context ?? request.context ?? result.context;
|
|
68
|
+
if (byId.size === 0 && context === void 0) return;
|
|
36
69
|
await writeRecord(accountId, {
|
|
37
70
|
media_buy_id: result.media_buy_id,
|
|
38
|
-
|
|
71
|
+
...context !== void 0 ? { context: structuredClone(context) } : {},
|
|
72
|
+
packages: Array.from(byId.values())
|
|
39
73
|
});
|
|
40
74
|
},
|
|
41
75
|
async mergeFromUpdate(accountId, mediaBuyId, patch) {
|
|
@@ -43,42 +77,56 @@ function createMediaBuyStore(options) {
|
|
|
43
77
|
media_buy_id: mediaBuyId,
|
|
44
78
|
packages: []
|
|
45
79
|
};
|
|
46
|
-
const byId = new Map(prior.packages.map((p) => [p.package_id, p
|
|
80
|
+
const byId = new Map(prior.packages.map((p) => [p.package_id, { ...p }]));
|
|
47
81
|
for (const pkg of patch.packages ?? []) {
|
|
48
82
|
const packageId = pkg?.package_id;
|
|
49
83
|
if (!packageId) continue;
|
|
50
84
|
if (!("targeting_overlay" in pkg)) continue;
|
|
51
85
|
const incoming = pkg.targeting_overlay;
|
|
52
86
|
if (incoming === void 0) continue;
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
87
|
+
const stored = byId.get(packageId);
|
|
88
|
+
const merged = applyTargetingInput(stored?.targeting_overlay, incoming);
|
|
89
|
+
if (merged) byId.set(packageId, { ...stored, package_id: packageId, targeting_overlay: merged });
|
|
90
|
+
else if (stored?.context !== void 0) {
|
|
91
|
+
byId.set(packageId, { package_id: packageId, context: stored.context });
|
|
92
|
+
} else byId.delete(packageId);
|
|
56
93
|
}
|
|
57
94
|
for (const pkg of patch.new_packages ?? []) {
|
|
58
95
|
if (!pkg?.targeting_overlay || !pkg.package_id) continue;
|
|
59
96
|
const resolved = resolveTargetingInput(pkg.targeting_overlay);
|
|
60
|
-
if (resolved)
|
|
97
|
+
if (resolved)
|
|
98
|
+
byId.set(pkg.package_id, {
|
|
99
|
+
...byId.get(pkg.package_id),
|
|
100
|
+
package_id: pkg.package_id,
|
|
101
|
+
targeting_overlay: resolved
|
|
102
|
+
});
|
|
61
103
|
}
|
|
62
104
|
await writeRecord(accountId, {
|
|
63
|
-
|
|
64
|
-
packages: Array.from(byId.
|
|
65
|
-
package_id,
|
|
66
|
-
targeting_overlay
|
|
67
|
-
}))
|
|
105
|
+
...prior,
|
|
106
|
+
packages: Array.from(byId.values())
|
|
68
107
|
});
|
|
69
108
|
},
|
|
70
109
|
async backfill(accountId, result) {
|
|
71
110
|
const buys = result.media_buys;
|
|
72
111
|
if (!buys || buys.length === 0) return result;
|
|
73
112
|
for (const buy of buys) {
|
|
74
|
-
if (!buy?.media_buy_id
|
|
113
|
+
if (!buy?.media_buy_id) continue;
|
|
75
114
|
const record = await loadRecord(accountId, buy.media_buy_id);
|
|
76
115
|
if (!record) continue;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
116
|
+
if (buy.context === void 0 && record.context !== void 0) {
|
|
117
|
+
buy.context = structuredClone(record.context);
|
|
118
|
+
}
|
|
119
|
+
const byId = new Map(record.packages.map((p) => [p.package_id, p]));
|
|
120
|
+
for (const pkg of buy.packages ?? []) {
|
|
121
|
+
if (!pkg?.package_id) continue;
|
|
122
|
+
const persisted = byId.get(pkg.package_id);
|
|
123
|
+
if (!persisted) continue;
|
|
124
|
+
if (pkg.targeting_overlay === void 0 && persisted.targeting_overlay !== void 0) {
|
|
125
|
+
pkg.targeting_overlay = persisted.targeting_overlay;
|
|
126
|
+
}
|
|
127
|
+
if (pkg.context === void 0 && persisted.context !== void 0) {
|
|
128
|
+
pkg.context = structuredClone(persisted.context);
|
|
129
|
+
}
|
|
82
130
|
}
|
|
83
131
|
}
|
|
84
132
|
return result;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { WebhookAttemptSuppressionReason } from '../webhook-emitter.mjs';
|
|
2
2
|
import type { NotificationSubscriptionConfigInput, NotificationSubscriptionView, NotificationSuppressionDisposition, PersistentNotificationRuntime, PersistentNotificationRuntimeOptions, StoredNotificationSubscription } from './types.mjs';
|
|
3
3
|
export declare const CALLER_NOTIFICATION_TYPES: readonly ["capabilities.changed", "principal.changed"];
|
|
4
|
-
export declare const ACCOUNT_NOTIFICATION_TYPES: readonly ["creative.status_changed", "creative.assignment_changed", "indicators.changed", "creative.purged", "account.status_changed", "account.change_recorded", "product.created", "product.updated", "product.priced", "product.removed", "signal.created", "signal.updated", "signal.priced", "signal.removed", "wholesale_feed.bulk_change", "reporting.delivery_ready", "reporting.status_changed", "reporting.ledger_changed"];
|
|
4
|
+
export declare const ACCOUNT_NOTIFICATION_TYPES: readonly ["creative.status_changed", "creative.assignment_changed", "indicators.changed", "creative.purged", "account.status_changed", "account.change_recorded", "product.created", "product.updated", "product.priced", "product.removed", "signal.created", "signal.updated", "signal.priced", "signal.removed", "wholesale_feed.bulk_change", "collection_card.updated", "collection_card.removed", "collection_catalog.bulk_change", "proposal.created", "reporting.delivery_ready", "reporting.status_changed", "reporting.ledger_changed"];
|
|
5
5
|
/**
|
|
6
6
|
* Durable subscription control plane. The supplied emitter factory is called
|
|
7
7
|
* exactly once with the runtime's mandatory live authorizer, preventing a
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { WebhookAttemptSuppressionReason } from '../webhook-emitter';
|
|
2
2
|
import type { NotificationSubscriptionConfigInput, NotificationSubscriptionView, NotificationSuppressionDisposition, PersistentNotificationRuntime, PersistentNotificationRuntimeOptions, StoredNotificationSubscription } from './types';
|
|
3
3
|
export declare const CALLER_NOTIFICATION_TYPES: readonly ["capabilities.changed", "principal.changed"];
|
|
4
|
-
export declare const ACCOUNT_NOTIFICATION_TYPES: readonly ["creative.status_changed", "creative.assignment_changed", "indicators.changed", "creative.purged", "account.status_changed", "account.change_recorded", "product.created", "product.updated", "product.priced", "product.removed", "signal.created", "signal.updated", "signal.priced", "signal.removed", "wholesale_feed.bulk_change", "reporting.delivery_ready", "reporting.status_changed", "reporting.ledger_changed"];
|
|
4
|
+
export declare const ACCOUNT_NOTIFICATION_TYPES: readonly ["creative.status_changed", "creative.assignment_changed", "indicators.changed", "creative.purged", "account.status_changed", "account.change_recorded", "product.created", "product.updated", "product.priced", "product.removed", "signal.created", "signal.updated", "signal.priced", "signal.removed", "wholesale_feed.bulk_change", "collection_card.updated", "collection_card.removed", "collection_catalog.bulk_change", "proposal.created", "reporting.delivery_ready", "reporting.status_changed", "reporting.ledger_changed"];
|
|
5
5
|
/**
|
|
6
6
|
* Durable subscription control plane. The supplied emitter factory is called
|
|
7
7
|
* exactly once with the runtime's mandatory live authorizer, preventing a
|
|
@@ -51,6 +51,10 @@ const ACCOUNT_NOTIFICATION_TYPES = Object.freeze([
|
|
|
51
51
|
"signal.priced",
|
|
52
52
|
"signal.removed",
|
|
53
53
|
"wholesale_feed.bulk_change",
|
|
54
|
+
"collection_card.updated",
|
|
55
|
+
"collection_card.removed",
|
|
56
|
+
"collection_catalog.bulk_change",
|
|
57
|
+
"proposal.created",
|
|
54
58
|
"reporting.delivery_ready",
|
|
55
59
|
"reporting.status_changed",
|
|
56
60
|
"reporting.ledger_changed"
|
|
@@ -22,6 +22,10 @@ const ACCOUNT_NOTIFICATION_TYPES = Object.freeze([
|
|
|
22
22
|
"signal.priced",
|
|
23
23
|
"signal.removed",
|
|
24
24
|
"wholesale_feed.bulk_change",
|
|
25
|
+
"collection_card.updated",
|
|
26
|
+
"collection_card.removed",
|
|
27
|
+
"collection_catalog.bulk_change",
|
|
28
|
+
"proposal.created",
|
|
25
29
|
"reporting.delivery_ready",
|
|
26
30
|
"reporting.status_changed",
|
|
27
31
|
"reporting.ledger_changed"
|
|
@@ -60,6 +60,7 @@ __export(responses_exports, {
|
|
|
60
60
|
module.exports = __toCommonJS(responses_exports);
|
|
61
61
|
var import_media_buy_helpers = require('./media-buy-helpers.js');
|
|
62
62
|
var import_reporting_delivery_config = require('./reporting-delivery-config.js');
|
|
63
|
+
var import_account_response_identity = require('./account-response-identity.js');
|
|
63
64
|
const explicitResponseSummaries = /* @__PURE__ */ new WeakMap();
|
|
64
65
|
function _getExplicitResponseSummary(response) {
|
|
65
66
|
return explicitResponseSummaries.get(response);
|
|
@@ -124,7 +125,14 @@ function stripBusinessEntityBank(row, key) {
|
|
|
124
125
|
return stripped;
|
|
125
126
|
}
|
|
126
127
|
function stripAccountWriteOnlyFields(account) {
|
|
127
|
-
const
|
|
128
|
+
const {
|
|
129
|
+
destination_billing_entity: _destination,
|
|
130
|
+
authInfo: _authInfo,
|
|
131
|
+
ctx_metadata: _metadata,
|
|
132
|
+
...responseFields
|
|
133
|
+
} = account;
|
|
134
|
+
const response = stripBusinessEntityBank(stripNotificationConfigSecrets(responseFields), "billing_entity");
|
|
135
|
+
const stripped = { ...response, ...(0, import_account_response_identity.projectAccountResponseIdentityFields)(response) };
|
|
128
136
|
const reportingDeliveryConfigs = stripped.reporting_delivery_configs;
|
|
129
137
|
if (reportingDeliveryConfigs === void 0) return stripped;
|
|
130
138
|
return {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { validActionsForStatus } from "./media-buy-helpers.mjs";
|
|
2
2
|
import { projectReportingDeliveryConfigStates } from "./reporting-delivery-config.mjs";
|
|
3
|
+
import { projectAccountResponseIdentityFields } from "./account-response-identity.mjs";
|
|
3
4
|
const explicitResponseSummaries = /* @__PURE__ */ new WeakMap();
|
|
4
5
|
function _getExplicitResponseSummary(response) {
|
|
5
6
|
return explicitResponseSummaries.get(response);
|
|
@@ -64,7 +65,14 @@ function stripBusinessEntityBank(row, key) {
|
|
|
64
65
|
return stripped;
|
|
65
66
|
}
|
|
66
67
|
function stripAccountWriteOnlyFields(account) {
|
|
67
|
-
const
|
|
68
|
+
const {
|
|
69
|
+
destination_billing_entity: _destination,
|
|
70
|
+
authInfo: _authInfo,
|
|
71
|
+
ctx_metadata: _metadata,
|
|
72
|
+
...responseFields
|
|
73
|
+
} = account;
|
|
74
|
+
const response = stripBusinessEntityBank(stripNotificationConfigSecrets(responseFields), "billing_entity");
|
|
75
|
+
const stripped = { ...response, ...projectAccountResponseIdentityFields(response) };
|
|
68
76
|
const reportingDeliveryConfigs = stripped.reporting_delivery_configs;
|
|
69
77
|
if (reportingDeliveryConfigs === void 0) return stripped;
|
|
70
78
|
return {
|
|
@@ -80,7 +80,7 @@ export interface BuildAgentSigningFetchOptions {
|
|
|
80
80
|
* 1. Sign immediately when the payload carries webhook authentication.
|
|
81
81
|
* 2. Resolve the AdCP operation and exact JSON-RPC protocol method.
|
|
82
82
|
* 3. Consult each capability namespace independently; either can request
|
|
83
|
-
* signing.
|
|
83
|
+
* signing. SDK AdCP task polls sign when the seller supports signing.
|
|
84
84
|
* 4. Resolve the seller's content-digest policy into a per-request toggle.
|
|
85
85
|
* 5. Delegate to `createSigningFetch` with the decision baked in.
|
|
86
86
|
*/
|
|
@@ -80,7 +80,7 @@ export interface BuildAgentSigningFetchOptions {
|
|
|
80
80
|
* 1. Sign immediately when the payload carries webhook authentication.
|
|
81
81
|
* 2. Resolve the AdCP operation and exact JSON-RPC protocol method.
|
|
82
82
|
* 3. Consult each capability namespace independently; either can request
|
|
83
|
-
* signing.
|
|
83
|
+
* signing. SDK AdCP task polls sign when the seller supports signing.
|
|
84
84
|
* 4. Resolve the seller's content-digest policy into a per-request toggle.
|
|
85
85
|
* 5. Delegate to `createSigningFetch` with the decision baked in.
|
|
86
86
|
*/
|
|
@@ -157,13 +157,13 @@ function buildAgentSigningFetch(options) {
|
|
|
157
157
|
}
|
|
158
158
|
const operation = extractAdcpOperation(init?.body);
|
|
159
159
|
if (operation === "get_adcp_capabilities" && (0, import_protocol_methods.hasUnsignedCapabilityBootstrap)(signing)) return false;
|
|
160
|
-
const isPollOperation = operation === "tasks_get" || operation === "tasks/get";
|
|
160
|
+
const isPollOperation = operation === "get_task_status" || operation === "tasks_get" || operation === "tasks/get";
|
|
161
161
|
const methods = policyMethods ?? (isPollOperation ? jsonRpcMethodsForSigning(init?.body) : []);
|
|
162
162
|
const profileCompatible = signing.profile === "web-bot-auth" ? (0, import_protocol_methods.signingListIncludes)(capability?.profiles, "web-bot-auth") : capability?.profiles === void 0 || (0, import_protocol_methods.signingListIncludes)(capability.profiles, "adcp/request-signing/v1");
|
|
163
|
-
const
|
|
163
|
+
const signedPoll = profileCompatible && capability?.supported === true && ((operation === "tasks_get" || operation === "get_task_status") && methods.includes("tools/call") || (operation === "tasks/get" || operation === "get_task_status") && methods.some(
|
|
164
164
|
(method) => ["message/send", "message/stream", "SendMessage", "SendStreamingMessage"].includes(method)
|
|
165
165
|
));
|
|
166
|
-
const sign = signing.profile === "web-bot-auth" && !!operation && (0, import_protocol_methods.signingListIncludes)(capability?.profiles, "web-bot-auth") || shouldSignOperation(operation, capability, signing) || methods.some((method) => shouldSignProtocolMethod(method, capability, signing)) ||
|
|
166
|
+
const sign = signing.profile === "web-bot-auth" && !!operation && (0, import_protocol_methods.signingListIncludes)(capability?.profiles, "web-bot-auth") || shouldSignOperation(operation, capability, signing) || methods.some((method) => shouldSignProtocolMethod(method, capability, signing)) || signedPoll;
|
|
167
167
|
if (sign && signing.profile === "web-bot-auth" && !(0, import_protocol_methods.signingListIncludes)(capability?.profiles, "web-bot-auth"))
|
|
168
168
|
throw new TypeError("Seller did not advertise the Web Bot Auth request signing profile");
|
|
169
169
|
return sign;
|
|
@@ -139,13 +139,13 @@ function buildAgentSigningFetch(options) {
|
|
|
139
139
|
}
|
|
140
140
|
const operation = extractAdcpOperation(init?.body);
|
|
141
141
|
if (operation === "get_adcp_capabilities" && hasUnsignedCapabilityBootstrap(signing)) return false;
|
|
142
|
-
const isPollOperation = operation === "tasks_get" || operation === "tasks/get";
|
|
142
|
+
const isPollOperation = operation === "get_task_status" || operation === "tasks_get" || operation === "tasks/get";
|
|
143
143
|
const methods = policyMethods ?? (isPollOperation ? jsonRpcMethodsForSigning(init?.body) : []);
|
|
144
144
|
const profileCompatible = signing.profile === "web-bot-auth" ? signingListIncludes(capability?.profiles, "web-bot-auth") : capability?.profiles === void 0 || signingListIncludes(capability.profiles, "adcp/request-signing/v1");
|
|
145
|
-
const
|
|
145
|
+
const signedPoll = profileCompatible && capability?.supported === true && ((operation === "tasks_get" || operation === "get_task_status") && methods.includes("tools/call") || (operation === "tasks/get" || operation === "get_task_status") && methods.some(
|
|
146
146
|
(method) => ["message/send", "message/stream", "SendMessage", "SendStreamingMessage"].includes(method)
|
|
147
147
|
));
|
|
148
|
-
const sign = signing.profile === "web-bot-auth" && !!operation && signingListIncludes(capability?.profiles, "web-bot-auth") || shouldSignOperation(operation, capability, signing) || methods.some((method) => shouldSignProtocolMethod(method, capability, signing)) ||
|
|
148
|
+
const sign = signing.profile === "web-bot-auth" && !!operation && signingListIncludes(capability?.profiles, "web-bot-auth") || shouldSignOperation(operation, capability, signing) || methods.some((method) => shouldSignProtocolMethod(method, capability, signing)) || signedPoll;
|
|
149
149
|
if (sign && signing.profile === "web-bot-auth" && !signingListIncludes(capability?.profiles, "web-bot-auth"))
|
|
150
150
|
throw new TypeError("Seller did not advertise the Web Bot Auth request signing profile");
|
|
151
151
|
return sign;
|
|
@@ -208,17 +208,41 @@ function evaluatePackage(pkg, pointer, index, products) {
|
|
|
208
208
|
actual: productId ?? null
|
|
209
209
|
};
|
|
210
210
|
}
|
|
211
|
+
const routes = [];
|
|
211
212
|
const formatOptionRefs = Array.isArray(pkg.format_option_refs) ? pkg.format_option_refs : [];
|
|
212
213
|
if (formatOptionRefs.length > 0) {
|
|
213
|
-
|
|
214
|
+
routes.push({ name: "format_option_refs", verdict: evaluateFormatOptionRefs(formatOptionRefs, product, pointer) });
|
|
214
215
|
}
|
|
215
216
|
const formatIds = Array.isArray(pkg.format_ids) ? pkg.format_ids : [];
|
|
216
217
|
if (formatIds.length > 0) {
|
|
217
|
-
|
|
218
|
+
routes.push({ name: "format_ids", verdict: evaluateLegacyFormatIds(formatIds, product, pointer, productId) });
|
|
218
219
|
}
|
|
219
220
|
const canonicalSelectors = extractCanonicalSelectors(pkg, pointer);
|
|
220
221
|
if (canonicalSelectors.length > 0) {
|
|
221
|
-
|
|
222
|
+
routes.push({ name: "canonical selectors", verdict: evaluateCanonicalSelectors(canonicalSelectors, product) });
|
|
223
|
+
}
|
|
224
|
+
const failed = routes.find((route) => !route.verdict.satisfied);
|
|
225
|
+
if (failed) return failed.verdict;
|
|
226
|
+
const primary = routes[0];
|
|
227
|
+
if (primary) {
|
|
228
|
+
const selected = new Set(primary.verdict.selectedDeclarations);
|
|
229
|
+
const conflicting = routes.slice(1).find((route) => {
|
|
230
|
+
const other = new Set(route.verdict.selectedDeclarations);
|
|
231
|
+
return selected.size !== other.size || [...selected].some((index2) => !other.has(index2));
|
|
232
|
+
});
|
|
233
|
+
if (conflicting) {
|
|
234
|
+
return {
|
|
235
|
+
satisfied: false,
|
|
236
|
+
bug_class: "directionality",
|
|
237
|
+
detail: `Conflicting selector routes ${primary.name} and ${conflicting.name} select different product format_options[] sets`,
|
|
238
|
+
json_pointer: pointer,
|
|
239
|
+
observations: routes.map((route) => ({
|
|
240
|
+
route: route.name,
|
|
241
|
+
selected_declarations: route.verdict.selectedDeclarations
|
|
242
|
+
}))
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
return primary.verdict;
|
|
222
246
|
}
|
|
223
247
|
return {
|
|
224
248
|
satisfied: true,
|
|
@@ -238,6 +262,7 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
|
|
|
238
262
|
actual: refs
|
|
239
263
|
};
|
|
240
264
|
}
|
|
265
|
+
const selected = /* @__PURE__ */ new Set();
|
|
241
266
|
for (let i = 0; i < refs.length; i++) {
|
|
242
267
|
const ref = refs[i];
|
|
243
268
|
if (!isRecord(ref)) {
|
|
@@ -267,13 +292,13 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
|
|
|
267
292
|
actual: ref
|
|
268
293
|
};
|
|
269
294
|
}
|
|
270
|
-
const match = declarations.
|
|
295
|
+
const match = declarations.findIndex((decl) => {
|
|
271
296
|
if (ref.scope === "publisher") {
|
|
272
297
|
return decl.publisher_domain === ref.publisher_domain && decl.format_option_id === ref.format_option_id && typeof ref.publisher_domain === "string";
|
|
273
298
|
}
|
|
274
299
|
return decl.format_option_id === ref.format_option_id && !decl.publisher_domain;
|
|
275
300
|
});
|
|
276
|
-
if (
|
|
301
|
+
if (match < 0) {
|
|
277
302
|
return {
|
|
278
303
|
satisfied: false,
|
|
279
304
|
bug_class: "closed_set",
|
|
@@ -283,16 +308,19 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
|
|
|
283
308
|
observations: [{ available_format_option_ids: declarations.map(declarationLabel).filter(Boolean) }]
|
|
284
309
|
};
|
|
285
310
|
}
|
|
311
|
+
selected.add(match);
|
|
286
312
|
}
|
|
287
313
|
return {
|
|
288
314
|
satisfied: true,
|
|
289
315
|
bug_class: "directionality",
|
|
290
316
|
detail: "Every format_option_refs[] entry resolved to the target product format_options[] closed set",
|
|
291
|
-
json_pointer: `${packagePointer}/format_option_refs
|
|
317
|
+
json_pointer: `${packagePointer}/format_option_refs`,
|
|
318
|
+
selectedDeclarations: [...selected]
|
|
292
319
|
};
|
|
293
320
|
}
|
|
294
321
|
function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
|
|
295
322
|
const declarations = productFormatOptions(product);
|
|
323
|
+
const selected = /* @__PURE__ */ new Set();
|
|
296
324
|
for (let i = 0; i < refs.length; i++) {
|
|
297
325
|
const ref = refs[i];
|
|
298
326
|
if (!isFormatId(ref)) {
|
|
@@ -304,12 +332,22 @@ function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
|
|
|
304
332
|
actual: ref
|
|
305
333
|
};
|
|
306
334
|
}
|
|
307
|
-
const direct = declarations.
|
|
308
|
-
|
|
335
|
+
const direct = declarations.flatMap(
|
|
336
|
+
(decl, index) => (decl.v1_format_ref ?? []).some((v1) => sameFormatId(v1, ref)) ? [index] : []
|
|
337
|
+
);
|
|
338
|
+
if (direct.length > 0) {
|
|
339
|
+
for (const index of direct) selected.add(index);
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
309
342
|
const projected = projectLegacyRef(ref, productId, `${packagePointer}/format_ids/${i}`);
|
|
310
343
|
if (projected) {
|
|
311
|
-
const
|
|
312
|
-
|
|
344
|
+
const matches = declarations.flatMap(
|
|
345
|
+
(decl, index) => canonicalSelectorSatisfiesDeclaration(projected, decl).ok ? [index] : []
|
|
346
|
+
);
|
|
347
|
+
if (matches.length > 0) {
|
|
348
|
+
for (const index of matches) selected.add(index);
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
313
351
|
}
|
|
314
352
|
if (declarations.length === 0 && Array.isArray(product.format_ids) && product.format_ids.some((fid) => isFormatId(fid) && sameFormatId(fid, ref))) {
|
|
315
353
|
continue;
|
|
@@ -327,7 +365,8 @@ function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
|
|
|
327
365
|
satisfied: true,
|
|
328
366
|
bug_class: "normalization",
|
|
329
367
|
detail: "Every legacy format_id normalized to a product canonical declaration or product legacy format_id",
|
|
330
|
-
json_pointer: `${packagePointer}/format_ids
|
|
368
|
+
json_pointer: `${packagePointer}/format_ids`,
|
|
369
|
+
selectedDeclarations: [...selected]
|
|
331
370
|
};
|
|
332
371
|
}
|
|
333
372
|
function evaluateCanonicalSelectors(selectors, product) {
|
|
@@ -341,6 +380,7 @@ function evaluateCanonicalSelectors(selectors, product) {
|
|
|
341
380
|
actual: selectors
|
|
342
381
|
};
|
|
343
382
|
}
|
|
383
|
+
const selected = /* @__PURE__ */ new Set();
|
|
344
384
|
for (const selector of selectors) {
|
|
345
385
|
const candidates = declarations.filter((decl) => decl.format_kind === selector.format_kind);
|
|
346
386
|
if (candidates.length === 0) {
|
|
@@ -353,7 +393,12 @@ function evaluateCanonicalSelectors(selectors, product) {
|
|
|
353
393
|
};
|
|
354
394
|
}
|
|
355
395
|
const checks = candidates.map((decl) => canonicalSelectorSatisfiesDeclaration(selector, decl));
|
|
356
|
-
if (checks.some((c) => c.ok))
|
|
396
|
+
if (checks.some((c) => c.ok)) {
|
|
397
|
+
for (const [index, decl] of declarations.entries()) {
|
|
398
|
+
if (canonicalSelectorSatisfiesDeclaration(selector, decl).ok) selected.add(index);
|
|
399
|
+
}
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
357
402
|
const primary = checks.find((c) => c.bug_class === "range_containment") ?? checks[0];
|
|
358
403
|
return {
|
|
359
404
|
satisfied: false,
|
|
@@ -368,7 +413,8 @@ function evaluateCanonicalSelectors(selectors, product) {
|
|
|
368
413
|
satisfied: true,
|
|
369
414
|
bug_class: "directionality",
|
|
370
415
|
detail: "Every canonical selector satisfies at least one product format_options[] declaration",
|
|
371
|
-
json_pointer: selectors[0]?.pointer ?? null
|
|
416
|
+
json_pointer: selectors[0]?.pointer ?? null,
|
|
417
|
+
selectedDeclarations: [...selected]
|
|
372
418
|
};
|
|
373
419
|
}
|
|
374
420
|
function canonicalSelectorSatisfiesDeclaration(selector, decl) {
|
|
@@ -737,7 +783,7 @@ function collectRejectionInfo(value, codes, fields, messages, depth = 0) {
|
|
|
737
783
|
}
|
|
738
784
|
function rejectionSupportsFormatFailure(rejection) {
|
|
739
785
|
if (!rejection) return false;
|
|
740
|
-
if (rejection.codes.some((code) => code.startsWith("FORMAT_"))) return true;
|
|
786
|
+
if (rejection.codes.some((code) => code.startsWith("FORMAT_") || code === "CONFLICTING_SELECTORS")) return true;
|
|
741
787
|
return [...rejection.fields, ...rejection.messages].some(
|
|
742
788
|
(text) => /format|format_option|format_id|selector/i.test(text)
|
|
743
789
|
);
|
|
@@ -184,17 +184,41 @@ function evaluatePackage(pkg, pointer, index, products) {
|
|
|
184
184
|
actual: productId ?? null
|
|
185
185
|
};
|
|
186
186
|
}
|
|
187
|
+
const routes = [];
|
|
187
188
|
const formatOptionRefs = Array.isArray(pkg.format_option_refs) ? pkg.format_option_refs : [];
|
|
188
189
|
if (formatOptionRefs.length > 0) {
|
|
189
|
-
|
|
190
|
+
routes.push({ name: "format_option_refs", verdict: evaluateFormatOptionRefs(formatOptionRefs, product, pointer) });
|
|
190
191
|
}
|
|
191
192
|
const formatIds = Array.isArray(pkg.format_ids) ? pkg.format_ids : [];
|
|
192
193
|
if (formatIds.length > 0) {
|
|
193
|
-
|
|
194
|
+
routes.push({ name: "format_ids", verdict: evaluateLegacyFormatIds(formatIds, product, pointer, productId) });
|
|
194
195
|
}
|
|
195
196
|
const canonicalSelectors = extractCanonicalSelectors(pkg, pointer);
|
|
196
197
|
if (canonicalSelectors.length > 0) {
|
|
197
|
-
|
|
198
|
+
routes.push({ name: "canonical selectors", verdict: evaluateCanonicalSelectors(canonicalSelectors, product) });
|
|
199
|
+
}
|
|
200
|
+
const failed = routes.find((route) => !route.verdict.satisfied);
|
|
201
|
+
if (failed) return failed.verdict;
|
|
202
|
+
const primary = routes[0];
|
|
203
|
+
if (primary) {
|
|
204
|
+
const selected = new Set(primary.verdict.selectedDeclarations);
|
|
205
|
+
const conflicting = routes.slice(1).find((route) => {
|
|
206
|
+
const other = new Set(route.verdict.selectedDeclarations);
|
|
207
|
+
return selected.size !== other.size || [...selected].some((index2) => !other.has(index2));
|
|
208
|
+
});
|
|
209
|
+
if (conflicting) {
|
|
210
|
+
return {
|
|
211
|
+
satisfied: false,
|
|
212
|
+
bug_class: "directionality",
|
|
213
|
+
detail: `Conflicting selector routes ${primary.name} and ${conflicting.name} select different product format_options[] sets`,
|
|
214
|
+
json_pointer: pointer,
|
|
215
|
+
observations: routes.map((route) => ({
|
|
216
|
+
route: route.name,
|
|
217
|
+
selected_declarations: route.verdict.selectedDeclarations
|
|
218
|
+
}))
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
return primary.verdict;
|
|
198
222
|
}
|
|
199
223
|
return {
|
|
200
224
|
satisfied: true,
|
|
@@ -214,6 +238,7 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
|
|
|
214
238
|
actual: refs
|
|
215
239
|
};
|
|
216
240
|
}
|
|
241
|
+
const selected = /* @__PURE__ */ new Set();
|
|
217
242
|
for (let i = 0; i < refs.length; i++) {
|
|
218
243
|
const ref = refs[i];
|
|
219
244
|
if (!isRecord(ref)) {
|
|
@@ -243,13 +268,13 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
|
|
|
243
268
|
actual: ref
|
|
244
269
|
};
|
|
245
270
|
}
|
|
246
|
-
const match = declarations.
|
|
271
|
+
const match = declarations.findIndex((decl) => {
|
|
247
272
|
if (ref.scope === "publisher") {
|
|
248
273
|
return decl.publisher_domain === ref.publisher_domain && decl.format_option_id === ref.format_option_id && typeof ref.publisher_domain === "string";
|
|
249
274
|
}
|
|
250
275
|
return decl.format_option_id === ref.format_option_id && !decl.publisher_domain;
|
|
251
276
|
});
|
|
252
|
-
if (
|
|
277
|
+
if (match < 0) {
|
|
253
278
|
return {
|
|
254
279
|
satisfied: false,
|
|
255
280
|
bug_class: "closed_set",
|
|
@@ -259,16 +284,19 @@ function evaluateFormatOptionRefs(refs, product, packagePointer) {
|
|
|
259
284
|
observations: [{ available_format_option_ids: declarations.map(declarationLabel).filter(Boolean) }]
|
|
260
285
|
};
|
|
261
286
|
}
|
|
287
|
+
selected.add(match);
|
|
262
288
|
}
|
|
263
289
|
return {
|
|
264
290
|
satisfied: true,
|
|
265
291
|
bug_class: "directionality",
|
|
266
292
|
detail: "Every format_option_refs[] entry resolved to the target product format_options[] closed set",
|
|
267
|
-
json_pointer: `${packagePointer}/format_option_refs
|
|
293
|
+
json_pointer: `${packagePointer}/format_option_refs`,
|
|
294
|
+
selectedDeclarations: [...selected]
|
|
268
295
|
};
|
|
269
296
|
}
|
|
270
297
|
function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
|
|
271
298
|
const declarations = productFormatOptions(product);
|
|
299
|
+
const selected = /* @__PURE__ */ new Set();
|
|
272
300
|
for (let i = 0; i < refs.length; i++) {
|
|
273
301
|
const ref = refs[i];
|
|
274
302
|
if (!isFormatId(ref)) {
|
|
@@ -280,12 +308,22 @@ function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
|
|
|
280
308
|
actual: ref
|
|
281
309
|
};
|
|
282
310
|
}
|
|
283
|
-
const direct = declarations.
|
|
284
|
-
|
|
311
|
+
const direct = declarations.flatMap(
|
|
312
|
+
(decl, index) => (decl.v1_format_ref ?? []).some((v1) => sameFormatId(v1, ref)) ? [index] : []
|
|
313
|
+
);
|
|
314
|
+
if (direct.length > 0) {
|
|
315
|
+
for (const index of direct) selected.add(index);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
285
318
|
const projected = projectLegacyRef(ref, productId, `${packagePointer}/format_ids/${i}`);
|
|
286
319
|
if (projected) {
|
|
287
|
-
const
|
|
288
|
-
|
|
320
|
+
const matches = declarations.flatMap(
|
|
321
|
+
(decl, index) => canonicalSelectorSatisfiesDeclaration(projected, decl).ok ? [index] : []
|
|
322
|
+
);
|
|
323
|
+
if (matches.length > 0) {
|
|
324
|
+
for (const index of matches) selected.add(index);
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
289
327
|
}
|
|
290
328
|
if (declarations.length === 0 && Array.isArray(product.format_ids) && product.format_ids.some((fid) => isFormatId(fid) && sameFormatId(fid, ref))) {
|
|
291
329
|
continue;
|
|
@@ -303,7 +341,8 @@ function evaluateLegacyFormatIds(refs, product, packagePointer, productId) {
|
|
|
303
341
|
satisfied: true,
|
|
304
342
|
bug_class: "normalization",
|
|
305
343
|
detail: "Every legacy format_id normalized to a product canonical declaration or product legacy format_id",
|
|
306
|
-
json_pointer: `${packagePointer}/format_ids
|
|
344
|
+
json_pointer: `${packagePointer}/format_ids`,
|
|
345
|
+
selectedDeclarations: [...selected]
|
|
307
346
|
};
|
|
308
347
|
}
|
|
309
348
|
function evaluateCanonicalSelectors(selectors, product) {
|
|
@@ -317,6 +356,7 @@ function evaluateCanonicalSelectors(selectors, product) {
|
|
|
317
356
|
actual: selectors
|
|
318
357
|
};
|
|
319
358
|
}
|
|
359
|
+
const selected = /* @__PURE__ */ new Set();
|
|
320
360
|
for (const selector of selectors) {
|
|
321
361
|
const candidates = declarations.filter((decl) => decl.format_kind === selector.format_kind);
|
|
322
362
|
if (candidates.length === 0) {
|
|
@@ -329,7 +369,12 @@ function evaluateCanonicalSelectors(selectors, product) {
|
|
|
329
369
|
};
|
|
330
370
|
}
|
|
331
371
|
const checks = candidates.map((decl) => canonicalSelectorSatisfiesDeclaration(selector, decl));
|
|
332
|
-
if (checks.some((c) => c.ok))
|
|
372
|
+
if (checks.some((c) => c.ok)) {
|
|
373
|
+
for (const [index, decl] of declarations.entries()) {
|
|
374
|
+
if (canonicalSelectorSatisfiesDeclaration(selector, decl).ok) selected.add(index);
|
|
375
|
+
}
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
333
378
|
const primary = checks.find((c) => c.bug_class === "range_containment") ?? checks[0];
|
|
334
379
|
return {
|
|
335
380
|
satisfied: false,
|
|
@@ -344,7 +389,8 @@ function evaluateCanonicalSelectors(selectors, product) {
|
|
|
344
389
|
satisfied: true,
|
|
345
390
|
bug_class: "directionality",
|
|
346
391
|
detail: "Every canonical selector satisfies at least one product format_options[] declaration",
|
|
347
|
-
json_pointer: selectors[0]?.pointer ?? null
|
|
392
|
+
json_pointer: selectors[0]?.pointer ?? null,
|
|
393
|
+
selectedDeclarations: [...selected]
|
|
348
394
|
};
|
|
349
395
|
}
|
|
350
396
|
function canonicalSelectorSatisfiesDeclaration(selector, decl) {
|
|
@@ -713,7 +759,7 @@ function collectRejectionInfo(value, codes, fields, messages, depth = 0) {
|
|
|
713
759
|
}
|
|
714
760
|
function rejectionSupportsFormatFailure(rejection) {
|
|
715
761
|
if (!rejection) return false;
|
|
716
|
-
if (rejection.codes.some((code) => code.startsWith("FORMAT_"))) return true;
|
|
762
|
+
if (rejection.codes.some((code) => code.startsWith("FORMAT_") || code === "CONFLICTING_SELECTORS")) return true;
|
|
717
763
|
return [...rejection.fields, ...rejection.messages].some(
|
|
718
764
|
(text) => /format|format_option|format_id|selector/i.test(text)
|
|
719
765
|
);
|
|
@@ -181,12 +181,9 @@ export declare function getExternalSchemaRootForCompliance(options: ResolveOptio
|
|
|
181
181
|
export declare function loadBundleStoryboards(ref: BundleRef): Storyboard[];
|
|
182
182
|
/** Enumerate every bundle present in the cache (universal + protocols + specialisms). */
|
|
183
183
|
export declare function listBundles(options?: ResolveOptions): BundleRef[];
|
|
184
|
-
/** List every storyboard the
|
|
184
|
+
/** List every storyboard the selected immutable bundle can produce, as detached records. */
|
|
185
185
|
export declare function listAllComplianceStoryboards(options?: ResolveOptions): Storyboard[];
|
|
186
|
-
/**
|
|
187
|
-
* Find a storyboard by its internal `id` (the YAML's `id:` field).
|
|
188
|
-
* Scans every bundle in the cache. Returns undefined if no match.
|
|
189
|
-
*/
|
|
186
|
+
/** Find a storyboard by its internal YAML id without reparsing a warm bundle. */
|
|
190
187
|
export declare function getComplianceStoryboardById(id: string, options?: ResolveOptions): Storyboard | undefined;
|
|
191
188
|
/** Find a bundle by its directory/file id (`media-buy`, `sales-guaranteed`, `capability-discovery`). */
|
|
192
189
|
export declare function findBundleById(id: string, options?: ResolveOptions): BundleRef | undefined;
|