@adcp/sdk 15.9.5 → 15.9.6
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/core/AgentClient.d.mts +4 -2
- package/dist/lib/core/AgentClient.d.ts +4 -2
- package/dist/lib/core/AgentClient.js +4 -2
- package/dist/lib/core/AgentClient.mjs +4 -2
- package/dist/lib/core/SingleAgentClient.d.mts +7 -3
- package/dist/lib/core/SingleAgentClient.d.ts +7 -3
- package/dist/lib/core/SingleAgentClient.js +204 -13
- package/dist/lib/core/SingleAgentClient.mjs +209 -13
- package/dist/lib/core/product-cache.d.mts +3 -1
- package/dist/lib/core/product-cache.d.ts +3 -1
- package/dist/lib/core/product-cache.js +2 -1
- package/dist/lib/core/product-cache.mjs +2 -1
- package/dist/lib/registry/types.d.mts +3 -2
- package/dist/lib/registry/types.d.ts +3 -2
- package/dist/lib/registry/types.generated.d.mts +21 -9
- package/dist/lib/registry/types.generated.d.ts +21 -9
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +6 -2
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +6 -2
- 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/augment-response.js +6 -3
- package/dist/lib/v2/projection/augment-response.mjs +8 -5
- package/dist/lib/v2/projection/creative-delivery.d.mts +2 -0
- package/dist/lib/v2/projection/creative-delivery.d.ts +2 -0
- package/dist/lib/v2/projection/creative-delivery.js +36 -17
- package/dist/lib/v2/projection/creative-delivery.mjs +37 -18
- package/dist/lib/v2/projection/legacy-metadata.d.mts +12 -0
- package/dist/lib/v2/projection/legacy-metadata.d.ts +12 -0
- package/dist/lib/v2/projection/legacy-metadata.js +41 -1
- package/dist/lib/v2/projection/legacy-metadata.mjs +37 -1
- package/dist/lib/v2/projection/v1-to-v2.d.mts +7 -0
- package/dist/lib/v2/projection/v1-to-v2.d.ts +7 -0
- package/dist/lib/v2/projection/v1-to-v2.js +83 -2
- package/dist/lib/v2/projection/v1-to-v2.mjs +86 -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.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/CREATIVE-DELIVERY.md +45 -6
- package/docs/llms.txt +2 -2
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/package.json +1 -1
|
@@ -159,6 +159,7 @@ import { resolvePropertyList } from "../server/targeting-helpers.mjs";
|
|
|
159
159
|
import {
|
|
160
160
|
CreativeFormatCapabilityError,
|
|
161
161
|
CreativeFormatProjectionError,
|
|
162
|
+
canUseProductOptionsForCreativeWire,
|
|
162
163
|
projectMediaBuyCreativesForDelivery,
|
|
163
164
|
projectCreativeForDelivery,
|
|
164
165
|
projectSyncCreativesForDelivery,
|
|
@@ -176,6 +177,10 @@ import {
|
|
|
176
177
|
import { toCanonicalOnlyResponse } from "../v2/projection/augment-response.mjs";
|
|
177
178
|
import {
|
|
178
179
|
legacyFormatRefsForDeclaration,
|
|
180
|
+
isSynthesizedFormatOption,
|
|
181
|
+
selectedFormatOptions,
|
|
182
|
+
rememberSellerFormatEvidence,
|
|
183
|
+
sellerFormatEvidence,
|
|
179
184
|
rememberSellerDeclaredFormatOption,
|
|
180
185
|
sellerDeclaredFormatOption,
|
|
181
186
|
structuredCloneWithLegacyCreativeMetadata
|
|
@@ -299,6 +304,56 @@ const RECORDLESS_HMAC_READ_ONLY_TASKS = /* @__PURE__ */ new Set([
|
|
|
299
304
|
]);
|
|
300
305
|
const TASK_SCOPED_STATE_LIMIT = 1e4;
|
|
301
306
|
const WEBHOOK_JWKS_RESOLVER_LIMIT = 1024;
|
|
307
|
+
function creativeMatchesProductOption(creative, declaration) {
|
|
308
|
+
const params = isPlainRecord(declaration.params) ? declaration.params : {};
|
|
309
|
+
const assets = isPlainRecord(creative.assets) ? creative.assets : {};
|
|
310
|
+
const slots = Array.isArray(params.slots) ? params.slots : [];
|
|
311
|
+
if (!slots.every((slot) => {
|
|
312
|
+
if (!isPlainRecord(slot) || typeof slot.asset_group_id !== "string") return false;
|
|
313
|
+
const value = assets[slot.asset_group_id];
|
|
314
|
+
const entries = value === void 0 ? [] : Array.isArray(value) ? value : [value];
|
|
315
|
+
const minimum = Math.max(typeof slot.min === "number" ? slot.min : 0, slot.required === true ? 1 : 0);
|
|
316
|
+
if (entries.length < minimum || typeof slot.max === "number" && entries.length > slot.max) return false;
|
|
317
|
+
return entries.every(
|
|
318
|
+
(asset) => isPlainRecord(asset) && (typeof slot.asset_type !== "string" || asset.asset_type === slot.asset_type)
|
|
319
|
+
);
|
|
320
|
+
}))
|
|
321
|
+
return false;
|
|
322
|
+
const formatParams = isPlainRecord(creative.format_parameters) ? creative.format_parameters : {};
|
|
323
|
+
const kind = String(creative.format_kind);
|
|
324
|
+
const mediaType = kind.startsWith("image") ? "image" : kind.startsWith("video") ? "video" : kind.startsWith("audio") ? "audio" : kind === "html5" ? "html" : void 0;
|
|
325
|
+
const assetTypes = mediaType === "video" ? ["video", "vast"] : mediaType === "audio" ? ["audio", "vast", "daast"] : mediaType === "html" ? ["html", "zip"] : mediaType ? [mediaType] : ["image", "video", "audio", "html", "zip", "vast", "daast"];
|
|
326
|
+
const requiredMediaSlots = slots.filter(
|
|
327
|
+
(slot) => isPlainRecord(slot) && (slot.required === true || typeof slot.min === "number" && slot.min > 0) && assetTypes.includes(String(slot.asset_type))
|
|
328
|
+
);
|
|
329
|
+
const preferredGroups = mediaType ? [`${mediaType}_main`, mediaType, kind, ...assetTypes] : [];
|
|
330
|
+
const primaryGroup = (requiredMediaSlots.length === 1 ? String(requiredMediaSlots[0].asset_group_id) : void 0) ?? preferredGroups.find((group) => assets[group] !== void 0);
|
|
331
|
+
const sourceAssets = primaryGroup ? [assets[primaryGroup]] : Object.values(assets);
|
|
332
|
+
const dimensionalAssets = sourceAssets.flatMap((value) => Array.isArray(value) ? value : [value]).filter(
|
|
333
|
+
(value) => isPlainRecord(value) && assetTypes.includes(String(value.asset_type))
|
|
334
|
+
);
|
|
335
|
+
return (dimensionalAssets.length > 0 ? dimensionalAssets : [{}]).every((asset) => {
|
|
336
|
+
const actual = { ...asset, ...formatParams };
|
|
337
|
+
for (const key of ["width", "height"]) {
|
|
338
|
+
if (typeof params[key] === "number" && actual[key] !== params[key]) return false;
|
|
339
|
+
const min = params[`min_${key}`];
|
|
340
|
+
const max = params[`max_${key}`];
|
|
341
|
+
if (typeof min === "number" && (typeof actual[key] !== "number" || actual[key] < min)) return false;
|
|
342
|
+
if (typeof max === "number" && (typeof actual[key] !== "number" || actual[key] > max)) return false;
|
|
343
|
+
}
|
|
344
|
+
if (Array.isArray(params.sizes) && !params.sizes.some((size) => isPlainRecord(size) && size.width === actual.width && size.height === actual.height))
|
|
345
|
+
return false;
|
|
346
|
+
const duration = actual.duration_ms ?? actual.duration_ms_exact;
|
|
347
|
+
const exact = params.duration_ms_exact ?? params.duration_ms;
|
|
348
|
+
if (typeof exact === "number" && duration !== exact) return false;
|
|
349
|
+
if (typeof exact !== "number" && Array.isArray(params.duration_ms_range)) {
|
|
350
|
+
const [min, max] = params.duration_ms_range;
|
|
351
|
+
if (typeof duration !== "number" || typeof min === "number" && duration < min || typeof max === "number" && duration > max)
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
return true;
|
|
355
|
+
});
|
|
356
|
+
}
|
|
302
357
|
function isDeferredClientFinalizationContext(value) {
|
|
303
358
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
304
359
|
const context = value;
|
|
@@ -1431,7 +1486,7 @@ class SingleAgentClient {
|
|
|
1431
1486
|
}
|
|
1432
1487
|
}
|
|
1433
1488
|
}
|
|
1434
|
-
rememberCanonicalProductRoutes(products, account, authoritativeProducts) {
|
|
1489
|
+
rememberCanonicalProductRoutes(products, account, authoritativeProducts, evidence) {
|
|
1435
1490
|
this.invalidateCanonicalProductRoutes(authoritativeProducts ?? products, account);
|
|
1436
1491
|
const accountScope = this.canonicalAccountScope(account);
|
|
1437
1492
|
const declaredOptions = authoritativeProducts ? this.sellerDeclaredFormatOptions(authoritativeProducts) : void 0;
|
|
@@ -1451,12 +1506,15 @@ class SingleAgentClient {
|
|
|
1451
1506
|
const refs = legacyFormatRefsForDeclaration(option);
|
|
1452
1507
|
const declared = declaredOptions ? declaredOptions.get(product.product_id)?.some((declaredRef) => this.sameCanonicalOptionRef(declaredRef, ref)) : sellerDeclaredFormatOption(option);
|
|
1453
1508
|
if (declared !== void 0) rememberSellerDeclaredFormatOption(option, declared);
|
|
1509
|
+
if (declared === true && evidence)
|
|
1510
|
+
rememberSellerFormatEvidence(option, { ...evidence, productId: product.product_id });
|
|
1454
1511
|
this.rememberCanonicalLegacyRoute(this.canonicalLegacyRouteKey(account, product.product_id, ref), {
|
|
1455
1512
|
kind: "product",
|
|
1456
1513
|
accountScope,
|
|
1457
1514
|
productId: product.product_id,
|
|
1458
1515
|
optionRef: ref,
|
|
1459
1516
|
refs,
|
|
1517
|
+
...declared === true && sellerFormatEvidence(option) ? { declaration: structuredCloneWithLegacyCreativeMetadata(option) } : {},
|
|
1460
1518
|
...declared === false ? { undeclaredSelector: undeclaredFormatOptionSelector(option) } : {}
|
|
1461
1519
|
});
|
|
1462
1520
|
}
|
|
@@ -4666,6 +4724,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4666
4724
|
}
|
|
4667
4725
|
}
|
|
4668
4726
|
const conditionalSnapshot = skipCacheRead ? void 0 : cache?.read(cacheScope, cacheParams, true);
|
|
4727
|
+
const productEvidence = this.usesScopedDiscoveryTransport(
|
|
4728
|
+
effectiveOptions
|
|
4729
|
+
) ? void 0 : {
|
|
4730
|
+
scopeKey: this.getCapabilityEvidenceScope().scopeKey,
|
|
4731
|
+
accountScope: this.canonicalAccountScope(account),
|
|
4732
|
+
expiresAt: Date.now() + resolveAgentDiscoveryTtlMs(this.config.discoveryCache?.ttlMs)
|
|
4733
|
+
};
|
|
4669
4734
|
const result = await this.executeAndHandle(
|
|
4670
4735
|
"get_products",
|
|
4671
4736
|
"onGetProductsStatusChange",
|
|
@@ -4678,7 +4743,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4678
4743
|
projectionCatalogs: projectionCatalogs ?? this.config.projectionCatalogs
|
|
4679
4744
|
});
|
|
4680
4745
|
const authoritativeProducts = Array.isArray(data.products) ? data.products : response.products;
|
|
4681
|
-
this.rememberCanonicalProductRoutes(response.products, account, authoritativeProducts);
|
|
4746
|
+
this.rememberCanonicalProductRoutes(response.products, account, authoritativeProducts, productEvidence);
|
|
4682
4747
|
const { _message: _dropLegacyMessage, ...canonical } = response;
|
|
4683
4748
|
void _dropLegacyMessage;
|
|
4684
4749
|
return { ...canonical, projection: { diagnostics } };
|
|
@@ -4689,7 +4754,9 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4689
4754
|
);
|
|
4690
4755
|
const finishCache = async (completed) => {
|
|
4691
4756
|
if (!cache) return completed;
|
|
4692
|
-
const cachedResult = cache.write(cacheScope, cacheParams, completed, conditionalSnapshot)
|
|
4757
|
+
const cachedResult = cache.write(cacheScope, cacheParams, completed, conditionalSnapshot, (materialized) => {
|
|
4758
|
+
this.rememberCanonicalProductRoutes(materialized.data?.products ?? [], account, void 0, productEvidence);
|
|
4759
|
+
});
|
|
4693
4760
|
if (cachedResult.success && cachedResult.status === "completed") {
|
|
4694
4761
|
if (!skipCacheRead && cacheParams.if_wholesale_feed_version === void 0 && cacheParams.if_pricing_version === void 0 && cachedResult.data.unchanged === true) {
|
|
4695
4762
|
return this.getProducts(params, inputHandler, {
|
|
@@ -4849,7 +4916,12 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4849
4916
|
if (hasCreativeFormatData) {
|
|
4850
4917
|
this.validateBeforeCreativeCapabilityProbe("create_media_buy", params, taskOptions);
|
|
4851
4918
|
}
|
|
4852
|
-
const wireMode = hasCreativeFormatData ? await this.
|
|
4919
|
+
const wireMode = hasCreativeFormatData ? await this.resolveCreativeWireMode(
|
|
4920
|
+
"create_media_buy",
|
|
4921
|
+
taskOptions,
|
|
4922
|
+
true,
|
|
4923
|
+
() => this.productOptionsSupportCanonicalWire("create_media_buy", params, [], options)
|
|
4924
|
+
) : "canonical";
|
|
4853
4925
|
const wireParams = params;
|
|
4854
4926
|
const result = await this.executeAndHandle(
|
|
4855
4927
|
"create_media_buy",
|
|
@@ -4937,7 +5009,12 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
4937
5009
|
if (hasCreativeFormatData) {
|
|
4938
5010
|
this.validateBeforeCreativeCapabilityProbe("update_media_buy", params, taskOptions);
|
|
4939
5011
|
}
|
|
4940
|
-
const wireMode = hasCreativeFormatData ? await this.
|
|
5012
|
+
const wireMode = hasCreativeFormatData ? await this.resolveCreativeWireMode(
|
|
5013
|
+
"update_media_buy",
|
|
5014
|
+
taskOptions,
|
|
5015
|
+
true,
|
|
5016
|
+
() => this.productOptionsSupportCanonicalWire("update_media_buy", params, [], options)
|
|
5017
|
+
) : "canonical";
|
|
4941
5018
|
const result = await this.executeAndHandle(
|
|
4942
5019
|
"update_media_buy",
|
|
4943
5020
|
"onUpdateMediaBuyStatusChange",
|
|
@@ -5026,7 +5103,6 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5026
5103
|
projectionCatalogs ?? this.config.projectionCatalogs
|
|
5027
5104
|
);
|
|
5028
5105
|
this.validateBeforeCreativeCapabilityProbe("sync_creatives", params, taskOptions);
|
|
5029
|
-
const wireMode = await this.resolveCreativeFormatWireMode("sync_creatives", taskOptions);
|
|
5030
5106
|
const configuredSelectorContainers = [
|
|
5031
5107
|
...creativeFormatProjection?.selectorContainers ?? []
|
|
5032
5108
|
];
|
|
@@ -5038,10 +5114,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5038
5114
|
const assignmentPackageContainers = Array.isArray(params.assignments) ? params.assignments.flatMap(
|
|
5039
5115
|
(assignment) => typeof assignment.package_id === "string" && !configuredPackageIds.has(assignment.package_id) ? [{ package_id: assignment.package_id }] : []
|
|
5040
5116
|
) : [];
|
|
5117
|
+
const selectorContainers = [...configuredSelectorContainers, ...assignmentPackageContainers];
|
|
5118
|
+
const wireMode = await this.resolveCreativeWireMode(
|
|
5119
|
+
"sync_creatives",
|
|
5120
|
+
taskOptions,
|
|
5121
|
+
true,
|
|
5122
|
+
() => this.productOptionsSupportCanonicalWire("sync_creatives", params, selectorContainers, options)
|
|
5123
|
+
);
|
|
5041
5124
|
const wireParams = this.projectUndeclaredFormatOptions(
|
|
5042
5125
|
projectSyncCreativesForDelivery(
|
|
5043
5126
|
params,
|
|
5044
|
-
|
|
5127
|
+
selectorContainers,
|
|
5045
5128
|
wireMode,
|
|
5046
5129
|
effectiveLegacyFormatConverter,
|
|
5047
5130
|
effectiveCanonicalFormatLegacyResolver
|
|
@@ -5081,16 +5164,17 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5081
5164
|
* sending a mutation. Discovers capabilities and the current tool's input
|
|
5082
5165
|
* schema, or reuses fresh cached/primed evidence, with this client's wire pin.
|
|
5083
5166
|
*
|
|
5084
|
-
* `unknown`
|
|
5085
|
-
*
|
|
5086
|
-
*
|
|
5167
|
+
* This context-free check returns `unknown` when capabilities and schema do
|
|
5168
|
+
* not establish support. A write to a proven 3.1 seller can still select
|
|
5169
|
+
* canonical delivery from matching seller-advertised product options;
|
|
5170
|
+
* otherwise projection requires an unambiguous legacy reference.
|
|
5087
5171
|
* Conflicting evidence and unproven support with a 3.2+ buyer pin throw
|
|
5088
5172
|
* `CreativeFormatCapabilityError`, just as they do during a write.
|
|
5089
5173
|
*/
|
|
5090
5174
|
async resolveCreativeFormatWireMode(taskType, options) {
|
|
5091
5175
|
return this.resolveCreativeWireMode(taskType, options, true);
|
|
5092
5176
|
}
|
|
5093
|
-
async resolveCreativeWireMode(taskType, options, canRediscover) {
|
|
5177
|
+
async resolveCreativeWireMode(taskType, options, canRediscover, matchingProductOptions) {
|
|
5094
5178
|
const discoveryContext = {};
|
|
5095
5179
|
const capabilities = await this.getCapabilities({
|
|
5096
5180
|
...options,
|
|
@@ -5109,13 +5193,16 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5109
5193
|
`Seller capability and ${taskType} input schema disagree about canonical creative support`
|
|
5110
5194
|
);
|
|
5111
5195
|
}
|
|
5112
|
-
|
|
5196
|
+
let resolved = declared !== "unknown" ? declared : schema;
|
|
5197
|
+
if (resolved === "unknown" && canUseProductOptionsForCreativeWire(capabilities, wireRelease) && matchingProductOptions?.()) {
|
|
5198
|
+
resolved = "canonical";
|
|
5199
|
+
}
|
|
5113
5200
|
const release = /^v?(\d+)\.(\d+)(?:\.|-|$)/.exec(wireRelease.trim());
|
|
5114
5201
|
const canonicalRequiredByBuyerPin = release !== null && (Number(release[1]) > 3 || Number(release[1]) === 3 && Number(release[2]) >= 2);
|
|
5115
5202
|
if (resolved === "unknown" && canonicalRequiredByBuyerPin) {
|
|
5116
5203
|
if (canRediscover && !usesScopedFetch && this.normalizedAgent.protocol === "mcp" && this.capabilitiesFromSharedCache && toolSchemas?.has(taskType) && !toolInputSchemasByProperties.has(toolSchemas)) {
|
|
5117
5204
|
await this.invalidateDiscoveryCache(options);
|
|
5118
|
-
return this.resolveCreativeWireMode(taskType, options, false);
|
|
5205
|
+
return this.resolveCreativeWireMode(taskType, options, false, matchingProductOptions);
|
|
5119
5206
|
}
|
|
5120
5207
|
throw new CreativeFormatCapabilityError(
|
|
5121
5208
|
`Cannot prove which AdCP release the seller serves for ${taskType}; a 3.2+ client will not guess a legacy creative wire shape`
|
|
@@ -5123,6 +5210,115 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
|
|
|
5123
5210
|
}
|
|
5124
5211
|
return resolved;
|
|
5125
5212
|
}
|
|
5213
|
+
usesScopedDiscoveryTransport(options) {
|
|
5214
|
+
return normalizeTransportOptions(options?.transport ?? this.config.transport)?.trustedFetchFn !== void 0;
|
|
5215
|
+
}
|
|
5216
|
+
/** Product evidence applies to this request only; it must never prime a tool-wide capability. */
|
|
5217
|
+
productOptionsSupportCanonicalWire(taskType, request, selectorContainers = [], options) {
|
|
5218
|
+
if (!isPlainRecord(request) || this.usesScopedDiscoveryTransport(options)) return false;
|
|
5219
|
+
const scopeKey = this.getCapabilityEvidenceScope().scopeKey;
|
|
5220
|
+
const accountScope = this.canonicalAccountScope(request.account);
|
|
5221
|
+
const optionRef = (value) => {
|
|
5222
|
+
if (!isPlainRecord(value) || typeof value.format_option_id !== "string" || !value.format_option_id) {
|
|
5223
|
+
return void 0;
|
|
5224
|
+
}
|
|
5225
|
+
if (typeof value.publisher_domain === "string") {
|
|
5226
|
+
return {
|
|
5227
|
+
scope: "publisher",
|
|
5228
|
+
publisher_domain: value.publisher_domain,
|
|
5229
|
+
format_option_id: value.format_option_id
|
|
5230
|
+
};
|
|
5231
|
+
}
|
|
5232
|
+
if (value.scope !== void 0 && value.scope !== "product") return void 0;
|
|
5233
|
+
return { scope: "product", format_option_id: value.format_option_id };
|
|
5234
|
+
};
|
|
5235
|
+
const accepts = (container, creative, depth = 0) => {
|
|
5236
|
+
if (depth > 32) return false;
|
|
5237
|
+
if (Array.isArray(container.selector_containers)) {
|
|
5238
|
+
return container.selector_containers.length > 0 && container.selector_containers.every((nested) => accepts(nested, creative, depth + 1));
|
|
5239
|
+
}
|
|
5240
|
+
const refs = Array.isArray(container.format_option_refs) ? container.format_option_refs.map(optionRef) : [];
|
|
5241
|
+
if (refs.some((ref) => ref === void 0)) return false;
|
|
5242
|
+
const creativeRef = isPlainRecord(creative) ? optionRef(creative.format_option_ref) : void 0;
|
|
5243
|
+
if (isPlainRecord(creative) && creative.format_option_ref !== void 0 && !creativeRef) return false;
|
|
5244
|
+
const isSellerDeclaration = (value) => {
|
|
5245
|
+
if (!isPlainRecord(value) || sellerDeclaredFormatOption(value) !== true || isSynthesizedFormatOption(value)) {
|
|
5246
|
+
return false;
|
|
5247
|
+
}
|
|
5248
|
+
const evidence2 = sellerFormatEvidence(value);
|
|
5249
|
+
if (!evidence2 || evidence2.scopeKey !== scopeKey || typeof container.product_id === "string" && evidence2.productId !== container.product_id || evidence2.expiresAt <= Date.now() || evidence2.accountScope !== accountScope && evidence2.accountScope !== "none")
|
|
5250
|
+
return false;
|
|
5251
|
+
const ref = optionRef(value);
|
|
5252
|
+
if (ref && formatOptionOriginFromRoutes(
|
|
5253
|
+
options?.canonicalFormatLegacyResolver,
|
|
5254
|
+
ref,
|
|
5255
|
+
typeof container.product_id === "string" ? container.product_id : void 0
|
|
5256
|
+
)?.seller_declared === false)
|
|
5257
|
+
return false;
|
|
5258
|
+
return !ref || typeof container.product_id !== "string" || this.cachedFormatOptionOrigin(request.account, ref, container.product_id)?.seller_declared !== false;
|
|
5259
|
+
};
|
|
5260
|
+
const declarations = [
|
|
5261
|
+
...(Array.isArray(container.format_options) ? container.format_options : []).filter(isSellerDeclaration),
|
|
5262
|
+
...selectedFormatOptions(container).filter(isSellerDeclaration)
|
|
5263
|
+
];
|
|
5264
|
+
if (typeof container.product_id === "string") {
|
|
5265
|
+
for (const ref of [...refs, ...creativeRef ? [creativeRef] : []]) {
|
|
5266
|
+
if (!ref) continue;
|
|
5267
|
+
const route = this.routeForOption(request.account, container.product_id, ref);
|
|
5268
|
+
if (route?.kind === "product" && route.declaration && isSellerDeclaration(route.declaration))
|
|
5269
|
+
declarations.push(route.declaration);
|
|
5270
|
+
}
|
|
5271
|
+
}
|
|
5272
|
+
const available = declarations.filter((declaration) => declaration.experimental !== true);
|
|
5273
|
+
const matchesRef = (declaration, ref) => {
|
|
5274
|
+
const declaredRef = optionRef(declaration);
|
|
5275
|
+
return declaredRef !== void 0 && this.sameCanonicalOptionRef(declaredRef, ref);
|
|
5276
|
+
};
|
|
5277
|
+
if (!refs.every((ref) => available.some((declaration) => matchesRef(declaration, ref)))) return false;
|
|
5278
|
+
const selected = available.filter(
|
|
5279
|
+
(declaration) => refs.length === 0 || refs.some((ref) => matchesRef(declaration, ref))
|
|
5280
|
+
);
|
|
5281
|
+
if (creative === void 0) return refs.length > 0 && selected.length > 0;
|
|
5282
|
+
if (!isPlainRecord(creative) || typeof creative.format_kind !== "string" || creative.format_id !== void 0)
|
|
5283
|
+
return false;
|
|
5284
|
+
return selected.some(
|
|
5285
|
+
(declaration) => declaration.format_kind === creative.format_kind && (!creativeRef || matchesRef(declaration, creativeRef)) && creativeMatchesProductOption(creative, declaration)
|
|
5286
|
+
);
|
|
5287
|
+
};
|
|
5288
|
+
if (taskType === "sync_creatives") {
|
|
5289
|
+
if (!Array.isArray(request.creatives) || request.creatives.length === 0) return false;
|
|
5290
|
+
const creatives = request.creatives;
|
|
5291
|
+
const assignments = Array.isArray(request.assignments) ? request.assignments : [];
|
|
5292
|
+
if (!assignments.every(
|
|
5293
|
+
(value) => isPlainRecord(value) && typeof value.package_id === "string" && typeof value.creative_id === "string" && creatives.some((creative) => isPlainRecord(creative) && creative.creative_id === value.creative_id)
|
|
5294
|
+
))
|
|
5295
|
+
return false;
|
|
5296
|
+
return creatives.every((creative) => {
|
|
5297
|
+
if (!isPlainRecord(creative)) return false;
|
|
5298
|
+
const assigned = new Set(
|
|
5299
|
+
assignments.flatMap(
|
|
5300
|
+
(value) => isPlainRecord(value) && value.creative_id === creative.creative_id && typeof value.package_id === "string" ? [value.package_id] : []
|
|
5301
|
+
)
|
|
5302
|
+
);
|
|
5303
|
+
const relevant = assigned.size === 0 ? selectorContainers : selectorContainers.filter(
|
|
5304
|
+
(container) => typeof container.package_id === "string" && assigned.has(container.package_id)
|
|
5305
|
+
);
|
|
5306
|
+
return relevant.length > 0 && [...assigned].every((id) => relevant.some((container) => container.package_id === id)) && relevant.every((container) => accepts(container, creative));
|
|
5307
|
+
});
|
|
5308
|
+
}
|
|
5309
|
+
const packages = ["packages", "new_packages"].flatMap((key) => Array.isArray(request[key]) ? request[key] : []);
|
|
5310
|
+
let evidence = false;
|
|
5311
|
+
return packages.length > 0 && packages.every((pkg) => {
|
|
5312
|
+
if (!isPlainRecord(pkg)) return false;
|
|
5313
|
+
const creatives = Array.isArray(pkg.creatives) ? pkg.creatives : [];
|
|
5314
|
+
const hasSelectors = Array.isArray(pkg.format_option_refs) && pkg.format_option_refs.length > 0;
|
|
5315
|
+
if (!hasSelectors && creatives.length === 0) {
|
|
5316
|
+
return pkg.format_kind === void 0 && pkg.format_ids === void 0;
|
|
5317
|
+
}
|
|
5318
|
+
evidence = true;
|
|
5319
|
+
return (!hasSelectors || accepts(pkg)) && creatives.every((creative) => accepts(pkg, creative));
|
|
5320
|
+
}) && evidence;
|
|
5321
|
+
}
|
|
5126
5322
|
/** Validate malformed creative payloads before capability discovery can perform I/O. */
|
|
5127
5323
|
validateBeforeCreativeCapabilityProbe(taskType, params, options) {
|
|
5128
5324
|
if (options.skipIdempotencyAutoInject || options.skipAccountValidation || options.skipRequestValidation) return;
|
|
@@ -12,7 +12,9 @@ export declare class ProductCache {
|
|
|
12
12
|
private key;
|
|
13
13
|
read<T>(scope: string, params: Record<string, unknown>, allowExpired?: boolean): TaskResult<T> | undefined;
|
|
14
14
|
conditionalParams(scope: string, params: Record<string, unknown>): Record<string, unknown>;
|
|
15
|
-
write<T>(scope: string, params: Record<string, unknown>, result: TaskResult<T>, conditionalSnapshot?: TaskResult<T
|
|
15
|
+
write<T>(scope: string, params: Record<string, unknown>, result: TaskResult<T>, conditionalSnapshot?: TaskResult<T>,
|
|
16
|
+
/** @internal Refresh private discovery evidence before a confirmed snapshot is cloned into storage. */
|
|
17
|
+
onRevalidated?: (materialized: TaskResult<T>) => void): TaskResult<T>;
|
|
16
18
|
clear(): void;
|
|
17
19
|
}
|
|
18
20
|
export declare function createProductCache(options?: ProductCacheOptions): ProductCache;
|
|
@@ -12,7 +12,9 @@ export declare class ProductCache {
|
|
|
12
12
|
private key;
|
|
13
13
|
read<T>(scope: string, params: Record<string, unknown>, allowExpired?: boolean): TaskResult<T> | undefined;
|
|
14
14
|
conditionalParams(scope: string, params: Record<string, unknown>): Record<string, unknown>;
|
|
15
|
-
write<T>(scope: string, params: Record<string, unknown>, result: TaskResult<T>, conditionalSnapshot?: TaskResult<T
|
|
15
|
+
write<T>(scope: string, params: Record<string, unknown>, result: TaskResult<T>, conditionalSnapshot?: TaskResult<T>,
|
|
16
|
+
/** @internal Refresh private discovery evidence before a confirmed snapshot is cloned into storage. */
|
|
17
|
+
onRevalidated?: (materialized: TaskResult<T>) => void): TaskResult<T>;
|
|
16
18
|
clear(): void;
|
|
17
19
|
}
|
|
18
20
|
export declare function createProductCache(options?: ProductCacheOptions): ProductCache;
|
|
@@ -86,7 +86,7 @@ class ProductCache {
|
|
|
86
86
|
...typeof data.pricing_version === "string" && { if_pricing_version: data.pricing_version }
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
|
-
write(scope, params, result, conditionalSnapshot) {
|
|
89
|
+
write(scope, params, result, conditionalSnapshot, onRevalidated) {
|
|
90
90
|
const key = this.key(scope, params);
|
|
91
91
|
if (!key) return result;
|
|
92
92
|
if (!result.success || result.status !== "completed" || !result.data || typeof result.data !== "object")
|
|
@@ -109,6 +109,7 @@ class ProductCache {
|
|
|
109
109
|
return result;
|
|
110
110
|
if (params.if_wholesale_feed_version !== void 0 || params.if_pricing_version !== void 0) return result;
|
|
111
111
|
completed = { ...result, data: (0, import_legacy_metadata.structuredCloneWithLegacyCreativeMetadata)(oldData) };
|
|
112
|
+
onRevalidated?.(completed);
|
|
112
113
|
} else if (!Array.isArray(data.products)) return result;
|
|
113
114
|
if (!this.entries.has(key) && this.entries.size >= (this.options.maxEntries ?? 1e3))
|
|
114
115
|
this.entries.delete(this.entries.keys().next().value);
|
|
@@ -62,7 +62,7 @@ class ProductCache {
|
|
|
62
62
|
...typeof data.pricing_version === "string" && { if_pricing_version: data.pricing_version }
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
-
write(scope, params, result, conditionalSnapshot) {
|
|
65
|
+
write(scope, params, result, conditionalSnapshot, onRevalidated) {
|
|
66
66
|
const key = this.key(scope, params);
|
|
67
67
|
if (!key) return result;
|
|
68
68
|
if (!result.success || result.status !== "completed" || !result.data || typeof result.data !== "object")
|
|
@@ -85,6 +85,7 @@ class ProductCache {
|
|
|
85
85
|
return result;
|
|
86
86
|
if (params.if_wholesale_feed_version !== void 0 || params.if_pricing_version !== void 0) return result;
|
|
87
87
|
completed = { ...result, data: structuredCloneWithLegacyCreativeMetadata(oldData) };
|
|
88
|
+
onRevalidated?.(completed);
|
|
88
89
|
} else if (!Array.isArray(data.products)) return result;
|
|
89
90
|
if (!this.entries.has(key) && this.entries.size >= (this.options.maxEntries ?? 1e3))
|
|
90
91
|
this.entries.delete(this.entries.keys().next().value);
|
|
@@ -144,9 +144,10 @@ export type SavePropertyRequest = Omit<RegistrySavePropertyRequest, 'authorized_
|
|
|
144
144
|
/** Response from POST /api/properties/save (200) */
|
|
145
145
|
export type SavePropertyResponse = operations['saveProperty']['responses']['200']['content']['application/json'];
|
|
146
146
|
type RegistryResolveIdentifiersRequest = NonNullable<operations['resolveIdentifiers']['requestBody']>['content']['application/json'];
|
|
147
|
-
/** Request body for POST /api/registry/resolve.
|
|
148
|
-
export type ResolveIdentifiersRequest = Omit<RegistryResolveIdentifiersRequest, 'mode'> & {
|
|
147
|
+
/** Request body for POST /api/registry/resolve. Mode and sandbox use the registry's defaults when omitted. */
|
|
148
|
+
export type ResolveIdentifiersRequest = Omit<RegistryResolveIdentifiersRequest, 'mode' | 'sandbox'> & {
|
|
149
149
|
mode?: RegistryResolveIdentifiersRequest['mode'];
|
|
150
|
+
sandbox?: RegistryResolveIdentifiersRequest['sandbox'];
|
|
150
151
|
};
|
|
151
152
|
/** Response from POST /api/registry/resolve (200) */
|
|
152
153
|
export type ResolveIdentifiersResponse = operations['resolveIdentifiers']['responses']['200']['content']['application/json'];
|
|
@@ -144,9 +144,10 @@ export type SavePropertyRequest = Omit<RegistrySavePropertyRequest, 'authorized_
|
|
|
144
144
|
/** Response from POST /api/properties/save (200) */
|
|
145
145
|
export type SavePropertyResponse = operations['saveProperty']['responses']['200']['content']['application/json'];
|
|
146
146
|
type RegistryResolveIdentifiersRequest = NonNullable<operations['resolveIdentifiers']['requestBody']>['content']['application/json'];
|
|
147
|
-
/** Request body for POST /api/registry/resolve.
|
|
148
|
-
export type ResolveIdentifiersRequest = Omit<RegistryResolveIdentifiersRequest, 'mode'> & {
|
|
147
|
+
/** Request body for POST /api/registry/resolve. Mode and sandbox use the registry's defaults when omitted. */
|
|
148
|
+
export type ResolveIdentifiersRequest = Omit<RegistryResolveIdentifiersRequest, 'mode' | 'sandbox'> & {
|
|
149
149
|
mode?: RegistryResolveIdentifiersRequest['mode'];
|
|
150
|
+
sandbox?: RegistryResolveIdentifiersRequest['sandbox'];
|
|
150
151
|
};
|
|
151
152
|
/** Response from POST /api/registry/resolve (200) */
|
|
152
153
|
export type ResolveIdentifiersResponse = operations['resolveIdentifiers']['responses']['200']['content']['application/json'];
|
|
@@ -283,7 +283,7 @@ export interface paths {
|
|
|
283
283
|
put?: never;
|
|
284
284
|
/**
|
|
285
285
|
* Save property
|
|
286
|
-
* @description Save or update a hosted property in the registry. Requires authentication. For existing properties, creates a revision-tracked edit. For new properties, creates the property directly. Cannot edit authoritative properties managed via adagents.json.
|
|
286
|
+
* @description Save or update a hosted property in the registry. Requires authentication. For bulk identifier contributions use resolveIdentifiers instead (up to 10,000 identifiers per request). This endpoint is limited to 60 requests/hour per user/IP. publisher_domain must be a lowercase hostname without a URL, port, whitespace, wildcard, or trailing dot. Reserved test domains are rejected unless sandbox is true. With sandbox: true the request is validated and a simulated result is returned without reading or writing a hosted property; the ID is ephemeral. For existing properties, creates a revision-tracked edit. For new properties, creates the property directly. Cannot edit authoritative properties managed via adagents.json.
|
|
287
287
|
*
|
|
288
288
|
* This is an identity-only write surface: the stored document always carries `authorized_agents: []`. Sales authorization lives solely in the publisher's own origin `adagents.json`; the community registry cannot mint or carry it. Any `authorized_agents` sent in the request body is ignored.
|
|
289
289
|
*/
|
|
@@ -4892,6 +4892,11 @@ export interface components {
|
|
|
4892
4892
|
*/
|
|
4893
4893
|
OrganizationRevenueTier: "under_1m" | "1m_5m" | "5m_50m" | "50m_250m" | "250m_1b" | "1b_plus";
|
|
4894
4894
|
ResolveResponse: {
|
|
4895
|
+
/**
|
|
4896
|
+
* @description Present for a non-persistent sandbox simulation. New property handles are ephemeral.
|
|
4897
|
+
* @enum {boolean}
|
|
4898
|
+
*/
|
|
4899
|
+
sandbox?: true;
|
|
4895
4900
|
resolved: components["schemas"]["ResolvedEntry"][];
|
|
4896
4901
|
summary: {
|
|
4897
4902
|
total: number;
|
|
@@ -4915,30 +4920,30 @@ export interface components {
|
|
|
4915
4920
|
CatalogIdentifier: {
|
|
4916
4921
|
/** @example domain */
|
|
4917
4922
|
type: string;
|
|
4918
|
-
/** @example
|
|
4923
|
+
/** @example streamhaus.com */
|
|
4919
4924
|
value: string;
|
|
4920
4925
|
};
|
|
4926
|
+
/** @description Up to 10,000 identifiers plus provenance. resolve requires authentication and contributes unknown identifiers; lookup is read-only. Domain/subdomain values must follow core/identifier.json; production rejects reserved test domains. sandbox: true simulates contributions without writes. */
|
|
4921
4927
|
ResolveRequest: {
|
|
4922
4928
|
/** @description Identifiers to resolve (and, in resolve mode, contribute). Max 10,000 per call for all callers. */
|
|
4923
4929
|
identifiers: components["schemas"]["CatalogIdentifier"][];
|
|
4924
4930
|
provenance: components["schemas"]["FactProvenance"];
|
|
4925
4931
|
/**
|
|
4926
|
-
* @description
|
|
4932
|
+
* @description resolve (default) contributes identifiers, creates missing catalog entries, and logs activity; authentication is required. lookup is a public read with no writes or activity logging.
|
|
4927
4933
|
* @default resolve
|
|
4928
4934
|
* @enum {string}
|
|
4929
4935
|
*/
|
|
4930
4936
|
mode: "resolve" | "lookup";
|
|
4937
|
+
/** @description Simulate contributions without storing properties, identifiers, facts, or activity. Reads existing catalog data; new handles are ephemeral. Reserved test domains are allowed only in sandbox mode. Defaults to false when omitted. */
|
|
4938
|
+
sandbox?: boolean;
|
|
4931
4939
|
};
|
|
4932
4940
|
FactProvenance: {
|
|
4933
4941
|
/**
|
|
4934
|
-
* @description How the caller knows these identifiers — the trust/audit envelope on the fact. Determines the confidence the catalog assigns.
|
|
4942
|
+
* @description How the caller knows these identifiers — the trust/audit envelope on the fact. Determines the confidence the catalog assigns. crawl is reserved for server-side pipelines; callers use the others.
|
|
4935
4943
|
* @enum {string}
|
|
4936
4944
|
*/
|
|
4937
4945
|
type: "agency_allowlist" | "publisher_declaration" | "impression_log" | "ssp_inventory" | "deal_history" | "crawl" | "data_partner" | "member_assertion";
|
|
4938
|
-
/**
|
|
4939
|
-
* @description Optional free-text annotation (campaign, dataset).
|
|
4940
|
-
* @example unilever_q3
|
|
4941
|
-
*/
|
|
4946
|
+
/** @description Optional free-text annotation (campaign, dataset). */
|
|
4942
4947
|
context?: string;
|
|
4943
4948
|
};
|
|
4944
4949
|
CatalogDisputeTriageResult: {
|
|
@@ -5731,6 +5736,11 @@ export interface operations {
|
|
|
5731
5736
|
"application/json": {
|
|
5732
5737
|
/** @example examplepub.com */
|
|
5733
5738
|
publisher_domain: string;
|
|
5739
|
+
/**
|
|
5740
|
+
* @description Validate and simulate a save without persisting it. Allows reserved test hostnames.
|
|
5741
|
+
* @default false
|
|
5742
|
+
*/
|
|
5743
|
+
sandbox?: boolean;
|
|
5734
5744
|
/**
|
|
5735
5745
|
* @description Ignored. Community-registry rows never assert sales authorization — the owner's origin adagents.json is the sole authorization source — so any value here is dropped and the stored document carries authorized_agents:[].
|
|
5736
5746
|
* @example []
|
|
@@ -5770,6 +5780,8 @@ export interface operations {
|
|
|
5770
5780
|
success: true;
|
|
5771
5781
|
message: string;
|
|
5772
5782
|
id: string;
|
|
5783
|
+
/** @enum {boolean} */
|
|
5784
|
+
sandbox?: true;
|
|
5773
5785
|
revision_number?: number;
|
|
5774
5786
|
};
|
|
5775
5787
|
};
|
|
@@ -8475,7 +8487,7 @@ export interface operations {
|
|
|
8475
8487
|
getAgentAuthorizations: {
|
|
8476
8488
|
parameters: {
|
|
8477
8489
|
query: {
|
|
8478
|
-
/** @description Agent URL to look up. Canonicalized server-side
|
|
8490
|
+
/** @description Agent URL to look up. Canonicalized server-side per AdCP URL canonicalization: the scheme and host fold, the path does not. */
|
|
8479
8491
|
agent_url: string;
|
|
8480
8492
|
/** @description `effective` (default) applies override layer; `raw` reads base table. */
|
|
8481
8493
|
include?: "raw" | "effective";
|
|
@@ -283,7 +283,7 @@ export interface paths {
|
|
|
283
283
|
put?: never;
|
|
284
284
|
/**
|
|
285
285
|
* Save property
|
|
286
|
-
* @description Save or update a hosted property in the registry. Requires authentication. For existing properties, creates a revision-tracked edit. For new properties, creates the property directly. Cannot edit authoritative properties managed via adagents.json.
|
|
286
|
+
* @description Save or update a hosted property in the registry. Requires authentication. For bulk identifier contributions use resolveIdentifiers instead (up to 10,000 identifiers per request). This endpoint is limited to 60 requests/hour per user/IP. publisher_domain must be a lowercase hostname without a URL, port, whitespace, wildcard, or trailing dot. Reserved test domains are rejected unless sandbox is true. With sandbox: true the request is validated and a simulated result is returned without reading or writing a hosted property; the ID is ephemeral. For existing properties, creates a revision-tracked edit. For new properties, creates the property directly. Cannot edit authoritative properties managed via adagents.json.
|
|
287
287
|
*
|
|
288
288
|
* This is an identity-only write surface: the stored document always carries `authorized_agents: []`. Sales authorization lives solely in the publisher's own origin `adagents.json`; the community registry cannot mint or carry it. Any `authorized_agents` sent in the request body is ignored.
|
|
289
289
|
*/
|
|
@@ -4892,6 +4892,11 @@ export interface components {
|
|
|
4892
4892
|
*/
|
|
4893
4893
|
OrganizationRevenueTier: "under_1m" | "1m_5m" | "5m_50m" | "50m_250m" | "250m_1b" | "1b_plus";
|
|
4894
4894
|
ResolveResponse: {
|
|
4895
|
+
/**
|
|
4896
|
+
* @description Present for a non-persistent sandbox simulation. New property handles are ephemeral.
|
|
4897
|
+
* @enum {boolean}
|
|
4898
|
+
*/
|
|
4899
|
+
sandbox?: true;
|
|
4895
4900
|
resolved: components["schemas"]["ResolvedEntry"][];
|
|
4896
4901
|
summary: {
|
|
4897
4902
|
total: number;
|
|
@@ -4915,30 +4920,30 @@ export interface components {
|
|
|
4915
4920
|
CatalogIdentifier: {
|
|
4916
4921
|
/** @example domain */
|
|
4917
4922
|
type: string;
|
|
4918
|
-
/** @example
|
|
4923
|
+
/** @example streamhaus.com */
|
|
4919
4924
|
value: string;
|
|
4920
4925
|
};
|
|
4926
|
+
/** @description Up to 10,000 identifiers plus provenance. resolve requires authentication and contributes unknown identifiers; lookup is read-only. Domain/subdomain values must follow core/identifier.json; production rejects reserved test domains. sandbox: true simulates contributions without writes. */
|
|
4921
4927
|
ResolveRequest: {
|
|
4922
4928
|
/** @description Identifiers to resolve (and, in resolve mode, contribute). Max 10,000 per call for all callers. */
|
|
4923
4929
|
identifiers: components["schemas"]["CatalogIdentifier"][];
|
|
4924
4930
|
provenance: components["schemas"]["FactProvenance"];
|
|
4925
4931
|
/**
|
|
4926
|
-
* @description
|
|
4932
|
+
* @description resolve (default) contributes identifiers, creates missing catalog entries, and logs activity; authentication is required. lookup is a public read with no writes or activity logging.
|
|
4927
4933
|
* @default resolve
|
|
4928
4934
|
* @enum {string}
|
|
4929
4935
|
*/
|
|
4930
4936
|
mode: "resolve" | "lookup";
|
|
4937
|
+
/** @description Simulate contributions without storing properties, identifiers, facts, or activity. Reads existing catalog data; new handles are ephemeral. Reserved test domains are allowed only in sandbox mode. Defaults to false when omitted. */
|
|
4938
|
+
sandbox?: boolean;
|
|
4931
4939
|
};
|
|
4932
4940
|
FactProvenance: {
|
|
4933
4941
|
/**
|
|
4934
|
-
* @description How the caller knows these identifiers — the trust/audit envelope on the fact. Determines the confidence the catalog assigns.
|
|
4942
|
+
* @description How the caller knows these identifiers — the trust/audit envelope on the fact. Determines the confidence the catalog assigns. crawl is reserved for server-side pipelines; callers use the others.
|
|
4935
4943
|
* @enum {string}
|
|
4936
4944
|
*/
|
|
4937
4945
|
type: "agency_allowlist" | "publisher_declaration" | "impression_log" | "ssp_inventory" | "deal_history" | "crawl" | "data_partner" | "member_assertion";
|
|
4938
|
-
/**
|
|
4939
|
-
* @description Optional free-text annotation (campaign, dataset).
|
|
4940
|
-
* @example unilever_q3
|
|
4941
|
-
*/
|
|
4946
|
+
/** @description Optional free-text annotation (campaign, dataset). */
|
|
4942
4947
|
context?: string;
|
|
4943
4948
|
};
|
|
4944
4949
|
CatalogDisputeTriageResult: {
|
|
@@ -5731,6 +5736,11 @@ export interface operations {
|
|
|
5731
5736
|
"application/json": {
|
|
5732
5737
|
/** @example examplepub.com */
|
|
5733
5738
|
publisher_domain: string;
|
|
5739
|
+
/**
|
|
5740
|
+
* @description Validate and simulate a save without persisting it. Allows reserved test hostnames.
|
|
5741
|
+
* @default false
|
|
5742
|
+
*/
|
|
5743
|
+
sandbox?: boolean;
|
|
5734
5744
|
/**
|
|
5735
5745
|
* @description Ignored. Community-registry rows never assert sales authorization — the owner's origin adagents.json is the sole authorization source — so any value here is dropped and the stored document carries authorized_agents:[].
|
|
5736
5746
|
* @example []
|
|
@@ -5770,6 +5780,8 @@ export interface operations {
|
|
|
5770
5780
|
success: true;
|
|
5771
5781
|
message: string;
|
|
5772
5782
|
id: string;
|
|
5783
|
+
/** @enum {boolean} */
|
|
5784
|
+
sandbox?: true;
|
|
5773
5785
|
revision_number?: number;
|
|
5774
5786
|
};
|
|
5775
5787
|
};
|
|
@@ -8475,7 +8487,7 @@ export interface operations {
|
|
|
8475
8487
|
getAgentAuthorizations: {
|
|
8476
8488
|
parameters: {
|
|
8477
8489
|
query: {
|
|
8478
|
-
/** @description Agent URL to look up. Canonicalized server-side
|
|
8490
|
+
/** @description Agent URL to look up. Canonicalized server-side per AdCP URL canonicalization: the scheme and host fold, the path does not. */
|
|
8479
8491
|
agent_url: string;
|
|
8480
8492
|
/** @description `effective` (default) applies override layer; `raw` reads base table. */
|
|
8481
8493
|
include?: "raw" | "effective";
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
"source_sha": "4e553ad955f83b49c7d221ab5c3ff78237ad02e3",
|
|
5
5
|
"source_tarball_sha256": "580656d6466ef9f0d1119985e6726c2efea718dc671e2ad30957fcb2fd54af0f",
|
|
6
6
|
"upstream_adcp_version": "2.5.3",
|
|
7
|
-
"synced_at": "2026-10-
|
|
7
|
+
"synced_at": "2026-10-19T00:55:30.097Z"
|
|
8
8
|
}
|