@adcp/sdk 15.3.0 → 15.4.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 (42) hide show
  1. package/dist/lib/reporting/ledger/handler.d.mts +6 -0
  2. package/dist/lib/reporting/ledger/handler.d.ts +6 -0
  3. package/dist/lib/reporting/ledger/handler.js +36 -7
  4. package/dist/lib/reporting/ledger/handler.mjs +35 -7
  5. package/dist/lib/reporting/ledger/index.d.mts +1 -0
  6. package/dist/lib/reporting/ledger/index.d.ts +1 -0
  7. package/dist/lib/reporting/ledger/index.js +3 -1
  8. package/dist/lib/reporting/ledger/index.mjs +1 -0
  9. package/dist/lib/reporting/ledger/lifecycle.js +3 -2
  10. package/dist/lib/reporting/ledger/lifecycle.mjs +3 -2
  11. package/dist/lib/reporting/ledger/managed-postgres.js +5 -5
  12. package/dist/lib/reporting/ledger/managed-postgres.mjs +5 -5
  13. package/dist/lib/reporting/ledger/postgres.d.mts +4 -1
  14. package/dist/lib/reporting/ledger/postgres.d.ts +4 -1
  15. package/dist/lib/reporting/ledger/postgres.js +38 -0
  16. package/dist/lib/reporting/ledger/postgres.mjs +38 -0
  17. package/dist/lib/reporting/ledger/producer.js +3 -2
  18. package/dist/lib/reporting/ledger/producer.mjs +3 -2
  19. package/dist/lib/reporting/ledger/revision-metadata.d.mts +17 -0
  20. package/dist/lib/reporting/ledger/revision-metadata.d.ts +17 -0
  21. package/dist/lib/reporting/ledger/revision-metadata.js +71 -0
  22. package/dist/lib/reporting/ledger/revision-metadata.mjs +44 -0
  23. package/dist/lib/reporting/ledger/row-encoding.d.mts +128 -0
  24. package/dist/lib/reporting/ledger/row-encoding.d.ts +128 -0
  25. package/dist/lib/reporting/ledger/row-encoding.js +355 -0
  26. package/dist/lib/reporting/ledger/row-encoding.mjs +315 -0
  27. package/dist/lib/reporting/ledger/types.d.mts +37 -0
  28. package/dist/lib/reporting/ledger/types.d.ts +37 -0
  29. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  30. package/dist/lib/signing/agent-resolver/fetch-helpers.js +1 -1
  31. package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +1 -1
  32. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  33. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  34. package/dist/lib/version.d.mts +3 -3
  35. package/dist/lib/version.d.ts +3 -3
  36. package/dist/lib/version.js +3 -3
  37. package/dist/lib/version.mjs +3 -3
  38. package/docs/TYPE-SUMMARY.md +1 -1
  39. package/docs/llms.txt +1 -1
  40. package/docs/migration-14.x-rc-worksheet.md +4 -4
  41. package/docs/recipes/verifying-inbound-webhooks.md +8 -0
  42. package/package.json +1 -1
@@ -15,6 +15,12 @@ export interface ReportingStatusConsumerScopeOptionsV1<TContext = unknown> {
15
15
  }
16
16
  export declare function createReportingStatusHandler(store: ReportingLedgerStore): (request: Parameters<ReportingStatusHandlerV1>[0], context: Pick<Parameters<ReportingStatusHandlerV1>[1], 'account' | 'signal'>) => ReturnType<ReportingStatusHandlerV1>;
17
17
  export declare function createReportingStatusHandler<TContext = unknown>(store: ReportingLedgerStore, options?: ReportingStatusConsumerScopeOptionsV1<TContext>): ReportingStatusHandlerV1;
18
+ /**
19
+ * Largest revision whose rows the `get_reporting_status` `revision` view
20
+ * returns inline. Larger revisions omit `reporting_rows` there; callers page
21
+ * them through the exact `get_media_buy_delivery` read.
22
+ */
23
+ export declare const REPORTING_STATUS_REVISION_VIEW_MAX_ROWS = 10000;
18
24
  /** Exact revision reader for createAdcpServer's getMediaBuyDelivery slot. */
19
25
  export declare function createReportingDeliveryHandler(store: ReportingLedgerStore): ReportingDeliveryHandlerV1;
20
26
  export interface ProjectManagedDeliveryInputV1 {
@@ -15,6 +15,12 @@ export interface ReportingStatusConsumerScopeOptionsV1<TContext = unknown> {
15
15
  }
16
16
  export declare function createReportingStatusHandler(store: ReportingLedgerStore): (request: Parameters<ReportingStatusHandlerV1>[0], context: Pick<Parameters<ReportingStatusHandlerV1>[1], 'account' | 'signal'>) => ReturnType<ReportingStatusHandlerV1>;
17
17
  export declare function createReportingStatusHandler<TContext = unknown>(store: ReportingLedgerStore, options?: ReportingStatusConsumerScopeOptionsV1<TContext>): ReportingStatusHandlerV1;
18
+ /**
19
+ * Largest revision whose rows the `get_reporting_status` `revision` view
20
+ * returns inline. Larger revisions omit `reporting_rows` there; callers page
21
+ * them through the exact `get_media_buy_delivery` read.
22
+ */
23
+ export declare const REPORTING_STATUS_REVISION_VIEW_MAX_ROWS = 10000;
18
24
  /** Exact revision reader for createAdcpServer's getMediaBuyDelivery slot. */
19
25
  export declare function createReportingDeliveryHandler(store: ReportingLedgerStore): ReportingDeliveryHandlerV1;
20
26
  export interface ProjectManagedDeliveryInputV1 {
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var handler_exports = {};
20
20
  __export(handler_exports, {
21
+ REPORTING_STATUS_REVISION_VIEW_MAX_ROWS: () => REPORTING_STATUS_REVISION_VIEW_MAX_ROWS,
21
22
  ReportingReadCapacityError: () => ReportingReadCapacityError,
22
23
  acquireAccountReadSlot: () => acquireAccountReadSlot,
23
24
  aggregateReportingCoverageV1: () => aggregateReportingCoverageV1,
@@ -34,6 +35,7 @@ var import_source = require('../source/index.js');
34
35
  var import_coverage = require('./coverage.js');
35
36
  var import_health = require('./health.js');
36
37
  var import_instant = require('./instant.js');
38
+ var import_revision_metadata = require('./revision-metadata.js');
37
39
  var import_schedule = require('./schedule.js');
38
40
  var import_types = require('./types.js');
39
41
  function createReportingStatusHandler(store, options) {
@@ -248,9 +250,22 @@ function createReportingStatusHandler(store, options) {
248
250
  const id = query.reporting_revision_id;
249
251
  const inSnapshot = id ? page.snapshot.revisions.some((value) => value.reporting_revision_id === id) : false;
250
252
  let revision = null;
253
+ let revisionRows;
251
254
  if (id && inSnapshot) {
252
255
  try {
253
- revision = await store.getRevision(id, accountId);
256
+ revision = await (0, import_revision_metadata.getRevisionMetadataFromStore)(store, id, accountId);
257
+ const rowCount = revision?.binding.rowCount ?? 0;
258
+ if (revision && rowCount <= REPORTING_STATUS_REVISION_VIEW_MAX_ROWS) {
259
+ const page2 = rowCount === 0 ? { rows: [], total: 0 } : await (0, import_revision_metadata.readRevisionRowsFromStore)(store, {
260
+ reporting_revision_id: id,
261
+ account_id: accountId,
262
+ offset: 0,
263
+ limit: rowCount,
264
+ ...context.signal ? { signal: context.signal } : {}
265
+ });
266
+ if (!page2 || page2.total !== rowCount) revision = null;
267
+ else revisionRows = page2.rows;
268
+ }
254
269
  } catch (error) {
255
270
  if (error instanceof ReportingReadCapacityError) return lookupUnavailable(view);
256
271
  throw error;
@@ -278,7 +293,7 @@ function createReportingStatusHandler(store, options) {
278
293
  revision_content_sha256: revision.wireRevision.revision_content_sha256,
279
294
  row_count: revision.binding.rowCount
280
295
  },
281
- reporting_rows: revision.rows,
296
+ ...revisionRows ? { reporting_rows: revisionRows } : {},
282
297
  adjustments: revisionAdjustments.map((value) => value.wireAdjustment),
283
298
  ...consumerId ? { consumer_statuses: (page.consumerStatuses ?? []).map(wireConsumerStatus) } : {},
284
299
  materializations: (page.materializations ?? []).filter(
@@ -391,6 +406,7 @@ function createReportingStatusHandler(store, options) {
391
406
  }
392
407
  };
393
408
  }
409
+ const REPORTING_STATUS_REVISION_VIEW_MAX_ROWS = 1e4;
394
410
  function createReportingDeliveryHandler(store) {
395
411
  const activeReadsByAccount = /* @__PURE__ */ new Map();
396
412
  return async (request, context) => {
@@ -411,7 +427,7 @@ function createReportingDeliveryHandler(store) {
411
427
  if (typeof raw.reporting_revision_id !== "string" || !raw.reporting_revision_id) {
412
428
  throw new Error("Ledger delivery reads require reporting_revision_id");
413
429
  }
414
- const revision = await store.getRevision(raw.reporting_revision_id, accountId);
430
+ const revision = await (0, import_revision_metadata.getRevisionMetadataFromStore)(store, raw.reporting_revision_id, accountId);
415
431
  if (!revision) throw new Error("Reporting revision is unavailable");
416
432
  const obligation = await store.getObligation(revision.reporting_obligation_id);
417
433
  if (!obligation || obligation.account.account_id !== accountId) {
@@ -419,11 +435,12 @@ function createReportingDeliveryHandler(store) {
419
435
  }
420
436
  const pagination = isRecord(raw.pagination) ? raw.pagination : {};
421
437
  const maxResults = typeof pagination.max_results === "number" && Number.isFinite(pagination.max_results) ? Math.max(1, Math.min(500, Math.trunc(pagination.max_results))) : 100;
438
+ const totalCount = revision.binding.rowCount;
422
439
  let offset = 0;
423
440
  if (typeof pagination.cursor === "string") {
424
441
  try {
425
442
  const cursor = JSON.parse(Buffer.from(pagination.cursor, "base64url").toString("utf8"));
426
- if (cursor.revisionId !== revision.reporting_revision_id || typeof cursor.offset !== "number" || !Number.isSafeInteger(cursor.offset) || cursor.offset < 0 || cursor.offset >= revision.rows.length) {
443
+ if (cursor.revisionId !== revision.reporting_revision_id || typeof cursor.offset !== "number" || !Number.isSafeInteger(cursor.offset) || cursor.offset < 0 || cursor.offset >= totalCount) {
427
444
  throw new Error("invalid");
428
445
  }
429
446
  offset = cursor.offset;
@@ -431,9 +448,20 @@ function createReportingDeliveryHandler(store) {
431
448
  throw new Error("Reporting delivery cursor is invalid");
432
449
  }
433
450
  }
434
- const reportingRows = revision.rows.slice(offset, offset + maxResults);
451
+ let reportingRows = [];
452
+ if (totalCount > 0) {
453
+ const page = await (0, import_revision_metadata.readRevisionRowsFromStore)(store, {
454
+ reporting_revision_id: revision.reporting_revision_id,
455
+ account_id: accountId,
456
+ offset,
457
+ limit: maxResults,
458
+ ...context.signal ? { signal: context.signal } : {}
459
+ });
460
+ if (!page || page.total !== totalCount) throw new Error("Reporting revision is unavailable");
461
+ reportingRows = page.rows;
462
+ }
435
463
  const nextOffset = offset + reportingRows.length;
436
- const hasMore = nextOffset < revision.rows.length;
464
+ const hasMore = nextOffset < totalCount;
437
465
  return {
438
466
  reporting_period: { start: obligation.period.start, end: obligation.period.end },
439
467
  media_buy_deliveries: [],
@@ -453,7 +481,7 @@ function createReportingDeliveryHandler(store) {
453
481
  errors: [],
454
482
  pagination: {
455
483
  has_more: hasMore,
456
- total_count: revision.rows.length,
484
+ total_count: totalCount,
457
485
  ...hasMore ? {
458
486
  cursor: Buffer.from(
459
487
  JSON.stringify({ revisionId: revision.reporting_revision_id, offset: nextOffset }),
@@ -966,6 +994,7 @@ function wireSchedule(obligation) {
966
994
  }
967
995
  // Annotate the CommonJS export names for ESM import in node:
968
996
  0 && (module.exports = {
997
+ REPORTING_STATUS_REVISION_VIEW_MAX_ROWS,
969
998
  ReportingReadCapacityError,
970
999
  acquireAccountReadSlot,
971
1000
  aggregateReportingCoverageV1,
@@ -18,6 +18,7 @@ import {
18
18
  projectReportingObligationHealthV1
19
19
  } from "./health.mjs";
20
20
  import { compareReportingInstants } from "./instant.mjs";
21
+ import { getRevisionMetadataFromStore, readRevisionRowsFromStore } from "./revision-metadata.mjs";
21
22
  import { reportingPeriodSchedule } from "./schedule.mjs";
22
23
  import { ReportingLedgerSnapshotUnavailableError } from "./types.mjs";
23
24
  function createReportingStatusHandler(store, options) {
@@ -232,9 +233,22 @@ function createReportingStatusHandler(store, options) {
232
233
  const id = query.reporting_revision_id;
233
234
  const inSnapshot = id ? page.snapshot.revisions.some((value) => value.reporting_revision_id === id) : false;
234
235
  let revision = null;
236
+ let revisionRows;
235
237
  if (id && inSnapshot) {
236
238
  try {
237
- revision = await store.getRevision(id, accountId);
239
+ revision = await getRevisionMetadataFromStore(store, id, accountId);
240
+ const rowCount = revision?.binding.rowCount ?? 0;
241
+ if (revision && rowCount <= REPORTING_STATUS_REVISION_VIEW_MAX_ROWS) {
242
+ const page2 = rowCount === 0 ? { rows: [], total: 0 } : await readRevisionRowsFromStore(store, {
243
+ reporting_revision_id: id,
244
+ account_id: accountId,
245
+ offset: 0,
246
+ limit: rowCount,
247
+ ...context.signal ? { signal: context.signal } : {}
248
+ });
249
+ if (!page2 || page2.total !== rowCount) revision = null;
250
+ else revisionRows = page2.rows;
251
+ }
238
252
  } catch (error) {
239
253
  if (error instanceof ReportingReadCapacityError) return lookupUnavailable(view);
240
254
  throw error;
@@ -262,7 +276,7 @@ function createReportingStatusHandler(store, options) {
262
276
  revision_content_sha256: revision.wireRevision.revision_content_sha256,
263
277
  row_count: revision.binding.rowCount
264
278
  },
265
- reporting_rows: revision.rows,
279
+ ...revisionRows ? { reporting_rows: revisionRows } : {},
266
280
  adjustments: revisionAdjustments.map((value) => value.wireAdjustment),
267
281
  ...consumerId ? { consumer_statuses: (page.consumerStatuses ?? []).map(wireConsumerStatus) } : {},
268
282
  materializations: (page.materializations ?? []).filter(
@@ -375,6 +389,7 @@ function createReportingStatusHandler(store, options) {
375
389
  }
376
390
  };
377
391
  }
392
+ const REPORTING_STATUS_REVISION_VIEW_MAX_ROWS = 1e4;
378
393
  function createReportingDeliveryHandler(store) {
379
394
  const activeReadsByAccount = /* @__PURE__ */ new Map();
380
395
  return async (request, context) => {
@@ -395,7 +410,7 @@ function createReportingDeliveryHandler(store) {
395
410
  if (typeof raw.reporting_revision_id !== "string" || !raw.reporting_revision_id) {
396
411
  throw new Error("Ledger delivery reads require reporting_revision_id");
397
412
  }
398
- const revision = await store.getRevision(raw.reporting_revision_id, accountId);
413
+ const revision = await getRevisionMetadataFromStore(store, raw.reporting_revision_id, accountId);
399
414
  if (!revision) throw new Error("Reporting revision is unavailable");
400
415
  const obligation = await store.getObligation(revision.reporting_obligation_id);
401
416
  if (!obligation || obligation.account.account_id !== accountId) {
@@ -403,11 +418,12 @@ function createReportingDeliveryHandler(store) {
403
418
  }
404
419
  const pagination = isRecord(raw.pagination) ? raw.pagination : {};
405
420
  const maxResults = typeof pagination.max_results === "number" && Number.isFinite(pagination.max_results) ? Math.max(1, Math.min(500, Math.trunc(pagination.max_results))) : 100;
421
+ const totalCount = revision.binding.rowCount;
406
422
  let offset = 0;
407
423
  if (typeof pagination.cursor === "string") {
408
424
  try {
409
425
  const cursor = JSON.parse(Buffer.from(pagination.cursor, "base64url").toString("utf8"));
410
- if (cursor.revisionId !== revision.reporting_revision_id || typeof cursor.offset !== "number" || !Number.isSafeInteger(cursor.offset) || cursor.offset < 0 || cursor.offset >= revision.rows.length) {
426
+ if (cursor.revisionId !== revision.reporting_revision_id || typeof cursor.offset !== "number" || !Number.isSafeInteger(cursor.offset) || cursor.offset < 0 || cursor.offset >= totalCount) {
411
427
  throw new Error("invalid");
412
428
  }
413
429
  offset = cursor.offset;
@@ -415,9 +431,20 @@ function createReportingDeliveryHandler(store) {
415
431
  throw new Error("Reporting delivery cursor is invalid");
416
432
  }
417
433
  }
418
- const reportingRows = revision.rows.slice(offset, offset + maxResults);
434
+ let reportingRows = [];
435
+ if (totalCount > 0) {
436
+ const page = await readRevisionRowsFromStore(store, {
437
+ reporting_revision_id: revision.reporting_revision_id,
438
+ account_id: accountId,
439
+ offset,
440
+ limit: maxResults,
441
+ ...context.signal ? { signal: context.signal } : {}
442
+ });
443
+ if (!page || page.total !== totalCount) throw new Error("Reporting revision is unavailable");
444
+ reportingRows = page.rows;
445
+ }
419
446
  const nextOffset = offset + reportingRows.length;
420
- const hasMore = nextOffset < revision.rows.length;
447
+ const hasMore = nextOffset < totalCount;
421
448
  return {
422
449
  reporting_period: { start: obligation.period.start, end: obligation.period.end },
423
450
  media_buy_deliveries: [],
@@ -437,7 +464,7 @@ function createReportingDeliveryHandler(store) {
437
464
  errors: [],
438
465
  pagination: {
439
466
  has_more: hasMore,
440
- total_count: revision.rows.length,
467
+ total_count: totalCount,
441
468
  ...hasMore ? {
442
469
  cursor: Buffer.from(
443
470
  JSON.stringify({ revisionId: revision.reporting_revision_id, offset: nextOffset }),
@@ -949,6 +976,7 @@ function wireSchedule(obligation) {
949
976
  };
950
977
  }
951
978
  export {
979
+ REPORTING_STATUS_REVISION_VIEW_MAX_ROWS,
952
980
  ReportingReadCapacityError,
953
981
  acquireAccountReadSlot,
954
982
  aggregateReportingCoverageV1,
@@ -11,3 +11,4 @@ export * from './managed.mjs';
11
11
  export * from './managed-postgres.mjs';
12
12
  export * from './object-writes.mjs';
13
13
  export * from './notification-activity.mjs';
14
+ export * from './row-encoding.mjs';
@@ -11,3 +11,4 @@ export * from './managed';
11
11
  export * from './managed-postgres';
12
12
  export * from './object-writes';
13
13
  export * from './notification-activity';
14
+ export * from './row-encoding';
@@ -28,6 +28,7 @@ __reExport(ledger_exports, require('./managed.js'), module.exports);
28
28
  __reExport(ledger_exports, require('./managed-postgres.js'), module.exports);
29
29
  __reExport(ledger_exports, require('./object-writes.js'), module.exports);
30
30
  __reExport(ledger_exports, require('./notification-activity.js'), module.exports);
31
+ __reExport(ledger_exports, require('./row-encoding.js'), module.exports);
31
32
  // Annotate the CommonJS export names for ESM import in node:
32
33
  0 && (module.exports = {
33
34
  ...require('./types.js'),
@@ -42,5 +43,6 @@ __reExport(ledger_exports, require('./notification-activity.js'), module.exports
42
43
  ...require('./managed.js'),
43
44
  ...require('./managed-postgres.js'),
44
45
  ...require('./object-writes.js'),
45
- ...require('./notification-activity.js')
46
+ ...require('./notification-activity.js'),
47
+ ...require('./row-encoding.js')
46
48
  });
@@ -11,3 +11,4 @@ export * from "./managed.mjs";
11
11
  export * from "./managed-postgres.mjs";
12
12
  export * from "./object-writes.mjs";
13
13
  export * from "./notification-activity.mjs";
14
+ export * from "./row-encoding.mjs";
@@ -28,6 +28,7 @@ var import_source = require('../source/index.js');
28
28
  var import_handler = require('./handler.js');
29
29
  var import_instant = require('./instant.js');
30
30
  var import_health = require('./health.js');
31
+ var import_revision_metadata = require('./revision-metadata.js');
31
32
  async function resolveLedgerAsOf(input, attempt) {
32
33
  const resolved = await input.store.readLedgerInstant?.() ?? (input.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
33
34
  if (input.ledgerAsOf === void 0) return resolved;
@@ -78,7 +79,7 @@ async function reconcileReportingStatusLifecycleV1(input, attempt = 0) {
78
79
  const transactionalNotifications = input.store.transactionalNotificationActivity === true;
79
80
  assertNotificationModesCompatible(input.store, input.subscribers);
80
81
  let ledgerAsOf = await resolveLedgerAsOf(input, attempt);
81
- const revisions = await input.store.listRevisions(obligation.reporting_obligation_id);
82
+ const revisions = await (0, import_revision_metadata.listRevisionMetadataFromStore)(input.store, obligation.reporting_obligation_id);
82
83
  let projected = revisions;
83
84
  const projectCore = (at) => (0, import_health.projectReportingObligationHealthV1)(
84
85
  obligation,
@@ -207,7 +208,7 @@ async function composeManagedLifecycleProjection(input, obligation, revisions, c
207
208
  ledgerAsOf: input.ledgerAsOf
208
209
  });
209
210
  if (!managed) return { projection: coreProjection };
210
- const stored = await input.store.listAdjustments(obligation.reporting_obligation_id);
211
+ const stored = await (0, import_revision_metadata.listAdjustmentMetadataFromStore)(input.store, obligation.reporting_obligation_id);
211
212
  const visibleAdjustmentIds = managed.visibleAdjustmentIds;
212
213
  const adjustments = visibleAdjustmentIds ? stored.filter((value) => visibleAdjustmentIds.includes(value.reporting_adjustment_id)) : stored.filter((value) => (0, import_instant.compareReportingInstants)(value.createdAt, input.ledgerAsOf) <= 0);
213
214
  const rosterAuthoritative = managed.obligatedConsumerRosterComplete === true && managed.receiptEvidenceComplete !== false;
@@ -3,6 +3,7 @@ import { canonicalJsonV1 } from "../source/index.mjs";
3
3
  import { moreSevereReportingHealthV1, projectManagedDelivery } from "./handler.mjs";
4
4
  import { compareReportingInstants } from "./instant.mjs";
5
5
  import { projectReportingObligationHealthV1 } from "./health.mjs";
6
+ import { listAdjustmentMetadataFromStore, listRevisionMetadataFromStore } from "./revision-metadata.mjs";
6
7
  async function resolveLedgerAsOf(input, attempt) {
7
8
  const resolved = await input.store.readLedgerInstant?.() ?? (input.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
8
9
  if (input.ledgerAsOf === void 0) return resolved;
@@ -53,7 +54,7 @@ async function reconcileReportingStatusLifecycleV1(input, attempt = 0) {
53
54
  const transactionalNotifications = input.store.transactionalNotificationActivity === true;
54
55
  assertNotificationModesCompatible(input.store, input.subscribers);
55
56
  let ledgerAsOf = await resolveLedgerAsOf(input, attempt);
56
- const revisions = await input.store.listRevisions(obligation.reporting_obligation_id);
57
+ const revisions = await listRevisionMetadataFromStore(input.store, obligation.reporting_obligation_id);
57
58
  let projected = revisions;
58
59
  const projectCore = (at) => projectReportingObligationHealthV1(
59
60
  obligation,
@@ -182,7 +183,7 @@ async function composeManagedLifecycleProjection(input, obligation, revisions, c
182
183
  ledgerAsOf: input.ledgerAsOf
183
184
  });
184
185
  if (!managed) return { projection: coreProjection };
185
- const stored = await input.store.listAdjustments(obligation.reporting_obligation_id);
186
+ const stored = await listAdjustmentMetadataFromStore(input.store, obligation.reporting_obligation_id);
186
187
  const visibleAdjustmentIds = managed.visibleAdjustmentIds;
187
188
  const adjustments = visibleAdjustmentIds ? stored.filter((value) => visibleAdjustmentIds.includes(value.reporting_adjustment_id)) : stored.filter((value) => compareReportingInstants(value.createdAt, input.ledgerAsOf) <= 0);
188
189
  const rosterAuthoritative = managed.obligatedConsumerRosterComplete === true && managed.receiptEvidenceComplete !== false;
@@ -987,7 +987,7 @@ class PostgresReportingManagedDeliveryStore {
987
987
  ])
988
988
  );
989
989
  const candidates = await client.query(
990
- `SELECT binding.data AS binding, obligation.data AS obligation, revision.data AS revision,
990
+ `SELECT binding.data AS binding, obligation.data AS obligation, revision.revision_id AS revision_id,
991
991
  GREATEST(COALESCE(MAX(existing.attempt), 0), COALESCE(MAX(tomb.highest_attempt), 0))::integer + 1
992
992
  AS attempt
993
993
  FROM adcp_reporting_managed_bindings binding
@@ -1007,7 +1007,7 @@ class PostgresReportingManagedDeliveryStore {
1007
1007
  ON tomb.configuration_id = binding.configuration_id AND tomb.revision_id = revision.revision_id
1008
1008
  WHERE ($1::text IS NULL OR binding.account_id = $1)
1009
1009
  GROUP BY binding.configuration_id, binding.data, obligation.obligation_id, obligation.data,
1010
- revision.revision_id, revision.data
1010
+ revision.revision_id
1011
1011
  HAVING NOT COALESCE(BOOL_OR(existing.status IN ('pending','available','delivered')), false)
1012
1012
  AND NOT COALESCE(BOOL_OR(tomb.reached_success), false)
1013
1013
  AND GREATEST(COALESCE(MAX(existing.attempt), 0), COALESCE(MAX(tomb.highest_attempt), 0))
@@ -1022,11 +1022,11 @@ class PostgresReportingManagedDeliveryStore {
1022
1022
  const remaining = remainingByAccount.get(binding.account_id) ?? 0;
1023
1023
  if (remaining <= 0) continue;
1024
1024
  const obligation = candidate.obligation;
1025
- const revision = candidate.revision;
1025
+ const revisionId = candidate.revision_id;
1026
1026
  const created_at = (/* @__PURE__ */ new Date()).toISOString();
1027
1027
  const materialization = {
1028
1028
  reporting_materialization_id: `rmat_${(0, import_node_crypto.randomUUID)()}`,
1029
- reporting_revision_id: revision.reporting_revision_id,
1029
+ reporting_revision_id: revisionId,
1030
1030
  reporting_obligation_id: obligation.reporting_obligation_id,
1031
1031
  delivery_config_id: binding.delivery_config_id,
1032
1032
  delivery_config_version: binding.delivery_config_version,
@@ -1049,7 +1049,7 @@ class PostgresReportingManagedDeliveryStore {
1049
1049
  binding.account_id,
1050
1050
  binding.configurationId,
1051
1051
  obligation.reporting_obligation_id,
1052
- revision.reporting_revision_id,
1052
+ revisionId,
1053
1053
  binding.destination_ref,
1054
1054
  binding.authorization_generation,
1055
1055
  candidate.attempt,
@@ -972,7 +972,7 @@ class PostgresReportingManagedDeliveryStore {
972
972
  ])
973
973
  );
974
974
  const candidates = await client.query(
975
- `SELECT binding.data AS binding, obligation.data AS obligation, revision.data AS revision,
975
+ `SELECT binding.data AS binding, obligation.data AS obligation, revision.revision_id AS revision_id,
976
976
  GREATEST(COALESCE(MAX(existing.attempt), 0), COALESCE(MAX(tomb.highest_attempt), 0))::integer + 1
977
977
  AS attempt
978
978
  FROM adcp_reporting_managed_bindings binding
@@ -992,7 +992,7 @@ class PostgresReportingManagedDeliveryStore {
992
992
  ON tomb.configuration_id = binding.configuration_id AND tomb.revision_id = revision.revision_id
993
993
  WHERE ($1::text IS NULL OR binding.account_id = $1)
994
994
  GROUP BY binding.configuration_id, binding.data, obligation.obligation_id, obligation.data,
995
- revision.revision_id, revision.data
995
+ revision.revision_id
996
996
  HAVING NOT COALESCE(BOOL_OR(existing.status IN ('pending','available','delivered')), false)
997
997
  AND NOT COALESCE(BOOL_OR(tomb.reached_success), false)
998
998
  AND GREATEST(COALESCE(MAX(existing.attempt), 0), COALESCE(MAX(tomb.highest_attempt), 0))
@@ -1007,11 +1007,11 @@ class PostgresReportingManagedDeliveryStore {
1007
1007
  const remaining = remainingByAccount.get(binding.account_id) ?? 0;
1008
1008
  if (remaining <= 0) continue;
1009
1009
  const obligation = candidate.obligation;
1010
- const revision = candidate.revision;
1010
+ const revisionId = candidate.revision_id;
1011
1011
  const created_at = (/* @__PURE__ */ new Date()).toISOString();
1012
1012
  const materialization = {
1013
1013
  reporting_materialization_id: `rmat_${randomUUID()}`,
1014
- reporting_revision_id: revision.reporting_revision_id,
1014
+ reporting_revision_id: revisionId,
1015
1015
  reporting_obligation_id: obligation.reporting_obligation_id,
1016
1016
  delivery_config_id: binding.delivery_config_id,
1017
1017
  delivery_config_version: binding.delivery_config_version,
@@ -1034,7 +1034,7 @@ class PostgresReportingManagedDeliveryStore {
1034
1034
  binding.account_id,
1035
1035
  binding.configurationId,
1036
1036
  obligation.reporting_obligation_id,
1037
- revision.reporting_revision_id,
1037
+ revisionId,
1038
1038
  binding.destination_ref,
1039
1039
  binding.authorization_generation,
1040
1040
  candidate.attempt,
@@ -1,5 +1,5 @@
1
1
  import { REPORTING_LEDGER_AUTHORITY } from './types.mjs';
2
- import type { ReportingLedgerConfigurationV1, ReportingLedgerAdjustmentV1, ReportingLedgerConsumerStatusV1, ReportingLedgerIssueV1, ReportingLedgerLeaseV1, ReportingLedgerObligationV1, ReportingLedgerPageV1, ReportingLedgerRevisionV1, ReportingLedgerSnapshotQueryV1, ReportingLedgerSnapshotV1, ReportingLedgerStatusTransitionV1, ReportingLedgerNotificationActivityPortV1, ReportingLedgerTransactionV1, ReportingObservedFinalityV1, ReportingLedgerStore, ReportingConsumerStatusBatchInputV1, ReportingConsumerStatusBatchResultV1, ReportingConsumerStatusReplayInputV1, ReportingLedgerRevisionMetadataV1, ReportingManagedLifecycleProjectionV1, ReportingLedgerAuthorityV1 } from './types.mjs';
2
+ import type { ReportingLedgerConfigurationV1, ReportingLedgerAdjustmentMetadataV1, ReportingLedgerAdjustmentV1, ReportingLedgerConsumerStatusV1, ReportingLedgerIssueV1, ReportingLedgerLeaseV1, ReportingLedgerObligationV1, ReportingLedgerPageV1, ReportingLedgerRevisionV1, ReportingLedgerSnapshotQueryV1, ReportingLedgerSnapshotV1, ReportingLedgerStatusTransitionV1, ReportingLedgerNotificationActivityPortV1, ReportingLedgerTransactionV1, ReportingObservedFinalityV1, ReportingLedgerStore, ReportingConsumerStatusBatchInputV1, ReportingConsumerStatusBatchResultV1, ReportingConsumerStatusReplayInputV1, ReportingLedgerRevisionMetadataV1, ReportingRevisionRowsPageV1, ReportingRevisionRowsReadV1, ReportingManagedLifecycleProjectionV1, ReportingLedgerAuthorityV1 } from './types.mjs';
3
3
  import type { ReportingConsumerMismatchEscalationV1 } from './types.mjs';
4
4
  type QueryResultRow = Record<string, unknown>;
5
5
  interface ReportingPgResult<Row extends QueryResultRow> {
@@ -144,12 +144,15 @@ export declare class PostgresReportingLedgerStore implements ReportingLedgerStor
144
144
  }>;
145
145
  getRevision(id: string, accountId: string): Promise<ReportingLedgerRevisionV1 | null>;
146
146
  getRevisionMetadata(id: string, accountId: string): Promise<ReportingLedgerRevisionMetadataV1 | null>;
147
+ readRevisionRows(input: ReportingRevisionRowsReadV1): Promise<ReportingRevisionRowsPageV1 | null>;
147
148
  listRevisions(obligationId: string): Promise<ReportingLedgerRevisionV1[]>;
149
+ listRevisionMetadata(obligationId: string, accountId?: string): Promise<ReportingLedgerRevisionMetadataV1[]>;
148
150
  commitAdjustment(adjustment: ReportingLedgerAdjustmentV1, lease: ReportingLedgerLeaseV1): Promise<{
149
151
  inserted: boolean;
150
152
  value: ReportingLedgerAdjustmentV1;
151
153
  }>;
152
154
  listAdjustments(obligationId: string): Promise<ReportingLedgerAdjustmentV1[]>;
155
+ listAdjustmentMetadata(obligationId: string): Promise<ReportingLedgerAdjustmentMetadataV1[]>;
153
156
  putConsumerStatus(status: ReportingLedgerConsumerStatusV1): Promise<{
154
157
  inserted: boolean;
155
158
  value: ReportingLedgerConsumerStatusV1;
@@ -1,5 +1,5 @@
1
1
  import { REPORTING_LEDGER_AUTHORITY } from './types';
2
- import type { ReportingLedgerConfigurationV1, ReportingLedgerAdjustmentV1, ReportingLedgerConsumerStatusV1, ReportingLedgerIssueV1, ReportingLedgerLeaseV1, ReportingLedgerObligationV1, ReportingLedgerPageV1, ReportingLedgerRevisionV1, ReportingLedgerSnapshotQueryV1, ReportingLedgerSnapshotV1, ReportingLedgerStatusTransitionV1, ReportingLedgerNotificationActivityPortV1, ReportingLedgerTransactionV1, ReportingObservedFinalityV1, ReportingLedgerStore, ReportingConsumerStatusBatchInputV1, ReportingConsumerStatusBatchResultV1, ReportingConsumerStatusReplayInputV1, ReportingLedgerRevisionMetadataV1, ReportingManagedLifecycleProjectionV1, ReportingLedgerAuthorityV1 } from './types';
2
+ import type { ReportingLedgerConfigurationV1, ReportingLedgerAdjustmentMetadataV1, ReportingLedgerAdjustmentV1, ReportingLedgerConsumerStatusV1, ReportingLedgerIssueV1, ReportingLedgerLeaseV1, ReportingLedgerObligationV1, ReportingLedgerPageV1, ReportingLedgerRevisionV1, ReportingLedgerSnapshotQueryV1, ReportingLedgerSnapshotV1, ReportingLedgerStatusTransitionV1, ReportingLedgerNotificationActivityPortV1, ReportingLedgerTransactionV1, ReportingObservedFinalityV1, ReportingLedgerStore, ReportingConsumerStatusBatchInputV1, ReportingConsumerStatusBatchResultV1, ReportingConsumerStatusReplayInputV1, ReportingLedgerRevisionMetadataV1, ReportingRevisionRowsPageV1, ReportingRevisionRowsReadV1, ReportingManagedLifecycleProjectionV1, ReportingLedgerAuthorityV1 } from './types';
3
3
  import type { ReportingConsumerMismatchEscalationV1 } from './types';
4
4
  type QueryResultRow = Record<string, unknown>;
5
5
  interface ReportingPgResult<Row extends QueryResultRow> {
@@ -144,12 +144,15 @@ export declare class PostgresReportingLedgerStore implements ReportingLedgerStor
144
144
  }>;
145
145
  getRevision(id: string, accountId: string): Promise<ReportingLedgerRevisionV1 | null>;
146
146
  getRevisionMetadata(id: string, accountId: string): Promise<ReportingLedgerRevisionMetadataV1 | null>;
147
+ readRevisionRows(input: ReportingRevisionRowsReadV1): Promise<ReportingRevisionRowsPageV1 | null>;
147
148
  listRevisions(obligationId: string): Promise<ReportingLedgerRevisionV1[]>;
149
+ listRevisionMetadata(obligationId: string, accountId?: string): Promise<ReportingLedgerRevisionMetadataV1[]>;
148
150
  commitAdjustment(adjustment: ReportingLedgerAdjustmentV1, lease: ReportingLedgerLeaseV1): Promise<{
149
151
  inserted: boolean;
150
152
  value: ReportingLedgerAdjustmentV1;
151
153
  }>;
152
154
  listAdjustments(obligationId: string): Promise<ReportingLedgerAdjustmentV1[]>;
155
+ listAdjustmentMetadata(obligationId: string): Promise<ReportingLedgerAdjustmentMetadataV1[]>;
153
156
  putConsumerStatus(status: ReportingLedgerConsumerStatusV1): Promise<{
154
157
  inserted: boolean;
155
158
  value: ReportingLedgerConsumerStatusV1;
@@ -695,6 +695,26 @@ ${managedDueArm} )
695
695
  [id, accountId]
696
696
  );
697
697
  }
698
+ async readRevisionRows(input) {
699
+ if (!Number.isSafeInteger(input.offset) || input.offset < 0 || !Number.isSafeInteger(input.limit) || input.limit < 1) {
700
+ throw new RangeError("Reporting row page bounds are invalid");
701
+ }
702
+ const result = await this.query(
703
+ `SELECT jsonb_array_length(revision.data->'rows') AS total,
704
+ jsonb_path_query_array(
705
+ revision.data->'rows',
706
+ '$[$from to $to]',
707
+ jsonb_build_object('from', $3::bigint, 'to', $3::bigint + $4::bigint - 1)
708
+ ) AS rows
709
+ FROM adcp_reporting_revisions revision
710
+ JOIN adcp_reporting_obligations obligation ON obligation.obligation_id = revision.obligation_id
711
+ WHERE revision.revision_id = $1 AND obligation.account_id = $2`,
712
+ [input.reporting_revision_id, input.account_id, input.offset, input.limit]
713
+ );
714
+ const row = result.rows[0];
715
+ if (!row) return null;
716
+ return { rows: clone(row.rows), total: Number(row.total) };
717
+ }
698
718
  async listRevisions(obligationId) {
699
719
  const result = await this.query(
700
720
  `SELECT data FROM adcp_reporting_revisions WHERE obligation_id = $1
@@ -703,6 +723,16 @@ ${managedDueArm} )
703
723
  );
704
724
  return result.rows.map((row) => clone(row.data));
705
725
  }
726
+ async listRevisionMetadata(obligationId, accountId) {
727
+ const result = await this.query(
728
+ `SELECT revision.data - 'rows' AS data FROM adcp_reporting_revisions revision
729
+ JOIN adcp_reporting_obligations obligation ON obligation.obligation_id = revision.obligation_id
730
+ WHERE revision.obligation_id = $1 AND ($2::text IS NULL OR obligation.account_id = $2)
731
+ ORDER BY revision.revision_number, revision.revision_id`,
732
+ [obligationId, accountId ?? null]
733
+ );
734
+ return result.rows.map((row) => clone(row.data));
735
+ }
706
736
  async commitAdjustment(adjustment, lease) {
707
737
  assertLeaseTarget(adjustment.reporting_obligation_id, lease);
708
738
  validateBoundRows(adjustment);
@@ -766,6 +796,14 @@ ${managedDueArm} )
766
796
  );
767
797
  return result.rows.map((row) => clone(row.data));
768
798
  }
799
+ async listAdjustmentMetadata(obligationId) {
800
+ const result = await this.query(
801
+ `SELECT data - 'rows' AS data FROM adcp_reporting_adjustments WHERE obligation_id = $1
802
+ ORDER BY adjustment_number, adjustment_id`,
803
+ [obligationId]
804
+ );
805
+ return result.rows.map((row) => clone(row.data));
806
+ }
769
807
  async putConsumerStatus(status) {
770
808
  const obligation = await this.getObligation(status.reporting_obligation_id);
771
809
  if (!obligation) throw new Error("Reporting consumer status obligation is unavailable");
@@ -686,6 +686,26 @@ ${managedDueArm} )
686
686
  [id, accountId]
687
687
  );
688
688
  }
689
+ async readRevisionRows(input) {
690
+ if (!Number.isSafeInteger(input.offset) || input.offset < 0 || !Number.isSafeInteger(input.limit) || input.limit < 1) {
691
+ throw new RangeError("Reporting row page bounds are invalid");
692
+ }
693
+ const result = await this.query(
694
+ `SELECT jsonb_array_length(revision.data->'rows') AS total,
695
+ jsonb_path_query_array(
696
+ revision.data->'rows',
697
+ '$[$from to $to]',
698
+ jsonb_build_object('from', $3::bigint, 'to', $3::bigint + $4::bigint - 1)
699
+ ) AS rows
700
+ FROM adcp_reporting_revisions revision
701
+ JOIN adcp_reporting_obligations obligation ON obligation.obligation_id = revision.obligation_id
702
+ WHERE revision.revision_id = $1 AND obligation.account_id = $2`,
703
+ [input.reporting_revision_id, input.account_id, input.offset, input.limit]
704
+ );
705
+ const row = result.rows[0];
706
+ if (!row) return null;
707
+ return { rows: clone(row.rows), total: Number(row.total) };
708
+ }
689
709
  async listRevisions(obligationId) {
690
710
  const result = await this.query(
691
711
  `SELECT data FROM adcp_reporting_revisions WHERE obligation_id = $1
@@ -694,6 +714,16 @@ ${managedDueArm} )
694
714
  );
695
715
  return result.rows.map((row) => clone(row.data));
696
716
  }
717
+ async listRevisionMetadata(obligationId, accountId) {
718
+ const result = await this.query(
719
+ `SELECT revision.data - 'rows' AS data FROM adcp_reporting_revisions revision
720
+ JOIN adcp_reporting_obligations obligation ON obligation.obligation_id = revision.obligation_id
721
+ WHERE revision.obligation_id = $1 AND ($2::text IS NULL OR obligation.account_id = $2)
722
+ ORDER BY revision.revision_number, revision.revision_id`,
723
+ [obligationId, accountId ?? null]
724
+ );
725
+ return result.rows.map((row) => clone(row.data));
726
+ }
697
727
  async commitAdjustment(adjustment, lease) {
698
728
  assertLeaseTarget(adjustment.reporting_obligation_id, lease);
699
729
  validateBoundRows(adjustment);
@@ -757,6 +787,14 @@ ${managedDueArm} )
757
787
  );
758
788
  return result.rows.map((row) => clone(row.data));
759
789
  }
790
+ async listAdjustmentMetadata(obligationId) {
791
+ const result = await this.query(
792
+ `SELECT data - 'rows' AS data FROM adcp_reporting_adjustments WHERE obligation_id = $1
793
+ ORDER BY adjustment_number, adjustment_id`,
794
+ [obligationId]
795
+ );
796
+ return result.rows.map((row) => clone(row.data));
797
+ }
760
798
  async putConsumerStatus(status) {
761
799
  const obligation = await this.getObligation(status.reporting_obligation_id);
762
800
  if (!obligation) throw new Error("Reporting consumer status obligation is unavailable");
@@ -32,6 +32,7 @@ var import_source = require('../source/index.js');
32
32
  var import_coverage = require('./coverage.js');
33
33
  var import_schedule = require('./schedule.js');
34
34
  var import_lifecycle = require('./lifecycle.js');
35
+ var import_revision_metadata = require('./revision-metadata.js');
35
36
  const DEFAULT_LEASE_MS = 3e5;
36
37
  const EXECUTION_DEADLINE_MS = 24e4;
37
38
  const DEFAULT_SETTLEMENT_GRACE_MS = 1e4;
@@ -268,8 +269,8 @@ function createReportingProducer(options) {
268
269
  );
269
270
  }
270
271
  }
271
- const previous = await options.store.listRevisions(obligation.reporting_obligation_id);
272
- const adjustments = await options.store.listAdjustments(obligation.reporting_obligation_id);
272
+ const previous = await (0, import_revision_metadata.listRevisionMetadataFromStore)(options.store, obligation.reporting_obligation_id);
273
+ const adjustments = await (0, import_revision_metadata.listAdjustmentMetadataFromStore)(options.store, obligation.reporting_obligation_id);
273
274
  const publicationCount = previous.length + adjustments.length;
274
275
  if (publicationCount > 0) {
275
276
  const scheduledAt = nextPublicationAt(obligation, publicationCount);
@@ -28,6 +28,7 @@ import {
28
28
  reconcileReportingStatusLifecycleV1,
29
29
  retryReportingStatusNotificationsV1
30
30
  } from "./lifecycle.mjs";
31
+ import { listAdjustmentMetadataFromStore, listRevisionMetadataFromStore } from "./revision-metadata.mjs";
31
32
  const DEFAULT_LEASE_MS = 3e5;
32
33
  const EXECUTION_DEADLINE_MS = 24e4;
33
34
  const DEFAULT_SETTLEMENT_GRACE_MS = 1e4;
@@ -264,8 +265,8 @@ function createReportingProducer(options) {
264
265
  );
265
266
  }
266
267
  }
267
- const previous = await options.store.listRevisions(obligation.reporting_obligation_id);
268
- const adjustments = await options.store.listAdjustments(obligation.reporting_obligation_id);
268
+ const previous = await listRevisionMetadataFromStore(options.store, obligation.reporting_obligation_id);
269
+ const adjustments = await listAdjustmentMetadataFromStore(options.store, obligation.reporting_obligation_id);
269
270
  const publicationCount = previous.length + adjustments.length;
270
271
  if (publicationCount > 0) {
271
272
  const scheduledAt = nextPublicationAt(obligation, publicationCount);