@adcp/sdk 16.0.0-beta.3 → 16.0.0-beta.5

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 (185) hide show
  1. package/dist/lib/auth/oauth/diagnose.js +3 -11
  2. package/dist/lib/auth/oauth/diagnose.mjs +4 -12
  3. package/dist/lib/auth/oauth/diagnostics.d.mts +2 -1
  4. package/dist/lib/auth/oauth/diagnostics.d.ts +2 -1
  5. package/dist/lib/auth/oauth/diagnostics.js +8 -10
  6. package/dist/lib/auth/oauth/diagnostics.mjs +7 -10
  7. package/dist/lib/index.d.mts +1 -1
  8. package/dist/lib/index.d.ts +1 -1
  9. package/dist/lib/index.js +2 -0
  10. package/dist/lib/index.mjs +7 -1
  11. package/dist/lib/reporting/consumer-runtime.js +2 -1
  12. package/dist/lib/reporting/consumer-runtime.mjs +2 -1
  13. package/dist/lib/reporting/ledger/handler.js +50 -11
  14. package/dist/lib/reporting/ledger/handler.mjs +50 -12
  15. package/dist/lib/reporting/ledger/index.d.mts +17 -14
  16. package/dist/lib/reporting/ledger/index.d.ts +17 -14
  17. package/dist/lib/reporting/ledger/index.js +32 -20
  18. package/dist/lib/reporting/ledger/index.mjs +21 -10
  19. package/dist/lib/reporting/ledger/offering-validation.d.mts +9 -0
  20. package/dist/lib/reporting/ledger/offering-validation.d.ts +9 -0
  21. package/dist/lib/reporting/{gcs/bucket-policy.js → ledger/offering-validation.js} +9 -8
  22. package/dist/lib/reporting/ledger/offering-validation.mjs +8 -0
  23. package/dist/lib/reporting/ledger/receipts.d.mts +48 -0
  24. package/dist/lib/reporting/ledger/receipts.d.ts +48 -0
  25. package/dist/lib/reporting/ledger/receipts.js +186 -0
  26. package/dist/lib/reporting/ledger/receipts.mjs +161 -0
  27. package/dist/lib/reporting/ledger/status-ingest.js +3 -3
  28. package/dist/lib/reporting/ledger/status-ingest.mjs +4 -5
  29. package/dist/lib/reporting/ledger/types.d.mts +43 -0
  30. package/dist/lib/reporting/ledger/types.d.ts +43 -0
  31. package/dist/lib/reporting/ledger/types.js +31 -2
  32. package/dist/lib/reporting/ledger/types.mjs +26 -1
  33. package/dist/lib/reporting/pagination.d.mts +6 -0
  34. package/dist/lib/reporting/pagination.d.ts +6 -0
  35. package/dist/lib/reporting/{gcs/errors.js → pagination.js} +12 -17
  36. package/dist/lib/reporting/pagination.mjs +12 -0
  37. package/dist/lib/reporting/reconciliation.d.mts +1 -0
  38. package/dist/lib/reporting/reconciliation.d.ts +1 -0
  39. package/dist/lib/reporting/reconciliation.js +3 -2
  40. package/dist/lib/reporting/reconciliation.mjs +3 -2
  41. package/dist/lib/reporting/service/index.d.mts +79 -153
  42. package/dist/lib/reporting/service/index.d.ts +79 -153
  43. package/dist/lib/reporting/service/index.js +34 -491
  44. package/dist/lib/reporting/service/index.mjs +36 -510
  45. package/dist/lib/reporting/service/scheduler-support.d.mts +43 -0
  46. package/dist/lib/reporting/service/scheduler-support.d.ts +43 -0
  47. package/dist/lib/reporting/service/scheduler-support.js +125 -0
  48. package/dist/lib/reporting/service/scheduler-support.mjs +96 -0
  49. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  50. package/dist/lib/signing/canonicalize.d.mts +4 -0
  51. package/dist/lib/signing/canonicalize.d.ts +4 -0
  52. package/dist/lib/signing/canonicalize.js +14 -8
  53. package/dist/lib/signing/canonicalize.mjs +14 -8
  54. package/dist/lib/signing/content-digest.d.mts +8 -0
  55. package/dist/lib/signing/content-digest.d.ts +8 -0
  56. package/dist/lib/signing/content-digest.js +11 -5
  57. package/dist/lib/signing/content-digest.mjs +10 -5
  58. package/dist/lib/signing/signer.js +9 -6
  59. package/dist/lib/signing/signer.mjs +10 -7
  60. package/dist/lib/signing/web-bot-auth.js +103 -37
  61. package/dist/lib/signing/web-bot-auth.mjs +108 -37
  62. package/dist/lib/testing/storyboard/junit.js +16 -3
  63. package/dist/lib/testing/storyboard/junit.mjs +16 -3
  64. package/dist/lib/testing/storyboard/request-signing/builder.js +10 -9
  65. package/dist/lib/testing/storyboard/request-signing/builder.mjs +10 -9
  66. package/dist/lib/testing/storyboard/runner.js +94 -25
  67. package/dist/lib/testing/storyboard/runner.mjs +94 -25
  68. package/dist/lib/testing/storyboard/types.d.mts +6 -0
  69. package/dist/lib/testing/storyboard/types.d.ts +6 -0
  70. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  71. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  72. package/dist/lib/types/schemas.generated.d.ts +907 -60
  73. package/dist/lib/types/schemas.generated.js +7 -7
  74. package/dist/lib/types/schemas.generated.mjs +7 -7
  75. package/dist/lib/version.d.mts +3 -3
  76. package/dist/lib/version.d.ts +3 -3
  77. package/dist/lib/version.js +3 -3
  78. package/dist/lib/version.mjs +3 -3
  79. package/docs/TYPE-SUMMARY.md +23 -5
  80. package/docs/guides/REPORTING-GCS-FENCE.md +3 -3
  81. package/docs/guides/REPORTING-GCS-MANAGED.md +4 -4
  82. package/docs/guides/REPORTING-LEDGER-CUTOVER.md +7 -7
  83. package/docs/guides/REPORTING-LEDGER.md +107 -51
  84. package/docs/guides/REPORTING-OPERATIONS.md +66 -5
  85. package/docs/guides/REPORTING-STABILITY.md +36 -32
  86. package/docs/llms.txt +4 -3
  87. package/docs/migration-14.x-rc-worksheet.md +4 -7
  88. package/docs/migration-reporting-storage-package.md +186 -0
  89. package/examples/README.md +1 -1
  90. package/package.json +13 -78
  91. package/dist/lib/reporting/azure/index.d.mts +0 -31
  92. package/dist/lib/reporting/azure/index.d.ts +0 -31
  93. package/dist/lib/reporting/azure/index.js +0 -266
  94. package/dist/lib/reporting/azure/index.mjs +0 -249
  95. package/dist/lib/reporting/bigquery/index.d.mts +0 -246
  96. package/dist/lib/reporting/bigquery/index.d.ts +0 -246
  97. package/dist/lib/reporting/bigquery/index.js +0 -633
  98. package/dist/lib/reporting/bigquery/index.mjs +0 -594
  99. package/dist/lib/reporting/gcs/adapter.d.mts +0 -38
  100. package/dist/lib/reporting/gcs/adapter.d.ts +0 -38
  101. package/dist/lib/reporting/gcs/adapter.js +0 -342
  102. package/dist/lib/reporting/gcs/adapter.mjs +0 -325
  103. package/dist/lib/reporting/gcs/bucket-policy.d.mts +0 -3
  104. package/dist/lib/reporting/gcs/bucket-policy.d.ts +0 -3
  105. package/dist/lib/reporting/gcs/bucket-policy.mjs +0 -7
  106. package/dist/lib/reporting/gcs/errors.d.mts +0 -11
  107. package/dist/lib/reporting/gcs/errors.d.ts +0 -11
  108. package/dist/lib/reporting/gcs/errors.mjs +0 -16
  109. package/dist/lib/reporting/gcs/fence.d.mts +0 -41
  110. package/dist/lib/reporting/gcs/fence.d.ts +0 -41
  111. package/dist/lib/reporting/gcs/fence.js +0 -250
  112. package/dist/lib/reporting/gcs/fence.mjs +0 -230
  113. package/dist/lib/reporting/gcs/index.d.mts +0 -18
  114. package/dist/lib/reporting/gcs/index.d.ts +0 -18
  115. package/dist/lib/reporting/gcs/index.js +0 -44
  116. package/dist/lib/reporting/gcs/index.mjs +0 -14
  117. package/dist/lib/reporting/gcs/io.d.mts +0 -7
  118. package/dist/lib/reporting/gcs/io.d.ts +0 -7
  119. package/dist/lib/reporting/gcs/io.js +0 -95
  120. package/dist/lib/reporting/gcs/io.mjs +0 -69
  121. package/dist/lib/reporting/gcs/reader.d.mts +0 -67
  122. package/dist/lib/reporting/gcs/reader.d.ts +0 -67
  123. package/dist/lib/reporting/gcs/reader.js +0 -193
  124. package/dist/lib/reporting/gcs/reader.mjs +0 -169
  125. package/dist/lib/reporting/gcs/row-provider.d.mts +0 -39
  126. package/dist/lib/reporting/gcs/row-provider.d.ts +0 -39
  127. package/dist/lib/reporting/gcs/row-provider.js +0 -225
  128. package/dist/lib/reporting/gcs/row-provider.mjs +0 -208
  129. package/dist/lib/reporting/gcs/validation.d.mts +0 -5
  130. package/dist/lib/reporting/gcs/validation.d.ts +0 -5
  131. package/dist/lib/reporting/gcs/validation.js +0 -49
  132. package/dist/lib/reporting/gcs/validation.mjs +0 -25
  133. package/dist/lib/reporting/ledger/change-feed.d.mts +0 -69
  134. package/dist/lib/reporting/ledger/change-feed.d.ts +0 -69
  135. package/dist/lib/reporting/ledger/change-feed.js +0 -107
  136. package/dist/lib/reporting/ledger/change-feed.mjs +0 -80
  137. package/dist/lib/reporting/ledger/managed-postgres.d.mts +0 -293
  138. package/dist/lib/reporting/ledger/managed-postgres.d.ts +0 -293
  139. package/dist/lib/reporting/ledger/managed-postgres.js +0 -2346
  140. package/dist/lib/reporting/ledger/managed-postgres.mjs +0 -2332
  141. package/dist/lib/reporting/ledger/managed-router.d.mts +0 -148
  142. package/dist/lib/reporting/ledger/managed-router.d.ts +0 -148
  143. package/dist/lib/reporting/ledger/managed-router.js +0 -280
  144. package/dist/lib/reporting/ledger/managed-router.mjs +0 -258
  145. package/dist/lib/reporting/ledger/managed.d.mts +0 -535
  146. package/dist/lib/reporting/ledger/managed.d.ts +0 -535
  147. package/dist/lib/reporting/ledger/managed.js +0 -761
  148. package/dist/lib/reporting/ledger/managed.mjs +0 -729
  149. package/dist/lib/reporting/ledger/notification-activity.d.mts +0 -332
  150. package/dist/lib/reporting/ledger/notification-activity.d.ts +0 -332
  151. package/dist/lib/reporting/ledger/notification-activity.js +0 -1366
  152. package/dist/lib/reporting/ledger/notification-activity.mjs +0 -1337
  153. package/dist/lib/reporting/ledger/object-writes.d.mts +0 -128
  154. package/dist/lib/reporting/ledger/object-writes.d.ts +0 -128
  155. package/dist/lib/reporting/ledger/object-writes.js +0 -147
  156. package/dist/lib/reporting/ledger/object-writes.mjs +0 -114
  157. package/dist/lib/reporting/ledger/postgres.d.mts +0 -689
  158. package/dist/lib/reporting/ledger/postgres.d.ts +0 -689
  159. package/dist/lib/reporting/ledger/postgres.js +0 -4462
  160. package/dist/lib/reporting/ledger/postgres.mjs +0 -4462
  161. package/dist/lib/reporting/ledger/row-storage-migration.d.mts +0 -59
  162. package/dist/lib/reporting/ledger/row-storage-migration.d.ts +0 -59
  163. package/dist/lib/reporting/ledger/row-storage-migration.js +0 -365
  164. package/dist/lib/reporting/ledger/row-storage-migration.mjs +0 -339
  165. package/dist/lib/reporting/ledger/row-storage-object.d.mts +0 -203
  166. package/dist/lib/reporting/ledger/row-storage-object.d.ts +0 -203
  167. package/dist/lib/reporting/ledger/row-storage-object.js +0 -379
  168. package/dist/lib/reporting/ledger/row-storage-object.mjs +0 -335
  169. package/dist/lib/reporting/ledger/row-storage-provider-io.d.mts +0 -44
  170. package/dist/lib/reporting/ledger/row-storage-provider-io.d.ts +0 -44
  171. package/dist/lib/reporting/ledger/row-storage-provider-io.js +0 -142
  172. package/dist/lib/reporting/ledger/row-storage-provider-io.mjs +0 -111
  173. package/dist/lib/reporting/ledger/row-storage.d.mts +0 -316
  174. package/dist/lib/reporting/ledger/row-storage.d.ts +0 -316
  175. package/dist/lib/reporting/ledger/row-storage.js +0 -812
  176. package/dist/lib/reporting/ledger/row-storage.mjs +0 -802
  177. package/dist/lib/reporting/s3/index.d.mts +0 -34
  178. package/dist/lib/reporting/s3/index.d.ts +0 -34
  179. package/dist/lib/reporting/s3/index.js +0 -347
  180. package/dist/lib/reporting/s3/index.mjs +0 -340
  181. package/dist/lib/reporting/service/maintenance.d.mts +0 -148
  182. package/dist/lib/reporting/service/maintenance.d.ts +0 -148
  183. package/dist/lib/reporting/service/maintenance.js +0 -185
  184. package/dist/lib/reporting/service/maintenance.mjs +0 -159
  185. package/examples/reliable-reporting-service/README.md +0 -169
@@ -1,21 +1,7 @@
1
1
  import { scanArgsForCredentials } from "../../server/credential-policy.mjs";
2
2
  import { canonicalize } from "../../utils/jcs.mjs";
3
- import { redactCredentialPatterns } from "../../utils/redact-credential-patterns.mjs";
4
- import { ReportingDeliveryCapabilitiesSchema, ReportingDeliveryOfferingSchema } from "../../types/schemas.generated.mjs";
3
+ import { ReportingDeliveryOfferingSchema } from "../../types/schemas.generated.mjs";
5
4
  import {
6
- createPostgresPersistentNotificationRuntime
7
- } from "../../server/notification-subscriptions/index.mjs";
8
- import {
9
- REPORTING_LEDGER_MIGRATION,
10
- REPORTING_MANAGED_DELIVERY_MIGRATION,
11
- REPORTING_ROW_STORAGE_MIGRATION,
12
- REPORTING_LEDGER_CHANGES_MIGRATION,
13
- PostgresReportingLedgerStore,
14
- sweepExpiredReportingLedgerState,
15
- PostgresReportingManagedDeliveryStore,
16
- createPostgresReportingNotificationActivityRuntime,
17
- createPostgresReportingNotificationAttemptCheckpoint,
18
- createReportingManagedDeliveryRuntime,
19
5
  assertReportingConsumerMismatchEscalation,
20
6
  reportingConsumerStatusCapabilityV1,
21
7
  reportingEffectiveConsumerMismatchEscalationV1,
@@ -25,15 +11,11 @@ import {
25
11
  createSyncReportingStatusHandler
26
12
  } from "../ledger/index.mjs";
27
13
  import {
28
- composeNotificationDeliveryAttemptCheckpoints,
29
- composeWebhookAttemptResultObservers,
30
- createPostgresReportingWebhookActivityV1,
31
- projectListAccountsReportingWebhookActivityV1
32
- } from "../webhook-activity.mjs";
33
- import {
34
- assertReportingLedgerMaintenanceOptions,
35
- runReportingLedgerMaintenance
36
- } from "./maintenance.mjs";
14
+ reportReportingSchedulerError,
15
+ reportingDeploymentWideAccountIds,
16
+ reportingSchedulerDelay,
17
+ rotateReportingRoster
18
+ } from "./scheduler-support.mjs";
37
19
  import { assertReportingCalendarDaySource, reportingCalendarDayOrigin } from "../ledger/schedule.mjs";
38
20
  import {
39
21
  ReportingCoverageConstituentIdentityV1Schema,
@@ -48,10 +30,11 @@ import {
48
30
  reportingSourceCapabilitiesV1
49
31
  } from "../source/index.mjs";
50
32
  const ADAPTER_SCOPE_KEY = "_adcp_reporting_adapter";
51
- const PRODUCTION_MANAGED_COMPOSITION = /* @__PURE__ */ Symbol("production-managed-reporting-composition");
52
- const DEFAULT_MAINTENANCE_INTERVAL_MILLISECONDS = 3e5;
33
+ const REPORTING_MANAGED_DELIVERY_COMPOSITION_V1 = /* @__PURE__ */ Symbol.for(
34
+ "@adcp/sdk/reporting/managed-delivery-composition"
35
+ );
53
36
  function createReliableReportingService(options) {
54
- const allowManagedDelivery = options[PRODUCTION_MANAGED_COMPOSITION] === true;
37
+ const allowManagedDelivery = options[REPORTING_MANAGED_DELIVERY_COMPOSITION_V1] === options.store;
55
38
  const adapterEntries = Object.entries(options.adapters);
56
39
  if (adapterEntries.length === 0) throw new TypeError("Reliable reporting requires at least one adapter");
57
40
  positiveInteger(options.automatedRecoveryWindowSeconds, "automatedRecoveryWindowSeconds");
@@ -111,52 +94,25 @@ function createReliableReportingService(options) {
111
94
  if (hasConsumerStatus) assertConsumerStatusStore(options.store);
112
95
  const retentionDays = options.statusRetentionDays;
113
96
  positiveInteger(retentionDays, "statusRetentionDays");
114
- const maintenance = options.maintenance;
115
- let maintenanceStore;
116
- let maintenanceIntervalMilliseconds = DEFAULT_MAINTENANCE_INTERVAL_MILLISECONDS;
117
- if (maintenance !== void 0) {
118
- if (maintenance === null || typeof maintenance !== "object") {
119
- throw new TypeError("maintenance must be an options object");
120
- }
121
- const candidate = options.store;
122
- for (const method of [
123
- "retireExpiredPeriods",
124
- "pruneChanges",
125
- "sweepRowWriteIntents",
126
- ...maintenance.compaction ? ["compactSupersededSnapshots"] : []
127
- ]) {
128
- if (typeof candidate[method] !== "function") {
129
- throw new TypeError(
130
- `maintenance requires a PostgresReportingLedgerStore (or a store with ${method}); the configured store cannot run ledger maintenance`
131
- );
132
- }
133
- }
134
- maintenanceStore = candidate;
135
- if (maintenance.compaction) {
136
- candidate.assertCompactionSafeRowBindings?.();
137
- }
138
- if (maintenance.changeFeed && maintenanceStore.changeFeedEnabled === false) {
97
+ let maintenance;
98
+ if (options.maintenance !== void 0) {
99
+ if (typeof options.maintenance !== "function") {
139
100
  throw new TypeError(
140
- "maintenance.changeFeed requires the store to be built with changeFeed: true; otherwise pruning silently does nothing"
101
+ "createReliableReportingService: `maintenance` must be a factory, not an options object. For a PostgreSQL ledger wrap your options with `reportingLedgerMaintenance({ ... })` from the `@adcp/reporting-storage` package, for example `maintenance: reportingLedgerMaintenance({ retention: { enabled: true } })`. See docs/migration-reporting-storage-package.md."
141
102
  );
142
103
  }
143
- if (maintenance.intervalMilliseconds !== void 0) {
144
- positiveInteger(maintenance.intervalMilliseconds, "maintenance.intervalMilliseconds");
145
- maintenanceIntervalMilliseconds = maintenance.intervalMilliseconds;
104
+ maintenance = options.maintenance({
105
+ store: options.store,
106
+ statusRetentionDays: retentionDays,
107
+ automatedRecoveryWindowSeconds: options.automatedRecoveryWindowSeconds
108
+ });
109
+ if (!maintenance || typeof maintenance.run !== "function" || !Number.isSafeInteger(maintenance.intervalMilliseconds) || maintenance.intervalMilliseconds <= 0) {
110
+ throw new TypeError(
111
+ "maintenance factory must return { intervalMilliseconds: positive integer, run(): Promise<results> }"
112
+ );
146
113
  }
147
- assertReportingLedgerMaintenanceOptions(maintenance, retentionDays);
148
114
  }
149
- const runLedgerMaintenance = (signal, report) => runReportingLedgerMaintenance({
150
- store: maintenanceStore,
151
- ...typeof maintenanceStore.sweepExpiredState === "function" ? { sweepSnapshots: (limit) => maintenanceStore.sweepExpiredState(limit) } : {},
152
- statusRetentionDays: retentionDays,
153
- automatedRecoveryWindowSeconds: options.automatedRecoveryWindowSeconds,
154
- retention: maintenance.retention,
155
- compaction: maintenance.compaction,
156
- changeFeed: maintenance.changeFeed,
157
- signal,
158
- ...report ? { report } : {}
159
- });
115
+ const runLedgerMaintenance = (signal, report) => maintenance.run({ signal, ...report ? { report } : {} });
160
116
  const capabilities = deepFreeze({
161
117
  supported: true,
162
118
  reliable_reporting_version: "1.0",
@@ -197,7 +153,7 @@ function createReliableReportingService(options) {
197
153
  const service = {
198
154
  setup: Object.freeze({
199
155
  component: "reliable-reporting-core",
200
- migrations: Object.freeze([REPORTING_LEDGER_MIGRATION]),
156
+ migrations: Object.freeze([...options.store.migrations ?? []]),
201
157
  requiresIsolatedLedgerDatabaseAcknowledgement: true
202
158
  }),
203
159
  capabilities,
@@ -345,10 +301,10 @@ function createReliableReportingService(options) {
345
301
  schedulerAbort = new AbortController();
346
302
  const signal = schedulerAbort.signal;
347
303
  const scheduledMaintenance = maintenance === void 0 ? void 0 : {
348
- intervalMilliseconds: maintenanceIntervalMilliseconds,
304
+ intervalMilliseconds: maintenance.intervalMilliseconds,
349
305
  run: () => runLedgerMaintenance(
350
306
  signal,
351
- (error) => reportSchedulerError(scheduler, signal, error, { phase: "maintenance" })
307
+ (error) => reportReportingSchedulerError(scheduler, signal, error, { phase: "maintenance" })
352
308
  )
353
309
  };
354
310
  schedulerPromise = schedulerLoop(service, scheduler, signal, options.store, scheduledMaintenance).finally(() => {
@@ -364,346 +320,6 @@ function createReliableReportingService(options) {
364
320
  };
365
321
  return service;
366
322
  }
367
- async function createPostgresReliableReportingProductionService(options) {
368
- if (!options.db || typeof options.db.query !== "function" || typeof options.db.connect !== "function") {
369
- throw new TypeError("Reliable Reporting production service requires a PostgreSQL pool");
370
- }
371
- if (!/^[A-Za-z0-9_.:-]{1,255}$/.test(options.namespace)) {
372
- throw new TypeError("Reliable Reporting production namespace must be a bounded non-secret identifier");
373
- }
374
- if (!/^[A-Za-z0-9_.:-]{1,255}$/.test(options.publisherScope)) {
375
- throw new TypeError("Reliable Reporting publisherScope must be a bounded non-secret identifier");
376
- }
377
- if (typeof options.resolveWebhookActivityScope !== "function") {
378
- throw new TypeError("Reliable Reporting production service requires resolveWebhookActivityScope");
379
- }
380
- if (typeof options.activity?.tenantScopeForAccount !== "function") {
381
- throw new TypeError("Reliable Reporting production service requires activity.tenantScopeForAccount");
382
- }
383
- assertReportingLedgerMaintenanceOptions({ compaction: options.compaction }, options.statusRetentionDays);
384
- if (Object.values(options.adapters).some(
385
- (adapter) => adapter.deliveryOffering.reconciliation_mode === "consumer_receipt"
386
- ) && typeof options.obligatedConsumers !== "function") {
387
- throw new TypeError("Reconciled Billing production offerings require a trusted obligatedConsumers roster");
388
- }
389
- const recipientCheckpoint = createPostgresReportingNotificationAttemptCheckpoint({
390
- db: options.db,
391
- namespace: options.namespace,
392
- ...options.activity?.tableName !== void 0 ? { tableName: options.activity.tableName } : {}
393
- });
394
- const webhookActivity = createPostgresReportingWebhookActivityV1({
395
- db: options.db,
396
- namespace: options.namespace,
397
- ...options.webhookActivity?.tableName !== void 0 ? { tableName: options.webhookActivity.tableName } : {},
398
- ...options.webhookActivity?.retentionDays !== void 0 ? { retentionDays: options.webhookActivity.retentionDays } : {}
399
- });
400
- const composedAttemptCheckpoint = composeNotificationDeliveryAttemptCheckpoints(
401
- recipientCheckpoint,
402
- webhookActivity.checkpointDeliveryAttempt
403
- );
404
- const attemptCheckpoint = Object.assign(
405
- async (input) => composedAttemptCheckpoint(input),
406
- { activityStore: recipientCheckpoint.activityStore }
407
- );
408
- const adopterAttemptResult = options.notifications.webhooks.onAttemptResult;
409
- const adopterAttemptObserverError = options.notifications.webhooks.onAttemptObserverError;
410
- const notifications = createPostgresPersistentNotificationRuntime({
411
- ...options.notifications,
412
- db: options.db,
413
- publisherScope: options.publisherScope,
414
- checkpointDeliveryAttempt: attemptCheckpoint,
415
- supportedAccountEventTypes: ["reporting.ledger_changed", "reporting.status_changed", "reporting.delivery_ready"],
416
- webhooks: {
417
- ...options.notifications.webhooks,
418
- onAttemptResult: composeWebhookAttemptResultObservers(
419
- webhookActivity.emitterObservers.onAttemptResult,
420
- adopterAttemptResult
421
- ),
422
- onAttemptObserverError(error, phase) {
423
- if (adopterAttemptObserverError) {
424
- try {
425
- adopterAttemptObserverError(error, phase);
426
- return;
427
- } catch (observerError) {
428
- console.warn(
429
- `[adcp/reporting] webhook observer-error hook failed: ${safeMessage(observerError)}; original: ${safeMessage(error)}`
430
- );
431
- return;
432
- }
433
- }
434
- console.warn(`[adcp/reporting] webhook ${phase} observer failed: ${safeMessage(error)}`);
435
- }
436
- }
437
- });
438
- const notificationActivity = createPostgresReportingNotificationActivityRuntime({
439
- ...options.activity,
440
- db: options.db,
441
- notifications,
442
- namespace: options.namespace,
443
- attemptCheckpoint,
444
- tenantScopeForAccount: options.activity.tenantScopeForAccount
445
- });
446
- const coreStore = new PostgresReportingLedgerStore(options.db, {
447
- acknowledgeIsolatedDatabase: options.acknowledgeIsolatedDatabase,
448
- managedDelivery: true,
449
- ...options.obligatedConsumers ? { obligatedConsumers: options.obligatedConsumers } : {},
450
- ...options.consumerMismatchEscalation ? { consumerMismatchEscalation: options.consumerMismatchEscalation } : {},
451
- notificationActivityPort: notificationActivity.port,
452
- ...options.rowStorage ? { rowStorage: options.rowStorage } : {},
453
- ...options.changeFeed ? { changeFeed: true } : {}
454
- });
455
- if (options.compaction) coreStore.assertCompactionSafeRowBindings();
456
- const managedStore = new PostgresReportingManagedDeliveryStore(options.db, {
457
- ...options.managedDelivery.store,
458
- statusRetentionDays: options.statusRetentionDays,
459
- advertisedRecoveryWindowSeconds: options.automatedRecoveryWindowSeconds,
460
- notificationActivityPort: notificationActivity.port
461
- });
462
- const coreOptions = {
463
- ...options,
464
- store: coreStore,
465
- [PRODUCTION_MANAGED_COMPOSITION]: true
466
- };
467
- const core = createReliableReportingService(coreOptions);
468
- const migrations = Object.freeze([
469
- REPORTING_LEDGER_MIGRATION,
470
- ...options.rowStorage ? [REPORTING_ROW_STORAGE_MIGRATION] : [],
471
- ...options.changeFeed ? [REPORTING_LEDGER_CHANGES_MIGRATION] : [],
472
- REPORTING_MANAGED_DELIVERY_MIGRATION,
473
- ...notifications.migrations.all,
474
- ...notificationActivity.migrations.all,
475
- ...webhookActivity.migrations.all
476
- ]);
477
- await options.applyMigrations?.(migrations);
478
- await coreStore.readyRowStorage();
479
- await notifications.probe();
480
- await notificationActivity.probe();
481
- await webhookActivity.probe();
482
- const managed = await createReportingManagedDeliveryRuntime({
483
- coreStore,
484
- ...options.legacyRevisionReader ? { legacyRevisionReader: options.legacyRevisionReader } : {},
485
- store: managedStore,
486
- adapter: options.managedDelivery.adapter,
487
- offerings: core.capabilities.offerings,
488
- automatedRecoveryWindowSeconds: options.automatedRecoveryWindowSeconds,
489
- statusRetentionDays: options.statusRetentionDays,
490
- resourceRetentionDays: options.managedDelivery.resourceRetentionDays,
491
- authorizationRevocationSeconds: options.managedDelivery.authorizationRevocationSeconds,
492
- ...options.resolveConsumerId ? { resolveConsumerId: options.resolveConsumerId } : {},
493
- ...options.consumerMismatchEscalation ? { consumerMismatchEscalation: options.consumerMismatchEscalation } : {}
494
- });
495
- const capabilities = deepFreeze(
496
- ReportingDeliveryCapabilitiesSchema.parse({
497
- ...core.capabilities,
498
- ...managed.reportingDeliveryCapabilities,
499
- ledger_notification: "reporting.ledger_changed",
500
- status_notification: "reporting.status_changed",
501
- readiness_notification: "reporting.delivery_ready",
502
- supports_webhook_activity: true
503
- })
504
- );
505
- const platform = {
506
- capabilities,
507
- getReportingStatus: (request, context) => managed.getReportingStatus(request, context),
508
- getMediaBuyDelivery: (request, context) => managed.getMediaBuyDelivery(request, context),
509
- ...core.platform.syncReportingStatus ? {
510
- syncReportingStatus: core.platform.syncReportingStatus,
511
- resolveConsumerId: core.platform.resolveConsumerId
512
- } : {},
513
- ...managed.syncReportingReceipts ? {
514
- syncReportingReceipts: (request, context) => managed.syncReportingReceipts(request, context)
515
- } : {},
516
- async projectListAccounts(request, response, context) {
517
- const withoutDiagnostics = () => projectListAccountsReportingWebhookActivityV1({
518
- request: { ...request, include_webhook_activity: false },
519
- response,
520
- tenantId: "diagnostics-not-requested",
521
- principalId: "diagnostics-not-requested",
522
- activity: webhookActivity
523
- });
524
- if (request.include_webhook_activity !== true) return withoutDiagnostics();
525
- try {
526
- const scope = await options.resolveWebhookActivityScope(context);
527
- return await projectListAccountsReportingWebhookActivityV1({
528
- request,
529
- response,
530
- tenantId: scope.tenantId,
531
- principalId: scope.principalId,
532
- activity: webhookActivity
533
- });
534
- } catch (error) {
535
- defaultSchedulerWarn(`[adcp/reporting] webhook activity projection unavailable: ${safeMessage(error)}`);
536
- return withoutDiagnostics();
537
- }
538
- }
539
- };
540
- let auxiliaryAbort;
541
- let auxiliaryPromise;
542
- let auxiliaryRotation = 0;
543
- const reportAuxiliaryError = async (scheduler, error) => {
544
- if (scheduler.onError) {
545
- try {
546
- await scheduler.onError(error);
547
- return;
548
- } catch (observerError) {
549
- warnSchedulerFailure(scheduler, { phase: "cycle" }, error, observerError);
550
- return;
551
- }
552
- }
553
- warnSchedulerFailure(scheduler, { phase: "cycle" }, error);
554
- };
555
- const runAuxiliaryPass = async (scheduler, signal) => {
556
- signal.throwIfAborted();
557
- try {
558
- const totalLimit = scheduler.notificationRecoveryLimit ?? 25;
559
- const concurrency = Math.min(scheduler.notificationRecoveryConcurrency ?? 4, totalLimit);
560
- const baseLimit = Math.floor(totalLimit / concurrency);
561
- const remainder = totalLimit % concurrency;
562
- await Promise.all(
563
- Array.from(
564
- { length: concurrency },
565
- (_, index) => notificationActivity.recoverOnce({
566
- limit: baseLimit + (index < remainder ? 1 : 0),
567
- signal,
568
- onError: (error) => reportAuxiliaryError(scheduler, error)
569
- })
570
- )
571
- );
572
- } catch (error) {
573
- if (!signal.aborted) await reportAuxiliaryError(scheduler, error);
574
- }
575
- signal.throwIfAborted();
576
- try {
577
- await notifications.recoverOnce({ limit: scheduler.webhookRecoveryLimit ?? 10 });
578
- } catch (error) {
579
- if (!signal.aborted) await reportAuxiliaryError(scheduler, error);
580
- }
581
- signal.throwIfAborted();
582
- const pruneResults = await Promise.allSettled([
583
- notificationActivity.pruneProjected({ limit: 1e3 }),
584
- webhookActivity.pruneCompleted({ limit: 1e3 })
585
- ]);
586
- for (const result of pruneResults) {
587
- if (result.status === "rejected" && !signal.aborted) await reportAuxiliaryError(scheduler, result.reason);
588
- }
589
- await runReportingLedgerMaintenance({
590
- store: coreStore,
591
- sweepSnapshots: (limit) => sweepExpiredReportingLedgerState(options.db, limit),
592
- statusRetentionDays: options.statusRetentionDays,
593
- automatedRecoveryWindowSeconds: options.automatedRecoveryWindowSeconds,
594
- retention: options.retention,
595
- compaction: options.compaction,
596
- changeFeed: options.changeFeed,
597
- signal,
598
- report: (error) => reportAuxiliaryError(scheduler, error)
599
- });
600
- const accountIds = rotate(await deploymentWideAccountIds(coreStore), auxiliaryRotation);
601
- auxiliaryRotation += 1;
602
- for (const accountId of accountIds) {
603
- signal.throwIfAborted();
604
- try {
605
- await managed.runWorker({
606
- signal,
607
- ...accountId ? { account_id: accountId } : {},
608
- ...scheduler.maxWorkerIterationsPerAccount !== void 0 ? { maxIterations: scheduler.maxWorkerIterationsPerAccount } : {}
609
- });
610
- if (accountId) await managedStore.pruneExpiredEvidence?.({ account_id: accountId, limit: 1e3 });
611
- } catch (error) {
612
- if (!signal.aborted) await reportAuxiliaryError(scheduler, error);
613
- }
614
- }
615
- };
616
- const service = {
617
- setup: Object.freeze({ component: "reliable-reporting-production", migrations }),
618
- capabilities,
619
- platform,
620
- core,
621
- managed,
622
- notifications,
623
- notificationActivity,
624
- webhookActivity,
625
- stores: Object.freeze({ core: coreStore, managed: managedStore }),
626
- get running() {
627
- return core.running || auxiliaryPromise !== void 0;
628
- },
629
- installConfiguration: core.installConfiguration.bind(core),
630
- install(target) {
631
- if (typeof target.accounts.upsert !== "function") {
632
- throw new TypeError("Reliable reporting requires accounts.upsert");
633
- }
634
- if (typeof target.accounts.list !== "function") {
635
- throw new TypeError(
636
- "Reliable reporting production webhook activity requires accounts.list so list_accounts can serve the advertised diagnostics"
637
- );
638
- }
639
- if (target.reporting && target.reporting !== platform) {
640
- throw new TypeError("DecisioningPlatform already has a reporting lifecycle installed");
641
- }
642
- if (!target.reporting) {
643
- Object.defineProperty(target, "reporting", {
644
- value: platform,
645
- enumerable: true,
646
- configurable: false,
647
- writable: false
648
- });
649
- }
650
- return target;
651
- },
652
- async runCycle(cycle) {
653
- const coreResult = await core.runCycle(cycle);
654
- const managedResult = await managed.runWorker({
655
- ...cycle.signal ? { signal: cycle.signal } : {},
656
- ...!cycle.deploymentWide ? { account_id: cycle.accountId } : {},
657
- ...cycle.maxWorkerIterations !== void 0 ? { maxIterations: cycle.maxWorkerIterations } : {}
658
- });
659
- return { core: coreResult, managed: managedResult };
660
- },
661
- async recoverOnce(recoveryOptions) {
662
- if (recoveryOptions?.deploymentWide !== true) {
663
- throw new TypeError("Reliable Reporting production recovery requires deploymentWide: true");
664
- }
665
- const activityResult = await notificationActivity.recoverOnce();
666
- const webhookOutbox = await notifications.recoverOnce();
667
- return { activity: activityResult, webhookOutbox };
668
- },
669
- start(scheduler) {
670
- if (auxiliaryPromise) throw new Error("Reliable Reporting production scheduler is already running");
671
- if (scheduler.deploymentWide !== true) {
672
- throw new TypeError("Reliable Reporting production scheduler requires deploymentWide: true");
673
- }
674
- if (scheduler.notificationRecoveryLimit !== void 0 && (!Number.isSafeInteger(scheduler.notificationRecoveryLimit) || scheduler.notificationRecoveryLimit < 1 || scheduler.notificationRecoveryLimit > 1e3)) {
675
- throw new TypeError("notificationRecoveryLimit must be an integer from 1 through 1000");
676
- }
677
- if (scheduler.notificationRecoveryConcurrency !== void 0 && (!Number.isSafeInteger(scheduler.notificationRecoveryConcurrency) || scheduler.notificationRecoveryConcurrency < 1 || scheduler.notificationRecoveryConcurrency > 64)) {
678
- throw new TypeError("notificationRecoveryConcurrency must be an integer from 1 through 64");
679
- }
680
- if (scheduler.webhookRecoveryLimit !== void 0 && (!Number.isSafeInteger(scheduler.webhookRecoveryLimit) || scheduler.webhookRecoveryLimit < 1 || scheduler.webhookRecoveryLimit > 1e3)) {
681
- throw new TypeError("webhookRecoveryLimit must be an integer from 1 through 1000");
682
- }
683
- core.start(scheduler);
684
- auxiliaryAbort = new AbortController();
685
- const signal = auxiliaryAbort.signal;
686
- auxiliaryPromise = (async () => {
687
- while (!signal.aborted) {
688
- try {
689
- await runAuxiliaryPass(scheduler, signal);
690
- } catch (error) {
691
- if (!signal.aborted) await reportAuxiliaryError(scheduler, error);
692
- }
693
- if (!signal.aborted) await abortableDelay(scheduler.intervalMilliseconds, signal);
694
- }
695
- })().finally(() => {
696
- auxiliaryAbort = void 0;
697
- auxiliaryPromise = void 0;
698
- });
699
- },
700
- async stop() {
701
- auxiliaryAbort?.abort();
702
- await Promise.all([core.stop(), auxiliaryPromise]);
703
- }
704
- };
705
- return service;
706
- }
707
323
  function createRoutedSource(sources, offerings) {
708
324
  const capabilities = reportingSourceCapabilitiesV1([...offerings.values()], "reliable-reporting-service-v1");
709
325
  return {
@@ -734,15 +350,15 @@ async function schedulerLoop(service, options, signal, store, maintenance) {
734
350
  // it — the producer's own default cap starves the rest just as an
735
351
  // explicit per-account cap would. Enumerate the roster so each tenant
736
352
  // gets its own bounded cycle, and rotate the starting point each pass.
737
- rotate(await deploymentWideAccountIds(store), rotation)
738
- ) : rotate(
353
+ rotateReportingRoster(await reportingDeploymentWideAccountIds(store), rotation)
354
+ ) : rotateReportingRoster(
739
355
  validateAccountIds(
740
356
  typeof options.accountIds === "function" ? await options.accountIds() : options.accountIds
741
357
  ),
742
358
  rotation
743
359
  );
744
360
  } catch (error) {
745
- await reportSchedulerError(options, signal, error, { phase: "roster" });
361
+ await reportReportingSchedulerError(options, signal, error, { phase: "roster" });
746
362
  }
747
363
  rotation += 1;
748
364
  for (const accountId of accountIds) {
@@ -758,7 +374,7 @@ async function schedulerLoop(service, options, signal, store, maintenance) {
758
374
  ...options.settlementGraceMilliseconds !== void 0 ? { settlementGraceMilliseconds: options.settlementGraceMilliseconds } : {}
759
375
  });
760
376
  } catch (error) {
761
- await reportSchedulerError(options, signal, error, { phase: "cycle", accountId });
377
+ await reportReportingSchedulerError(options, signal, error, { phase: "cycle", accountId });
762
378
  }
763
379
  }
764
380
  if (maintenance && !signal.aborted && (lastMaintenanceAt === void 0 || Date.now() - lastMaintenanceAt >= maintenance.intervalMilliseconds)) {
@@ -766,99 +382,12 @@ async function schedulerLoop(service, options, signal, store, maintenance) {
766
382
  try {
767
383
  await maintenance.run();
768
384
  } catch (error) {
769
- await reportSchedulerError(options, signal, error, { phase: "maintenance" });
385
+ await reportReportingSchedulerError(options, signal, error, { phase: "maintenance" });
770
386
  }
771
387
  }
772
- if (!signal.aborted) await abortableDelay(options.intervalMilliseconds, signal);
388
+ if (!signal.aborted) await reportingSchedulerDelay(options.intervalMilliseconds, signal);
773
389
  }
774
390
  }
775
- async function reportSchedulerError(options, signal, error, site) {
776
- if (signal.aborted) return;
777
- if (options.onError) {
778
- try {
779
- await options.onError(error);
780
- } catch (observerError) {
781
- warnSchedulerFailure(options, site, error, observerError);
782
- }
783
- return;
784
- }
785
- warnSchedulerFailure(options, site, error);
786
- }
787
- function warnSchedulerFailure(options, site, error, observerError) {
788
- const where = site.phase === "roster" ? "could not resolve its account roster, so this pass ran no tenants" : site.phase === "maintenance" ? "ledger maintenance failed; the scheduler continues" : site.accountId === void 0 ? "deployment-wide cycle failed; the scheduler continues" : `cycle failed for account ${site.accountId}; later tenants continue`;
789
- const observed = observerError === void 0 ? "" : ` (the configured onError also threw: ${safeMessage(observerError)})`;
790
- const message = `[adcp/reporting] scheduler ${where}: ${safeMessage(error)}${observed}`;
791
- const logger = options.logger;
792
- try {
793
- if (logger !== void 0) logger.warn(message);
794
- else defaultSchedulerWarn(message);
795
- } catch {
796
- }
797
- }
798
- function defaultSchedulerWarn(message) {
799
- console.warn(message);
800
- }
801
- const MAX_SCHEDULER_MESSAGE_CHARS = 512;
802
- const MAX_SCHEDULER_SCAN_CHARS = 8192;
803
- const UNREPORTABLE_SCHEDULER_ERROR = "<unreportable error>";
804
- function safeMessage(error) {
805
- try {
806
- const raw = rawMessage(error);
807
- const redacted = redactCredentialPatterns(raw.slice(0, MAX_SCHEDULER_SCAN_CHARS));
808
- const text = typeof redacted === "string" && redacted.length > 0 ? redacted : UNREPORTABLE_SCHEDULER_ERROR;
809
- return text.length > MAX_SCHEDULER_MESSAGE_CHARS ? `${text.slice(0, MAX_SCHEDULER_MESSAGE_CHARS)}\u2026` : text;
810
- } catch {
811
- return UNREPORTABLE_SCHEDULER_ERROR;
812
- }
813
- }
814
- function rawMessage(error) {
815
- switch (typeof error) {
816
- case "string":
817
- return error;
818
- case "number":
819
- case "boolean":
820
- case "bigint":
821
- return String(error);
822
- case "undefined":
823
- return "undefined";
824
- case "symbol":
825
- return error.description ?? "symbol";
826
- default:
827
- break;
828
- }
829
- if (error === null) return "null";
830
- const message = error.message;
831
- return typeof message === "string" ? message : "non-Error scheduler failure";
832
- }
833
- const MAX_TIMER_DELAY_MILLISECONDS = 2147483647;
834
- async function abortableDelay(milliseconds, signal) {
835
- let remaining = milliseconds;
836
- while (remaining > 0 && !signal.aborted) {
837
- const chunk = Math.min(remaining, MAX_TIMER_DELAY_MILLISECONDS);
838
- await abortableTimeout(chunk, signal);
839
- remaining -= chunk;
840
- }
841
- }
842
- function abortableTimeout(milliseconds, signal) {
843
- return new Promise((resolve) => {
844
- const timer = setTimeout(done, milliseconds);
845
- function done() {
846
- clearTimeout(timer);
847
- signal.removeEventListener("abort", done);
848
- resolve();
849
- }
850
- signal.addEventListener("abort", done, { once: true });
851
- });
852
- }
853
- function rotate(values, by) {
854
- if (values.length < 2) return [...values];
855
- const offset = (by % values.length + values.length) % values.length;
856
- return [...values.slice(offset), ...values.slice(0, offset)];
857
- }
858
- async function deploymentWideAccountIds(store) {
859
- const configurations = await store.listConfigurations();
860
- return [...new Set(configurations.map((value) => value.account.account_id))].sort();
861
- }
862
391
  function validateAccountIds(values) {
863
392
  if (!Array.isArray(values)) {
864
393
  throw new TypeError("Reporting scheduler accountIds resolver must return an array");
@@ -912,7 +441,7 @@ function validateDeliveryOffering(source, delivery, allowManagedDelivery = false
912
441
  }
913
442
  if (!allowManagedDelivery && (delivery.method !== void 0 || delivery.reconciliation_mode !== "delivery_only" || delivery.feed_purpose === "billing")) {
914
443
  throw new TypeError(
915
- "Managed Delivery and Reconciled Billing require createPostgresReliableReportingProductionService from @adcp/sdk/reporting/service"
444
+ "Managed Delivery and Reconciled Billing require createPostgresReliableReportingProductionService from @adcp/reporting-storage/service"
916
445
  );
917
446
  }
918
447
  if (delivery.schedule.alignment !== "utc" && delivery.schedule.alignment !== "source_timezone") {
@@ -1254,11 +783,8 @@ function deepFreeze(value) {
1254
783
  return value;
1255
784
  }
1256
785
  export * from "./conformance.mjs";
1257
- import {
1258
- ReportingMaintenancePartialFailureError
1259
- } from "./maintenance.mjs";
786
+ export * from "./scheduler-support.mjs";
1260
787
  export {
1261
- ReportingMaintenancePartialFailureError,
1262
- createPostgresReliableReportingProductionService,
788
+ REPORTING_MANAGED_DELIVERY_COMPOSITION_V1,
1263
789
  createReliableReportingService
1264
790
  };