@adcp/sdk 14.0.0-rc.39 → 14.0.0-rc.40
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/README.md +2 -0
- package/dist/lib/core/AgentClient.d.mts +4 -3
- package/dist/lib/core/AgentClient.d.ts +4 -3
- package/dist/lib/core/AsyncHandler.d.mts +3 -0
- package/dist/lib/core/AsyncHandler.d.ts +3 -0
- package/dist/lib/core/AsyncHandler.js +3 -0
- package/dist/lib/core/AsyncHandler.mjs +3 -0
- package/dist/lib/core/SingleAgentClient.d.mts +6 -1
- package/dist/lib/core/SingleAgentClient.d.ts +6 -1
- package/dist/lib/core/SingleAgentClient.js +57 -17
- package/dist/lib/core/SingleAgentClient.mjs +59 -17
- package/dist/lib/discovery/adagents-redirects.d.mts +5 -1
- package/dist/lib/discovery/adagents-redirects.d.ts +5 -1
- package/dist/lib/discovery/adagents-redirects.js +10 -3
- package/dist/lib/discovery/adagents-redirects.mjs +10 -3
- package/dist/lib/discovery/types.d.mts +42 -0
- package/dist/lib/discovery/types.d.ts +42 -0
- package/dist/lib/index.d.mts +3 -1
- package/dist/lib/index.d.ts +3 -1
- package/dist/lib/index.js +3 -1
- package/dist/lib/index.mjs +1 -0
- package/dist/lib/net/ssrf-fetch.js +47 -21
- package/dist/lib/net/ssrf-fetch.mjs +47 -21
- package/dist/lib/registry/index.d.mts +3 -0
- package/dist/lib/registry/index.d.ts +3 -0
- package/dist/lib/registry/index.js +8 -0
- package/dist/lib/registry/index.mjs +8 -0
- package/dist/lib/registry/types.d.mts +2 -1
- package/dist/lib/registry/types.d.ts +2 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/supply-path/evaluate.d.mts +17 -0
- package/dist/lib/supply-path/evaluate.d.ts +17 -0
- package/dist/lib/supply-path/evaluate.js +436 -0
- package/dist/lib/supply-path/evaluate.mjs +407 -0
- package/dist/lib/supply-path/fetch-evidence.d.mts +36 -0
- package/dist/lib/supply-path/fetch-evidence.d.ts +36 -0
- package/dist/lib/supply-path/fetch-evidence.js +293 -0
- package/dist/lib/supply-path/fetch-evidence.mjs +268 -0
- package/dist/lib/supply-path/index.d.mts +6 -0
- package/dist/lib/supply-path/index.d.ts +6 -0
- package/dist/lib/supply-path/index.js +49 -0
- package/dist/lib/supply-path/index.mjs +23 -0
- package/dist/lib/supply-path/products.d.mts +41 -0
- package/dist/lib/supply-path/products.d.ts +41 -0
- package/dist/lib/supply-path/products.js +228 -0
- package/dist/lib/supply-path/products.mjs +204 -0
- package/dist/lib/supply-path/revocations.d.mts +55 -0
- package/dist/lib/supply-path/revocations.d.ts +55 -0
- package/dist/lib/supply-path/revocations.js +127 -0
- package/dist/lib/supply-path/revocations.mjs +99 -0
- package/dist/lib/supply-path/types.d.mts +168 -0
- package/dist/lib/supply-path/types.d.ts +168 -0
- package/dist/lib/supply-path/types.js +16 -0
- package/dist/lib/supply-path/types.mjs +0 -0
- package/dist/lib/supply-path/validation.d.mts +10 -0
- package/dist/lib/supply-path/validation.d.ts +10 -0
- package/dist/lib/supply-path/validation.js +152 -0
- package/dist/lib/supply-path/validation.mjs +122 -0
- package/dist/lib/supply-path/verify.d.mts +25 -0
- package/dist/lib/supply-path/verify.d.ts +25 -0
- package/dist/lib/supply-path/verify.js +218 -0
- package/dist/lib/supply-path/verify.mjs +203 -0
- package/dist/lib/testing/storyboard/request-signing/grader.js +19 -9
- package/dist/lib/testing/storyboard/request-signing/grader.mjs +19 -9
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/v2/projection/creative-delivery.d.mts +1 -1
- package/dist/lib/v2/projection/creative-delivery.d.ts +1 -1
- package/dist/lib/validation/schema-loader.js +7 -5
- package/dist/lib/validation/schema-loader.mjs +7 -5
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/SUPPLY-PATH-VERIFICATION.md +101 -0
- package/docs/llms.txt +2 -2
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/examples/README.md +2 -0
- package/examples/supply-path-verification.ts +29 -0
- package/package.json +2 -1
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var evaluate_exports = {};
|
|
20
|
+
__export(evaluate_exports, {
|
|
21
|
+
SUPPLY_PATH_STATES: () => SUPPLY_PATH_STATES,
|
|
22
|
+
combineInventoryPartnerDomains: () => combineInventoryPartnerDomains,
|
|
23
|
+
evaluateSupplyPath: () => evaluateSupplyPath,
|
|
24
|
+
evaluationLimitVerdict: () => evaluationLimitVerdict,
|
|
25
|
+
hasValidPropertySelectorPredicate: () => hasValidPropertySelectorPredicate,
|
|
26
|
+
inventoryPartnersForInput: () => inventoryPartnersForInput,
|
|
27
|
+
isUnqualifiedPropertySelector: () => isUnqualifiedPropertySelector,
|
|
28
|
+
parseInventoryPartnerDomains: () => parseInventoryPartnerDomains,
|
|
29
|
+
supplyPathAdsTxtPolicy: () => supplyPathAdsTxtPolicy
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(evaluate_exports);
|
|
32
|
+
var import_resolve_agent_properties = require('../discovery/resolve-agent-properties.js');
|
|
33
|
+
var import_publisher_property_selector = require('../discovery/publisher-property-selector.js');
|
|
34
|
+
var import_enums = require('../types/enums.generated.js');
|
|
35
|
+
var import_validation = require('./validation.js');
|
|
36
|
+
const SUPPLY_PATH_STATES = ["unverified", "owner_attested", "host_delegated", "verified_owner_sold"];
|
|
37
|
+
function parseInventoryPartnerDomains(content) {
|
|
38
|
+
const partners = /* @__PURE__ */ new Set();
|
|
39
|
+
for (const line of content.split(/\r?\n/)) {
|
|
40
|
+
const match = line.trim().match(/^inventorypartnerdomain\s*=\s*([A-Za-z0-9.-]+)\s*(?:#.*)?$/i);
|
|
41
|
+
const value = match ? (0, import_validation.domain)(match[1]) : null;
|
|
42
|
+
if (value) partners.add(value);
|
|
43
|
+
}
|
|
44
|
+
return [...partners];
|
|
45
|
+
}
|
|
46
|
+
function revoked(manifest, publisher) {
|
|
47
|
+
if (manifest.revoked_publisher_domains === void 0) return false;
|
|
48
|
+
if (!Array.isArray(manifest.revoked_publisher_domains)) return true;
|
|
49
|
+
return manifest.revoked_publisher_domains.some(
|
|
50
|
+
(item) => !(0, import_validation.domain)((0, import_validation.record)(item) ? item.publisher_domain : item) || (0, import_validation.domain)((0, import_validation.record)(item) ? item.publisher_domain : item) === publisher
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
function coversCollection(entry, owner, id) {
|
|
54
|
+
if (entry.collections === void 0) return true;
|
|
55
|
+
if (!Array.isArray(entry.collections) || entry.collections.length === 0) return false;
|
|
56
|
+
if (!entry.collections.every(
|
|
57
|
+
(selector) => (0, import_validation.record)(selector) && (0, import_validation.domain)(selector.publisher_domain) && (selector.collection_ids === void 0 || (0, import_validation.strings)(selector.collection_ids))
|
|
58
|
+
))
|
|
59
|
+
return false;
|
|
60
|
+
return entry.collections.some(
|
|
61
|
+
(selector) => (0, import_validation.domain)(selector.publisher_domain) === owner && (selector.collection_ids === void 0 || id !== void 0 && selector.collection_ids.includes(id))
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
const PROPERTY_TYPES = new Set(import_enums.PropertyTypeValues);
|
|
65
|
+
const PROPERTY_IDENTIFIER_TYPES = /* @__PURE__ */ new Set([
|
|
66
|
+
...import_enums.PropertyIdentifierTypesValues,
|
|
67
|
+
// Retained only for the pinned canonical corpus, whose CTV properties use
|
|
68
|
+
// this distribution identifier in property records.
|
|
69
|
+
"roku_channel_id"
|
|
70
|
+
]);
|
|
71
|
+
const PROPERTY_CHANNELS = new Set(import_enums.MediaChannelValues);
|
|
72
|
+
function isPropertyToken(value) {
|
|
73
|
+
return typeof value === "string" && /^[a-z0-9_]+$/.test(value);
|
|
74
|
+
}
|
|
75
|
+
function isPropertyTokenList(value) {
|
|
76
|
+
return Array.isArray(value) && value.length > 0 && value.every(isPropertyToken);
|
|
77
|
+
}
|
|
78
|
+
function isOptionalUniqueList(value, valid) {
|
|
79
|
+
return value === void 0 || Array.isArray(value) && value.every(valid) && new Set(value).size === value.length;
|
|
80
|
+
}
|
|
81
|
+
function isValidPropertyRecord(value) {
|
|
82
|
+
if (!(0, import_validation.record)(value) || typeof value.property_type !== "string" || !PROPERTY_TYPES.has(value.property_type) || typeof value.name !== "string" || value.name.length === 0 || !Array.isArray(value.identifiers) || value.identifiers.length === 0) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
if (value.property_id !== void 0 && !isPropertyToken(value.property_id)) return false;
|
|
86
|
+
if (value.publisher_domain !== void 0 && !(0, import_validation.domain)(value.publisher_domain)) return false;
|
|
87
|
+
if (!isOptionalUniqueList(value.tags, isPropertyToken) || !isOptionalUniqueList(value.supported_channels, (item) => typeof item === "string" && PROPERTY_CHANNELS.has(item))) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
return value.identifiers.every(
|
|
91
|
+
(identifier) => (0, import_validation.record)(identifier) && typeof identifier.type === "string" && PROPERTY_IDENTIFIER_TYPES.has(identifier.type) && typeof identifier.value === "string" && identifier.value.length > 0
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
function hasPropertyAuthorizationEnvelope(entry) {
|
|
95
|
+
if (entry.authorization_type === "property_ids") return isPropertyTokenList(entry.property_ids);
|
|
96
|
+
if (entry.authorization_type === "property_tags") return isPropertyTokenList(entry.property_tags);
|
|
97
|
+
if (entry.authorization_type === "inline_properties") {
|
|
98
|
+
return Array.isArray(entry.properties) && entry.properties.length > 0 && entry.properties.every(isValidPropertyRecord);
|
|
99
|
+
}
|
|
100
|
+
if (entry.authorization_type === "publisher_properties") {
|
|
101
|
+
if (!Array.isArray(entry.publisher_properties) || entry.publisher_properties.length === 0 || !entry.publisher_properties.every(import_validation.record)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
for (const raw of entry.publisher_properties) {
|
|
106
|
+
const selector = (0, import_publisher_property_selector.parsePublisherPropertySelector)(raw);
|
|
107
|
+
const value = raw;
|
|
108
|
+
if (selector.selection_type === "by_id" && (!isPropertyTokenList(value.property_ids) || value.property_tags !== void 0) || selector.selection_type === "by_tag" && (!isPropertyTokenList(value.property_tags) || value.property_ids !== void 0) || selector.selection_type === "all" && (value.property_ids !== void 0 || value.property_tags !== void 0)) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return true;
|
|
113
|
+
} catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
function propertyScope(entry, host, manifest, requirePublisher = false) {
|
|
120
|
+
if (revoked(manifest, host)) return /* @__PURE__ */ new Set();
|
|
121
|
+
if (!["property_ids", "property_tags", "publisher_properties", "inline_properties"].includes(
|
|
122
|
+
String(entry.authorization_type)
|
|
123
|
+
))
|
|
124
|
+
return /* @__PURE__ */ new Set();
|
|
125
|
+
if (entry.authorization_type === "publisher_properties") {
|
|
126
|
+
if (!Array.isArray(entry.publisher_properties) || entry.publisher_properties.length === 0) return /* @__PURE__ */ new Set();
|
|
127
|
+
const properties = (0, import_validation.records)(manifest.properties).filter(
|
|
128
|
+
(p) => isValidPropertyRecord(p) && (p.publisher_domain === void 0 && !requirePublisher || (0, import_validation.domain)(p.publisher_domain) === host)
|
|
129
|
+
);
|
|
130
|
+
const ids = /* @__PURE__ */ new Set();
|
|
131
|
+
try {
|
|
132
|
+
for (const raw of entry.publisher_properties) {
|
|
133
|
+
const selector = (0, import_publisher_property_selector.parsePublisherPropertySelector)(raw);
|
|
134
|
+
if ("property_ids" in selector && !(0, import_validation.strings)(selector.property_ids)) return /* @__PURE__ */ new Set();
|
|
135
|
+
if ("property_tags" in selector && !(0, import_validation.strings)(selector.property_tags)) return /* @__PURE__ */ new Set();
|
|
136
|
+
for (const single of (0, import_publisher_property_selector.expandPublisherPropertySelector)(selector)) {
|
|
137
|
+
if ((0, import_validation.domain)(single.publisher_domain) !== host) continue;
|
|
138
|
+
for (const property of properties) {
|
|
139
|
+
if (typeof property.property_id !== "string") continue;
|
|
140
|
+
if (single.selection_type === "all" || single.selection_type === "by_id" && single.property_ids.includes(property.property_id) || single.selection_type === "by_tag" && (0, import_validation.strings)(property.tags) && property.tags.some((t) => single.property_tags.includes(t))) {
|
|
141
|
+
ids.add(property.property_id);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
return /* @__PURE__ */ new Set();
|
|
148
|
+
}
|
|
149
|
+
return ids;
|
|
150
|
+
}
|
|
151
|
+
if (entry.authorization_type === "property_ids" && !(0, import_validation.strings)(entry.property_ids)) return /* @__PURE__ */ new Set();
|
|
152
|
+
if (entry.authorization_type === "property_tags" && !(0, import_validation.strings)(entry.property_tags)) return /* @__PURE__ */ new Set();
|
|
153
|
+
if (manifest.properties !== void 0 && (!Array.isArray(manifest.properties) || !manifest.properties.every(import_validation.record)))
|
|
154
|
+
return /* @__PURE__ */ new Set();
|
|
155
|
+
if (entry.authorization_type === "inline_properties" && (!Array.isArray(entry.properties) || !entry.properties.every(import_validation.record)))
|
|
156
|
+
return /* @__PURE__ */ new Set();
|
|
157
|
+
const result = (0, import_resolve_agent_properties.resolveAgentProperties)(
|
|
158
|
+
{ ...manifest, authorized_agents: [entry] },
|
|
159
|
+
String(entry.url)
|
|
160
|
+
);
|
|
161
|
+
return new Set(
|
|
162
|
+
result.properties.filter(
|
|
163
|
+
(p) => isValidPropertyRecord(p) && (p.publisher_domain === void 0 && !requirePublisher || (0, import_validation.domain)(p.publisher_domain) === host)
|
|
164
|
+
).map((p) => p.property_id).filter((id) => typeof id === "string" && id.length > 0)
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
function isUnqualifiedPropertySelector(value) {
|
|
168
|
+
return (0, import_validation.record)(value) && Object.keys(value).every(
|
|
169
|
+
(key) => ["publisher_domain", "publisher_domains", "selection_type", "property_ids", "property_tags"].includes(key)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
function hasValidPropertySelectorPredicate(value) {
|
|
173
|
+
if (!isUnqualifiedPropertySelector(value)) return false;
|
|
174
|
+
try {
|
|
175
|
+
const selector = (0, import_publisher_property_selector.parsePublisherPropertySelector)(value);
|
|
176
|
+
const raw = value;
|
|
177
|
+
if (selector.selection_type === "by_id")
|
|
178
|
+
return isPropertyTokenList(raw.property_ids) && raw.property_tags === void 0;
|
|
179
|
+
if (selector.selection_type === "by_tag")
|
|
180
|
+
return isPropertyTokenList(raw.property_tags) && raw.property_ids === void 0;
|
|
181
|
+
return raw.property_ids === void 0 && raw.property_tags === void 0;
|
|
182
|
+
} catch {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const UNDERSTOOD_GRANT_FIELDS = /* @__PURE__ */ new Set([
|
|
187
|
+
"url",
|
|
188
|
+
"authorized_for",
|
|
189
|
+
"authorization_type",
|
|
190
|
+
"property_ids",
|
|
191
|
+
"property_tags",
|
|
192
|
+
"properties",
|
|
193
|
+
"publisher_properties",
|
|
194
|
+
"collections",
|
|
195
|
+
"delegation_type",
|
|
196
|
+
"exclusive",
|
|
197
|
+
"signing_keys",
|
|
198
|
+
"encryption_keys",
|
|
199
|
+
"last_updated"
|
|
200
|
+
]);
|
|
201
|
+
function unsupportedConstraints(entry) {
|
|
202
|
+
const unknown = Object.keys(entry).filter((key) => !UNDERSTOOD_GRANT_FIELDS.has(key));
|
|
203
|
+
for (const selector of (0, import_validation.records)(entry.collections)) {
|
|
204
|
+
unknown.push(
|
|
205
|
+
...Object.keys(selector).filter((key) => !["publisher_domain", "collection_ids"].includes(key)).map((key) => `collections[].${key}`)
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
for (const selector of (0, import_validation.records)(entry.publisher_properties)) {
|
|
209
|
+
unknown.push(
|
|
210
|
+
...Object.keys(selector).filter(
|
|
211
|
+
(key) => !["publisher_domain", "publisher_domains", "selection_type", "property_ids", "property_tags"].includes(key)
|
|
212
|
+
).map((key) => `publisher_properties[].${key}`)
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
return unknown;
|
|
216
|
+
}
|
|
217
|
+
function nodeCost(value) {
|
|
218
|
+
const stack = [value];
|
|
219
|
+
let cost = 0;
|
|
220
|
+
while (stack.length) {
|
|
221
|
+
const item = stack.pop();
|
|
222
|
+
if (++cost > 32768) return Infinity;
|
|
223
|
+
if (typeof item === "string" && item.length > 8192) return Infinity;
|
|
224
|
+
if (Array.isArray(item)) {
|
|
225
|
+
if (item.length > 1024) return Infinity;
|
|
226
|
+
stack.push(...item);
|
|
227
|
+
} else if ((0, import_validation.record)(item)) {
|
|
228
|
+
const values = Object.values(item);
|
|
229
|
+
if (values.length > 1024) return Infinity;
|
|
230
|
+
stack.push(...values);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return cost;
|
|
234
|
+
}
|
|
235
|
+
function evaluationLimitVerdict() {
|
|
236
|
+
const failure = { ok: false, failure: "evaluation_limit_exceeded" };
|
|
237
|
+
return {
|
|
238
|
+
semantics_version: "1",
|
|
239
|
+
state: "unverified",
|
|
240
|
+
legs: {
|
|
241
|
+
owner_collection_declared: { ...failure },
|
|
242
|
+
owner_distribution_carriage: { ...failure },
|
|
243
|
+
owner_agent_declared: { ...failure },
|
|
244
|
+
host_authorization: { ...failure },
|
|
245
|
+
inventory_partner_domain: { ...failure }
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function evaluateSupplyPath(input) {
|
|
250
|
+
const total = nodeCost(input);
|
|
251
|
+
if (!Number.isFinite(total)) return evaluationLimitVerdict();
|
|
252
|
+
const grants = nodeCost(input.hostManifest?.authorized_agents);
|
|
253
|
+
const properties = nodeCost(input.hostManifest?.properties);
|
|
254
|
+
const collections = (0, import_validation.records)(input.ownerManifest?.collections).length;
|
|
255
|
+
if (!Number.isFinite(total) || grants * properties + Math.max(1, collections) * total * 4 > 4e6) {
|
|
256
|
+
return evaluationLimitVerdict();
|
|
257
|
+
}
|
|
258
|
+
if (input.collectionId === void 0) {
|
|
259
|
+
const collections2 = (0, import_validation.records)(input.ownerManifest?.collections).filter(
|
|
260
|
+
(c) => typeof c.collection_id === "string" && c.collection_id.length > 0
|
|
261
|
+
);
|
|
262
|
+
if (collections2.length) {
|
|
263
|
+
const verdicts = collections2.map((c) => evaluateSupplyPath({ ...input, collectionId: c.collection_id }));
|
|
264
|
+
return verdicts.reduce(
|
|
265
|
+
(best, next) => SUPPLY_PATH_STATES.indexOf(next.state) > SUPPLY_PATH_STATES.indexOf(best.state) ? next : best
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const owner = (0, import_validation.domain)(input.ownerDomain);
|
|
270
|
+
const host = (0, import_validation.domain)(input.hostDomain);
|
|
271
|
+
const agent = (0, import_validation.agentIdentity)(input.agentUrl);
|
|
272
|
+
const ownerManifest = (0, import_validation.record)(input.ownerManifest) ? input.ownerManifest : null;
|
|
273
|
+
const hostManifest = (0, import_validation.record)(input.hostManifest) ? input.hostManifest : null;
|
|
274
|
+
const isRevoked = (role, publisher) => {
|
|
275
|
+
const manifest = role === "owner" ? ownerManifest : hostManifest;
|
|
276
|
+
return manifest !== null && revoked(manifest, publisher) || (input.heldRevocations?.[role] ?? []).some((value) => (0, import_validation.domain)(value) === publisher);
|
|
277
|
+
};
|
|
278
|
+
const collectionLeg = { ok: false };
|
|
279
|
+
const declared = (0, import_validation.records)(ownerManifest?.collections).filter(
|
|
280
|
+
(c) => c.publisher_domain === void 0 && !input.requireExplicitOwnerPublisherDomain || (0, import_validation.domain)(c.publisher_domain) === owner
|
|
281
|
+
);
|
|
282
|
+
const targets = declared.filter((c) => c.collection_id === input.collectionId && typeof c.collection_id === "string");
|
|
283
|
+
if (!ownerManifest) collectionLeg.failure = "manifest_not_found";
|
|
284
|
+
else if (owner && isRevoked("owner", owner)) collectionLeg.failure = "publisher_revoked";
|
|
285
|
+
else if (!input.collectionId && !declared.length) collectionLeg.failure = "no_collections_declared";
|
|
286
|
+
else if (!owner || !input.collectionId?.trim() || targets.length !== 1) {
|
|
287
|
+
collectionLeg.failure = "collection_not_declared";
|
|
288
|
+
collectionLeg.detail = `owner declares ${declared.length} collection(s); none has an unambiguous collection_id "${input.collectionId}"`;
|
|
289
|
+
} else {
|
|
290
|
+
collectionLeg.ok = true;
|
|
291
|
+
if (typeof targets[0].kind === "string") collectionLeg.detail = `kind: ${targets[0].kind}`;
|
|
292
|
+
}
|
|
293
|
+
const carriage = { ok: false };
|
|
294
|
+
const entries = collectionLeg.ok ? (0, import_validation.records)(targets[0].distribution).filter((e) => (0, import_validation.domain)(e.publisher_domain) === host) : [];
|
|
295
|
+
let claimed = [];
|
|
296
|
+
if (!collectionLeg.ok) carriage.failure = "collection_leg_failed";
|
|
297
|
+
else if (!host || !entries.length) carriage.failure = "no_distribution_for_host";
|
|
298
|
+
else {
|
|
299
|
+
const valid = entries.every(
|
|
300
|
+
(e) => Object.keys(e).every((key) => ["publisher_domain", "property_ids", "identifiers"].includes(key)) && (e.property_ids === void 0 || (0, import_validation.strings)(e.property_ids)) && (e.identifiers === void 0 || Array.isArray(e.identifiers) && e.identifiers.length > 0 && e.identifiers.every(
|
|
301
|
+
(i) => (0, import_validation.record)(i) && typeof i.type === "string" && i.type.length > 0 && typeof i.value === "string" && i.value.length > 0
|
|
302
|
+
)) && (e.property_ids !== void 0 || e.identifiers !== void 0)
|
|
303
|
+
);
|
|
304
|
+
claimed = [...new Set(entries.flatMap((e) => (0, import_validation.strings)(e.property_ids) ? e.property_ids : []))];
|
|
305
|
+
if (!valid) {
|
|
306
|
+
carriage.failure = "property_ids_unresolved";
|
|
307
|
+
carriage.detail = "Malformed distribution constraints";
|
|
308
|
+
} else if (!claimed.length) {
|
|
309
|
+
carriage.ok = true;
|
|
310
|
+
carriage.detail = "carriage asserted without host property_ids (identifiers only)";
|
|
311
|
+
} else if (!hostManifest) {
|
|
312
|
+
carriage.failure = "host_manifest_not_found";
|
|
313
|
+
carriage.property_ids_unmatched = claimed;
|
|
314
|
+
} else {
|
|
315
|
+
const properties2 = (0, import_validation.records)(hostManifest.properties).filter(
|
|
316
|
+
(p) => isValidPropertyRecord(p) && (p.publisher_domain === void 0 && !input.requireExplicitHostPublisherDomain || (0, import_validation.domain)(p.publisher_domain) === host)
|
|
317
|
+
);
|
|
318
|
+
const counts = /* @__PURE__ */ new Map();
|
|
319
|
+
for (const property of properties2) counts.set(property.property_id, (counts.get(property.property_id) ?? 0) + 1);
|
|
320
|
+
const known = new Set([...counts].filter(([, count]) => count === 1).map(([id]) => id));
|
|
321
|
+
carriage.property_ids_matched = claimed.filter((id) => known.has(id));
|
|
322
|
+
carriage.property_ids_unmatched = claimed.filter((id) => !known.has(id));
|
|
323
|
+
carriage.ok = carriage.property_ids_unmatched.length === 0;
|
|
324
|
+
if (!carriage.ok) carriage.failure = "property_ids_unresolved";
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
const ownerAgent = !ownerManifest ? { ok: false, failure: "manifest_not_found" } : agent && (0, import_validation.records)(ownerManifest.authorized_agents).some(
|
|
328
|
+
(e) => (0, import_validation.agentIdentity)(e.url) === agent && owner && hasPropertyAuthorizationEnvelope(e) && (!input.requireExplicitOwnerPublisherDomain || e.collections !== void 0) && coversCollection(e, owner, input.collectionId) && !unsupportedConstraints(e).length
|
|
329
|
+
) ? { ok: true } : { ok: false, failure: "agent_not_declared_by_owner" };
|
|
330
|
+
const hostLeg = { ok: false };
|
|
331
|
+
if (!hostManifest) hostLeg.failure = "manifest_not_found";
|
|
332
|
+
else {
|
|
333
|
+
const agents = agent ? (0, import_validation.records)(hostManifest.authorized_agents).filter((e) => (0, import_validation.agentIdentity)(e.url) === agent) : [];
|
|
334
|
+
const covered = owner && !isRevoked("host", owner) && !(host && isRevoked("owner", host)) ? agents.filter((e) => e.collections !== void 0 && coversCollection(e, owner, input.collectionId)) : [];
|
|
335
|
+
if (!agents.length) hostLeg.failure = "no_agent_entry";
|
|
336
|
+
else if (!covered.length) hostLeg.failure = "collection_scope_mismatch";
|
|
337
|
+
else {
|
|
338
|
+
const matched = host && !isRevoked("host", host) && carriage.ok && collectionLeg.ok && covered.find((e) => {
|
|
339
|
+
if (!hasPropertyAuthorizationEnvelope(e) || unsupportedConstraints(e).length) return false;
|
|
340
|
+
const scope = propertyScope(e, host, hostManifest, input.requireExplicitHostPublisherDomain);
|
|
341
|
+
const required = input.requiredHostPropertyIds ?? claimed;
|
|
342
|
+
if (input.requiredHostPropertyIds && (!required.length || claimed.length && !required.every((id) => claimed.includes(id))))
|
|
343
|
+
return false;
|
|
344
|
+
if (!claimed.length) return false;
|
|
345
|
+
return required.length ? required.every((id) => scope.has(id)) : scope.size > 0;
|
|
346
|
+
});
|
|
347
|
+
if (!matched) {
|
|
348
|
+
const constraints = [...new Set(covered.flatMap(unsupportedConstraints))].sort();
|
|
349
|
+
hostLeg.failure = covered.every((e) => unsupportedConstraints(e).length) ? "unsupported_constraints" : "property_scope_mismatch";
|
|
350
|
+
hostLeg.detail = constraints.length ? `Unevaluated grant fields: ${constraints.join(", ")}` : "No grant proves the complete carried property scope";
|
|
351
|
+
} else {
|
|
352
|
+
hostLeg.ok = true;
|
|
353
|
+
hostLeg.matched_entry = {
|
|
354
|
+
url: String(matched.url),
|
|
355
|
+
...typeof matched.authorization_type === "string" ? { authorization_type: matched.authorization_type } : {},
|
|
356
|
+
...typeof matched.delegation_type === "string" ? { delegation_type: matched.delegation_type } : {},
|
|
357
|
+
...Array.isArray(matched.collections) ? {
|
|
358
|
+
collections: matched.collections.map((s) => ({
|
|
359
|
+
publisher_domain: String(s.publisher_domain),
|
|
360
|
+
...s.collection_ids !== void 0 ? { collection_ids: [...s.collection_ids] } : {}
|
|
361
|
+
}))
|
|
362
|
+
} : {}
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const partners = input.hostInventoryPartnerDomainsByFile ? inventoryPartnersForInput(input) : input.hostInventoryPartnerDomains;
|
|
368
|
+
const partner = input.inventoryPartnerDomainEvaluated === false ? { ok: false, failure: "not_evaluated" } : partners === null ? { ok: false, failure: "ads_txt_unavailable" } : owner && partners.some((d) => (0, import_validation.domain)(d) === owner) ? { ok: true } : { ok: false, failure: "not_declared" };
|
|
369
|
+
const attested = collectionLeg.ok && entries.length > 0;
|
|
370
|
+
const state = hostLeg.ok && collectionLeg.ok && carriage.ok ? "verified_owner_sold" : partner.ok && ownerAgent.ok && collectionLeg.ok && !(owner && isRevoked("host", owner) || host && isRevoked("host", host)) && !(host && isRevoked("owner", host)) ? "host_delegated" : attested ? "owner_attested" : "unverified";
|
|
371
|
+
return {
|
|
372
|
+
semantics_version: "1",
|
|
373
|
+
...collectionLeg.ok ? { resolved_collection_id: input.collectionId } : {},
|
|
374
|
+
state,
|
|
375
|
+
legs: {
|
|
376
|
+
owner_collection_declared: collectionLeg,
|
|
377
|
+
owner_distribution_carriage: carriage,
|
|
378
|
+
owner_agent_declared: ownerAgent,
|
|
379
|
+
host_authorization: hostLeg,
|
|
380
|
+
inventory_partner_domain: partner
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function supplyPathAdsTxtPolicy(input) {
|
|
385
|
+
if (input.collectionId === void 0) {
|
|
386
|
+
const candidates = (0, import_validation.records)(input.ownerManifest?.collections).filter(
|
|
387
|
+
(c) => typeof c.collection_id === "string" && c.collection_id.length > 0
|
|
388
|
+
);
|
|
389
|
+
if (candidates.length) {
|
|
390
|
+
const policies = candidates.map((c) => supplyPathAdsTxtPolicy({ ...input, collectionId: String(c.collection_id) }));
|
|
391
|
+
return { files: [...new Set(policies.flatMap((policy) => policy.files))].sort(), requireAll: false };
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
const collectionIds = new Set(
|
|
395
|
+
(0, import_validation.records)(input.ownerManifest?.collections).filter((c) => input.collectionId === void 0 || c.collection_id === input.collectionId).flatMap(
|
|
396
|
+
(c) => (0, import_validation.records)(c.distribution).filter((d) => (0, import_validation.domain)(d.publisher_domain) === (0, import_validation.domain)(input.hostDomain)).flatMap((d) => (0, import_validation.strings)(d.property_ids) ? d.property_ids : [])
|
|
397
|
+
)
|
|
398
|
+
);
|
|
399
|
+
const requested = input.requiredHostPropertyIds ? new Set(input.requiredHostPropertyIds) : collectionIds;
|
|
400
|
+
const properties = (0, import_validation.records)(input.hostManifest?.properties).filter(
|
|
401
|
+
(p) => requested.has(String(p.property_id)) && (p.publisher_domain === void 0 && !input.requireExplicitHostPublisherDomain || (0, import_validation.domain)(p.publisher_domain) === (0, import_validation.domain)(input.hostDomain))
|
|
402
|
+
);
|
|
403
|
+
const files = /* @__PURE__ */ new Set();
|
|
404
|
+
for (const property of properties) {
|
|
405
|
+
if (property.property_type === "website") files.add("ads.txt");
|
|
406
|
+
if (property.property_type === "mobile_app" || property.property_type === "ctv_app") files.add("app-ads.txt");
|
|
407
|
+
}
|
|
408
|
+
if (!input.hostManifest || !properties.length) return { files: ["app-ads.txt", "ads.txt"], requireAll: false };
|
|
409
|
+
return { files: [...files].sort(), requireAll: true };
|
|
410
|
+
}
|
|
411
|
+
function combineInventoryPartnerDomains(contents, requireAll) {
|
|
412
|
+
if (!contents.length || requireAll && contents.some((c) => c === null)) return null;
|
|
413
|
+
const fetched = contents.filter((c) => c !== null).map(parseInventoryPartnerDomains);
|
|
414
|
+
if (!fetched.length) return null;
|
|
415
|
+
return requireAll ? fetched[0].filter((d) => fetched.every((domains) => domains.includes(d))) : [...new Set(fetched.flat())];
|
|
416
|
+
}
|
|
417
|
+
function inventoryPartnersForInput(input) {
|
|
418
|
+
const policy = supplyPathAdsTxtPolicy(input);
|
|
419
|
+
const values = policy.files.map((file) => input.hostInventoryPartnerDomainsByFile?.[file] ?? null);
|
|
420
|
+
if (!values.length || policy.requireAll && values.some((value) => value === null)) return null;
|
|
421
|
+
const fetched = values.filter((value) => value !== null);
|
|
422
|
+
if (!fetched.length) return null;
|
|
423
|
+
return policy.requireAll ? fetched[0].filter((domain2) => fetched.every((value) => value.includes(domain2))) : [...new Set(fetched.flat())];
|
|
424
|
+
}
|
|
425
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
426
|
+
0 && (module.exports = {
|
|
427
|
+
SUPPLY_PATH_STATES,
|
|
428
|
+
combineInventoryPartnerDomains,
|
|
429
|
+
evaluateSupplyPath,
|
|
430
|
+
evaluationLimitVerdict,
|
|
431
|
+
hasValidPropertySelectorPredicate,
|
|
432
|
+
inventoryPartnersForInput,
|
|
433
|
+
isUnqualifiedPropertySelector,
|
|
434
|
+
parseInventoryPartnerDomains,
|
|
435
|
+
supplyPathAdsTxtPolicy
|
|
436
|
+
});
|