@adcp/sdk 15.2.2 → 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 (48) hide show
  1. package/dist/lib/core/ConversationTypes.d.mts +5 -0
  2. package/dist/lib/core/ConversationTypes.d.ts +5 -0
  3. package/dist/lib/core/SingleAgentClient.d.mts +19 -1
  4. package/dist/lib/core/SingleAgentClient.d.ts +19 -1
  5. package/dist/lib/core/SingleAgentClient.js +38 -7
  6. package/dist/lib/core/SingleAgentClient.mjs +38 -7
  7. package/dist/lib/index.d.mts +1 -1
  8. package/dist/lib/index.d.ts +1 -1
  9. package/dist/lib/reporting/ledger/handler.d.mts +6 -0
  10. package/dist/lib/reporting/ledger/handler.d.ts +6 -0
  11. package/dist/lib/reporting/ledger/handler.js +36 -7
  12. package/dist/lib/reporting/ledger/handler.mjs +35 -7
  13. package/dist/lib/reporting/ledger/index.d.mts +1 -0
  14. package/dist/lib/reporting/ledger/index.d.ts +1 -0
  15. package/dist/lib/reporting/ledger/index.js +3 -1
  16. package/dist/lib/reporting/ledger/index.mjs +1 -0
  17. package/dist/lib/reporting/ledger/lifecycle.js +3 -2
  18. package/dist/lib/reporting/ledger/lifecycle.mjs +3 -2
  19. package/dist/lib/reporting/ledger/managed-postgres.js +5 -5
  20. package/dist/lib/reporting/ledger/managed-postgres.mjs +5 -5
  21. package/dist/lib/reporting/ledger/postgres.d.mts +4 -1
  22. package/dist/lib/reporting/ledger/postgres.d.ts +4 -1
  23. package/dist/lib/reporting/ledger/postgres.js +38 -0
  24. package/dist/lib/reporting/ledger/postgres.mjs +38 -0
  25. package/dist/lib/reporting/ledger/producer.js +3 -2
  26. package/dist/lib/reporting/ledger/producer.mjs +3 -2
  27. package/dist/lib/reporting/ledger/revision-metadata.d.mts +17 -0
  28. package/dist/lib/reporting/ledger/revision-metadata.d.ts +17 -0
  29. package/dist/lib/reporting/ledger/revision-metadata.js +71 -0
  30. package/dist/lib/reporting/ledger/revision-metadata.mjs +44 -0
  31. package/dist/lib/reporting/ledger/row-encoding.d.mts +128 -0
  32. package/dist/lib/reporting/ledger/row-encoding.d.ts +128 -0
  33. package/dist/lib/reporting/ledger/row-encoding.js +355 -0
  34. package/dist/lib/reporting/ledger/row-encoding.mjs +315 -0
  35. package/dist/lib/reporting/ledger/types.d.mts +37 -0
  36. package/dist/lib/reporting/ledger/types.d.ts +37 -0
  37. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  38. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  39. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  40. package/dist/lib/version.d.mts +3 -3
  41. package/dist/lib/version.d.ts +3 -3
  42. package/dist/lib/version.js +3 -3
  43. package/dist/lib/version.mjs +3 -3
  44. package/docs/TYPE-SUMMARY.md +2 -1
  45. package/docs/guides/PUSH-NOTIFICATION-CONFIG.md +39 -0
  46. package/docs/llms.txt +1 -1
  47. package/docs/migration-14.x-rc-worksheet.md +4 -4
  48. package/package.json +1 -1
@@ -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);
@@ -0,0 +1,17 @@
1
+ import type { ReportingLedgerAdjustmentMetadataV1, ReportingLedgerRevisionMetadataV1, ReportingLedgerStore, ReportingRevisionRowsPageV1, ReportingRevisionRowsReadV1 } from './types.mjs';
2
+ /**
3
+ * Row-free revision listing for paths that only need identity, finality,
4
+ * supersession, binding and wire metadata. Prefers the store's
5
+ * `listRevisionMetadata`; a store without it is read through `listRevisions`
6
+ * and its rows are dropped before they reach the caller.
7
+ */
8
+ export declare function listRevisionMetadataFromStore(store: Pick<ReportingLedgerStore, 'listRevisions' | 'listRevisionMetadata'>, reporting_obligation_id: string): Promise<ReportingLedgerRevisionMetadataV1[]>;
9
+ /** Row-free counterpart of {@link listRevisionMetadataFromStore} for adjustments. */
10
+ export declare function listAdjustmentMetadataFromStore(store: Pick<ReportingLedgerStore, 'listAdjustments' | 'listAdjustmentMetadata'>, reporting_obligation_id: string): Promise<ReportingLedgerAdjustmentMetadataV1[]>;
11
+ /** Account-scoped revision metadata, preferring the store's row-free read. */
12
+ export declare function getRevisionMetadataFromStore(store: Pick<ReportingLedgerStore, 'getRevision' | 'getRevisionMetadata'>, reporting_revision_id: string, account_id: string): Promise<ReportingLedgerRevisionMetadataV1 | null>;
13
+ /**
14
+ * One page of a revision's rows. Prefers the store's paged reader; otherwise
15
+ * loads the revision through `getRevision` and slices it.
16
+ */
17
+ export declare function readRevisionRowsFromStore(store: Pick<ReportingLedgerStore, 'getRevision' | 'readRevisionRows'>, input: ReportingRevisionRowsReadV1): Promise<ReportingRevisionRowsPageV1 | null>;
@@ -0,0 +1,17 @@
1
+ import type { ReportingLedgerAdjustmentMetadataV1, ReportingLedgerRevisionMetadataV1, ReportingLedgerStore, ReportingRevisionRowsPageV1, ReportingRevisionRowsReadV1 } from './types';
2
+ /**
3
+ * Row-free revision listing for paths that only need identity, finality,
4
+ * supersession, binding and wire metadata. Prefers the store's
5
+ * `listRevisionMetadata`; a store without it is read through `listRevisions`
6
+ * and its rows are dropped before they reach the caller.
7
+ */
8
+ export declare function listRevisionMetadataFromStore(store: Pick<ReportingLedgerStore, 'listRevisions' | 'listRevisionMetadata'>, reporting_obligation_id: string): Promise<ReportingLedgerRevisionMetadataV1[]>;
9
+ /** Row-free counterpart of {@link listRevisionMetadataFromStore} for adjustments. */
10
+ export declare function listAdjustmentMetadataFromStore(store: Pick<ReportingLedgerStore, 'listAdjustments' | 'listAdjustmentMetadata'>, reporting_obligation_id: string): Promise<ReportingLedgerAdjustmentMetadataV1[]>;
11
+ /** Account-scoped revision metadata, preferring the store's row-free read. */
12
+ export declare function getRevisionMetadataFromStore(store: Pick<ReportingLedgerStore, 'getRevision' | 'getRevisionMetadata'>, reporting_revision_id: string, account_id: string): Promise<ReportingLedgerRevisionMetadataV1 | null>;
13
+ /**
14
+ * One page of a revision's rows. Prefers the store's paged reader; otherwise
15
+ * loads the revision through `getRevision` and slices it.
16
+ */
17
+ export declare function readRevisionRowsFromStore(store: Pick<ReportingLedgerStore, 'getRevision' | 'readRevisionRows'>, input: ReportingRevisionRowsReadV1): Promise<ReportingRevisionRowsPageV1 | null>;
@@ -0,0 +1,71 @@
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 revision_metadata_exports = {};
20
+ __export(revision_metadata_exports, {
21
+ getRevisionMetadataFromStore: () => getRevisionMetadataFromStore,
22
+ listAdjustmentMetadataFromStore: () => listAdjustmentMetadataFromStore,
23
+ listRevisionMetadataFromStore: () => listRevisionMetadataFromStore,
24
+ readRevisionRowsFromStore: () => readRevisionRowsFromStore
25
+ });
26
+ module.exports = __toCommonJS(revision_metadata_exports);
27
+ async function listRevisionMetadataFromStore(store, reporting_obligation_id) {
28
+ if (typeof store.listRevisionMetadata === "function") {
29
+ return store.listRevisionMetadata(reporting_obligation_id);
30
+ }
31
+ const revisions = await store.listRevisions(reporting_obligation_id);
32
+ return revisions.map(({ rows: _rows, ...metadata }) => metadata);
33
+ }
34
+ async function listAdjustmentMetadataFromStore(store, reporting_obligation_id) {
35
+ if (typeof store.listAdjustmentMetadata === "function") {
36
+ return store.listAdjustmentMetadata(reporting_obligation_id);
37
+ }
38
+ const adjustments = await store.listAdjustments(reporting_obligation_id);
39
+ return adjustments.map(({ rows: _rows, ...metadata }) => metadata);
40
+ }
41
+ async function getRevisionMetadataFromStore(store, reporting_revision_id, account_id) {
42
+ if (typeof store.getRevisionMetadata === "function") {
43
+ return store.getRevisionMetadata(reporting_revision_id, account_id);
44
+ }
45
+ const revision = await store.getRevision(reporting_revision_id, account_id);
46
+ if (!revision) return null;
47
+ const { rows: _rows, ...metadata } = revision;
48
+ return metadata;
49
+ }
50
+ async function readRevisionRowsFromStore(store, input) {
51
+ if (!Number.isSafeInteger(input.offset) || input.offset < 0) {
52
+ throw new RangeError("Reporting row page offset must be a non-negative integer");
53
+ }
54
+ if (!Number.isSafeInteger(input.limit) || input.limit < 1) {
55
+ throw new RangeError("Reporting row page limit must be a positive integer");
56
+ }
57
+ if (typeof store.readRevisionRows === "function") return store.readRevisionRows(input);
58
+ const revision = await store.getRevision(input.reporting_revision_id, input.account_id);
59
+ if (!revision) return null;
60
+ return {
61
+ rows: revision.rows.slice(input.offset, input.offset + input.limit),
62
+ total: revision.rows.length
63
+ };
64
+ }
65
+ // Annotate the CommonJS export names for ESM import in node:
66
+ 0 && (module.exports = {
67
+ getRevisionMetadataFromStore,
68
+ listAdjustmentMetadataFromStore,
69
+ listRevisionMetadataFromStore,
70
+ readRevisionRowsFromStore
71
+ });
@@ -0,0 +1,44 @@
1
+ async function listRevisionMetadataFromStore(store, reporting_obligation_id) {
2
+ if (typeof store.listRevisionMetadata === "function") {
3
+ return store.listRevisionMetadata(reporting_obligation_id);
4
+ }
5
+ const revisions = await store.listRevisions(reporting_obligation_id);
6
+ return revisions.map(({ rows: _rows, ...metadata }) => metadata);
7
+ }
8
+ async function listAdjustmentMetadataFromStore(store, reporting_obligation_id) {
9
+ if (typeof store.listAdjustmentMetadata === "function") {
10
+ return store.listAdjustmentMetadata(reporting_obligation_id);
11
+ }
12
+ const adjustments = await store.listAdjustments(reporting_obligation_id);
13
+ return adjustments.map(({ rows: _rows, ...metadata }) => metadata);
14
+ }
15
+ async function getRevisionMetadataFromStore(store, reporting_revision_id, account_id) {
16
+ if (typeof store.getRevisionMetadata === "function") {
17
+ return store.getRevisionMetadata(reporting_revision_id, account_id);
18
+ }
19
+ const revision = await store.getRevision(reporting_revision_id, account_id);
20
+ if (!revision) return null;
21
+ const { rows: _rows, ...metadata } = revision;
22
+ return metadata;
23
+ }
24
+ async function readRevisionRowsFromStore(store, input) {
25
+ if (!Number.isSafeInteger(input.offset) || input.offset < 0) {
26
+ throw new RangeError("Reporting row page offset must be a non-negative integer");
27
+ }
28
+ if (!Number.isSafeInteger(input.limit) || input.limit < 1) {
29
+ throw new RangeError("Reporting row page limit must be a positive integer");
30
+ }
31
+ if (typeof store.readRevisionRows === "function") return store.readRevisionRows(input);
32
+ const revision = await store.getRevision(input.reporting_revision_id, input.account_id);
33
+ if (!revision) return null;
34
+ return {
35
+ rows: revision.rows.slice(input.offset, input.offset + input.limit),
36
+ total: revision.rows.length
37
+ };
38
+ }
39
+ export {
40
+ getRevisionMetadataFromStore,
41
+ listAdjustmentMetadataFromStore,
42
+ listRevisionMetadataFromStore,
43
+ readRevisionRowsFromStore
44
+ };
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Canonical JSONL row encoding for reporting revisions (shared SDK
3
+ * persistence contract, `reporting-row-storage` v1).
4
+ *
5
+ * Rows are stored as `JCS(row) + "\n"` in ordinal order. JCS escapes newline
6
+ * characters inside strings, so the `0x0A` byte only ever separates rows.
7
+ * Rows are grouped into segments (the unit of verification and paged reads)
8
+ * and chunks (the unit of storage). Boundaries are fixed by the contract so
9
+ * every SDK produces byte-identical chunks and manifests for the same rows:
10
+ *
11
+ * - a new chunk starts when the current chunk holds
12
+ * {@link REPORTING_ROW_CHUNK_MAX_ROWS} rows, or when appending the next row
13
+ * would exceed {@link REPORTING_ROW_CHUNK_MAX_BYTES} canonical bytes;
14
+ * - segments restart at each chunk boundary and close every
15
+ * {@link REPORTING_ROW_SEGMENT_MAX_ROWS} rows.
16
+ *
17
+ * A row larger than the chunk byte limit forms its own segment and chunk.
18
+ * Digests always cover uncompressed canonical bytes.
19
+ */
20
+ export declare const REPORTING_ROW_ENCODING_V1: "adcp_canonical_jsonl_v1";
21
+ export declare const REPORTING_ROW_SEGMENT_MAX_ROWS = 500;
22
+ export declare const REPORTING_ROW_CHUNK_MAX_SEGMENTS = 20;
23
+ export declare const REPORTING_ROW_CHUNK_MAX_ROWS: number;
24
+ export declare const REPORTING_ROW_CHUNK_MAX_BYTES: number;
25
+ export type ReportingRowEncodingErrorCode = 'INVALID_ROW' | 'MANIFEST_MISMATCH' | 'CHUNK_INTEGRITY_FAILED' | 'ENVELOPE_INTEGRITY_FAILED';
26
+ export declare class ReportingRowEncodingError extends Error {
27
+ readonly code: ReportingRowEncodingErrorCode;
28
+ constructor(code: ReportingRowEncodingErrorCode, detail: string);
29
+ }
30
+ export declare function isReportingRowEncodingError(error: unknown): error is ReportingRowEncodingError;
31
+ export interface ReportingRowSegmentManifestV1 {
32
+ first_ordinal: number;
33
+ row_count: number;
34
+ /** Offset of the segment within its chunk's uncompressed canonical bytes. */
35
+ byte_offset: number;
36
+ byte_count: number;
37
+ sha256: string;
38
+ }
39
+ export interface ReportingRowChunkManifestV1 {
40
+ chunk_index: number;
41
+ first_ordinal: number;
42
+ row_count: number;
43
+ byte_count: number;
44
+ sha256: string;
45
+ segments: ReportingRowSegmentManifestV1[];
46
+ }
47
+ export interface ReportingRowChunkV1 {
48
+ manifest: ReportingRowChunkManifestV1;
49
+ /** Uncompressed canonical JSONL bytes. */
50
+ bytes: Buffer;
51
+ }
52
+ export interface ReportingEncodedRowsV1 {
53
+ encoding: typeof REPORTING_ROW_ENCODING_V1;
54
+ rowCount: number;
55
+ /** Total canonical JSONL bytes across all chunks. */
56
+ byteCount: number;
57
+ chunks: ReportingRowChunkV1[];
58
+ manifests: ReportingRowChunkManifestV1[];
59
+ /** `sha256(JCS(manifests))`; bound immutably on the revision header. */
60
+ rowManifestSha256: string;
61
+ }
62
+ export interface ReportingRevisionEnvelopeInputV1 {
63
+ reporting_revision_id: string;
64
+ row_count: number;
65
+ control_totals: readonly unknown[];
66
+ }
67
+ export interface ReportingRevisionEnvelopeDigestV1 {
68
+ sha256: string;
69
+ /** Byte length of the canonical envelope; equals `binding.byteCount`. */
70
+ byteCount: number;
71
+ }
72
+ /**
73
+ * Canonicalize one row for storage. Refuses values whose canonical bytes are
74
+ * not portable across conforming JCS implementations: non-plain objects,
75
+ * non-finite numbers, integers outside ±(2^53 − 1), and lone surrogates.
76
+ */
77
+ export declare function canonicalReportingRowV1(row: unknown, ordinal?: number): string;
78
+ /** Encode rows into contract-fixed canonical JSONL chunks and manifests. */
79
+ export declare function encodeReportingRowsV1(rows: readonly unknown[]): ReportingEncodedRowsV1;
80
+ /** `sha256(JCS(manifests))` over the ordered chunk manifests, locators excluded. */
81
+ export declare function reportingRowManifestSha256V1(manifests: readonly ReportingRowChunkManifestV1[]): string;
82
+ /**
83
+ * Verify that a manifest set is internally consistent and matches the
84
+ * header's committed `row_manifest_sha256` and `row_count`. Ordinals must be
85
+ * contiguous from zero, chunk and segment boundaries must follow the contract
86
+ * limits, and segment byte ranges must tile their chunk exactly.
87
+ */
88
+ export declare function verifyReportingRowManifestsV1(manifests: readonly ReportingRowChunkManifestV1[], expected: {
89
+ rowCount: number;
90
+ rowManifestSha256: string;
91
+ }): void;
92
+ /**
93
+ * Verify a whole chunk's canonical bytes against its manifest: total digest,
94
+ * byte count, and every segment's digest and line count.
95
+ */
96
+ export declare function verifyReportingRowChunkV1(manifest: ReportingRowChunkManifestV1, bytes: Uint8Array): void;
97
+ /**
98
+ * Verify and decode a contiguous range of segments `[fromSegment, toSegment]`
99
+ * (inclusive). `bytes` must hold exactly those segments' canonical bytes,
100
+ * starting at the first segment's `byte_offset` — the shape returned by a
101
+ * ranged object read. Rows are released only after every segment verifies.
102
+ */
103
+ export declare function decodeVerifiedReportingRowSegmentsV1(manifest: ReportingRowChunkManifestV1, segmentRange: readonly [fromSegment: number, toSegment: number], bytes: Uint8Array): Record<string, unknown>[];
104
+ /**
105
+ * Streaming hasher for the protocol revision binding
106
+ * `sha256(JCS({reporting_revision_id, row_count, control_totals, reporting_rows}))`.
107
+ * Feed verified chunk bytes in order; rows are never parsed.
108
+ */
109
+ export declare function createReportingRevisionEnvelopeHasherV1(envelope: ReportingRevisionEnvelopeInputV1): {
110
+ update(chunkBytes: Uint8Array): void;
111
+ digest(): ReportingRevisionEnvelopeDigestV1;
112
+ };
113
+ /** Envelope digest over already-encoded chunk bytes. */
114
+ export declare function reportingRevisionEnvelopeDigestV1(envelope: ReportingRevisionEnvelopeInputV1, chunks: Iterable<Uint8Array>): ReportingRevisionEnvelopeDigestV1;
115
+ /** Streaming hasher for digest profile `rows_v1`: `sha256(JCS(rows))`. */
116
+ export declare function createReportingRowsOnlyHasherV1(rowCount: number): {
117
+ update(chunkBytes: Uint8Array): void;
118
+ digest(): ReportingRevisionEnvelopeDigestV1;
119
+ };
120
+ /**
121
+ * Throw unless the canonical chunks reproduce the header's committed revision
122
+ * binding. Used at write time (proof that chunks and envelope agree) and for
123
+ * full-revision reads.
124
+ */
125
+ export declare function assertReportingRevisionEnvelopeV1(envelope: ReportingRevisionEnvelopeInputV1, chunks: Iterable<Uint8Array>, expected: {
126
+ sha256: string;
127
+ byteCount?: number;
128
+ }): void;