@tiangong-lca/cli 0.0.22 → 0.0.23

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.
@@ -0,0 +1,270 @@
1
+ import { CliError } from './errors.js';
2
+ function isRecord(value) {
3
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
4
+ }
5
+ function isIntegerBetween(value, minimum, maximum) {
6
+ return Number.isInteger(value) && Number(value) >= minimum && Number(value) <= maximum;
7
+ }
8
+ export function isDatasetMaintenanceSnapshotCompleteness(value, expectedTables) {
9
+ if (!isRecord(value))
10
+ return false;
11
+ if (value.status !== 'complete' ||
12
+ value.complete !== true ||
13
+ value.strategy !== 'postgrest_exact_count_multi_request' ||
14
+ !isIntegerBetween(value.requested_page_size, 1, 5_000) ||
15
+ !isIntegerBetween(value.page_count, expectedTables.length, Number.MAX_SAFE_INTEGER) ||
16
+ !isIntegerBetween(value.row_count, 0, Number.MAX_SAFE_INTEGER)) {
17
+ return false;
18
+ }
19
+ const entityCounts = value.entity_counts;
20
+ if (!isRecord(entityCounts))
21
+ return false;
22
+ const expectedTableSet = new Set(expectedTables);
23
+ const entityCountKeys = Object.keys(entityCounts);
24
+ if (entityCountKeys.length !== expectedTables.length ||
25
+ entityCountKeys.some((table) => !expectedTableSet.has(table))) {
26
+ return false;
27
+ }
28
+ for (const table of expectedTables) {
29
+ if (!isIntegerBetween(entityCounts[table], 0, Number.MAX_SAFE_INTEGER)) {
30
+ return false;
31
+ }
32
+ }
33
+ if (!Array.isArray(value.tables) || value.tables.length !== expectedTables.length)
34
+ return false;
35
+ const observedTables = new Set();
36
+ let pageCount = 0;
37
+ let rowCount = 0;
38
+ for (const rawTable of value.tables) {
39
+ if (!isRecord(rawTable))
40
+ return false;
41
+ const table = rawTable.table;
42
+ if (typeof table !== 'string' || !expectedTableSet.has(table) || observedTables.has(table)) {
43
+ return false;
44
+ }
45
+ if (rawTable.status !== 'complete' ||
46
+ rawTable.complete !== true ||
47
+ rawTable.strategy !== 'postgrest_exact_count' ||
48
+ rawTable.requested_page_size !== value.requested_page_size ||
49
+ !isIntegerBetween(rawTable.effective_page_size, 0, value.requested_page_size) ||
50
+ !isIntegerBetween(rawTable.pages_fetched, 1, Number.MAX_SAFE_INTEGER) ||
51
+ !isIntegerBetween(rawTable.rows_fetched, 0, Number.MAX_SAFE_INTEGER) ||
52
+ rawTable.exact_total !== rawTable.rows_fetched ||
53
+ (rawTable.rows_fetched === 0) !== (rawTable.effective_page_size === 0) ||
54
+ (rawTable.rows_fetched === 0
55
+ ? rawTable.pages_fetched !== 1
56
+ : rawTable.pages_fetched > rawTable.rows_fetched ||
57
+ rawTable.effective_page_size > rawTable.rows_fetched - rawTable.pages_fetched + 1 ||
58
+ rawTable.rows_fetched > rawTable.pages_fetched * rawTable.effective_page_size) ||
59
+ rawTable.termination_reason !== 'content_range_total_reached' ||
60
+ rawTable.content_range_verified !== true ||
61
+ rawTable.ordering_verified !== true ||
62
+ rawTable.duplicate_count !== 0 ||
63
+ rawTable.rows_fetched !== entityCounts[table]) {
64
+ return false;
65
+ }
66
+ observedTables.add(table);
67
+ pageCount += rawTable.pages_fetched;
68
+ rowCount += rawTable.rows_fetched;
69
+ }
70
+ return pageCount === value.page_count && rowCount === value.row_count;
71
+ }
72
+ export function isSnapshotCompletenessCompatible(value, baseline, expectedTables) {
73
+ if (value === undefined)
74
+ return baseline === undefined;
75
+ if (!isDatasetMaintenanceSnapshotCompleteness(value, expectedTables))
76
+ return false;
77
+ if (baseline === undefined)
78
+ return true;
79
+ return (value.row_count === baseline.row_count &&
80
+ expectedTables.every((table) => value.entity_counts[table] === baseline.entity_counts[table]));
81
+ }
82
+ function incomplete(details) {
83
+ throw new CliError('PostgREST pagination could not prove a complete maintenance snapshot.', {
84
+ code: 'DATASET_MAINTENANCE_SNAPSHOT_INCOMPLETE',
85
+ exitCode: 1,
86
+ details,
87
+ });
88
+ }
89
+ export function parseExactContentRange(value, details = {}) {
90
+ const match = value?.trim().match(/^(?:items\s+)?(?:(\d+)-(\d+)|\*)\/(\d+)$/iu);
91
+ if (!match) {
92
+ return incomplete({
93
+ ...details,
94
+ reason: 'content_range_missing_or_invalid',
95
+ content_range: value,
96
+ });
97
+ }
98
+ const start = match[1] === undefined ? null : Number.parseInt(match[1], 10);
99
+ const end = match[2] === undefined ? null : Number.parseInt(match[2], 10);
100
+ const total = Number.parseInt(match[3], 10);
101
+ if (!Number.isSafeInteger(total) ||
102
+ (start !== null &&
103
+ (end === null || !Number.isSafeInteger(start) || !Number.isSafeInteger(end))) ||
104
+ (start !== null && end < start)) {
105
+ return incomplete({ ...details, reason: 'content_range_out_of_bounds', content_range: value });
106
+ }
107
+ return { start, end, total };
108
+ }
109
+ export async function fetchCompletePostgrestPages(options) {
110
+ const rows = [];
111
+ const sourceUrls = [];
112
+ let expectedTotal = null;
113
+ let offset = 0;
114
+ let pagesFetched = 0;
115
+ let effectivePageSize = 0;
116
+ let previousIdentity = null;
117
+ while (true) {
118
+ const page = await options.fetchPage(offset);
119
+ pagesFetched += 1;
120
+ sourceUrls.push(page.source_url);
121
+ effectivePageSize = Math.max(effectivePageSize, page.rows.length);
122
+ const range = parseExactContentRange(page.content_range, {
123
+ table: options.table,
124
+ offset,
125
+ source_url: page.source_url,
126
+ });
127
+ if (expectedTotal === null) {
128
+ expectedTotal = range.total;
129
+ }
130
+ else if (range.total !== expectedTotal) {
131
+ return incomplete({
132
+ table: options.table,
133
+ offset,
134
+ source_url: page.source_url,
135
+ reason: 'exact_total_changed_between_pages',
136
+ expected_total: expectedTotal,
137
+ observed_total: range.total,
138
+ });
139
+ }
140
+ if (page.rows.length === 0) {
141
+ if (range.start !== null || offset !== 0 || range.total !== 0) {
142
+ return incomplete({
143
+ table: options.table,
144
+ offset,
145
+ source_url: page.source_url,
146
+ reason: 'empty_page_before_exact_total',
147
+ expected_total: expectedTotal,
148
+ content_range: page.content_range,
149
+ });
150
+ }
151
+ return {
152
+ rows,
153
+ source_urls: sourceUrls,
154
+ completeness: {
155
+ status: 'complete',
156
+ complete: true,
157
+ strategy: 'postgrest_exact_count',
158
+ requested_page_size: options.requestedPageSize,
159
+ effective_page_size: effectivePageSize,
160
+ pages_fetched: pagesFetched,
161
+ rows_fetched: 0,
162
+ exact_total: 0,
163
+ termination_reason: 'content_range_total_reached',
164
+ content_range_verified: true,
165
+ ordering_verified: true,
166
+ duplicate_count: 0,
167
+ },
168
+ };
169
+ }
170
+ if (page.rows.length > options.requestedPageSize ||
171
+ range.start !== offset ||
172
+ range.end !== offset + page.rows.length - 1) {
173
+ return incomplete({
174
+ table: options.table,
175
+ offset,
176
+ source_url: page.source_url,
177
+ reason: 'content_range_does_not_match_page',
178
+ requested_page_size: options.requestedPageSize,
179
+ returned_rows: page.rows.length,
180
+ content_range: page.content_range,
181
+ });
182
+ }
183
+ for (const row of page.rows) {
184
+ const identity = options.rowIdentity(row);
185
+ if (!identity) {
186
+ return incomplete({
187
+ table: options.table,
188
+ offset,
189
+ source_url: page.source_url,
190
+ reason: 'row_identity_missing',
191
+ });
192
+ }
193
+ if (previousIdentity !== null && identity <= previousIdentity) {
194
+ return incomplete({
195
+ table: options.table,
196
+ offset,
197
+ source_url: page.source_url,
198
+ reason: identity === previousIdentity ? 'duplicate_row_identity' : 'row_order_not_strict',
199
+ previous_identity: previousIdentity,
200
+ observed_identity: identity,
201
+ });
202
+ }
203
+ previousIdentity = identity;
204
+ }
205
+ rows.push(...page.rows);
206
+ const nextOffset = offset + page.rows.length;
207
+ if (nextOffset > expectedTotal) {
208
+ return incomplete({
209
+ table: options.table,
210
+ offset,
211
+ source_url: page.source_url,
212
+ reason: 'rows_exceed_exact_total',
213
+ expected_total: expectedTotal,
214
+ rows_fetched: nextOffset,
215
+ });
216
+ }
217
+ if (nextOffset === expectedTotal) {
218
+ return {
219
+ rows,
220
+ source_urls: sourceUrls,
221
+ completeness: {
222
+ status: 'complete',
223
+ complete: true,
224
+ strategy: 'postgrest_exact_count',
225
+ requested_page_size: options.requestedPageSize,
226
+ effective_page_size: effectivePageSize,
227
+ pages_fetched: pagesFetched,
228
+ rows_fetched: rows.length,
229
+ exact_total: expectedTotal,
230
+ termination_reason: 'content_range_total_reached',
231
+ content_range_verified: true,
232
+ ordering_verified: true,
233
+ duplicate_count: 0,
234
+ },
235
+ };
236
+ }
237
+ offset = nextOffset;
238
+ }
239
+ }
240
+ export function buildSnapshotCompleteness(options) {
241
+ const expectedTables = new Set(options.tables);
242
+ const observedTables = new Set(options.results.map((result) => result.table));
243
+ if (options.results.length !== options.tables.length ||
244
+ observedTables.size !== expectedTables.size ||
245
+ [...observedTables].some((table) => !expectedTables.has(table))) {
246
+ return incomplete({
247
+ reason: 'aggregate_table_set_invalid',
248
+ expected_tables: [...options.tables],
249
+ observed_tables: options.results.map((result) => result.table),
250
+ });
251
+ }
252
+ const entityCounts = Object.fromEntries(options.tables.map((table) => [
253
+ table,
254
+ options.results.find((result) => result.table === table).completeness.rows_fetched,
255
+ ]));
256
+ return {
257
+ status: 'complete',
258
+ complete: true,
259
+ strategy: 'postgrest_exact_count_multi_request',
260
+ requested_page_size: options.requestedPageSize,
261
+ page_count: options.results.reduce((sum, result) => sum + result.completeness.pages_fetched, 0),
262
+ row_count: options.results.reduce((sum, result) => sum + result.completeness.rows_fetched, 0),
263
+ entity_counts: entityCounts,
264
+ tables: options.results.map((result) => ({
265
+ table: result.table,
266
+ ...result.completeness,
267
+ })),
268
+ };
269
+ }
270
+ //# sourceMappingURL=dataset-maintenance-pagination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataset-maintenance-pagination.js","sourceRoot":"","sources":["../../../src/lib/dataset-maintenance-pagination.ts"],"names":[],"mappings":"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","sourcesContent":["import { CliError } from './errors.js';\n\nexport type DatasetMaintenanceTableCompleteness = {\n status: 'complete';\n complete: true;\n strategy: 'postgrest_exact_count';\n requested_page_size: number;\n effective_page_size: number;\n pages_fetched: number;\n rows_fetched: number;\n exact_total: number;\n termination_reason: 'content_range_total_reached';\n content_range_verified: true;\n ordering_verified: true;\n duplicate_count: 0;\n};\n\nexport type DatasetMaintenanceSnapshotCompleteness<Table extends string = string> = {\n status: 'complete';\n complete: true;\n strategy: 'postgrest_exact_count_multi_request';\n requested_page_size: number;\n page_count: number;\n row_count: number;\n entity_counts: Record<Table, number>;\n tables: Array<{ table: Table } & DatasetMaintenanceTableCompleteness>;\n};\n\nexport type DatasetMaintenancePage<T> = {\n rows: T[];\n source_url: string;\n content_range: string | null;\n};\n\ntype ParsedContentRange = {\n start: number | null;\n end: number | null;\n total: number;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isIntegerBetween(value: unknown, minimum: number, maximum: number): value is number {\n return Number.isInteger(value) && Number(value) >= minimum && Number(value) <= maximum;\n}\n\nexport function isDatasetMaintenanceSnapshotCompleteness<Table extends string>(\n value: unknown,\n expectedTables: readonly Table[],\n): value is DatasetMaintenanceSnapshotCompleteness<Table> {\n if (!isRecord(value)) return false;\n if (\n value.status !== 'complete' ||\n value.complete !== true ||\n value.strategy !== 'postgrest_exact_count_multi_request' ||\n !isIntegerBetween(value.requested_page_size, 1, 5_000) ||\n !isIntegerBetween(value.page_count, expectedTables.length, Number.MAX_SAFE_INTEGER) ||\n !isIntegerBetween(value.row_count, 0, Number.MAX_SAFE_INTEGER)\n ) {\n return false;\n }\n\n const entityCounts = value.entity_counts;\n if (!isRecord(entityCounts)) return false;\n const expectedTableSet = new Set<string>(expectedTables);\n const entityCountKeys = Object.keys(entityCounts);\n if (\n entityCountKeys.length !== expectedTables.length ||\n entityCountKeys.some((table) => !expectedTableSet.has(table))\n ) {\n return false;\n }\n for (const table of expectedTables) {\n if (!isIntegerBetween(entityCounts[table], 0, Number.MAX_SAFE_INTEGER)) {\n return false;\n }\n }\n\n if (!Array.isArray(value.tables) || value.tables.length !== expectedTables.length) return false;\n const observedTables = new Set<string>();\n let pageCount = 0;\n let rowCount = 0;\n for (const rawTable of value.tables) {\n if (!isRecord(rawTable)) return false;\n const table = rawTable.table;\n if (typeof table !== 'string' || !expectedTableSet.has(table) || observedTables.has(table)) {\n return false;\n }\n if (\n rawTable.status !== 'complete' ||\n rawTable.complete !== true ||\n rawTable.strategy !== 'postgrest_exact_count' ||\n rawTable.requested_page_size !== value.requested_page_size ||\n !isIntegerBetween(rawTable.effective_page_size, 0, value.requested_page_size) ||\n !isIntegerBetween(rawTable.pages_fetched, 1, Number.MAX_SAFE_INTEGER) ||\n !isIntegerBetween(rawTable.rows_fetched, 0, Number.MAX_SAFE_INTEGER) ||\n rawTable.exact_total !== rawTable.rows_fetched ||\n (rawTable.rows_fetched === 0) !== (rawTable.effective_page_size === 0) ||\n (rawTable.rows_fetched === 0\n ? rawTable.pages_fetched !== 1\n : rawTable.pages_fetched > rawTable.rows_fetched ||\n rawTable.effective_page_size > rawTable.rows_fetched - rawTable.pages_fetched + 1 ||\n rawTable.rows_fetched > rawTable.pages_fetched * rawTable.effective_page_size) ||\n rawTable.termination_reason !== 'content_range_total_reached' ||\n rawTable.content_range_verified !== true ||\n rawTable.ordering_verified !== true ||\n rawTable.duplicate_count !== 0 ||\n rawTable.rows_fetched !== entityCounts[table]\n ) {\n return false;\n }\n observedTables.add(table);\n pageCount += rawTable.pages_fetched;\n rowCount += rawTable.rows_fetched;\n }\n\n return pageCount === value.page_count && rowCount === value.row_count;\n}\n\nexport function isSnapshotCompletenessCompatible<Table extends string>(\n value: unknown,\n baseline: DatasetMaintenanceSnapshotCompleteness<Table> | undefined,\n expectedTables: readonly Table[],\n): boolean {\n if (value === undefined) return baseline === undefined;\n if (!isDatasetMaintenanceSnapshotCompleteness(value, expectedTables)) return false;\n if (baseline === undefined) return true;\n return (\n value.row_count === baseline.row_count &&\n expectedTables.every((table) => value.entity_counts[table] === baseline.entity_counts[table])\n );\n}\n\nfunction incomplete(details: Record<string, unknown>): never {\n throw new CliError('PostgREST pagination could not prove a complete maintenance snapshot.', {\n code: 'DATASET_MAINTENANCE_SNAPSHOT_INCOMPLETE',\n exitCode: 1,\n details,\n });\n}\n\nexport function parseExactContentRange(\n value: string | null,\n details: Record<string, unknown> = {},\n): ParsedContentRange {\n const match = value?.trim().match(/^(?:items\\s+)?(?:(\\d+)-(\\d+)|\\*)\\/(\\d+)$/iu);\n if (!match) {\n return incomplete({\n ...details,\n reason: 'content_range_missing_or_invalid',\n content_range: value,\n });\n }\n const start = match[1] === undefined ? null : Number.parseInt(match[1], 10);\n const end = match[2] === undefined ? null : Number.parseInt(match[2], 10);\n const total = Number.parseInt(match[3]!, 10);\n if (\n !Number.isSafeInteger(total) ||\n (start !== null &&\n (end === null || !Number.isSafeInteger(start) || !Number.isSafeInteger(end))) ||\n (start !== null && end! < start)\n ) {\n return incomplete({ ...details, reason: 'content_range_out_of_bounds', content_range: value });\n }\n return { start, end, total };\n}\n\nexport async function fetchCompletePostgrestPages<T>(options: {\n table: string;\n requestedPageSize: number;\n fetchPage: (offset: number) => Promise<DatasetMaintenancePage<T>>;\n rowIdentity: (row: T) => string | null;\n}): Promise<{\n rows: T[];\n source_urls: string[];\n completeness: DatasetMaintenanceTableCompleteness;\n}> {\n const rows: T[] = [];\n const sourceUrls: string[] = [];\n let expectedTotal: number | null = null;\n let offset = 0;\n let pagesFetched = 0;\n let effectivePageSize = 0;\n let previousIdentity: string | null = null;\n\n while (true) {\n const page = await options.fetchPage(offset);\n pagesFetched += 1;\n sourceUrls.push(page.source_url);\n effectivePageSize = Math.max(effectivePageSize, page.rows.length);\n const range = parseExactContentRange(page.content_range, {\n table: options.table,\n offset,\n source_url: page.source_url,\n });\n if (expectedTotal === null) {\n expectedTotal = range.total;\n } else if (range.total !== expectedTotal) {\n return incomplete({\n table: options.table,\n offset,\n source_url: page.source_url,\n reason: 'exact_total_changed_between_pages',\n expected_total: expectedTotal,\n observed_total: range.total,\n });\n }\n\n if (page.rows.length === 0) {\n if (range.start !== null || offset !== 0 || range.total !== 0) {\n return incomplete({\n table: options.table,\n offset,\n source_url: page.source_url,\n reason: 'empty_page_before_exact_total',\n expected_total: expectedTotal,\n content_range: page.content_range,\n });\n }\n return {\n rows,\n source_urls: sourceUrls,\n completeness: {\n status: 'complete',\n complete: true,\n strategy: 'postgrest_exact_count',\n requested_page_size: options.requestedPageSize,\n effective_page_size: effectivePageSize,\n pages_fetched: pagesFetched,\n rows_fetched: 0,\n exact_total: 0,\n termination_reason: 'content_range_total_reached',\n content_range_verified: true,\n ordering_verified: true,\n duplicate_count: 0,\n },\n };\n }\n\n if (\n page.rows.length > options.requestedPageSize ||\n range.start !== offset ||\n range.end !== offset + page.rows.length - 1\n ) {\n return incomplete({\n table: options.table,\n offset,\n source_url: page.source_url,\n reason: 'content_range_does_not_match_page',\n requested_page_size: options.requestedPageSize,\n returned_rows: page.rows.length,\n content_range: page.content_range,\n });\n }\n\n for (const row of page.rows) {\n const identity = options.rowIdentity(row);\n if (!identity) {\n return incomplete({\n table: options.table,\n offset,\n source_url: page.source_url,\n reason: 'row_identity_missing',\n });\n }\n if (previousIdentity !== null && identity <= previousIdentity) {\n return incomplete({\n table: options.table,\n offset,\n source_url: page.source_url,\n reason: identity === previousIdentity ? 'duplicate_row_identity' : 'row_order_not_strict',\n previous_identity: previousIdentity,\n observed_identity: identity,\n });\n }\n previousIdentity = identity;\n }\n\n rows.push(...page.rows);\n const nextOffset = offset + page.rows.length;\n if (nextOffset > expectedTotal) {\n return incomplete({\n table: options.table,\n offset,\n source_url: page.source_url,\n reason: 'rows_exceed_exact_total',\n expected_total: expectedTotal,\n rows_fetched: nextOffset,\n });\n }\n if (nextOffset === expectedTotal) {\n return {\n rows,\n source_urls: sourceUrls,\n completeness: {\n status: 'complete',\n complete: true,\n strategy: 'postgrest_exact_count',\n requested_page_size: options.requestedPageSize,\n effective_page_size: effectivePageSize,\n pages_fetched: pagesFetched,\n rows_fetched: rows.length,\n exact_total: expectedTotal,\n termination_reason: 'content_range_total_reached',\n content_range_verified: true,\n ordering_verified: true,\n duplicate_count: 0,\n },\n };\n }\n offset = nextOffset;\n }\n}\n\nexport function buildSnapshotCompleteness<Table extends string>(options: {\n tables: readonly Table[];\n requestedPageSize: number;\n results: Array<{ table: Table; completeness: DatasetMaintenanceTableCompleteness }>;\n}): DatasetMaintenanceSnapshotCompleteness<Table> {\n const expectedTables = new Set(options.tables);\n const observedTables = new Set(options.results.map((result) => result.table));\n if (\n options.results.length !== options.tables.length ||\n observedTables.size !== expectedTables.size ||\n [...observedTables].some((table) => !expectedTables.has(table))\n ) {\n return incomplete({\n reason: 'aggregate_table_set_invalid',\n expected_tables: [...options.tables],\n observed_tables: options.results.map((result) => result.table),\n });\n }\n const entityCounts = Object.fromEntries(\n options.tables.map((table) => [\n table,\n options.results.find((result) => result.table === table)!.completeness.rows_fetched,\n ]),\n ) as Record<Table, number>;\n return {\n status: 'complete',\n complete: true,\n strategy: 'postgrest_exact_count_multi_request',\n requested_page_size: options.requestedPageSize,\n page_count: options.results.reduce((sum, result) => sum + result.completeness.pages_fetched, 0),\n row_count: options.results.reduce((sum, result) => sum + result.completeness.rows_fetched, 0),\n entity_counts: entityCounts,\n tables: options.results.map((result) => ({\n table: result.table,\n ...result.completeness,\n })),\n };\n}\n"]}
@@ -375,6 +375,7 @@ export async function runDatasetMaintenancePlan(options) {
375
375
  status: allBlockers.length ? 'blocked' : 'ready',
376
376
  scope_sha256: scopeSha256,
377
377
  visible_snapshot_sha256: sha256Json(snapshotRows),
378
+ snapshot_completeness: accountSnapshot.completeness,
378
379
  projected_reference_sha256: sha256Json(maintenanceProjectedReferenceFingerprint(intendedRows)),
379
380
  plan_sha256: '',
380
381
  summary: {
@@ -418,6 +419,7 @@ export async function runDatasetMaintenancePlan(options) {
418
419
  session_source: context.account.session_source,
419
420
  },
420
421
  page_size: pageSize,
422
+ completeness: accountSnapshot.completeness,
421
423
  source_urls: accountSnapshot.source_urls,
422
424
  row_count: snapshotRows.length,
423
425
  snapshot_sha256: plan.visible_snapshot_sha256,
@@ -452,6 +454,7 @@ export async function runDatasetMaintenancePlan(options) {
452
454
  task_id: plan.task_id,
453
455
  plan_sha256: plan.plan_sha256,
454
456
  account: plan.account,
457
+ snapshot_completeness: accountSnapshot.completeness,
455
458
  summary: plan.summary,
456
459
  actions: plan.actions.map((action) => ({
457
460
  action_id: action.action_id,
@@ -1 +1 @@
1
- {"version":3,"file":"dataset-maintenance-plan.js","sourceRoot":"","sources":["../../../src/lib/dataset-maintenance-plan.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { collectRemoteReferences } from './dataset-remote-verify.js';\nimport {\n buildAliasRewritePlan,\n type DatasetMaintenanceAliasSchemas,\n} from './dataset-maintenance-alias-rewrite.js';\nimport { CliError } from './errors.js';\nimport type { FetchLike } from './http.js';\nimport {\n computePlanSha256,\n isJsonObject,\n maintenanceRowKey,\n parseMaintenanceScope,\n readJsonFile,\n safeActionFileName,\n sha256Json,\n snapshotRemoteRow,\n writeImmutableJson,\n writeImmutableJsonLines,\n type DatasetMaintenanceBlocker,\n type DatasetMaintenanceAliasBatchPlan,\n type DatasetMaintenanceOperation,\n type DatasetMaintenancePlan,\n type DatasetMaintenancePlanAction,\n type DatasetMaintenanceProtectedRow,\n type DatasetMaintenanceReferenceImpact,\n type DatasetMaintenanceRemoteRow,\n type DatasetMaintenanceRowSnapshot,\n type DatasetMaintenanceScopeAction,\n type JsonObject,\n} from './dataset-maintenance-contract.js';\nimport {\n inspectMaintenanceSupportPayload,\n maintenancePayloadIdentity,\n type DatasetMaintenanceSupportSchemas,\n} from './dataset-maintenance-support-validation.js';\nimport {\n fetchMaintenanceAccountRows,\n fetchMaintenanceExactRows,\n normalizeMaintenancePageSize,\n resolveMaintenanceRemoteContext,\n} from './dataset-maintenance-remote.js';\n\nexport type RunDatasetMaintenancePlanOptions = {\n scopePath: string;\n operation: DatasetMaintenanceOperation;\n outDir: string;\n pageSize?: number;\n timeoutMs?: number;\n env: NodeJS.ProcessEnv;\n fetchImpl: FetchLike;\n now?: Date;\n supportSchemas?: DatasetMaintenanceSupportSchemas;\n aliasSchemas?: DatasetMaintenanceAliasSchemas;\n};\n\nfunction normalizeEmail(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction blocker(\n action: DatasetMaintenanceScopeAction,\n code: string,\n message: string,\n details?: unknown,\n): DatasetMaintenanceBlocker {\n return {\n code,\n message,\n action_id: action.action_id,\n table: action.table,\n id: action.id,\n version: action.version,\n ...(details === undefined ? {} : { details }),\n };\n}\n\nfunction referenceImpacts(options: {\n rows: DatasetMaintenanceRemoteRow[];\n deletes: DatasetMaintenanceScopeAction[];\n phase: DatasetMaintenanceReferenceImpact['phase'];\n}): DatasetMaintenanceReferenceImpact[] {\n const payloadRows = options.rows\n .filter((row) => row.json_ordered !== null)\n .map((row) => ({\n table: row.table,\n id: row.id,\n version: row.version,\n json_ordered: row.json_ordered as JsonObject,\n }));\n const references = collectRemoteReferences(payloadRows).filter(\n (reference) => reference.role === 'reference',\n );\n const impacts: DatasetMaintenanceReferenceImpact[] = [];\n for (const reference of references) {\n const source = payloadRows[reference.row_index];\n if (!reference.table || !reference.id) {\n continue;\n }\n for (const target of options.deletes) {\n const sameTarget =\n reference.table === target.table &&\n reference.id === target.id &&\n (!reference.version || reference.version === target.version);\n if (sameTarget) {\n impacts.push({\n target_action_id: target.action_id,\n target_table: target.table,\n target_id: target.id,\n target_version: target.version,\n phase: options.phase,\n source_table: source!.table,\n source_id: source!.id,\n source_version: source!.version,\n reference_path: reference.path,\n reference_version: reference.version,\n });\n }\n }\n }\n return impacts.sort((left, right) =>\n [\n left.target_action_id,\n left.source_table,\n left.source_id,\n left.source_version,\n left.reference_path,\n ]\n .join('\\u0000')\n .localeCompare(\n [\n right.target_action_id,\n right.source_table,\n right.source_id,\n right.source_version,\n right.reference_path,\n ].join('\\u0000'),\n ),\n );\n}\n\nfunction projectedRows(options: {\n current: DatasetMaintenanceRemoteRow[];\n actions: DatasetMaintenancePlanAction[];\n desiredPayloads: Map<string, JsonObject>;\n}): DatasetMaintenanceRemoteRow[] {\n const projected = new Map(options.current.map((row) => [maintenanceRowKey(row), { ...row }]));\n for (const action of options.actions.filter((entry) =>\n ['save_draft', 'update_json_ordered'].includes(entry.action),\n )) {\n const key = maintenanceRowKey(action);\n const row = projected.get(key);\n const payload = options.desiredPayloads.get(action.action_id);\n if (row && payload) {\n projected.set(key, { ...row, json_ordered: payload });\n }\n }\n for (const action of options.actions.filter((entry) => entry.action === 'delete')) {\n projected.delete(maintenanceRowKey(action));\n }\n return [...projected.values()].sort((left, right) =>\n maintenanceRowKey(left).localeCompare(maintenanceRowKey(right)),\n );\n}\n\nexport function maintenanceProjectedReferenceFingerprint(\n rows: DatasetMaintenanceRemoteRow[],\n): unknown[] {\n const payloadRows = rows\n .filter((row) => row.json_ordered !== null)\n .map((row) => ({\n table: row.table,\n id: row.id,\n version: row.version,\n json_ordered: row.json_ordered as JsonObject,\n }));\n return collectRemoteReferences(payloadRows)\n .filter((reference) => reference.role === 'reference')\n .map((reference) => ({\n source: maintenanceRowKey(payloadRows[reference.row_index]!),\n table: reference.table,\n id: reference.id,\n version: reference.version,\n path: reference.path,\n }))\n .sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));\n}\n\nfunction protectedRows(options: {\n snapshot: DatasetMaintenanceRowSnapshot[];\n actions: DatasetMaintenancePlanAction[];\n}): DatasetMaintenanceProtectedRow[] {\n const readyActionKeys = new Set(\n options.actions\n .filter((action) => action.before && action.status === 'ready')\n .map(maintenanceRowKey),\n );\n const blockedActionKeys = new Set(\n options.actions\n .filter((action) => action.before && action.status === 'blocked')\n .map(maintenanceRowKey),\n );\n return options.snapshot\n .filter((row) => !readyActionKeys.has(maintenanceRowKey(row)))\n .map((row) => ({\n table: row.table,\n id: row.id,\n version: row.version,\n modified_at: row.modified_at,\n row_sha256: row.row_sha256,\n payload_sha256: row.payload_sha256,\n reason: blockedActionKeys.has(maintenanceRowKey(row))\n ? ('blocked_action_row' as const)\n : ('non_action_visible_row' as const),\n }));\n}\n\nexport async function runDatasetMaintenancePlan(\n options: RunDatasetMaintenancePlanOptions,\n): Promise<DatasetMaintenancePlan> {\n const scopePath = path.resolve(options.scopePath);\n const outDir = path.resolve(options.outDir);\n const pageSize = normalizeMaintenancePageSize(options.pageSize);\n const generatedAtUtc = (options.now ?? new Date()).toISOString();\n const scope = parseMaintenanceScope(\n readJsonFile(scopePath, 'Maintenance scope'),\n options.operation,\n );\n const context = await resolveMaintenanceRemoteContext({\n env: options.env,\n fetchImpl: options.fetchImpl,\n timeoutMs: options.timeoutMs,\n now: options.now,\n });\n if (context.account.user_id !== scope.account.user_id) {\n throw new CliError('Current authenticated user does not match maintenance scope account.', {\n code: 'DATASET_MAINTENANCE_ACCOUNT_MISMATCH',\n exitCode: 1,\n details: {\n expected_user_id: scope.account.user_id,\n current_user_id: context.account.user_id,\n },\n });\n }\n if (\n scope.account.email &&\n normalizeEmail(scope.account.email) !== normalizeEmail(context.account.email)\n ) {\n throw new CliError('Current authenticated email does not match maintenance scope account.', {\n code: 'DATASET_MAINTENANCE_ACCOUNT_EMAIL_MISMATCH',\n exitCode: 1,\n details: {\n expected_email: scope.account.email,\n current_email: context.account.email,\n },\n });\n }\n\n const accountSnapshot = await fetchMaintenanceAccountRows({\n context,\n userId: scope.account.user_id,\n pageSize,\n });\n const snapshotRows = accountSnapshot.rows\n .map(snapshotRemoteRow)\n .sort((left, right) => maintenanceRowKey(left).localeCompare(maintenanceRowKey(right)));\n const snapshotByKey = new Map(snapshotRows.map((row) => [maintenanceRowKey(row), row]));\n const desiredPayloads = new Map<string, JsonObject>();\n const actionPlans: DatasetMaintenancePlanAction[] = [];\n const aliasTargetSnapshots = new Map<\n string,\n DatasetMaintenanceAliasBatchPlan['target_snapshots']\n >();\n for (const batch of scope.alias_batches ?? []) {\n const targetRows = await Promise.all(\n (['unitgroup', 'flowproperty'] as const).map(async (kind) => {\n const target = batch.target[kind];\n const table = kind === 'unitgroup' ? 'unitgroups' : 'flowproperties';\n const exact = await fetchMaintenanceExactRows({\n context,\n table,\n id: target.id,\n version: target.version,\n });\n const row = exact.rows.length === 1 ? exact.rows[0] : null;\n if (!row?.json_ordered) return null;\n const inspection = inspectMaintenanceSupportPayload({\n table,\n payload: row.json_ordered,\n schemas: options.supportSchemas,\n });\n return inspection.identity.id === target.id &&\n inspection.identity.version === target.version &&\n inspection.schemaResult.success\n ? snapshotRemoteRow(row)\n : null;\n }),\n );\n const sourceUnitGroupSnapshot = snapshotByKey.get(\n maintenanceRowKey({\n table: 'unitgroups',\n id: batch.source.unitgroup.id,\n version: batch.source.unitgroup.version,\n }),\n );\n const sourceUnitGroupInspection = sourceUnitGroupSnapshot?.json_ordered\n ? inspectMaintenanceSupportPayload({\n table: 'unitgroups',\n payload: sourceUnitGroupSnapshot.json_ordered,\n schemas: options.supportSchemas,\n })\n : null;\n aliasTargetSnapshots.set(batch.batch_id, {\n unitgroup: targetRows[0],\n flowproperty: targetRows[1],\n source_unitgroup:\n sourceUnitGroupSnapshot &&\n sourceUnitGroupInspection?.identity.id === batch.source.unitgroup.id &&\n sourceUnitGroupInspection.identity.version === batch.source.unitgroup.version &&\n sourceUnitGroupInspection.schemaResult.success\n ? sourceUnitGroupSnapshot\n : null,\n });\n }\n\n for (const [ordinal, action] of scope.actions.entries()) {\n const actionBlockers: DatasetMaintenanceBlocker[] = [];\n const exact = await fetchMaintenanceExactRows({\n context,\n table: action.table,\n id: action.id,\n version: action.version,\n });\n const remote = exact.rows[0] ?? null;\n if (exact.rows.length === 0) {\n actionBlockers.push(\n blocker(\n action,\n 'TARGET_NOT_VISIBLE',\n 'Exact target row is not visible under the current authenticated RLS session.',\n ),\n );\n }\n if (exact.rows.length > 1) {\n actionBlockers.push(\n blocker(action, 'TARGET_NOT_UNIQUE', 'Exact target lookup returned multiple rows.'),\n );\n }\n const before = remote ? snapshotRemoteRow(remote) : null;\n if (before && before.user_id !== action.expected_user_id) {\n actionBlockers.push(\n blocker(action, 'TARGET_OWNER_MISMATCH', 'Target row is not owned by the expected user.', {\n visible_user_id: before.user_id,\n }),\n );\n }\n if (before && before.state_code !== 0) {\n actionBlockers.push(\n blocker(action, 'TARGET_NOT_DRAFT', 'Target row is not a draft with state_code=0.', {\n visible_state_code: before.state_code,\n }),\n );\n }\n if (before && !before.json_ordered) {\n actionBlockers.push(\n blocker(action, 'TARGET_PAYLOAD_MISSING', 'Target row has no object json_ordered payload.'),\n );\n }\n if (action.action === 'update_json_ordered' && before && !before.modified_at) {\n actionBlockers.push(\n blocker(\n action,\n 'ALIAS_EXPECTED_MODIFIED_AT_MISSING',\n `${action.action} target requires a non-null modified_at optimistic-lock value.`,\n ),\n );\n }\n if (\n before &&\n action.expected_before_sha256 &&\n action.expected_before_sha256 !== before.row_sha256\n ) {\n actionBlockers.push(\n blocker(action, 'EXPECTED_BEFORE_HASH_MISMATCH', 'Target row hash differs from scope.', {\n expected: action.expected_before_sha256,\n actual: before.row_sha256,\n }),\n );\n }\n const snapshotRow = snapshotByKey.get(maintenanceRowKey(action));\n if (before && (!snapshotRow || snapshotRow.row_sha256 !== before.row_sha256)) {\n actionBlockers.push(\n blocker(\n action,\n 'SNAPSHOT_DRIFT',\n 'Exact target row differs from the same-account visible snapshot.',\n ),\n );\n }\n\n let desiredPayload: DatasetMaintenancePlanAction['desired_payload'] = null;\n if (action.action === 'save_draft' && action.desired_payload_path) {\n const sourcePayloadPath = path.resolve(path.dirname(scopePath), action.desired_payload_path);\n const rawPayload = readJsonFile(sourcePayloadPath, 'Maintenance desired payload');\n if (!isJsonObject(rawPayload)) {\n throw new CliError(`Desired payload must be a JSON object: ${sourcePayloadPath}`, {\n code: 'DATASET_MAINTENANCE_DESIRED_PAYLOAD_INVALID',\n exitCode: 2,\n });\n }\n const payloadPath = path.join(\n outDir,\n 'payloads',\n `${safeActionFileName(action.action_id)}.json`,\n );\n writeImmutableJson(payloadPath, rawPayload);\n desiredPayloads.set(action.action_id, rawPayload);\n desiredPayload = {\n path: path.relative(outDir, payloadPath),\n sha256: sha256Json(rawPayload),\n };\n const identity = maintenancePayloadIdentity(rawPayload);\n if (identity.id !== action.id || identity.version !== action.version) {\n actionBlockers.push(\n blocker(\n action,\n 'DESIRED_PAYLOAD_IDENTITY_MISMATCH',\n 'Desired payload root id/version does not match the target row.',\n identity,\n ),\n );\n }\n }\n actionPlans.push({\n ...action,\n ordinal,\n status: actionBlockers.length ? 'blocked' : 'ready',\n before,\n desired_payload: desiredPayload,\n blockers: actionBlockers,\n rollback: {\n strategy:\n action.action === 'save_draft'\n ? 'save_before_snapshot'\n : action.action === 'delete'\n ? 'restore_deleted_before_snapshot'\n : 'restore_atomic_alias_before_snapshot',\n before_payload_sha256: before?.payload_sha256 ?? null,\n before_payload: before?.json_ordered ?? null,\n model_id: before?.model_id ?? null,\n rule_verification: before?.rule_verification ?? null,\n },\n });\n }\n\n let aliasBatches: DatasetMaintenanceAliasBatchPlan[] | undefined;\n if (scope.operation === 'merge-support-aliases') {\n const aliasPlan = buildAliasRewritePlan({\n scope,\n actions: actionPlans,\n accountRows: accountSnapshot.rows,\n targetSnapshots: aliasTargetSnapshots,\n schemas: options.aliasSchemas,\n });\n aliasBatches = aliasPlan.batches;\n for (const action of actionPlans) {\n const rawPayload = aliasPlan.desired_payloads.get(action.action_id);\n if (!rawPayload) continue;\n const payloadPath = path.join(\n outDir,\n 'payloads',\n `${safeActionFileName(action.action_id)}.json`,\n );\n writeImmutableJson(payloadPath, rawPayload);\n desiredPayloads.set(action.action_id, rawPayload);\n action.desired_payload = {\n path: path.relative(outDir, payloadPath),\n sha256: sha256Json(rawPayload),\n };\n const identity = maintenancePayloadIdentity(rawPayload);\n if (identity.id !== action.id || identity.version !== action.version) {\n action.blockers.push(\n blocker(\n action,\n 'DESIRED_PAYLOAD_IDENTITY_MISMATCH',\n 'Generated alias payload root id/version does not match the target row.',\n identity,\n ),\n );\n action.status = 'blocked';\n }\n }\n }\n\n const intendedRows = projectedRows({\n current: accountSnapshot.rows,\n actions: actionPlans,\n desiredPayloads,\n });\n const deleteActions = scope.actions.filter((action) => action.action === 'delete');\n const currentImpacts = referenceImpacts({\n rows: accountSnapshot.rows,\n deletes: deleteActions,\n phase: 'current',\n });\n const projectedImpacts = referenceImpacts({\n rows: intendedRows,\n deletes: deleteActions,\n phase: 'projected',\n });\n for (const action of actionPlans.filter((entry) => entry.action === 'delete')) {\n const impacts = projectedImpacts.filter(\n (impact) => impact.target_action_id === action.action_id,\n );\n if (impacts.length) {\n action.blockers.push(\n blocker(\n action,\n 'PROJECTED_INBOUND_REFERENCES',\n `Projected state still contains ${impacts.length} inbound reference(s) to this delete target.`,\n impacts,\n ),\n );\n action.status = 'blocked';\n }\n }\n const allBlockers = actionPlans.flatMap((action) => action.blockers);\n const protectedRowList = protectedRows({ snapshot: snapshotRows, actions: actionPlans });\n const scopeSha256 = sha256Json(scope);\n const plan: DatasetMaintenancePlan = {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n task_id: scope.task_id,\n operation: scope.operation,\n operation_id: `maintenance-${scopeSha256.slice(0, 20)}`,\n account: {\n user_id: scope.account.user_id,\n email: context.account.email,\n },\n source_import_run_id: scope.source_import_run_id ?? null,\n source_lineage: scope.source_lineage ?? null,\n target_mode: scope.target_mode ?? null,\n status: allBlockers.length ? 'blocked' : 'ready',\n scope_sha256: scopeSha256,\n visible_snapshot_sha256: sha256Json(snapshotRows),\n projected_reference_sha256: sha256Json(maintenanceProjectedReferenceFingerprint(intendedRows)),\n plan_sha256: '',\n summary: {\n actions: actionPlans.length,\n save_draft: actionPlans.filter((action) => action.action === 'save_draft').length,\n delete: actionPlans.filter((action) => action.action === 'delete').length,\n update_json_ordered: actionPlans.filter((action) => action.action === 'update_json_ordered')\n .length,\n atomic_batches: aliasBatches?.length ?? 0,\n scaled_exchanges: aliasBatches?.reduce((sum, batch) => sum + batch.summary.exchanges, 0) ?? 0,\n scaled_amount_fields:\n aliasBatches?.reduce((sum, batch) => sum + batch.summary.amount_fields, 0) ?? 0,\n unrelated_exchanges_preserved:\n aliasBatches?.reduce((sum, batch) => sum + batch.summary.unrelated_exchanges, 0) ?? 0,\n protected_rows: protectedRowList.length,\n blockers: allBlockers.length,\n current_reference_impacts: currentImpacts.length,\n projected_reference_impacts: projectedImpacts.length,\n },\n artifacts: {\n maintenance_scope: 'maintenance-scope.json',\n rls_visible_snapshot: 'rls-visible-snapshot.json',\n protected_rows: 'protected-rows.jsonl',\n reference_impact_report: 'reference-impact-report.json',\n maintenance_plan: 'maintenance-plan.json',\n dry_run_report: 'dry-run-report.json',\n payload_dir: 'payloads',\n ...(aliasBatches ? { exchange_rewrite_plan: 'exchange-rewrite-plan.jsonl' } : {}),\n },\n actions: actionPlans,\n ...(aliasBatches ? { alias_batches: aliasBatches } : {}),\n protected_rows: protectedRowList,\n blockers: allBlockers,\n };\n plan.plan_sha256 = computePlanSha256(plan);\n\n writeImmutableJson(path.join(outDir, plan.artifacts.maintenance_scope), scope);\n writeImmutableJson(path.join(outDir, plan.artifacts.rls_visible_snapshot), {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n account: {\n user_id: scope.account.user_id,\n email: context.account.email,\n session_source: context.account.session_source,\n },\n page_size: pageSize,\n source_urls: accountSnapshot.source_urls,\n row_count: snapshotRows.length,\n snapshot_sha256: plan.visible_snapshot_sha256,\n rows: snapshotRows,\n });\n writeImmutableJsonLines(path.join(outDir, plan.artifacts.protected_rows), protectedRowList);\n if (plan.artifacts.exchange_rewrite_plan) {\n writeImmutableJsonLines(\n path.join(outDir, plan.artifacts.exchange_rewrite_plan),\n plan.alias_batches!.flatMap((batch) =>\n batch.exchange_rewrites.map((rewrite) => ({\n schema_version: 1,\n plan_sha256: plan.plan_sha256,\n operation_id: plan.operation_id,\n batch_id: batch.batch_id,\n factor: batch.factor,\n ...rewrite,\n })),\n ),\n );\n }\n writeImmutableJson(path.join(outDir, plan.artifacts.reference_impact_report), {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n plan_sha256: plan.plan_sha256,\n status: plan.status,\n current: currentImpacts,\n projected: projectedImpacts,\n projected_reference_sha256: plan.projected_reference_sha256,\n });\n writeImmutableJson(path.join(outDir, plan.artifacts.dry_run_report), {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n status: plan.status,\n operation: plan.operation,\n target_mode: plan.target_mode,\n task_id: plan.task_id,\n plan_sha256: plan.plan_sha256,\n account: plan.account,\n summary: plan.summary,\n actions: plan.actions.map((action) => ({\n action_id: action.action_id,\n action: action.action,\n table: action.table,\n id: action.id,\n version: action.version,\n status: action.status,\n blockers: action.blockers,\n })),\n alias_batches: plan.alias_batches?.map((batch) => ({\n batch_id: batch.batch_id,\n dimension: batch.dimension,\n factor: batch.factor,\n summary: batch.summary,\n postconditions: batch.postconditions,\n target_snapshots: batch.target_snapshots,\n })),\n blockers: plan.blockers,\n });\n writeImmutableJson(path.join(outDir, plan.artifacts.maintenance_plan), plan);\n return plan;\n}\n\nexport const __testInternals = {\n desiredPayloadIdentity: maintenancePayloadIdentity,\n maintenanceProjectedReferenceFingerprint,\n projectedRows,\n protectedRows,\n referenceImpacts,\n};\n"]}
1
+ {"version":3,"file":"dataset-maintenance-plan.js","sourceRoot":"","sources":["../../../src/lib/dataset-maintenance-plan.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { collectRemoteReferences } from './dataset-remote-verify.js';\nimport {\n buildAliasRewritePlan,\n type DatasetMaintenanceAliasSchemas,\n} from './dataset-maintenance-alias-rewrite.js';\nimport { CliError } from './errors.js';\nimport type { FetchLike } from './http.js';\nimport {\n computePlanSha256,\n isJsonObject,\n maintenanceRowKey,\n parseMaintenanceScope,\n readJsonFile,\n safeActionFileName,\n sha256Json,\n snapshotRemoteRow,\n writeImmutableJson,\n writeImmutableJsonLines,\n type DatasetMaintenanceBlocker,\n type DatasetMaintenanceAliasBatchPlan,\n type DatasetMaintenanceOperation,\n type DatasetMaintenancePlan,\n type DatasetMaintenancePlanAction,\n type DatasetMaintenanceProtectedRow,\n type DatasetMaintenanceReferenceImpact,\n type DatasetMaintenanceRemoteRow,\n type DatasetMaintenanceRowSnapshot,\n type DatasetMaintenanceScopeAction,\n type JsonObject,\n} from './dataset-maintenance-contract.js';\nimport {\n inspectMaintenanceSupportPayload,\n maintenancePayloadIdentity,\n type DatasetMaintenanceSupportSchemas,\n} from './dataset-maintenance-support-validation.js';\nimport {\n fetchMaintenanceAccountRows,\n fetchMaintenanceExactRows,\n normalizeMaintenancePageSize,\n resolveMaintenanceRemoteContext,\n} from './dataset-maintenance-remote.js';\n\nexport type RunDatasetMaintenancePlanOptions = {\n scopePath: string;\n operation: DatasetMaintenanceOperation;\n outDir: string;\n pageSize?: number;\n timeoutMs?: number;\n env: NodeJS.ProcessEnv;\n fetchImpl: FetchLike;\n now?: Date;\n supportSchemas?: DatasetMaintenanceSupportSchemas;\n aliasSchemas?: DatasetMaintenanceAliasSchemas;\n};\n\nfunction normalizeEmail(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction blocker(\n action: DatasetMaintenanceScopeAction,\n code: string,\n message: string,\n details?: unknown,\n): DatasetMaintenanceBlocker {\n return {\n code,\n message,\n action_id: action.action_id,\n table: action.table,\n id: action.id,\n version: action.version,\n ...(details === undefined ? {} : { details }),\n };\n}\n\nfunction referenceImpacts(options: {\n rows: DatasetMaintenanceRemoteRow[];\n deletes: DatasetMaintenanceScopeAction[];\n phase: DatasetMaintenanceReferenceImpact['phase'];\n}): DatasetMaintenanceReferenceImpact[] {\n const payloadRows = options.rows\n .filter((row) => row.json_ordered !== null)\n .map((row) => ({\n table: row.table,\n id: row.id,\n version: row.version,\n json_ordered: row.json_ordered as JsonObject,\n }));\n const references = collectRemoteReferences(payloadRows).filter(\n (reference) => reference.role === 'reference',\n );\n const impacts: DatasetMaintenanceReferenceImpact[] = [];\n for (const reference of references) {\n const source = payloadRows[reference.row_index];\n if (!reference.table || !reference.id) {\n continue;\n }\n for (const target of options.deletes) {\n const sameTarget =\n reference.table === target.table &&\n reference.id === target.id &&\n (!reference.version || reference.version === target.version);\n if (sameTarget) {\n impacts.push({\n target_action_id: target.action_id,\n target_table: target.table,\n target_id: target.id,\n target_version: target.version,\n phase: options.phase,\n source_table: source!.table,\n source_id: source!.id,\n source_version: source!.version,\n reference_path: reference.path,\n reference_version: reference.version,\n });\n }\n }\n }\n return impacts.sort((left, right) =>\n [\n left.target_action_id,\n left.source_table,\n left.source_id,\n left.source_version,\n left.reference_path,\n ]\n .join('\\u0000')\n .localeCompare(\n [\n right.target_action_id,\n right.source_table,\n right.source_id,\n right.source_version,\n right.reference_path,\n ].join('\\u0000'),\n ),\n );\n}\n\nfunction projectedRows(options: {\n current: DatasetMaintenanceRemoteRow[];\n actions: DatasetMaintenancePlanAction[];\n desiredPayloads: Map<string, JsonObject>;\n}): DatasetMaintenanceRemoteRow[] {\n const projected = new Map(options.current.map((row) => [maintenanceRowKey(row), { ...row }]));\n for (const action of options.actions.filter((entry) =>\n ['save_draft', 'update_json_ordered'].includes(entry.action),\n )) {\n const key = maintenanceRowKey(action);\n const row = projected.get(key);\n const payload = options.desiredPayloads.get(action.action_id);\n if (row && payload) {\n projected.set(key, { ...row, json_ordered: payload });\n }\n }\n for (const action of options.actions.filter((entry) => entry.action === 'delete')) {\n projected.delete(maintenanceRowKey(action));\n }\n return [...projected.values()].sort((left, right) =>\n maintenanceRowKey(left).localeCompare(maintenanceRowKey(right)),\n );\n}\n\nexport function maintenanceProjectedReferenceFingerprint(\n rows: DatasetMaintenanceRemoteRow[],\n): unknown[] {\n const payloadRows = rows\n .filter((row) => row.json_ordered !== null)\n .map((row) => ({\n table: row.table,\n id: row.id,\n version: row.version,\n json_ordered: row.json_ordered as JsonObject,\n }));\n return collectRemoteReferences(payloadRows)\n .filter((reference) => reference.role === 'reference')\n .map((reference) => ({\n source: maintenanceRowKey(payloadRows[reference.row_index]!),\n table: reference.table,\n id: reference.id,\n version: reference.version,\n path: reference.path,\n }))\n .sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));\n}\n\nfunction protectedRows(options: {\n snapshot: DatasetMaintenanceRowSnapshot[];\n actions: DatasetMaintenancePlanAction[];\n}): DatasetMaintenanceProtectedRow[] {\n const readyActionKeys = new Set(\n options.actions\n .filter((action) => action.before && action.status === 'ready')\n .map(maintenanceRowKey),\n );\n const blockedActionKeys = new Set(\n options.actions\n .filter((action) => action.before && action.status === 'blocked')\n .map(maintenanceRowKey),\n );\n return options.snapshot\n .filter((row) => !readyActionKeys.has(maintenanceRowKey(row)))\n .map((row) => ({\n table: row.table,\n id: row.id,\n version: row.version,\n modified_at: row.modified_at,\n row_sha256: row.row_sha256,\n payload_sha256: row.payload_sha256,\n reason: blockedActionKeys.has(maintenanceRowKey(row))\n ? ('blocked_action_row' as const)\n : ('non_action_visible_row' as const),\n }));\n}\n\nexport async function runDatasetMaintenancePlan(\n options: RunDatasetMaintenancePlanOptions,\n): Promise<DatasetMaintenancePlan> {\n const scopePath = path.resolve(options.scopePath);\n const outDir = path.resolve(options.outDir);\n const pageSize = normalizeMaintenancePageSize(options.pageSize);\n const generatedAtUtc = (options.now ?? new Date()).toISOString();\n const scope = parseMaintenanceScope(\n readJsonFile(scopePath, 'Maintenance scope'),\n options.operation,\n );\n const context = await resolveMaintenanceRemoteContext({\n env: options.env,\n fetchImpl: options.fetchImpl,\n timeoutMs: options.timeoutMs,\n now: options.now,\n });\n if (context.account.user_id !== scope.account.user_id) {\n throw new CliError('Current authenticated user does not match maintenance scope account.', {\n code: 'DATASET_MAINTENANCE_ACCOUNT_MISMATCH',\n exitCode: 1,\n details: {\n expected_user_id: scope.account.user_id,\n current_user_id: context.account.user_id,\n },\n });\n }\n if (\n scope.account.email &&\n normalizeEmail(scope.account.email) !== normalizeEmail(context.account.email)\n ) {\n throw new CliError('Current authenticated email does not match maintenance scope account.', {\n code: 'DATASET_MAINTENANCE_ACCOUNT_EMAIL_MISMATCH',\n exitCode: 1,\n details: {\n expected_email: scope.account.email,\n current_email: context.account.email,\n },\n });\n }\n\n const accountSnapshot = await fetchMaintenanceAccountRows({\n context,\n userId: scope.account.user_id,\n pageSize,\n });\n const snapshotRows = accountSnapshot.rows\n .map(snapshotRemoteRow)\n .sort((left, right) => maintenanceRowKey(left).localeCompare(maintenanceRowKey(right)));\n const snapshotByKey = new Map(snapshotRows.map((row) => [maintenanceRowKey(row), row]));\n const desiredPayloads = new Map<string, JsonObject>();\n const actionPlans: DatasetMaintenancePlanAction[] = [];\n const aliasTargetSnapshots = new Map<\n string,\n DatasetMaintenanceAliasBatchPlan['target_snapshots']\n >();\n for (const batch of scope.alias_batches ?? []) {\n const targetRows = await Promise.all(\n (['unitgroup', 'flowproperty'] as const).map(async (kind) => {\n const target = batch.target[kind];\n const table = kind === 'unitgroup' ? 'unitgroups' : 'flowproperties';\n const exact = await fetchMaintenanceExactRows({\n context,\n table,\n id: target.id,\n version: target.version,\n });\n const row = exact.rows.length === 1 ? exact.rows[0] : null;\n if (!row?.json_ordered) return null;\n const inspection = inspectMaintenanceSupportPayload({\n table,\n payload: row.json_ordered,\n schemas: options.supportSchemas,\n });\n return inspection.identity.id === target.id &&\n inspection.identity.version === target.version &&\n inspection.schemaResult.success\n ? snapshotRemoteRow(row)\n : null;\n }),\n );\n const sourceUnitGroupSnapshot = snapshotByKey.get(\n maintenanceRowKey({\n table: 'unitgroups',\n id: batch.source.unitgroup.id,\n version: batch.source.unitgroup.version,\n }),\n );\n const sourceUnitGroupInspection = sourceUnitGroupSnapshot?.json_ordered\n ? inspectMaintenanceSupportPayload({\n table: 'unitgroups',\n payload: sourceUnitGroupSnapshot.json_ordered,\n schemas: options.supportSchemas,\n })\n : null;\n aliasTargetSnapshots.set(batch.batch_id, {\n unitgroup: targetRows[0],\n flowproperty: targetRows[1],\n source_unitgroup:\n sourceUnitGroupSnapshot &&\n sourceUnitGroupInspection?.identity.id === batch.source.unitgroup.id &&\n sourceUnitGroupInspection.identity.version === batch.source.unitgroup.version &&\n sourceUnitGroupInspection.schemaResult.success\n ? sourceUnitGroupSnapshot\n : null,\n });\n }\n\n for (const [ordinal, action] of scope.actions.entries()) {\n const actionBlockers: DatasetMaintenanceBlocker[] = [];\n const exact = await fetchMaintenanceExactRows({\n context,\n table: action.table,\n id: action.id,\n version: action.version,\n });\n const remote = exact.rows[0] ?? null;\n if (exact.rows.length === 0) {\n actionBlockers.push(\n blocker(\n action,\n 'TARGET_NOT_VISIBLE',\n 'Exact target row is not visible under the current authenticated RLS session.',\n ),\n );\n }\n if (exact.rows.length > 1) {\n actionBlockers.push(\n blocker(action, 'TARGET_NOT_UNIQUE', 'Exact target lookup returned multiple rows.'),\n );\n }\n const before = remote ? snapshotRemoteRow(remote) : null;\n if (before && before.user_id !== action.expected_user_id) {\n actionBlockers.push(\n blocker(action, 'TARGET_OWNER_MISMATCH', 'Target row is not owned by the expected user.', {\n visible_user_id: before.user_id,\n }),\n );\n }\n if (before && before.state_code !== 0) {\n actionBlockers.push(\n blocker(action, 'TARGET_NOT_DRAFT', 'Target row is not a draft with state_code=0.', {\n visible_state_code: before.state_code,\n }),\n );\n }\n if (before && !before.json_ordered) {\n actionBlockers.push(\n blocker(action, 'TARGET_PAYLOAD_MISSING', 'Target row has no object json_ordered payload.'),\n );\n }\n if (action.action === 'update_json_ordered' && before && !before.modified_at) {\n actionBlockers.push(\n blocker(\n action,\n 'ALIAS_EXPECTED_MODIFIED_AT_MISSING',\n `${action.action} target requires a non-null modified_at optimistic-lock value.`,\n ),\n );\n }\n if (\n before &&\n action.expected_before_sha256 &&\n action.expected_before_sha256 !== before.row_sha256\n ) {\n actionBlockers.push(\n blocker(action, 'EXPECTED_BEFORE_HASH_MISMATCH', 'Target row hash differs from scope.', {\n expected: action.expected_before_sha256,\n actual: before.row_sha256,\n }),\n );\n }\n const snapshotRow = snapshotByKey.get(maintenanceRowKey(action));\n if (before && (!snapshotRow || snapshotRow.row_sha256 !== before.row_sha256)) {\n actionBlockers.push(\n blocker(\n action,\n 'SNAPSHOT_DRIFT',\n 'Exact target row differs from the same-account visible snapshot.',\n ),\n );\n }\n\n let desiredPayload: DatasetMaintenancePlanAction['desired_payload'] = null;\n if (action.action === 'save_draft' && action.desired_payload_path) {\n const sourcePayloadPath = path.resolve(path.dirname(scopePath), action.desired_payload_path);\n const rawPayload = readJsonFile(sourcePayloadPath, 'Maintenance desired payload');\n if (!isJsonObject(rawPayload)) {\n throw new CliError(`Desired payload must be a JSON object: ${sourcePayloadPath}`, {\n code: 'DATASET_MAINTENANCE_DESIRED_PAYLOAD_INVALID',\n exitCode: 2,\n });\n }\n const payloadPath = path.join(\n outDir,\n 'payloads',\n `${safeActionFileName(action.action_id)}.json`,\n );\n writeImmutableJson(payloadPath, rawPayload);\n desiredPayloads.set(action.action_id, rawPayload);\n desiredPayload = {\n path: path.relative(outDir, payloadPath),\n sha256: sha256Json(rawPayload),\n };\n const identity = maintenancePayloadIdentity(rawPayload);\n if (identity.id !== action.id || identity.version !== action.version) {\n actionBlockers.push(\n blocker(\n action,\n 'DESIRED_PAYLOAD_IDENTITY_MISMATCH',\n 'Desired payload root id/version does not match the target row.',\n identity,\n ),\n );\n }\n }\n actionPlans.push({\n ...action,\n ordinal,\n status: actionBlockers.length ? 'blocked' : 'ready',\n before,\n desired_payload: desiredPayload,\n blockers: actionBlockers,\n rollback: {\n strategy:\n action.action === 'save_draft'\n ? 'save_before_snapshot'\n : action.action === 'delete'\n ? 'restore_deleted_before_snapshot'\n : 'restore_atomic_alias_before_snapshot',\n before_payload_sha256: before?.payload_sha256 ?? null,\n before_payload: before?.json_ordered ?? null,\n model_id: before?.model_id ?? null,\n rule_verification: before?.rule_verification ?? null,\n },\n });\n }\n\n let aliasBatches: DatasetMaintenanceAliasBatchPlan[] | undefined;\n if (scope.operation === 'merge-support-aliases') {\n const aliasPlan = buildAliasRewritePlan({\n scope,\n actions: actionPlans,\n accountRows: accountSnapshot.rows,\n targetSnapshots: aliasTargetSnapshots,\n schemas: options.aliasSchemas,\n });\n aliasBatches = aliasPlan.batches;\n for (const action of actionPlans) {\n const rawPayload = aliasPlan.desired_payloads.get(action.action_id);\n if (!rawPayload) continue;\n const payloadPath = path.join(\n outDir,\n 'payloads',\n `${safeActionFileName(action.action_id)}.json`,\n );\n writeImmutableJson(payloadPath, rawPayload);\n desiredPayloads.set(action.action_id, rawPayload);\n action.desired_payload = {\n path: path.relative(outDir, payloadPath),\n sha256: sha256Json(rawPayload),\n };\n const identity = maintenancePayloadIdentity(rawPayload);\n if (identity.id !== action.id || identity.version !== action.version) {\n action.blockers.push(\n blocker(\n action,\n 'DESIRED_PAYLOAD_IDENTITY_MISMATCH',\n 'Generated alias payload root id/version does not match the target row.',\n identity,\n ),\n );\n action.status = 'blocked';\n }\n }\n }\n\n const intendedRows = projectedRows({\n current: accountSnapshot.rows,\n actions: actionPlans,\n desiredPayloads,\n });\n const deleteActions = scope.actions.filter((action) => action.action === 'delete');\n const currentImpacts = referenceImpacts({\n rows: accountSnapshot.rows,\n deletes: deleteActions,\n phase: 'current',\n });\n const projectedImpacts = referenceImpacts({\n rows: intendedRows,\n deletes: deleteActions,\n phase: 'projected',\n });\n for (const action of actionPlans.filter((entry) => entry.action === 'delete')) {\n const impacts = projectedImpacts.filter(\n (impact) => impact.target_action_id === action.action_id,\n );\n if (impacts.length) {\n action.blockers.push(\n blocker(\n action,\n 'PROJECTED_INBOUND_REFERENCES',\n `Projected state still contains ${impacts.length} inbound reference(s) to this delete target.`,\n impacts,\n ),\n );\n action.status = 'blocked';\n }\n }\n const allBlockers = actionPlans.flatMap((action) => action.blockers);\n const protectedRowList = protectedRows({ snapshot: snapshotRows, actions: actionPlans });\n const scopeSha256 = sha256Json(scope);\n const plan: DatasetMaintenancePlan = {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n task_id: scope.task_id,\n operation: scope.operation,\n operation_id: `maintenance-${scopeSha256.slice(0, 20)}`,\n account: {\n user_id: scope.account.user_id,\n email: context.account.email,\n },\n source_import_run_id: scope.source_import_run_id ?? null,\n source_lineage: scope.source_lineage ?? null,\n target_mode: scope.target_mode ?? null,\n status: allBlockers.length ? 'blocked' : 'ready',\n scope_sha256: scopeSha256,\n visible_snapshot_sha256: sha256Json(snapshotRows),\n snapshot_completeness: accountSnapshot.completeness,\n projected_reference_sha256: sha256Json(maintenanceProjectedReferenceFingerprint(intendedRows)),\n plan_sha256: '',\n summary: {\n actions: actionPlans.length,\n save_draft: actionPlans.filter((action) => action.action === 'save_draft').length,\n delete: actionPlans.filter((action) => action.action === 'delete').length,\n update_json_ordered: actionPlans.filter((action) => action.action === 'update_json_ordered')\n .length,\n atomic_batches: aliasBatches?.length ?? 0,\n scaled_exchanges: aliasBatches?.reduce((sum, batch) => sum + batch.summary.exchanges, 0) ?? 0,\n scaled_amount_fields:\n aliasBatches?.reduce((sum, batch) => sum + batch.summary.amount_fields, 0) ?? 0,\n unrelated_exchanges_preserved:\n aliasBatches?.reduce((sum, batch) => sum + batch.summary.unrelated_exchanges, 0) ?? 0,\n protected_rows: protectedRowList.length,\n blockers: allBlockers.length,\n current_reference_impacts: currentImpacts.length,\n projected_reference_impacts: projectedImpacts.length,\n },\n artifacts: {\n maintenance_scope: 'maintenance-scope.json',\n rls_visible_snapshot: 'rls-visible-snapshot.json',\n protected_rows: 'protected-rows.jsonl',\n reference_impact_report: 'reference-impact-report.json',\n maintenance_plan: 'maintenance-plan.json',\n dry_run_report: 'dry-run-report.json',\n payload_dir: 'payloads',\n ...(aliasBatches ? { exchange_rewrite_plan: 'exchange-rewrite-plan.jsonl' } : {}),\n },\n actions: actionPlans,\n ...(aliasBatches ? { alias_batches: aliasBatches } : {}),\n protected_rows: protectedRowList,\n blockers: allBlockers,\n };\n plan.plan_sha256 = computePlanSha256(plan);\n\n writeImmutableJson(path.join(outDir, plan.artifacts.maintenance_scope), scope);\n writeImmutableJson(path.join(outDir, plan.artifacts.rls_visible_snapshot), {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n account: {\n user_id: scope.account.user_id,\n email: context.account.email,\n session_source: context.account.session_source,\n },\n page_size: pageSize,\n completeness: accountSnapshot.completeness,\n source_urls: accountSnapshot.source_urls,\n row_count: snapshotRows.length,\n snapshot_sha256: plan.visible_snapshot_sha256,\n rows: snapshotRows,\n });\n writeImmutableJsonLines(path.join(outDir, plan.artifacts.protected_rows), protectedRowList);\n if (plan.artifacts.exchange_rewrite_plan) {\n writeImmutableJsonLines(\n path.join(outDir, plan.artifacts.exchange_rewrite_plan),\n plan.alias_batches!.flatMap((batch) =>\n batch.exchange_rewrites.map((rewrite) => ({\n schema_version: 1,\n plan_sha256: plan.plan_sha256,\n operation_id: plan.operation_id,\n batch_id: batch.batch_id,\n factor: batch.factor,\n ...rewrite,\n })),\n ),\n );\n }\n writeImmutableJson(path.join(outDir, plan.artifacts.reference_impact_report), {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n plan_sha256: plan.plan_sha256,\n status: plan.status,\n current: currentImpacts,\n projected: projectedImpacts,\n projected_reference_sha256: plan.projected_reference_sha256,\n });\n writeImmutableJson(path.join(outDir, plan.artifacts.dry_run_report), {\n schema_version: 1,\n generated_at_utc: generatedAtUtc,\n status: plan.status,\n operation: plan.operation,\n target_mode: plan.target_mode,\n task_id: plan.task_id,\n plan_sha256: plan.plan_sha256,\n account: plan.account,\n snapshot_completeness: accountSnapshot.completeness,\n summary: plan.summary,\n actions: plan.actions.map((action) => ({\n action_id: action.action_id,\n action: action.action,\n table: action.table,\n id: action.id,\n version: action.version,\n status: action.status,\n blockers: action.blockers,\n })),\n alias_batches: plan.alias_batches?.map((batch) => ({\n batch_id: batch.batch_id,\n dimension: batch.dimension,\n factor: batch.factor,\n summary: batch.summary,\n postconditions: batch.postconditions,\n target_snapshots: batch.target_snapshots,\n })),\n blockers: plan.blockers,\n });\n writeImmutableJson(path.join(outDir, plan.artifacts.maintenance_plan), plan);\n return plan;\n}\n\nexport const __testInternals = {\n desiredPayloadIdentity: maintenancePayloadIdentity,\n maintenanceProjectedReferenceFingerprint,\n projectedRows,\n protectedRows,\n referenceImpacts,\n};\n"]}