@adcp/sdk 14.0.0-beta.27 → 14.0.0-beta.28
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 +5 -1
- package/dist/lib/core/AgentClient.d.ts +5 -1
- package/dist/lib/core/SingleAgentClient.js +2 -0
- package/dist/lib/core/SingleAgentClient.mjs +2 -0
- package/dist/lib/index.d.mts +1 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.mjs +1 -0
- package/dist/lib/reporting/evidence.d.mts +4 -0
- package/dist/lib/reporting/evidence.d.ts +4 -0
- package/dist/lib/reporting/evidence.js +136 -0
- package/dist/lib/reporting/evidence.mjs +109 -0
- package/dist/lib/reporting/index.d.mts +4 -0
- package/dist/lib/reporting/index.d.ts +4 -0
- package/dist/lib/reporting/index.js +45 -0
- package/dist/lib/reporting/index.mjs +24 -0
- package/dist/lib/reporting/inspection.d.mts +88 -0
- package/dist/lib/reporting/inspection.d.ts +88 -0
- package/dist/lib/reporting/inspection.js +1125 -0
- package/dist/lib/reporting/inspection.mjs +1094 -0
- package/dist/lib/reporting/reconciliation.d.mts +199 -0
- package/dist/lib/reporting/reconciliation.d.ts +199 -0
- package/dist/lib/reporting/reconciliation.js +870 -0
- package/dist/lib/reporting/reconciliation.mjs +844 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.js +1 -0
- package/dist/lib/server/decisioning/runtime/protocol-for-tool.mjs +1 -0
- package/dist/lib/server/wire-spec-fields.generated.d.mts +11 -1
- package/dist/lib/server/wire-spec-fields.generated.d.ts +11 -1
- package/dist/lib/server/wire-spec-fields.generated.js +10 -0
- package/dist/lib/server/wire-spec-fields.generated.mjs +10 -0
- package/dist/lib/testing/storyboard/runner.js +13 -2
- package/dist/lib/testing/storyboard/runner.mjs +13 -2
- package/dist/lib/testing/storyboard/types.d.mts +8 -0
- package/dist/lib/testing/storyboard/types.d.ts +8 -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/index.d.mts +1 -0
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/schemas.generated.js +29 -2
- package/dist/lib/types/schemas.generated.mjs +29 -2
- package/dist/lib/utils/reporting-status-response.d.mts +2 -0
- package/dist/lib/utils/reporting-status-response.d.ts +2 -0
- package/dist/lib/utils/reporting-status-response.js +338 -0
- package/dist/lib/utils/reporting-status-response.mjs +319 -0
- package/dist/lib/utils/response-schemas.js +6 -1
- package/dist/lib/utils/response-schemas.mjs +6 -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 +1 -1
- package/docs/guides/REPORTING-RECONCILIATION.md +107 -0
- package/docs/llms.txt +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
isReportingCanonicalDigest,
|
|
4
|
+
isReportingControlTotals,
|
|
5
|
+
isReportingReceiptEvidence,
|
|
6
|
+
isReportingVerificationEvidence
|
|
7
|
+
} from "../reporting/evidence.mjs";
|
|
8
|
+
import { isReportingCoverageEvidence } from "../reporting/reconciliation.mjs";
|
|
9
|
+
const SHA256_HEX = /^[A-Fa-f0-9]{64}$/;
|
|
10
|
+
function isRecord(value) {
|
|
11
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
12
|
+
}
|
|
13
|
+
function hasFields(value, fields) {
|
|
14
|
+
return fields.every((field) => value[field] !== void 0);
|
|
15
|
+
}
|
|
16
|
+
function isNonEmptyString(value) {
|
|
17
|
+
return typeof value === "string" && value.length > 0;
|
|
18
|
+
}
|
|
19
|
+
function isOffsetDateTime(value) {
|
|
20
|
+
return typeof value === "string" && value.includes("T") && /(?:Z|[+-]\d{2}:\d{2})$/.test(value) && Number.isFinite(Date.parse(value));
|
|
21
|
+
}
|
|
22
|
+
function nonnegativeInteger(value) {
|
|
23
|
+
return Number.isInteger(value) && Number(value) >= 0;
|
|
24
|
+
}
|
|
25
|
+
function stringArray(value) {
|
|
26
|
+
return Array.isArray(value) && value.every(isNonEmptyString);
|
|
27
|
+
}
|
|
28
|
+
function isReportingStatusIssue(value) {
|
|
29
|
+
if (!isRecord(value) || !hasFields(value, ["code", "severity", "responsible_party", "recommended_action"])) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return [
|
|
33
|
+
"REPORT_OVERDUE",
|
|
34
|
+
"PRODUCTION_FAILED",
|
|
35
|
+
"DELIVERY_FAILED",
|
|
36
|
+
"ACCESS_REQUIRED",
|
|
37
|
+
"CONFIGURATION_REQUIRED",
|
|
38
|
+
"REPORTING_COVERAGE_INCOMPLETE",
|
|
39
|
+
"RESOURCE_EXPIRED",
|
|
40
|
+
"READER_INCOMPATIBLE",
|
|
41
|
+
"HISTORY_UNAVAILABLE"
|
|
42
|
+
].includes(String(value.code)) && ["delayed", "action_required"].includes(String(value.severity)) && ["buyer", "seller", "provider"].includes(String(value.responsible_party)) && [
|
|
43
|
+
"wait_for_retry",
|
|
44
|
+
"contact_buyer",
|
|
45
|
+
"contact_seller",
|
|
46
|
+
"contact_provider",
|
|
47
|
+
"repair_access",
|
|
48
|
+
"update_configuration",
|
|
49
|
+
"change_reporting_scope",
|
|
50
|
+
"use_supported_reader"
|
|
51
|
+
].includes(String(value.recommended_action));
|
|
52
|
+
}
|
|
53
|
+
function isReportingSchedule(value) {
|
|
54
|
+
if (!isRecord(value)) return false;
|
|
55
|
+
const required = ["period_duration", "alignment", "delivery_sla"];
|
|
56
|
+
const optional = ["period_anchor", "period_timezone"];
|
|
57
|
+
if (!hasFields(value, required) || !Object.keys(value).every((key) => [...required, ...optional].includes(key)))
|
|
58
|
+
return false;
|
|
59
|
+
const periodDuration = /^P(?=.*[1-9])(?=\d|T)(?:\d+Y)?(?:\d+M)?(?:\d+D)?(?:T(?=\d)(?:\d+H)?(?:\d+M)?(?:\d+S)?)?$/;
|
|
60
|
+
const deliverySla = /^P(?=\d|T)(?=.*\d)(?:\d+Y)?(?:\d+M)?(?:\d+D)?(?:T(?=\d)(?:\d+H)?(?:\d+M)?(?:\d+S)?)?$/;
|
|
61
|
+
if (typeof value.period_duration !== "string" || !periodDuration.test(value.period_duration) || !["utc", "account_timezone", "billing_cycle"].includes(String(value.alignment)) || typeof value.delivery_sla !== "string" || !deliverySla.test(value.delivery_sla))
|
|
62
|
+
return false;
|
|
63
|
+
return value.alignment === "billing_cycle" ? isOffsetDateTime(value.period_anchor) && isNonEmptyString(value.period_timezone) && value.period_timezone.length <= 255 : value.period_anchor === void 0 && value.period_timezone === void 0;
|
|
64
|
+
}
|
|
65
|
+
function isReportingResource(value) {
|
|
66
|
+
if (!isRecord(value)) return false;
|
|
67
|
+
const required = ["resource_ref", "kind", "location", "immutability", "expires_at"];
|
|
68
|
+
const optional = ["native_version_ref", "manifest_version", "manifest_sha256", "reader_compatibility"];
|
|
69
|
+
if (!hasFields(value, required) || !Object.keys(value).every((key) => [...required, ...optional].includes(key)))
|
|
70
|
+
return false;
|
|
71
|
+
if (!isNonEmptyString(value.resource_ref) || value.resource_ref.length > 255 || !["manifest", "dataset", "warehouse_relation"].includes(String(value.kind)) || !isNonEmptyString(value.location) || value.location.length > 2048 || !["immutable_location", "native_version"].includes(String(value.immutability)) || !isOffsetDateTime(value.expires_at) || value.reader_compatibility !== void 0 && (!Array.isArray(value.reader_compatibility) || !value.reader_compatibility.every(isNonEmptyString) || new Set(value.reader_compatibility).size !== value.reader_compatibility.length))
|
|
72
|
+
return false;
|
|
73
|
+
if (value.kind === "manifest" && (value.manifest_version !== "1.0" || typeof value.manifest_sha256 !== "string" || !SHA256_HEX.test(value.manifest_sha256)))
|
|
74
|
+
return false;
|
|
75
|
+
return value.immutability !== "native_version" || isNonEmptyString(value.native_version_ref);
|
|
76
|
+
}
|
|
77
|
+
function isReportingMaterialization(value) {
|
|
78
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
79
|
+
"reporting_materialization_id",
|
|
80
|
+
"reporting_revision_id",
|
|
81
|
+
"reporting_obligation_id",
|
|
82
|
+
"delivery_config_id",
|
|
83
|
+
"delivery_config_version",
|
|
84
|
+
"destination_ref",
|
|
85
|
+
"feed_purpose",
|
|
86
|
+
"method",
|
|
87
|
+
"transport",
|
|
88
|
+
"attempt",
|
|
89
|
+
"status",
|
|
90
|
+
"ready_at",
|
|
91
|
+
"failed_at",
|
|
92
|
+
"failure_code",
|
|
93
|
+
"resource",
|
|
94
|
+
"verification",
|
|
95
|
+
"created_at"
|
|
96
|
+
]);
|
|
97
|
+
if (!isRecord(value) || Object.keys(value).some((key) => !allowed.has(key)) || !hasFields(value, [
|
|
98
|
+
"reporting_materialization_id",
|
|
99
|
+
"reporting_revision_id",
|
|
100
|
+
"reporting_obligation_id",
|
|
101
|
+
"delivery_config_id",
|
|
102
|
+
"delivery_config_version",
|
|
103
|
+
"destination_ref",
|
|
104
|
+
"feed_purpose",
|
|
105
|
+
"method",
|
|
106
|
+
"attempt",
|
|
107
|
+
"status",
|
|
108
|
+
"created_at"
|
|
109
|
+
])) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
if (!isNonEmptyString(value.reporting_materialization_id) || !isNonEmptyString(value.reporting_revision_id) || !isNonEmptyString(value.reporting_obligation_id) || !isNonEmptyString(value.delivery_config_id) || !Number.isSafeInteger(value.delivery_config_version) || Number(value.delivery_config_version) < 1 || !isNonEmptyString(value.destination_ref) || !["pacing", "analytics", "billing"].includes(String(value.feed_purpose)) || !["file_transfer", "dataset_share", "warehouse_materialization"].includes(String(value.method)) || value.transport !== void 0 && (typeof value.transport !== "string" || !/^[a-z][a-z0-9_.-]{0,63}$/.test(value.transport)) || !Number.isSafeInteger(value.attempt) || Number(value.attempt) < 1 || !isOffsetDateTime(value.created_at))
|
|
113
|
+
return false;
|
|
114
|
+
if (value.resource !== void 0 && !isReportingResource(value.resource) || value.verification !== void 0 && !isReportingVerificationEvidence(value.verification) || value.ready_at !== void 0 && !isOffsetDateTime(value.ready_at) || value.failed_at !== void 0 && !isOffsetDateTime(value.failed_at))
|
|
115
|
+
return false;
|
|
116
|
+
if (!["pending", "available", "delivered", "failed"].includes(String(value.status))) return false;
|
|
117
|
+
if (value.status === "failed") return isOffsetDateTime(value.failed_at) && isNonEmptyString(value.failure_code);
|
|
118
|
+
if (value.status === "pending") return true;
|
|
119
|
+
if (!isOffsetDateTime(value.ready_at) || !isReportingResource(value.resource) || !isRecord(value.verification) || !isReportingVerificationEvidence(value.verification))
|
|
120
|
+
return false;
|
|
121
|
+
const resource = value.resource;
|
|
122
|
+
const verification = value.verification;
|
|
123
|
+
if (resource.immutability === "native_version" && !isNonEmptyString(resource.native_version_ref)) return false;
|
|
124
|
+
if (value.method === "file_transfer") {
|
|
125
|
+
return resource.kind === "manifest" && resource.manifest_version === "1.0" && typeof resource.manifest_sha256 === "string" && SHA256_HEX.test(resource.manifest_sha256) && Array.isArray(verification.physical_checksums) && verification.physical_checksums.length > 0;
|
|
126
|
+
}
|
|
127
|
+
if (value.method === "dataset_share") {
|
|
128
|
+
return resource.kind === "dataset" && verification.verification_path === "representative_consumer";
|
|
129
|
+
}
|
|
130
|
+
if (value.method === "warehouse_materialization") {
|
|
131
|
+
return resource.kind === "warehouse_relation" && verification.verification_path === "destination";
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
function isReportingReceipt(value) {
|
|
136
|
+
return isReportingReceiptEvidence(value);
|
|
137
|
+
}
|
|
138
|
+
function isReportingPeriod(value) {
|
|
139
|
+
return isRecord(value) && Object.keys(value).every((key) => ["start", "end", "source_timezone"].includes(key)) && isOffsetDateTime(value.start) && isOffsetDateTime(value.end) && isNonEmptyString(value.source_timezone);
|
|
140
|
+
}
|
|
141
|
+
function isReportingObligation(value) {
|
|
142
|
+
const fields = [
|
|
143
|
+
"reporting_obligation_id",
|
|
144
|
+
"delivery_config_id",
|
|
145
|
+
"delivery_config_version",
|
|
146
|
+
"report_definition_id",
|
|
147
|
+
"feed_purpose",
|
|
148
|
+
"reporting_profile",
|
|
149
|
+
"account_id",
|
|
150
|
+
"scope_resolved_at",
|
|
151
|
+
"media_buy_ids",
|
|
152
|
+
"coverage",
|
|
153
|
+
"period",
|
|
154
|
+
"expected_at",
|
|
155
|
+
"schedule",
|
|
156
|
+
"destination_ref",
|
|
157
|
+
"required_finality",
|
|
158
|
+
"reconciliation_mode",
|
|
159
|
+
"reconciliation_status",
|
|
160
|
+
"health",
|
|
161
|
+
"production_status",
|
|
162
|
+
"revision_count",
|
|
163
|
+
"materialization_count",
|
|
164
|
+
"successful_materialization_count",
|
|
165
|
+
"receipt_count",
|
|
166
|
+
"accepted_receipt_count",
|
|
167
|
+
"issues"
|
|
168
|
+
];
|
|
169
|
+
if (!isRecord(value) || !hasFields(value, fields)) return false;
|
|
170
|
+
return isNonEmptyString(value.reporting_obligation_id) && isNonEmptyString(value.delivery_config_id) && Number.isInteger(value.delivery_config_version) && Number(value.delivery_config_version) >= 1 && isNonEmptyString(value.report_definition_id) && ["pacing", "analytics", "billing"].includes(String(value.feed_purpose)) && isNonEmptyString(value.reporting_profile) && isNonEmptyString(value.account_id) && isOffsetDateTime(value.scope_resolved_at) && stringArray(value.media_buy_ids) && isReportingCoverageEvidence(value.coverage) && isReportingPeriod(value.period) && isOffsetDateTime(value.expected_at) && isReportingSchedule(value.schedule) && isNonEmptyString(value.destination_ref) && ["snapshot", "official"].includes(String(value.required_finality)) && ["delivery_only", "consumer_receipt"].includes(String(value.reconciliation_mode)) && ["not_required", "pending", "accepted", "rejected"].includes(String(value.reconciliation_status)) && ["waiting", "healthy", "delayed", "action_required", "complete"].includes(String(value.health)) && ["not_due", "pending", "published", "failed"].includes(String(value.production_status)) && [
|
|
171
|
+
"revision_count",
|
|
172
|
+
"materialization_count",
|
|
173
|
+
"successful_materialization_count",
|
|
174
|
+
"receipt_count",
|
|
175
|
+
"accepted_receipt_count"
|
|
176
|
+
].every((field) => nonnegativeInteger(value[field])) && Array.isArray(value.issues) && value.issues.every(isReportingStatusIssue);
|
|
177
|
+
}
|
|
178
|
+
function isCanonicalDigest(value) {
|
|
179
|
+
return isReportingCanonicalDigest(value);
|
|
180
|
+
}
|
|
181
|
+
function isReportingRevision(value) {
|
|
182
|
+
const fields = [
|
|
183
|
+
"reporting_revision_id",
|
|
184
|
+
"report_definition_id",
|
|
185
|
+
"report_definition_uri",
|
|
186
|
+
"report_definition_sha256",
|
|
187
|
+
"reporting_profile",
|
|
188
|
+
"schema_version",
|
|
189
|
+
"schema_uri",
|
|
190
|
+
"schema_sha256",
|
|
191
|
+
"schema_dialect",
|
|
192
|
+
"schema_ref_policy",
|
|
193
|
+
"account_id",
|
|
194
|
+
"media_buy_ids",
|
|
195
|
+
"coverage",
|
|
196
|
+
"period",
|
|
197
|
+
"finality",
|
|
198
|
+
"observed_at",
|
|
199
|
+
"data_through",
|
|
200
|
+
"data_through_precision",
|
|
201
|
+
"row_count",
|
|
202
|
+
"control_totals",
|
|
203
|
+
"created_at"
|
|
204
|
+
];
|
|
205
|
+
if (!isRecord(value) || !hasFields(value, fields)) return false;
|
|
206
|
+
const officialFields = ["finality_basis", "finality_policy_id", "finalized_at"];
|
|
207
|
+
const official = value.finality === "official";
|
|
208
|
+
if (official !== officialFields.every((field) => value[field] !== void 0)) return false;
|
|
209
|
+
if (!official && officialFields.some((field) => value[field] !== void 0)) return false;
|
|
210
|
+
if (official && (!["source_final", "contractual_cutoff", "stabilized"].includes(String(value.finality_basis)) || !isNonEmptyString(value.finality_policy_id) || !isOffsetDateTime(value.finalized_at))) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
const precision = String(value.data_through_precision);
|
|
214
|
+
if (!["exact", "lower_bound", "unknown"].includes(precision) || (precision === "unknown" ? value.data_through !== null : !isOffsetDateTime(value.data_through))) {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
return isNonEmptyString(value.reporting_revision_id) && isNonEmptyString(value.report_definition_id) && isNonEmptyString(value.report_definition_uri) && typeof value.report_definition_sha256 === "string" && SHA256_HEX.test(value.report_definition_sha256) && isNonEmptyString(value.reporting_profile) && isNonEmptyString(value.schema_version) && isNonEmptyString(value.schema_uri) && typeof value.schema_sha256 === "string" && SHA256_HEX.test(value.schema_sha256) && value.schema_dialect === "https://json-schema.org/draft/2020-12/schema" && value.schema_ref_policy === "local_fragment_only" && isNonEmptyString(value.account_id) && stringArray(value.media_buy_ids) && isReportingCoverageEvidence(value.coverage) && isReportingPeriod(value.period) && ["snapshot", "official"].includes(String(value.finality)) && isOffsetDateTime(value.observed_at) && nonnegativeInteger(value.row_count) && isReportingControlTotals(value.control_totals) && isOffsetDateTime(value.created_at) && (value.canonical_content_digest === void 0 || isCanonicalDigest(value.canonical_content_digest));
|
|
218
|
+
}
|
|
219
|
+
const scopeKeys = [
|
|
220
|
+
"period_start",
|
|
221
|
+
"period_end",
|
|
222
|
+
"scope_closed",
|
|
223
|
+
"media_buy_ids",
|
|
224
|
+
"all_accessible_media_buys",
|
|
225
|
+
"delivery_config_generations",
|
|
226
|
+
"feed_purposes",
|
|
227
|
+
"finality",
|
|
228
|
+
"ledger_retained_from",
|
|
229
|
+
"coverage_complete"
|
|
230
|
+
];
|
|
231
|
+
function isReportingScope(value) {
|
|
232
|
+
if (!isRecord(value) || !Object.keys(value).every((key) => scopeKeys.includes(key)) || !hasFields(
|
|
233
|
+
value,
|
|
234
|
+
scopeKeys.filter((key) => key !== "media_buy_ids")
|
|
235
|
+
)) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
const generations = value.delivery_config_generations;
|
|
239
|
+
return isOffsetDateTime(value.period_start) && isOffsetDateTime(value.period_end) && typeof value.scope_closed === "boolean" && typeof value.all_accessible_media_buys === "boolean" && (value.all_accessible_media_buys || stringArray(value.media_buy_ids)) && Array.isArray(generations) && generations.every(
|
|
240
|
+
(generation) => isRecord(generation) && Object.keys(generation).every(
|
|
241
|
+
(key) => ["delivery_config_id", "delivery_config_version", "feed_purpose"].includes(key)
|
|
242
|
+
) && isNonEmptyString(generation.delivery_config_id) && Number.isInteger(generation.delivery_config_version) && Number(generation.delivery_config_version) >= 1 && ["pacing", "analytics", "billing"].includes(String(generation.feed_purpose))
|
|
243
|
+
) && Array.isArray(value.feed_purposes) && value.feed_purposes.every((item) => ["pacing", "analytics", "billing"].includes(String(item))) && Array.isArray(value.finality) && value.finality.every((item) => ["snapshot", "official"].includes(String(item))) && isOffsetDateTime(value.ledger_retained_from) && typeof value.coverage_complete === "boolean";
|
|
244
|
+
}
|
|
245
|
+
function isPagination(value) {
|
|
246
|
+
return isRecord(value) && typeof value.has_more === "boolean" && nonnegativeInteger(value.total_count);
|
|
247
|
+
}
|
|
248
|
+
function lacksFields(value, fields) {
|
|
249
|
+
return fields.every((field) => value[field] === void 0);
|
|
250
|
+
}
|
|
251
|
+
function hasCompletedCommon(value) {
|
|
252
|
+
return value.status === "completed" && isNonEmptyString(value.ledger_snapshot_id) && isOffsetDateTime(value.ledger_as_of) && isNonEmptyString(value.account_id);
|
|
253
|
+
}
|
|
254
|
+
function isSummaryResponse(value) {
|
|
255
|
+
if (!isRecord(value.obligation_counts)) return false;
|
|
256
|
+
const obligationCounts = value.obligation_counts;
|
|
257
|
+
if (!hasCompletedCommon(value) || value.view !== "summary" || !isReportingScope(value.scope) || !isReportingCoverageEvidence(value.coverage) || !(value.data_through === null || isOffsetDateTime(value.data_through)) || !lacksFields(value, ["periods", "revisions", "pagination", "revision", "materializations", "receipts"]) || !["healthy", "waiting", "delayed", "action_required", "complete"].includes(String(value.health)) || !Array.isArray(value.issues) || !value.issues.every(isReportingStatusIssue) || !["total", "waiting", "healthy", "delayed", "action_required", "complete"].every(
|
|
258
|
+
(field) => nonnegativeInteger(obligationCounts[field])
|
|
259
|
+
)) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
const health = String(value.health);
|
|
263
|
+
if (health === "complete" && (!value.scope.scope_closed || !value.scope.coverage_complete || value.next_expected_at !== void 0)) {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
if (["healthy", "waiting", "complete"].includes(health) && value.issues.length !== 0) return false;
|
|
267
|
+
if (health === "action_required" && !value.issues.some((issue) => isRecord(issue) && issue.severity === "action_required")) {
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
if (health === "delayed" && (value.issues.length === 0 || value.issues.some((issue) => !isRecord(issue) || issue.severity !== "delayed"))) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
if (!value.scope.coverage_complete && (health !== "action_required" || !value.issues.some(
|
|
274
|
+
(issue) => isRecord(issue) && issue.code === "HISTORY_UNAVAILABLE" && issue.severity === "action_required"
|
|
275
|
+
))) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
function isGetReportingStatusResponse(value) {
|
|
281
|
+
if (!isRecord(value)) return false;
|
|
282
|
+
if (value.status === "failed") {
|
|
283
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
284
|
+
"adcp_version",
|
|
285
|
+
"adcp_major_version",
|
|
286
|
+
"status",
|
|
287
|
+
"view",
|
|
288
|
+
"failure_kind",
|
|
289
|
+
"context_id",
|
|
290
|
+
"context",
|
|
291
|
+
"message",
|
|
292
|
+
"timestamp",
|
|
293
|
+
"replayed",
|
|
294
|
+
"adcp_error",
|
|
295
|
+
"errors"
|
|
296
|
+
]);
|
|
297
|
+
if (Object.keys(value).some((key) => !allowed.has(key)) || !["summary", "periods", "revision"].includes(String(value.view)) || !["lookup_unavailable", "operational"].includes(String(value.failure_kind)) || !Array.isArray(value.errors) || value.errors.length === 0 || !value.errors.every((error) => isRecord(error) && isNonEmptyString(error.code) && isNonEmptyString(error.message)))
|
|
298
|
+
return false;
|
|
299
|
+
if (value.failure_kind === "lookup_unavailable") {
|
|
300
|
+
return value.errors.length === 1 && Object.keys(value.errors[0]).every((key) => ["code", "message"].includes(key)) && value.errors[0].code === "NOT_FOUND" && value.errors[0].message === "Reporting status resource is unavailable." && (value.message === void 0 || value.message === "Reporting status resource is unavailable.") && (value.adcp_error === void 0 || isRecord(value.adcp_error) && Object.keys(value.adcp_error).every((key) => ["code", "message"].includes(key)) && value.adcp_error.code === "NOT_FOUND" && value.adcp_error.message === "Reporting status resource is unavailable.");
|
|
301
|
+
}
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
if (value.status !== "completed") return false;
|
|
305
|
+
if (value.view === "summary") return isSummaryResponse(value);
|
|
306
|
+
if (value.view === "periods") {
|
|
307
|
+
return hasCompletedCommon(value) && isReportingScope(value.scope) && Array.isArray(value.periods) && value.periods.every(isReportingObligation) && Array.isArray(value.revisions) && value.revisions.every(isReportingRevision) && Array.isArray(value.materializations) && value.materializations.every(isReportingMaterialization) && Array.isArray(value.receipts) && value.receipts.every(isReportingReceipt) && isPagination(value.pagination) && lacksFields(value, ["revision"]);
|
|
308
|
+
}
|
|
309
|
+
if (value.view === "revision") {
|
|
310
|
+
return hasCompletedCommon(value) && isReportingRevision(value.revision) && Array.isArray(value.materializations) && value.materializations.every(isReportingMaterialization) && Array.isArray(value.receipts) && value.receipts.every(isReportingReceipt) && isPagination(value.pagination) && lacksFields(value, ["scope", "health", "periods", "revisions"]);
|
|
311
|
+
}
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
const GetReportingStatusResponseCurrentSchema = z.custom(isGetReportingStatusResponse, {
|
|
315
|
+
message: "get_reporting_status response does not satisfy the current reporting protocol"
|
|
316
|
+
});
|
|
317
|
+
export {
|
|
318
|
+
GetReportingStatusResponseCurrentSchema
|
|
319
|
+
};
|
|
@@ -36,6 +36,7 @@ var import_zod = require("zod");
|
|
|
36
36
|
var schemas = __toESM(require('../types/schemas.generated.js'));
|
|
37
37
|
var import_sync_creatives = require('../validation/sync-creatives.js');
|
|
38
38
|
var import_adcp_version_config = require('./adcp-version-config.js');
|
|
39
|
+
var import_reporting_status_response = require('./reporting-status-response.js');
|
|
39
40
|
var import_version = require('../version.js');
|
|
40
41
|
function declaresLegacy30xPayload(response) {
|
|
41
42
|
const adcpVersion = response.adcp_version;
|
|
@@ -81,7 +82,11 @@ const TOOL_RESPONSE_SCHEMAS = {
|
|
|
81
82
|
update_media_buy: schemas.UpdateMediaBuyResponseSchema,
|
|
82
83
|
get_media_buys: schemas.GetMediaBuysResponseSchema,
|
|
83
84
|
get_media_buy_delivery: schemas.GetMediaBuyDeliveryResponseSchema,
|
|
84
|
-
|
|
85
|
+
// The generated Zod schema does not retain every composed `allOf`
|
|
86
|
+
// requirement or nested `additionalProperties: false` boundary from the
|
|
87
|
+
// signed protocol schema. Preserve the stricter billing-evidence validator
|
|
88
|
+
// until code generation represents those constraints directly.
|
|
89
|
+
get_reporting_status: import_reporting_status_response.GetReportingStatusResponseCurrentSchema,
|
|
85
90
|
sync_reporting_receipts: schemas.SyncReportingReceiptsResponseSchema,
|
|
86
91
|
provide_performance_feedback: schemas.ProvidePerformanceFeedbackResponseSchema,
|
|
87
92
|
// Creative
|
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
import * as schemas from "../types/schemas.generated.mjs";
|
|
3
3
|
import { SyncCreativesResponseStrictSchema } from "../validation/sync-creatives.mjs";
|
|
4
4
|
import { isPre31AdcpVersion } from "./adcp-version-config.mjs";
|
|
5
|
+
import { GetReportingStatusResponseCurrentSchema } from "./reporting-status-response.mjs";
|
|
5
6
|
import { toReleasePrecisionVersion } from "../version.mjs";
|
|
6
7
|
function declaresLegacy30xPayload(response) {
|
|
7
8
|
const adcpVersion = response.adcp_version;
|
|
@@ -47,7 +48,11 @@ const TOOL_RESPONSE_SCHEMAS = {
|
|
|
47
48
|
update_media_buy: schemas.UpdateMediaBuyResponseSchema,
|
|
48
49
|
get_media_buys: schemas.GetMediaBuysResponseSchema,
|
|
49
50
|
get_media_buy_delivery: schemas.GetMediaBuyDeliveryResponseSchema,
|
|
50
|
-
|
|
51
|
+
// The generated Zod schema does not retain every composed `allOf`
|
|
52
|
+
// requirement or nested `additionalProperties: false` boundary from the
|
|
53
|
+
// signed protocol schema. Preserve the stricter billing-evidence validator
|
|
54
|
+
// until code generation represents those constraints directly.
|
|
55
|
+
get_reporting_status: GetReportingStatusResponseCurrentSchema,
|
|
51
56
|
sync_reporting_receipts: schemas.SyncReportingReceiptsResponseSchema,
|
|
52
57
|
provide_performance_feedback: schemas.ProvidePerformanceFeedbackResponseSchema,
|
|
53
58
|
// Creative
|
package/dist/lib/version.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AdCP SDK library version
|
|
3
3
|
*/
|
|
4
|
-
export declare const LIBRARY_VERSION = "14.0.0-beta.
|
|
4
|
+
export declare const LIBRARY_VERSION = "14.0.0-beta.28";
|
|
5
5
|
/**
|
|
6
6
|
* AdCP specification version this library is built for
|
|
7
7
|
*/
|
|
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
|
|
|
33
33
|
* Full version information
|
|
34
34
|
*/
|
|
35
35
|
export declare const VERSION_INFO: {
|
|
36
|
-
readonly library: "14.0.0-beta.
|
|
36
|
+
readonly library: "14.0.0-beta.28";
|
|
37
37
|
readonly adcp: "3.2.0-beta.10";
|
|
38
38
|
readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0-beta.1", "3.0-beta.1", "3.0-beta", "3.0.0-beta.3", "3.0-beta.3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.2.0-beta.10", "3.2-beta.10"];
|
|
39
|
-
readonly generatedAt: "2026-09-
|
|
39
|
+
readonly generatedAt: "2026-09-02T09:57:23.680Z";
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Get the AdCP specification version this library is built for
|
package/dist/lib/version.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AdCP SDK library version
|
|
3
3
|
*/
|
|
4
|
-
export declare const LIBRARY_VERSION = "14.0.0-beta.
|
|
4
|
+
export declare const LIBRARY_VERSION = "14.0.0-beta.28";
|
|
5
5
|
/**
|
|
6
6
|
* AdCP specification version this library is built for
|
|
7
7
|
*/
|
|
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
|
|
|
33
33
|
* Full version information
|
|
34
34
|
*/
|
|
35
35
|
export declare const VERSION_INFO: {
|
|
36
|
-
readonly library: "14.0.0-beta.
|
|
36
|
+
readonly library: "14.0.0-beta.28";
|
|
37
37
|
readonly adcp: "3.2.0-beta.10";
|
|
38
38
|
readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0-beta.1", "3.0-beta.1", "3.0-beta", "3.0.0-beta.3", "3.0-beta.3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.2.0-beta.10", "3.2-beta.10"];
|
|
39
|
-
readonly generatedAt: "2026-09-
|
|
39
|
+
readonly generatedAt: "2026-09-02T09:57:23.680Z";
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Get the AdCP specification version this library is built for
|
package/dist/lib/version.js
CHANGED
|
@@ -31,7 +31,7 @@ __export(version_exports, {
|
|
|
31
31
|
toReleasePrecisionVersion: () => toReleasePrecisionVersion
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(version_exports);
|
|
34
|
-
const LIBRARY_VERSION = "14.0.0-beta.
|
|
34
|
+
const LIBRARY_VERSION = "14.0.0-beta.28";
|
|
35
35
|
const ADCP_VERSION = "3.2.0-beta.10";
|
|
36
36
|
const ADCP_MAJOR_VERSION = 3;
|
|
37
37
|
const COMPATIBLE_ADCP_VERSIONS = [
|
|
@@ -94,10 +94,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
|
|
|
94
94
|
"3.2-beta.10"
|
|
95
95
|
];
|
|
96
96
|
const VERSION_INFO = {
|
|
97
|
-
library: "14.0.0-beta.
|
|
97
|
+
library: "14.0.0-beta.28",
|
|
98
98
|
adcp: "3.2.0-beta.10",
|
|
99
99
|
compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
|
|
100
|
-
generatedAt: "2026-09-
|
|
100
|
+
generatedAt: "2026-09-02T09:57:23.680Z"
|
|
101
101
|
};
|
|
102
102
|
function getAdcpVersion() {
|
|
103
103
|
return ADCP_VERSION;
|
package/dist/lib/version.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const LIBRARY_VERSION = "14.0.0-beta.
|
|
1
|
+
const LIBRARY_VERSION = "14.0.0-beta.28";
|
|
2
2
|
const ADCP_VERSION = "3.2.0-beta.10";
|
|
3
3
|
const ADCP_MAJOR_VERSION = 3;
|
|
4
4
|
const COMPATIBLE_ADCP_VERSIONS = [
|
|
@@ -61,10 +61,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
|
|
|
61
61
|
"3.2-beta.10"
|
|
62
62
|
];
|
|
63
63
|
const VERSION_INFO = {
|
|
64
|
-
library: "14.0.0-beta.
|
|
64
|
+
library: "14.0.0-beta.28",
|
|
65
65
|
adcp: "3.2.0-beta.10",
|
|
66
66
|
compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
|
|
67
|
-
generatedAt: "2026-09-
|
|
67
|
+
generatedAt: "2026-09-02T09:57:23.680Z"
|
|
68
68
|
};
|
|
69
69
|
function getAdcpVersion() {
|
|
70
70
|
return ADCP_VERSION;
|
package/docs/TYPE-SUMMARY.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AdCP Type Summary
|
|
2
2
|
|
|
3
3
|
> Generated at: 2026-09-02
|
|
4
|
-
> @adcp/sdk v14.0.0-beta.
|
|
4
|
+
> @adcp/sdk v14.0.0-beta.28
|
|
5
5
|
|
|
6
6
|
Curated reference of the types that matter for using the AdCP client. For full generated types see `src/lib/types/tools.generated.ts` and `src/lib/types/core.generated.ts`.
|
|
7
7
|
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Reporting reconciliation
|
|
2
|
+
|
|
3
|
+
`reconcileReporting` turns the reporting ledger into a buyer-verifiable result. It reads one stable ledger snapshot, checks the expected period set, inspects each current destination materialization, submits any required consumer receipts, and then reads the seller's ledger back before returning.
|
|
4
|
+
|
|
5
|
+
The helper only returns `definitive: true` when all of these conditions hold:
|
|
6
|
+
|
|
7
|
+
- the buyer supplies its own complete `expectedPeriods` denominator;
|
|
8
|
+
- the seller closes the requested scope and declares its coverage complete;
|
|
9
|
+
- every expected report definition, feed, reporting profile, campaign set, and period has an obligation;
|
|
10
|
+
- every obligation's history counts match the returned immutable records;
|
|
11
|
+
- the current revision has the required finality;
|
|
12
|
+
- a verified, unexpired materialization matches the obligation;
|
|
13
|
+
- every consumer-receipt obligation has an accepted receipt for the same revision, materialization, row count, control totals, and required verification evidence.
|
|
14
|
+
|
|
15
|
+
An omitted expected-period denominator can still diagnose delivery, but can never prove completeness. Pass `[]` only when the buyer independently knows that no periods are expected in the requested scope.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import {
|
|
19
|
+
createHttpsReportingResourceReader,
|
|
20
|
+
reconcileReporting,
|
|
21
|
+
} from '@adcp/sdk';
|
|
22
|
+
|
|
23
|
+
const result = await reconcileReporting({
|
|
24
|
+
client: seller,
|
|
25
|
+
request: {
|
|
26
|
+
account: { account_id: 'account-1' },
|
|
27
|
+
period: {
|
|
28
|
+
start: '2026-08-01T00:00:00Z',
|
|
29
|
+
end: '2026-09-01T00:00:00Z',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
expectedPeriods: [{
|
|
33
|
+
deliveryConfigId: 'billing-feed',
|
|
34
|
+
deliveryConfigVersion: 3,
|
|
35
|
+
reportDefinitionId: 'billing-v1',
|
|
36
|
+
feedPurpose: 'billing',
|
|
37
|
+
reportingProfile: 'billing-v1',
|
|
38
|
+
mediaBuyIds: ['buy-1', 'buy-2'],
|
|
39
|
+
destinationRef: 'destination-billing-v3',
|
|
40
|
+
deliveryMethod: 'file_transfer',
|
|
41
|
+
requiredFinality: 'official',
|
|
42
|
+
reconciliationMode: 'consumer_receipt',
|
|
43
|
+
coverageRequirement: 'full',
|
|
44
|
+
coverage: {
|
|
45
|
+
status: 'full',
|
|
46
|
+
media_buy_ids: ['buy-1', 'buy-2'],
|
|
47
|
+
fully_covered_media_buy_ids: ['buy-1', 'buy-2'],
|
|
48
|
+
partially_covered_media_buy_ids: [],
|
|
49
|
+
unsupported_media_buy_ids: [],
|
|
50
|
+
unknown_media_buy_ids: [],
|
|
51
|
+
package_ids: ['package-1', 'package-2'],
|
|
52
|
+
covered_package_ids: ['package-1', 'package-2'],
|
|
53
|
+
unsupported_package_ids: [],
|
|
54
|
+
unknown_package_ids: [],
|
|
55
|
+
},
|
|
56
|
+
reportDefinitionUri: 'https://schemas.seller.example/report-definitions/billing-v1.json',
|
|
57
|
+
reportDefinitionSha256: savedBillingDefinitionSha256,
|
|
58
|
+
schemaVersion: '1',
|
|
59
|
+
schemaUri: 'https://schemas.seller.example/reporting/billing-v1.json',
|
|
60
|
+
schemaSha256: savedBillingSchemaSha256,
|
|
61
|
+
schemaDialect: 'https://json-schema.org/draft/2020-12/schema',
|
|
62
|
+
schemaRefPolicy: 'local_fragment_only',
|
|
63
|
+
officialFinality: {
|
|
64
|
+
policyId: 'billing-close-v1',
|
|
65
|
+
basis: 'contractual_cutoff',
|
|
66
|
+
},
|
|
67
|
+
verificationProfile: 'canonical_digest',
|
|
68
|
+
canonicalization: {
|
|
69
|
+
id: 'billing-rows-v1',
|
|
70
|
+
uri: 'https://schemas.seller.example/canonicalization/billing-rows-v1.json',
|
|
71
|
+
sha256: savedCanonicalizationSha256,
|
|
72
|
+
primaryKeys: ['media_buy_id', 'date'],
|
|
73
|
+
},
|
|
74
|
+
periodStart: '2026-08-01T00:00:00Z',
|
|
75
|
+
periodEnd: '2026-09-01T00:00:00Z',
|
|
76
|
+
}],
|
|
77
|
+
resourceReader: createHttpsReportingResourceReader(),
|
|
78
|
+
credentialProvider: {
|
|
79
|
+
async getCredentials({ obligation }) {
|
|
80
|
+
const destination = await loadSavedDestination(obligation.destination_ref);
|
|
81
|
+
return {
|
|
82
|
+
headers: {
|
|
83
|
+
authorization: `Bearer ${await destinationToken(obligation.destination_ref)}`,
|
|
84
|
+
},
|
|
85
|
+
allowedOrigins: [destination.readerOrigin],
|
|
86
|
+
};
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
manifestInspectorOptions: {
|
|
90
|
+
referenceAllowedOrigins: ['https://schemas.seller.example'],
|
|
91
|
+
consumerCommitRef: 'buyer-reporting-ledger:2026-08',
|
|
92
|
+
maxInspectionMs: 60_000,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (!result.definitive) {
|
|
97
|
+
throw new Error('Reporting is not ready for billing');
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
When `inspect` is omitted, `resourceReader` enables the built-in manifest path. It verifies the exact manifest bytes before parsing, manifest identity and completeness, every object size and SHA-256, declared compression and format, the pinned row schema and report definition, row count and control totals, and the pinned RFC 8785 canonical-content contract. The bundled decoders cover JSONL and CSV with `none` or `gzip` compression. Configure format/compression decoders for Parquet, Avro, ORC, Zstandard, or Snappy. The aggregate inspection deadline covers credential lookup, reads, reference resolution, custom adapters, validation, and canonicalization.
|
|
102
|
+
|
|
103
|
+
The HTTPS reader applies the SDK's DNS-pinned SSRF controls, refuses redirects and cross-origin `object_ref` values, and accepts short-lived headers only through the credential provider. `allowedOrigins` must come from the consumer's saved destination configuration; the reader refuses to send credentials to an origin named only by the seller's resource descriptor. For S3, GCS, or Azure, implement `ReportingResourceReader`; it receives the destination-bound context and opaque credentials without placing either in the ledger or receipt. Complex control totals can supply `controlTotalCalculator`; the default handles only report-definition metrics whose declared aggregation is `sum` and whose `source_expression` resolves to numeric row values.
|
|
104
|
+
|
|
105
|
+
Keep `inspect` as the advanced override for native snapshots. A BigQuery adapter can inspect a table version, while Snowflake or Databricks adapters can verify a shared relation. `ReportingInspectionError.retryable` distinguishes transport/readiness failures from permanent digest, schema, or integrity failures, so permanent failures are never retried. Store receipts in a durable `checkpointStore` so a process restart does not repeat destination work. Set `checkpointScope` to a stable, non-secret seller-and-authenticated-principal identifier; checkpoint keys also include account, obligation, revision, materialization, and destination. The checkpoint preserves the receipt-write idempotency key across uncertain retries.
|
|
106
|
+
|
|
107
|
+
Totals are returned once per canonical reporting revision. Each entry includes its coverage status and covered/package denominators, so partial evidence cannot be mistaken for full billing totals. Delivering the same revision to a buyer, governance agent, and archive destination does not multiply its rows or financial control totals. Each consumer still authenticates independently and submits its own receipt; one consumer's acceptance never implies another's.
|
package/docs/llms.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Ad Context Protocol (AdCP)
|
|
2
2
|
|
|
3
3
|
> Generated at: 2026-09-02
|
|
4
|
-
> Library: @adcp/sdk v14.0.0-beta.
|
|
4
|
+
> Library: @adcp/sdk v14.0.0-beta.28
|
|
5
5
|
> AdCP major version: 3
|
|
6
6
|
> Canonical URL: https://adcontextprotocol.github.io/adcp-client/llms.txt
|
|
7
7
|
> Note: the `Library` stamp reflects the package.json version at doc-generation time. The narrative below describes the surface that lands on the next-published minor — including any 6.7 helpers documented here ahead of the release tag.
|