@adcp/sdk 15.0.0 → 15.2.0

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.
Files changed (142) hide show
  1. package/bin/adcp-grade.js +46 -2
  2. package/bin/adcp.js +7 -2
  3. package/dist/lib/canonical-references/index.d.mts +19 -1
  4. package/dist/lib/canonical-references/index.d.ts +19 -1
  5. package/dist/lib/canonical-references/index.js +81 -9
  6. package/dist/lib/canonical-references/index.mjs +80 -9
  7. package/dist/lib/client/core.d.mts +1 -0
  8. package/dist/lib/client/core.d.ts +1 -0
  9. package/dist/lib/core/AgentClient.d.mts +9 -1
  10. package/dist/lib/core/AgentClient.d.ts +9 -1
  11. package/dist/lib/core/AgentClient.js +10 -0
  12. package/dist/lib/core/AgentClient.mjs +10 -0
  13. package/dist/lib/core/SingleAgentClient.d.mts +13 -2
  14. package/dist/lib/core/SingleAgentClient.d.ts +13 -2
  15. package/dist/lib/core/SingleAgentClient.js +23 -5
  16. package/dist/lib/core/SingleAgentClient.mjs +23 -5
  17. package/dist/lib/index.d.mts +1 -1
  18. package/dist/lib/index.d.ts +1 -1
  19. package/dist/lib/reporting/gcs/adapter.d.mts +31 -0
  20. package/dist/lib/reporting/gcs/adapter.d.ts +31 -0
  21. package/dist/lib/reporting/gcs/adapter.js +342 -0
  22. package/dist/lib/reporting/gcs/adapter.mjs +325 -0
  23. package/dist/lib/reporting/gcs/bucket-policy.d.mts +3 -0
  24. package/dist/lib/reporting/gcs/bucket-policy.d.ts +3 -0
  25. package/dist/lib/reporting/gcs/bucket-policy.js +31 -0
  26. package/dist/lib/reporting/gcs/bucket-policy.mjs +7 -0
  27. package/dist/lib/reporting/gcs/errors.d.mts +5 -0
  28. package/dist/lib/reporting/gcs/errors.d.ts +5 -0
  29. package/dist/lib/reporting/gcs/errors.js +41 -0
  30. package/dist/lib/reporting/gcs/errors.mjs +16 -0
  31. package/dist/lib/reporting/gcs/fence.d.mts +36 -0
  32. package/dist/lib/reporting/gcs/fence.d.ts +36 -0
  33. package/dist/lib/reporting/gcs/fence.js +250 -0
  34. package/dist/lib/reporting/gcs/fence.mjs +230 -0
  35. package/dist/lib/reporting/gcs/index.d.mts +7 -0
  36. package/dist/lib/reporting/gcs/index.d.ts +7 -0
  37. package/dist/lib/reporting/gcs/index.js +41 -0
  38. package/dist/lib/reporting/gcs/index.mjs +12 -0
  39. package/dist/lib/reporting/gcs/io.d.mts +7 -0
  40. package/dist/lib/reporting/gcs/io.d.ts +7 -0
  41. package/dist/lib/reporting/gcs/io.js +95 -0
  42. package/dist/lib/reporting/gcs/io.mjs +69 -0
  43. package/dist/lib/reporting/gcs/reader.d.mts +43 -0
  44. package/dist/lib/reporting/gcs/reader.d.ts +43 -0
  45. package/dist/lib/reporting/gcs/reader.js +193 -0
  46. package/dist/lib/reporting/gcs/reader.mjs +169 -0
  47. package/dist/lib/reporting/gcs/validation.d.mts +5 -0
  48. package/dist/lib/reporting/gcs/validation.d.ts +5 -0
  49. package/dist/lib/reporting/gcs/validation.js +49 -0
  50. package/dist/lib/reporting/gcs/validation.mjs +25 -0
  51. package/dist/lib/reporting/ledger/handler.d.mts +1 -0
  52. package/dist/lib/reporting/ledger/handler.d.ts +1 -0
  53. package/dist/lib/reporting/ledger/index.d.mts +1 -0
  54. package/dist/lib/reporting/ledger/index.d.ts +1 -0
  55. package/dist/lib/reporting/ledger/index.js +2 -0
  56. package/dist/lib/reporting/ledger/index.mjs +1 -0
  57. package/dist/lib/reporting/ledger/managed-postgres.d.mts +16 -1
  58. package/dist/lib/reporting/ledger/managed-postgres.d.ts +16 -1
  59. package/dist/lib/reporting/ledger/managed-postgres.js +243 -2
  60. package/dist/lib/reporting/ledger/managed-postgres.mjs +248 -2
  61. package/dist/lib/reporting/ledger/object-writes.d.mts +69 -0
  62. package/dist/lib/reporting/ledger/object-writes.d.ts +69 -0
  63. package/dist/lib/reporting/ledger/object-writes.js +147 -0
  64. package/dist/lib/reporting/ledger/object-writes.mjs +114 -0
  65. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  66. package/dist/lib/server/a2a-adapter.d.mts +50 -1
  67. package/dist/lib/server/a2a-adapter.d.ts +50 -1
  68. package/dist/lib/server/a2a-adapter.js +230 -7
  69. package/dist/lib/server/a2a-adapter.mjs +237 -7
  70. package/dist/lib/server/auth-signature.d.mts +84 -46
  71. package/dist/lib/server/auth-signature.d.ts +84 -46
  72. package/dist/lib/server/auth-signature.js +48 -14
  73. package/dist/lib/server/auth-signature.mjs +58 -15
  74. package/dist/lib/server/create-adcp-server.js +5 -16
  75. package/dist/lib/server/create-adcp-server.mjs +5 -16
  76. package/dist/lib/server/index.d.mts +1 -1
  77. package/dist/lib/server/index.d.ts +1 -1
  78. package/dist/lib/server/index.js +2 -0
  79. package/dist/lib/server/index.mjs +3 -1
  80. package/dist/lib/signing/agent-fetch.js +3 -33
  81. package/dist/lib/signing/agent-fetch.mjs +3 -33
  82. package/dist/lib/signing/middleware.d.mts +9 -1
  83. package/dist/lib/signing/middleware.d.ts +9 -1
  84. package/dist/lib/signing/operation-resolution.d.mts +37 -0
  85. package/dist/lib/signing/operation-resolution.d.ts +37 -0
  86. package/dist/lib/signing/operation-resolution.js +154 -0
  87. package/dist/lib/signing/operation-resolution.mjs +125 -0
  88. package/dist/lib/signing/postgres-replay-store.d.mts +1 -1
  89. package/dist/lib/signing/postgres-replay-store.d.ts +1 -1
  90. package/dist/lib/signing/redis-replay-store.d.mts +1 -1
  91. package/dist/lib/signing/redis-replay-store.d.ts +1 -1
  92. package/dist/lib/signing/server.d.mts +1 -0
  93. package/dist/lib/signing/server.d.ts +1 -0
  94. package/dist/lib/signing/server.js +7 -0
  95. package/dist/lib/signing/server.mjs +8 -0
  96. package/dist/lib/signing/verifier.d.mts +36 -1
  97. package/dist/lib/signing/verifier.d.ts +36 -1
  98. package/dist/lib/signing/verifier.js +66 -34
  99. package/dist/lib/signing/verifier.mjs +61 -34
  100. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.mts +12 -0
  101. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.d.ts +12 -0
  102. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.js +29 -2
  103. package/dist/lib/testing/storyboard/request-signing/a2a-dispatch.mjs +27 -1
  104. package/dist/lib/testing/storyboard/request-signing/a2a-operation-resolution.d.mts +61 -0
  105. package/dist/lib/testing/storyboard/request-signing/a2a-operation-resolution.d.ts +61 -0
  106. package/dist/lib/testing/storyboard/request-signing/a2a-operation-resolution.js +298 -0
  107. package/dist/lib/testing/storyboard/request-signing/a2a-operation-resolution.mjs +276 -0
  108. package/dist/lib/testing/storyboard/request-signing/grader.d.mts +31 -1
  109. package/dist/lib/testing/storyboard/request-signing/grader.d.ts +31 -1
  110. package/dist/lib/testing/storyboard/request-signing/grader.js +11 -0
  111. package/dist/lib/testing/storyboard/request-signing/grader.mjs +11 -0
  112. package/dist/lib/testing/storyboard/request-signing/index.d.mts +5 -4
  113. package/dist/lib/testing/storyboard/request-signing/index.d.ts +5 -4
  114. package/dist/lib/testing/storyboard/request-signing/index.js +13 -0
  115. package/dist/lib/testing/storyboard/request-signing/index.mjs +18 -2
  116. package/dist/lib/testing/storyboard/request-signing/types.d.mts +43 -0
  117. package/dist/lib/testing/storyboard/request-signing/types.d.ts +43 -0
  118. package/dist/lib/testing/storyboard/request-signing/types.js +3 -0
  119. package/dist/lib/testing/storyboard/request-signing/types.mjs +2 -0
  120. package/dist/lib/testing/storyboard/request-signing/vector-loader.d.mts +42 -1
  121. package/dist/lib/testing/storyboard/request-signing/vector-loader.d.ts +42 -1
  122. package/dist/lib/testing/storyboard/request-signing/vector-loader.js +100 -1
  123. package/dist/lib/testing/storyboard/request-signing/vector-loader.mjs +104 -3
  124. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  125. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  126. package/dist/lib/version.d.mts +3 -3
  127. package/dist/lib/version.d.ts +3 -3
  128. package/dist/lib/version.js +3 -3
  129. package/dist/lib/version.mjs +3 -3
  130. package/docs/TYPE-SUMMARY.md +2 -2
  131. package/docs/guides/BUILD-AN-AGENT.md +9 -4
  132. package/docs/guides/CREATIVE-DELIVERY.md +34 -0
  133. package/docs/guides/REPORTING-GCS-FENCE.md +52 -0
  134. package/docs/guides/REPORTING-GCS-MANAGED.md +56 -0
  135. package/docs/guides/REPORTING-OPERATIONS.md +4 -0
  136. package/docs/guides/SIGNING-GUIDE.md +20 -6
  137. package/docs/guides/VALIDATE-YOUR-AGENT.md +4 -0
  138. package/docs/llms.txt +2 -2
  139. package/docs/migration-14.x-rc-worksheet.md +5 -4
  140. package/docs/migration-buyer-agent-registry.md +1 -1
  141. package/package.json +19 -1
  142. package/skills/build-seller-agent/specialisms/signed-requests.md +2 -0
@@ -0,0 +1,325 @@
1
+ import { createHash } from "node:crypto";
2
+ import { canonicalize } from "../../utils/jcs.mjs";
3
+ import { createReportingManifestInspector } from "../inspection.mjs";
4
+ import { createReportingStatusHandler } from "../ledger/handler.mjs";
5
+ import {
6
+ reportingObjectWriteName,
7
+ reportingObjectWriteScopeKey
8
+ } from "../ledger/object-writes.mjs";
9
+ import { createGcsReportingObjectFenceV1 } from "./fence.mjs";
10
+ import { ReportingGcsFenceError } from "./errors.mjs";
11
+ import { activeGcsSignal, withGcsDeadline } from "./io.mjs";
12
+ import { assertExpectedBinding } from "./validation.mjs";
13
+ import {
14
+ createGcsReportingResourceReaderV1,
15
+ createGcsReportingReferenceResolverV1,
16
+ createGcsScopedObjectReadV1
17
+ } from "./reader.mjs";
18
+ const hash = (bytes) => createHash("sha256").update(bytes).digest("hex");
19
+ const scopeFor = (binding) => ({
20
+ account_id: binding.account_id,
21
+ destination_ref: binding.destination_ref,
22
+ generation: binding.authorization_generation
23
+ });
24
+ function deliveryIdentity(input) {
25
+ return hash(
26
+ canonicalize([
27
+ input.binding.configurationId,
28
+ input.binding.delivery_config_id,
29
+ input.binding.delivery_config_version,
30
+ input.materialization.reporting_materialization_id,
31
+ input.materialization.reporting_revision_id,
32
+ input.materialization.reporting_obligation_id
33
+ ])
34
+ );
35
+ }
36
+ function matchingBinding(input) {
37
+ const { materialization: m, binding: b } = input;
38
+ if (b.method !== "file_transfer" || b.transport !== "gcs" || m.method !== b.method || m.transport !== b.transport || m.destination_ref !== b.destination_ref || m.delivery_config_id !== b.delivery_config_id || m.delivery_config_version !== b.delivery_config_version || m.feed_purpose !== b.feed_purpose || !["manifest_checksums", "canonical_digest"].includes(b.verification_profile) || !Number.isSafeInteger(b.resource_retention_days) || b.resource_retention_days < 1 || b.resource_retention_days > 3650)
39
+ throw new ReportingGcsFenceError("INVALID_INPUT");
40
+ }
41
+ async function createGcsReportingManagedDeliveryAdapterV1(options, context = {}) {
42
+ const milliseconds = options.operationDeadlineMilliseconds ?? 6e4;
43
+ const { resolveExpectedPeriod, resolveContractReader, namespace: hostNamespace } = options;
44
+ const minimumDays = options.minimumResourceRetentionDays ?? 1;
45
+ if (options.acknowledgeDedicatedFreshBucket !== true || typeof hostNamespace !== "string" || hostNamespace.length < 1 || hostNamespace.length > 255 || !Number.isSafeInteger(minimumDays) || minimumDays < 1 || minimumDays > 3650 || typeof options.resolveExpectedPeriod !== "function" || typeof options.resolveContractReader !== "function")
46
+ throw new ReportingGcsFenceError("INVALID_INPUT");
47
+ const { storage, coreStore, store, bucket } = options;
48
+ const { id, fence } = await withGcsDeadline(
49
+ async (signal) => {
50
+ if (await store.probeObjectWriteAuthority({ signal }) !== true)
51
+ throw new ReportingGcsFenceError("STATE_UNAVAILABLE");
52
+ activeGcsSignal(signal);
53
+ if (await store.probe(coreStore) !== true) throw new ReportingGcsFenceError("STATE_UNAVAILABLE");
54
+ activeGcsSignal(signal);
55
+ const id2 = await store.getObjectWriteAuthorityId({ signal });
56
+ activeGcsSignal(signal);
57
+ const fence2 = createGcsReportingObjectFenceV1({
58
+ storage,
59
+ store,
60
+ bucket,
61
+ namespace: hash(canonicalize([hostNamespace, id2])),
62
+ operationDeadlineMilliseconds: milliseconds
63
+ });
64
+ await fence2.probe({ signal });
65
+ activeGcsSignal(signal);
66
+ return { id: id2, fence: fence2 };
67
+ },
68
+ { signal: context.signal, milliseconds }
69
+ );
70
+ const getStatus = createReportingStatusHandler(coreStore);
71
+ async function readerOptions(binding, signal) {
72
+ const scope = scopeFor(binding);
73
+ const provider = await store.getAuthorizedObjectWriteBinding(scope, { signal });
74
+ activeGcsSignal(signal);
75
+ if (!provider) throw new ReportingGcsFenceError("REVOKED");
76
+ const prefix = `adcp-reporting/${provider.namespace_key}/${reportingObjectWriteScopeKey(scope)}/`;
77
+ return {
78
+ scope: { ...scope, principal_id: `producer:${id}` },
79
+ bucket: provider.bucket,
80
+ objectPrefix: prefix,
81
+ getStorage: async () => storage,
82
+ authorize: async (request, call) => {
83
+ if (request.bucket !== provider.bucket || request.objectPrefix !== prefix || request.scope.principal_id !== `producer:${id}` || request.scope.account_id !== scope.account_id || request.scope.destination_ref !== scope.destination_ref || request.scope.generation !== scope.generation)
84
+ return false;
85
+ const current = await store.getAuthorizedObjectWriteBinding(scope, { signal: call.signal });
86
+ return current?.bucket === provider.bucket && current.namespace_key === provider.namespace_key;
87
+ },
88
+ operationDeadlineMilliseconds: milliseconds
89
+ };
90
+ }
91
+ async function trueObligation(input, signal) {
92
+ let cursor;
93
+ for (let page = 0; page < 25; page++) {
94
+ activeGcsSignal(signal);
95
+ const status = await getStatus(
96
+ {
97
+ account: { account_id: input.binding.account_id },
98
+ view: "periods",
99
+ delivery_config_ids: [input.binding.delivery_config_id],
100
+ period: input.revision.wireRevision.period,
101
+ pagination: { max_results: 100, ...cursor ? { cursor } : {} }
102
+ },
103
+ { account: { id: input.binding.account_id, account_id: input.binding.account_id }, signal }
104
+ );
105
+ activeGcsSignal(signal);
106
+ const selected = status.periods?.find(
107
+ (value) => value.reporting_obligation_id === input.obligation.reporting_obligation_id
108
+ );
109
+ if (selected) return selected;
110
+ cursor = status.pagination?.cursor;
111
+ if (!cursor) break;
112
+ }
113
+ throw new ReportingGcsFenceError("STATE_UNAVAILABLE");
114
+ }
115
+ async function hostCallback(work, signal) {
116
+ try {
117
+ const result = await work();
118
+ activeGcsSignal(signal);
119
+ return result;
120
+ } catch {
121
+ activeGcsSignal(signal);
122
+ throw new ReportingGcsFenceError("HOST_CALLBACK_FAILED");
123
+ }
124
+ }
125
+ return {
126
+ verificationProfiles: Object.freeze(["manifest_checksums", "canonical_digest"]),
127
+ revocationFencesDeliveryGenerations: true,
128
+ async deliver(caller, call) {
129
+ return withGcsDeadline(
130
+ async (signal) => {
131
+ matchingBinding(caller);
132
+ if (!Number.isSafeInteger(caller.maxBytes) || caller.maxBytes < 1 || caller.maxBytes > 64 * 1024 * 1024 || caller.revision.binding.byteCount > caller.maxBytes || caller.revision.rows.length > 1e5)
133
+ throw new ReportingGcsFenceError("INVALID_INPUT");
134
+ const input = structuredClone(caller);
135
+ matchingBinding(input);
136
+ if (input.revision.rows.length > 1e5 || input.revision.binding.byteCount > input.maxBytes || !Number.isSafeInteger(input.maxBytes) || input.maxBytes < 1 || input.maxBytes > 64 * 1024 * 1024)
137
+ throw new ReportingGcsFenceError("INVALID_INPUT");
138
+ const { revision, binding, materialization, obligation } = input;
139
+ if (revision.reporting_revision_id !== materialization.reporting_revision_id || revision.reporting_obligation_id !== obligation.reporting_obligation_id || materialization.reporting_obligation_id !== obligation.reporting_obligation_id || obligation.account.account_id !== binding.account_id || obligation.configurationId !== binding.configurationId || obligation.delivery_config_id !== binding.delivery_config_id || obligation.delivery_config_version !== binding.delivery_config_version)
140
+ throw new ReportingGcsFenceError("INVALID_INPUT");
141
+ const coreBytes = Buffer.from(
142
+ canonicalize({
143
+ reporting_revision_id: revision.reporting_revision_id,
144
+ row_count: revision.wireRevision.row_count,
145
+ control_totals: revision.wireRevision.control_totals,
146
+ reporting_rows: revision.rows
147
+ })
148
+ );
149
+ if (revision.binding.algorithm !== "rfc8785_jcs_v1" || coreBytes.length !== revision.binding.byteCount || hash(coreBytes) !== revision.binding.sha256 || revision.wireRevision.revision_content_sha256 !== revision.binding.sha256 || revision.binding.rowCount !== revision.rows.length || revision.wireRevision.row_count !== revision.rows.length)
150
+ throw new ReportingGcsFenceError("CONTENT_CONFLICT");
151
+ const expected = await hostCallback(async () => {
152
+ const value = structuredClone(await resolveExpectedPeriod(structuredClone(input), { signal }));
153
+ if (!value || typeof value !== "object" || !Array.isArray(value.mediaBuyIds) || !value.coverage || typeof value.coverage !== "object" || Array.isArray(value.coverage) || value.verificationProfile === "canonical_digest" && (!value.canonicalization || typeof value.canonicalization !== "object"))
154
+ throw new ReportingGcsFenceError("HOST_CALLBACK_FAILED");
155
+ return value;
156
+ }, signal);
157
+ activeGcsSignal(signal);
158
+ assertExpectedBinding(input, expected);
159
+ const actualObligation = await trueObligation(input, signal);
160
+ const contractOptions = await hostCallback(
161
+ () => resolveContractReader(structuredClone(input), { signal }),
162
+ signal
163
+ );
164
+ activeGcsSignal(signal);
165
+ if (!contractOptions || typeof contractOptions !== "object" || !contractOptions.scope)
166
+ throw new ReportingGcsFenceError("HOST_CALLBACK_FAILED");
167
+ let contractResolver;
168
+ try {
169
+ contractResolver = createGcsReportingReferenceResolverV1({
170
+ ...contractOptions,
171
+ signal: contractOptions.signal ? AbortSignal.any([signal, contractOptions.signal]) : signal
172
+ });
173
+ } catch {
174
+ throw new ReportingGcsFenceError("HOST_CALLBACK_FAILED");
175
+ }
176
+ if (contractOptions.scope.account_id !== binding.account_id || contractOptions.scope.destination_ref !== binding.destination_ref || contractOptions.scope.generation !== binding.authorization_generation)
177
+ throw new ReportingGcsFenceError("INVALID_INPUT");
178
+ const rows = Buffer.from(revision.rows.map((row) => canonicalize(row) + "\n").join(""));
179
+ const manifestBytes = Buffer.from(
180
+ canonicalize({
181
+ manifest_version: "1.0",
182
+ complete: true,
183
+ reporting_revision_id: revision.reporting_revision_id,
184
+ reporting_obligation_id: obligation.reporting_obligation_id,
185
+ reporting_materialization_id: materialization.reporting_materialization_id,
186
+ period: revision.wireRevision.period,
187
+ format: "jsonl",
188
+ compression: "none",
189
+ files: [
190
+ { object_ref: "0", size_bytes: rows.length, sha256: hash(rows), row_count: revision.rows.length }
191
+ ],
192
+ total_size_bytes: rows.length,
193
+ row_count: revision.rows.length,
194
+ control_totals: revision.wireRevision.control_totals,
195
+ created_at: revision.createdAt
196
+ })
197
+ );
198
+ if (rows.length + manifestBytes.length > input.maxBytes) throw new ReportingGcsFenceError("INVALID_INPUT");
199
+ const scope = scopeFor(binding);
200
+ const plan = await fence.register(scope, deliveryIdentity(input), [rows, manifestBytes], { signal });
201
+ activeGcsSignal(signal);
202
+ await fence.write(plan, 0, rows, { signal });
203
+ await fence.write(plan, 1, manifestBytes, { signal });
204
+ activeGcsSignal(signal);
205
+ const readerConfig = await readerOptions(binding, signal);
206
+ const location = `https://storage.googleapis.com/${plan.provider.bucket}/${plan.objects[1].object_name}`;
207
+ const read = await createGcsScopedObjectReadV1(readerConfig)(location, input.maxBytes, signal);
208
+ activeGcsSignal(signal);
209
+ if (hash(read.body) !== hash(manifestBytes)) throw new ReportingGcsFenceError("CONTENT_CONFLICT");
210
+ const resource = {
211
+ resource_ref: `gcs:${plan.plan_id}`,
212
+ kind: "manifest",
213
+ location,
214
+ manifest_version: "1.0",
215
+ manifest_sha256: hash(read.body),
216
+ immutability: "native_version",
217
+ native_version_ref: read.generation,
218
+ expires_at: new Date(
219
+ Date.now() + Math.max(minimumDays, binding.resource_retention_days) * 864e5
220
+ ).toISOString(),
221
+ reader_compatibility: ["jsonl", "utf-8"]
222
+ };
223
+ const inspectionContext = {
224
+ obligation: actualObligation,
225
+ revision: revision.wireRevision,
226
+ materialization: { ...materialization, resource },
227
+ expected
228
+ };
229
+ const reader = createGcsReportingResourceReaderV1(readerConfig);
230
+ const observedChecksums = /* @__PURE__ */ new Map();
231
+ const inspect = createReportingManifestInspector({
232
+ reader: {
233
+ async read(request) {
234
+ const result = await reader.read({
235
+ ...request,
236
+ signal: request.signal ? AbortSignal.any([signal, request.signal]) : signal
237
+ });
238
+ activeGcsSignal(signal);
239
+ if (request.role === "object")
240
+ observedChecksums.set(request.objectRef, {
241
+ object_ref: request.objectRef,
242
+ algorithm: "sha256",
243
+ value: hash(result.body)
244
+ });
245
+ return result;
246
+ }
247
+ },
248
+ referenceResolver: contractResolver,
249
+ referenceAllowedOrigins: ["https://storage.googleapis.com"],
250
+ maxTotalBytes: input.maxBytes,
251
+ maxObjectBytes: input.maxBytes,
252
+ maxRows: 1e5
253
+ });
254
+ const observation = await inspect(inspectionContext);
255
+ activeGcsSignal(signal);
256
+ if (!observedChecksums.size) throw new ReportingGcsFenceError("CONTENT_CONFLICT");
257
+ resource.expires_at = new Date(
258
+ Date.now() + Math.max(minimumDays, binding.resource_retention_days) * 864e5 + milliseconds
259
+ ).toISOString();
260
+ const checksums = [...observedChecksums.values()];
261
+ if (checksums.length !== 1 || checksums[0].object_ref !== "0" || checksums[0].value !== plan.objects[0].sha256)
262
+ throw new ReportingGcsFenceError("CONTENT_CONFLICT");
263
+ const verification = {
264
+ verified_at: (/* @__PURE__ */ new Date()).toISOString(),
265
+ verification_path: "producer",
266
+ verification_profile: binding.verification_profile,
267
+ row_count: observation.rowCount,
268
+ control_totals: observation.controlTotals,
269
+ physical_checksums: [checksums[0], ...checksums.slice(1)],
270
+ ...observation.canonicalContentDigest ? { canonical_content_digest: observation.canonicalContentDigest } : {}
271
+ };
272
+ if (!await store.getAuthorizedObjectWriteBinding(scope, { signal }))
273
+ throw new ReportingGcsFenceError("REVOKED");
274
+ activeGcsSignal(signal);
275
+ return { status: "available", resource, verification };
276
+ },
277
+ { signal: call.signal, milliseconds }
278
+ );
279
+ },
280
+ async read(caller, call) {
281
+ return withGcsDeadline(
282
+ async (signal) => {
283
+ const input = structuredClone(caller);
284
+ matchingBinding(input);
285
+ const planId = hash(deliveryIdentity(input));
286
+ const scope = scopeFor(input.binding);
287
+ const plan = await store.getObjectWritePlan(scope, planId, { signal });
288
+ activeGcsSignal(signal);
289
+ if (!plan) throw new ReportingGcsFenceError("REVOKED");
290
+ const location = `https://storage.googleapis.com/${plan.provider.bucket}/${reportingObjectWriteName(scope, plan.provider, planId, 1)}`;
291
+ if (plan.objects.length !== 2 || input.resource.resource_ref !== `gcs:${planId}` || input.resource.location !== location || input.resource.kind !== "manifest" || input.resource.immutability !== "native_version" || !input.resource.native_version_ref || !Number.isFinite(Date.parse(input.resource.expires_at ?? "")) || input.resource.manifest_sha256 !== plan.objects[1]?.sha256)
292
+ throw new ReportingGcsFenceError("INVALID_INPUT");
293
+ const config = await readerOptions(input.binding, signal);
294
+ const result = await createGcsScopedObjectReadV1(config)(
295
+ location,
296
+ input.maxBytes,
297
+ signal,
298
+ input.resource.native_version_ref
299
+ );
300
+ if (hash(result.body) !== input.resource.manifest_sha256)
301
+ throw new ReportingGcsFenceError("CONTENT_CONFLICT");
302
+ return result.body;
303
+ },
304
+ { signal: call.signal, milliseconds }
305
+ );
306
+ },
307
+ async revoke(input, call) {
308
+ await withGcsDeadline(
309
+ async (signal) => {
310
+ for (let page = 0; page < 1e3; page++) {
311
+ activeGcsSignal(signal);
312
+ const result = await fence.revoke(input.authorization, { signal });
313
+ if (result.complete) return;
314
+ if (result.fenced < 1) throw new ReportingGcsFenceError("STATE_UNAVAILABLE");
315
+ }
316
+ throw new ReportingGcsFenceError("STATE_UNAVAILABLE");
317
+ },
318
+ { signal: call.signal, milliseconds }
319
+ );
320
+ }
321
+ };
322
+ }
323
+ export {
324
+ createGcsReportingManagedDeliveryAdapterV1
325
+ };
@@ -0,0 +1,3 @@
1
+ import type { BucketMetadata } from '@google-cloud/storage';
2
+ /** Pure policy guard shared by the real-provider probe and deterministic negative controls. */
3
+ export declare function assertGcsReportingBucketPolicy(metadata: BucketMetadata): void;
@@ -0,0 +1,3 @@
1
+ import type { BucketMetadata } from '@google-cloud/storage';
2
+ /** Pure policy guard shared by the real-provider probe and deterministic negative controls. */
3
+ export declare function assertGcsReportingBucketPolicy(metadata: BucketMetadata): void;
@@ -0,0 +1,31 @@
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 bucket_policy_exports = {};
20
+ __export(bucket_policy_exports, {
21
+ assertGcsReportingBucketPolicy: () => assertGcsReportingBucketPolicy
22
+ });
23
+ module.exports = __toCommonJS(bucket_policy_exports);
24
+ function assertGcsReportingBucketPolicy(metadata) {
25
+ if (!metadata || metadata.versioning?.enabled || metadata.softDeletePolicy?.retentionDurationSeconds === void 0 || Number(metadata.softDeletePolicy.retentionDurationSeconds) !== 0 || Number(metadata.retentionPolicy?.retentionPeriod ?? 0) !== 0 || metadata.defaultEventBasedHold === true || metadata.objectRetention?.mode === "Enabled" || (metadata.lifecycle?.rule?.length ?? 0) > 0 || metadata.iamConfiguration?.uniformBucketLevelAccess?.enabled !== true || metadata.iamConfiguration?.publicAccessPrevention !== "enforced")
26
+ throw new Error("Unsafe reporting GCS bucket policy");
27
+ }
28
+ // Annotate the CommonJS export names for ESM import in node:
29
+ 0 && (module.exports = {
30
+ assertGcsReportingBucketPolicy
31
+ });
@@ -0,0 +1,7 @@
1
+ function assertGcsReportingBucketPolicy(metadata) {
2
+ if (!metadata || metadata.versioning?.enabled || metadata.softDeletePolicy?.retentionDurationSeconds === void 0 || Number(metadata.softDeletePolicy.retentionDurationSeconds) !== 0 || Number(metadata.retentionPolicy?.retentionPeriod ?? 0) !== 0 || metadata.defaultEventBasedHold === true || metadata.objectRetention?.mode === "Enabled" || (metadata.lifecycle?.rule?.length ?? 0) > 0 || metadata.iamConfiguration?.uniformBucketLevelAccess?.enabled !== true || metadata.iamConfiguration?.publicAccessPrevention !== "enforced")
3
+ throw new Error("Unsafe reporting GCS bucket policy");
4
+ }
5
+ export {
6
+ assertGcsReportingBucketPolicy
7
+ };
@@ -0,0 +1,5 @@
1
+ export declare class ReportingGcsFenceError extends Error {
2
+ readonly code: 'INVALID_INPUT' | 'UNSAFE_BUCKET' | 'REVOKED' | 'NOT_REVOKED' | 'CONTENT_CONFLICT' | 'ABORTED' | 'PROVIDER_UNAVAILABLE' | 'DEADLINE_EXCEEDED' | 'HOST_CALLBACK_FAILED' | 'STATE_UNAVAILABLE';
3
+ constructor(code: 'INVALID_INPUT' | 'UNSAFE_BUCKET' | 'REVOKED' | 'NOT_REVOKED' | 'CONTENT_CONFLICT' | 'ABORTED' | 'PROVIDER_UNAVAILABLE' | 'DEADLINE_EXCEEDED' | 'HOST_CALLBACK_FAILED' | 'STATE_UNAVAILABLE');
4
+ }
5
+ export declare function isReportingGcsFenceError(error: unknown): error is ReportingGcsFenceError;
@@ -0,0 +1,5 @@
1
+ export declare class ReportingGcsFenceError extends Error {
2
+ readonly code: 'INVALID_INPUT' | 'UNSAFE_BUCKET' | 'REVOKED' | 'NOT_REVOKED' | 'CONTENT_CONFLICT' | 'ABORTED' | 'PROVIDER_UNAVAILABLE' | 'DEADLINE_EXCEEDED' | 'HOST_CALLBACK_FAILED' | 'STATE_UNAVAILABLE';
3
+ constructor(code: 'INVALID_INPUT' | 'UNSAFE_BUCKET' | 'REVOKED' | 'NOT_REVOKED' | 'CONTENT_CONFLICT' | 'ABORTED' | 'PROVIDER_UNAVAILABLE' | 'DEADLINE_EXCEEDED' | 'HOST_CALLBACK_FAILED' | 'STATE_UNAVAILABLE');
4
+ }
5
+ export declare function isReportingGcsFenceError(error: unknown): error is ReportingGcsFenceError;
@@ -0,0 +1,41 @@
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 errors_exports = {};
20
+ __export(errors_exports, {
21
+ ReportingGcsFenceError: () => ReportingGcsFenceError,
22
+ isReportingGcsFenceError: () => isReportingGcsFenceError
23
+ });
24
+ module.exports = __toCommonJS(errors_exports);
25
+ class ReportingGcsFenceError extends Error {
26
+ constructor(code) {
27
+ super(`Reporting GCS fence: ${code}`);
28
+ this.code = code;
29
+ this.name = "ReportingGcsFenceError";
30
+ Object.defineProperty(this, /* @__PURE__ */ Symbol.for("adcp.reportingGcsFenceError"), { value: true });
31
+ }
32
+ code;
33
+ }
34
+ function isReportingGcsFenceError(error) {
35
+ return !!error && typeof error === "object" && error[/* @__PURE__ */ Symbol.for("adcp.reportingGcsFenceError")] === true;
36
+ }
37
+ // Annotate the CommonJS export names for ESM import in node:
38
+ 0 && (module.exports = {
39
+ ReportingGcsFenceError,
40
+ isReportingGcsFenceError
41
+ });
@@ -0,0 +1,16 @@
1
+ class ReportingGcsFenceError extends Error {
2
+ constructor(code) {
3
+ super(`Reporting GCS fence: ${code}`);
4
+ this.code = code;
5
+ this.name = "ReportingGcsFenceError";
6
+ Object.defineProperty(this, /* @__PURE__ */ Symbol.for("adcp.reportingGcsFenceError"), { value: true });
7
+ }
8
+ code;
9
+ }
10
+ function isReportingGcsFenceError(error) {
11
+ return !!error && typeof error === "object" && error[/* @__PURE__ */ Symbol.for("adcp.reportingGcsFenceError")] === true;
12
+ }
13
+ export {
14
+ ReportingGcsFenceError,
15
+ isReportingGcsFenceError
16
+ };
@@ -0,0 +1,36 @@
1
+ import type { Storage } from '@google-cloud/storage';
2
+ import { type ReportingObjectWriteScopeV1, type ReportingObjectWritePlanV1, type ReportingObjectWriteStoreV1 } from '../ledger/object-writes.mjs';
3
+ export { ReportingGcsFenceError } from './errors.mjs';
4
+ export interface GcsReportingObjectFenceV1 {
5
+ probe(context?: {
6
+ signal?: AbortSignal;
7
+ }): Promise<void>;
8
+ register(scope: ReportingObjectWriteScopeV1, deliveryId: string, bodies: readonly Uint8Array[], context?: {
9
+ signal?: AbortSignal;
10
+ }): Promise<ReportingObjectWritePlanV1>;
11
+ write(plan: ReportingObjectWritePlanV1, index: number, bytes: Uint8Array, context: {
12
+ signal: AbortSignal;
13
+ }): Promise<void>;
14
+ revoke(scope: ReportingObjectWriteScopeV1, context: {
15
+ signal: AbortSignal;
16
+ maxObjects?: number;
17
+ }): Promise<{
18
+ fenced: number;
19
+ complete: boolean;
20
+ }>;
21
+ }
22
+ /**
23
+ * Provider-side write fence, not a complete Managed Delivery adapter.
24
+ * Derive scope from authenticated host state; these methods do not authorize callers.
25
+ * Bucket configuration must remain managed exclusively by the trusted host.
26
+ * Tombstones and inventory MUST NOT be deleted while stale requests can execute.
27
+ * Inject the official Storage client with host-owned, keyless credentials.
28
+ */
29
+ export declare function createGcsReportingObjectFenceV1(options: {
30
+ storage: Storage;
31
+ store: ReportingObjectWriteStoreV1;
32
+ bucket: string;
33
+ /** Opaque deployment identity, separate from account and destination generations. */
34
+ namespace: string;
35
+ operationDeadlineMilliseconds?: number;
36
+ }): GcsReportingObjectFenceV1;
@@ -0,0 +1,36 @@
1
+ import type { Storage } from '@google-cloud/storage';
2
+ import { type ReportingObjectWriteScopeV1, type ReportingObjectWritePlanV1, type ReportingObjectWriteStoreV1 } from '../ledger/object-writes';
3
+ export { ReportingGcsFenceError } from './errors';
4
+ export interface GcsReportingObjectFenceV1 {
5
+ probe(context?: {
6
+ signal?: AbortSignal;
7
+ }): Promise<void>;
8
+ register(scope: ReportingObjectWriteScopeV1, deliveryId: string, bodies: readonly Uint8Array[], context?: {
9
+ signal?: AbortSignal;
10
+ }): Promise<ReportingObjectWritePlanV1>;
11
+ write(plan: ReportingObjectWritePlanV1, index: number, bytes: Uint8Array, context: {
12
+ signal: AbortSignal;
13
+ }): Promise<void>;
14
+ revoke(scope: ReportingObjectWriteScopeV1, context: {
15
+ signal: AbortSignal;
16
+ maxObjects?: number;
17
+ }): Promise<{
18
+ fenced: number;
19
+ complete: boolean;
20
+ }>;
21
+ }
22
+ /**
23
+ * Provider-side write fence, not a complete Managed Delivery adapter.
24
+ * Derive scope from authenticated host state; these methods do not authorize callers.
25
+ * Bucket configuration must remain managed exclusively by the trusted host.
26
+ * Tombstones and inventory MUST NOT be deleted while stale requests can execute.
27
+ * Inject the official Storage client with host-owned, keyless credentials.
28
+ */
29
+ export declare function createGcsReportingObjectFenceV1(options: {
30
+ storage: Storage;
31
+ store: ReportingObjectWriteStoreV1;
32
+ bucket: string;
33
+ /** Opaque deployment identity, separate from account and destination generations. */
34
+ namespace: string;
35
+ operationDeadlineMilliseconds?: number;
36
+ }): GcsReportingObjectFenceV1;