@book.dev/sdk 3.7.0 → 3.9.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 (53) hide show
  1. package/dist/ai.d.ts +12 -2
  2. package/dist/ai.js.map +1 -1
  3. package/dist/blockCatalogue.d.ts +560 -0
  4. package/dist/blockCatalogue.js +336 -0
  5. package/dist/blockCatalogue.js.map +1 -0
  6. package/dist/bookFolder.d.ts +9 -1
  7. package/dist/bookFolder.js +64 -2
  8. package/dist/bookFolder.js.map +1 -1
  9. package/dist/client.d.ts +22 -2
  10. package/dist/client.js +6 -2
  11. package/dist/client.js.map +1 -1
  12. package/dist/content.d.ts +40 -1
  13. package/dist/content.js +29 -7
  14. package/dist/content.js.map +1 -1
  15. package/dist/forwarding/forwardingClient.d.ts +68 -2
  16. package/dist/forwarding/forwardingClient.js +126 -12
  17. package/dist/forwarding/forwardingClient.js.map +1 -1
  18. package/dist/forwarding/index.d.ts +2 -1
  19. package/dist/forwarding/index.js +2 -1
  20. package/dist/forwarding/index.js.map +1 -1
  21. package/dist/forwarding/namespacedKeyStore.d.ts +52 -0
  22. package/dist/forwarding/namespacedKeyStore.js +99 -0
  23. package/dist/forwarding/namespacedKeyStore.js.map +1 -0
  24. package/dist/index.d.ts +10 -5
  25. package/dist/index.js +10 -5
  26. package/dist/index.js.map +1 -1
  27. package/dist/ledger.d.ts +29 -0
  28. package/dist/ledger.js +43 -0
  29. package/dist/ledger.js.map +1 -1
  30. package/dist/ledgerExportSection.d.ts +160 -0
  31. package/dist/ledgerExportSection.js +594 -0
  32. package/dist/ledgerExportSection.js.map +1 -0
  33. package/dist/orderKeys.d.ts +36 -0
  34. package/dist/orderKeys.js +88 -0
  35. package/dist/orderKeys.js.map +1 -0
  36. package/dist/plugins.d.ts +76 -4
  37. package/dist/plugins.js +95 -12
  38. package/dist/plugins.js.map +1 -1
  39. package/dist/provenance.d.ts +13 -0
  40. package/dist/registryClient.d.ts +227 -0
  41. package/dist/registryClient.js +397 -0
  42. package/dist/registryClient.js.map +1 -0
  43. package/dist/routes.d.ts +9 -0
  44. package/dist/routes.js +9 -0
  45. package/dist/routes.js.map +1 -1
  46. package/dist/suggestions.d.ts +12 -2
  47. package/dist/tableSnapshot.d.ts +233 -0
  48. package/dist/tableSnapshot.js +680 -0
  49. package/dist/tableSnapshot.js.map +1 -0
  50. package/dist/templates.d.ts +8 -0
  51. package/dist/templates.js +7 -2
  52. package/dist/templates.js.map +1 -1
  53. package/package.json +1 -1
@@ -0,0 +1,594 @@
1
+ import { LEDGER_ACCOUNT_STATUSES, LEDGER_ACCOUNT_TYPES, LEDGER_CLEARED_STATES, LEDGER_MAX_TRANSACTION_LIMIT, LEDGER_PERIOD_STATUSES, LEDGER_PROP, LEDGER_RECONCILIATION_STATUSES, LEDGER_TRANSACTION_STATES, isIncomeStatementAccountType, isValidLedgerAccountName, isValidLedgerDate, ledgerAuditEventHash, } from './ledger';
2
+ import { isValidCurrencyCode, isValidMinor } from './money';
3
+ /** Mirrors the server writer's free-text cap (`MAX_DESCRIPTION_LENGTH`) so a
4
+ * section that would be refused mid-replay is refused BEFORE the first write. */
5
+ const SECTION_MAX_TEXT = 1000;
6
+ /** Mirrors the server writer's per-entry posting cap (`MAX_POSTINGS_PER_TRANSACTION`). */
7
+ const SECTION_MAX_POSTINGS = 1000;
8
+ const LEDGER_DB_KEYS = ['accounts', 'transactions', 'postings', 'reconciliations'];
9
+ /** A page read that treats "missing" as failure — the ledger's own pages are
10
+ * never legitimately absent, so a `null` here means "not readable/consistent"
11
+ * and the whole capture must fail closed. */
12
+ async function requirePage(client, id) {
13
+ const page = await client.getPage(id);
14
+ if (!page)
15
+ throw new Error(`ledger export: page ${id} unreadable`);
16
+ return page;
17
+ }
18
+ /**
19
+ * Capture the {@link LedgerExportSection} through the exporting principal's own
20
+ * read paths, or `null` when there is nothing to include: no seeded ledger,
21
+ * a principal who cannot read it, or any partial read failure (fail-closed —
22
+ * never embed half a book).
23
+ */
24
+ export async function gatherLedgerExportSection(client) {
25
+ try {
26
+ const info = await client.ledgerInfo();
27
+ if (!info.exists || !info.hostPageId || !info.databases)
28
+ return null;
29
+ const pages = [await requirePage(client, info.hostPageId)];
30
+ const databases = [];
31
+ const hostPages = {};
32
+ const rowCount = {};
33
+ for (const key of LEDGER_DB_KEYS) {
34
+ const db = await client.getDatabase(info.databases[key]);
35
+ if (!db)
36
+ return null;
37
+ databases.push(db);
38
+ hostPages[key] = db.pageId;
39
+ pages.push(await requirePage(client, db.pageId));
40
+ const rows = await client.listRows(db.id);
41
+ rowCount[key] = rows.length;
42
+ for (const row of rows) {
43
+ pages.push(await requirePage(client, row.id));
44
+ }
45
+ }
46
+ // COMPLETENESS TRIPWIRE (fail-closed). The generic row reads above are
47
+ // read-FILTERED per principal — a row the caller may not read is silently
48
+ // omitted, never an error — while row pages do NOT inherit an ACL grant
49
+ // placed on the ledger host pages (ancestor inheritance is OB-207). A
50
+ // principal holding host grants but not row reads would otherwise export
51
+ // schemas with zero (or partial) rows and no way to tell. The typed ledger
52
+ // reads are gated on the host pages only, so cross-checking their counts
53
+ // against the captured rows proves the generic surface was unfiltered.
54
+ // Any mismatch ⇒ no section: never embed half a book.
55
+ const accounts = await client.ledgerListAccounts();
56
+ if (rowCount.accounts !== accounts.length)
57
+ return null;
58
+ const reconciliations = await client.ledgerListReconciliations();
59
+ if (rowCount.reconciliations !== reconciliations.length)
60
+ return null;
61
+ const transactions = await client.ledgerListTransactions({ limit: LEDGER_MAX_TRANSACTION_LIMIT });
62
+ // The typed transaction read is CAPPED (the server clamps `limit` to
63
+ // LEDGER_MAX_TRANSACTION_LIMIT), so the parity check is only sound when
64
+ // the result is known-complete — strictly under the cap. AT the cap there
65
+ // is no requireLedger-gated, uncapped count surface to prove completeness
66
+ // against (`ledgerVerify` is admin-gated, not a read surface), so fail
67
+ // CLOSED: a >=1000-tx book with partially-granted row pages would
68
+ // otherwise ship a complete chart of accounts plus a silently partial
69
+ // journal. Never embed half a book — a book that big belongs in a real
70
+ // backup (LGR-15), not a document export.
71
+ if (transactions.length >= LEDGER_MAX_TRANSACTION_LIMIT)
72
+ return null;
73
+ if (rowCount.transactions !== transactions.length)
74
+ return null;
75
+ const postings = transactions.reduce((n, t) => n + t.postings.length, 0);
76
+ if (rowCount.postings !== postings)
77
+ return null;
78
+ // The stored `ledgerDb` settings-row shape (server `LedgerIds`), rebuilt
79
+ // from reads the principal is authorized for.
80
+ const ledgerDb = {
81
+ hostPageId: info.hostPageId,
82
+ ...info.databases,
83
+ hostPages,
84
+ };
85
+ const periods = await client.ledgerListPeriods();
86
+ const settings = {
87
+ ledgerDb,
88
+ ...(periods.length > 0 ? { ledgerPeriods: periods } : {}),
89
+ };
90
+ const [head] = await client.ledgerListAudit({ limit: 1 });
91
+ const auditHead = head ? { seq: head.seq, hash: await ledgerAuditEventHash(head) } : null;
92
+ return { settings, library: { pages, databases }, auditHead };
93
+ }
94
+ catch {
95
+ // Unreadable (guest/viewer without a grant), mid-flight revocation, or any
96
+ // transport failure: no section. The export still succeeds without records.
97
+ return null;
98
+ }
99
+ }
100
+ const isRecord = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
101
+ const asStr = (v) => (typeof v === 'string' ? v : '');
102
+ const asStrOrNull = (v) => (typeof v === 'string' && v !== '' ? v : null);
103
+ const oneOf = (v, list) => typeof v === 'string' && list.includes(v);
104
+ /** Refusal helper: every `ok: false` reason is prefixed consistently. */
105
+ const refuse = (reason) => ({ ok: false, reason });
106
+ /** Overflow-refusing minor-unit addition: `null` when the sum leaves the safe
107
+ * integer range (±2^53) — the caller turns that into a typed refusal, never a
108
+ * thrown MoneyError mid-parse (the total-refusal contract). */
109
+ const addMinor = (a, b) => {
110
+ const sum = a + b;
111
+ return Number.isSafeInteger(sum) ? sum : null;
112
+ };
113
+ /**
114
+ * Parse + deep-validate a {@link LedgerExportSection} into a replayable
115
+ * {@link LedgerSectionBook}, or refuse with a reason. Refusals are TOTAL —
116
+ * a section is either a coherent book or it is not restored at all (never a
117
+ * partial parse the writer then trips over halfway).
118
+ *
119
+ * Validated here (beyond the island reader's shape check):
120
+ * - the `ledgerDb` ids resolve to four DISTINCT databases the section carries;
121
+ * - every row page belongs to one of the four (host pages are pass-through);
122
+ * - enums, dates, and amounts are valid; posted/void entries balance to zero
123
+ * with ≥2 postings; postings reference known accounts/transactions;
124
+ * - the reversal graph is coherent: every `void` entry has exactly one
125
+ * reversal, every reversal negates its original leg-for-leg;
126
+ * - reconciliation invariants: `reconciled` ⇔ frozen by a FINISHED
127
+ * reconciliation on the same account, at most one OPEN per account;
128
+ * - period records are well-formed, closing entries are referenced by
129
+ * exactly one period, and closed ranges do not overlap.
130
+ */
131
+ export function parseLedgerExportSection(section) {
132
+ // The HTTP door hands this raw request JSON — hold the whole envelope to the
133
+ // same suspicion as its contents (a null/array body must refuse, not throw).
134
+ if (!isRecord(section) || !isRecord(section.settings) || !isRecord(section.library)) {
135
+ return refuse('the section is not a {settings, library, auditHead} object');
136
+ }
137
+ if (!Array.isArray(section.library.pages) || !Array.isArray(section.library.databases)) {
138
+ return refuse('the section library does not carry pages[] and databases[]');
139
+ }
140
+ // STRICT envelope (Sasha F1's root): every key of the section, its settings,
141
+ // and its library must be one this parser reads. An unread key is a place
142
+ // arbitrarily deep/large junk can hide — junk the validated projection (and
143
+ // therefore the provenance hash) would silently exclude — so its presence is
144
+ // a refusal, not a shrug. A future exporter that adds a key must teach this
145
+ // parser to read it (fail closed beats silently dropping new content).
146
+ for (const key of Object.keys(section)) {
147
+ if (key !== 'settings' && key !== 'library' && key !== 'auditHead') {
148
+ return refuse(`unexpected section key ${JSON.stringify(key)} — this export is newer than this importer, or the file was tampered with`);
149
+ }
150
+ }
151
+ for (const key of Object.keys(section.settings)) {
152
+ if (key !== 'ledgerDb' && key !== 'ledgerPeriods') {
153
+ return refuse(`unexpected settings key ${JSON.stringify(key)}`);
154
+ }
155
+ }
156
+ for (const key of Object.keys(section.library)) {
157
+ if (key !== 'pages' && key !== 'databases') {
158
+ return refuse(`unexpected library key ${JSON.stringify(key)}`);
159
+ }
160
+ }
161
+ // Element-level shape guards (Sasha F2): the arrays are untrusted too — a
162
+ // null/primitive element must refuse before anything dereferences it.
163
+ for (const p of section.library.pages) {
164
+ if (!isRecord(p) || typeof p.id !== 'string' || p.id === '') {
165
+ return refuse('a library page entry is not a record with a string id');
166
+ }
167
+ }
168
+ for (const d of section.library.databases) {
169
+ if (!isRecord(d) || typeof d.id !== 'string' || d.id === '' || typeof d.pageId !== 'string') {
170
+ return refuse('a library database entry is not a record with string id and pageId');
171
+ }
172
+ }
173
+ let auditHead = null;
174
+ if (section.auditHead !== null && section.auditHead !== undefined) {
175
+ const { seq, hash } = section.auditHead;
176
+ // The hash is copied verbatim into the provenance payload (an append-only
177
+ // audit row), so it is bounded to exactly what a chain hash IS — 64 hex
178
+ // chars — and the seq to a non-negative safe integer (Quinn 4).
179
+ if (typeof seq !== 'number' || !Number.isSafeInteger(seq) || seq < 0 || typeof hash !== 'string' || !/^[0-9a-f]{64}$/.test(hash)) {
180
+ return refuse('the section auditHead is not null or {seq: non-negative integer, hash: 64 hex chars}');
181
+ }
182
+ auditHead = { seq, hash };
183
+ }
184
+ const rawIds = section.settings?.['ledgerDb'];
185
+ if (!isRecord(rawIds))
186
+ return refuse('the section has no ledgerDb settings entry');
187
+ const dbIds = {};
188
+ for (const key of LEDGER_DB_KEYS) {
189
+ const id = rawIds[key];
190
+ if (typeof id !== 'string' || id === '')
191
+ return refuse(`the ledgerDb settings entry has no ${key} database id`);
192
+ dbIds[key] = id;
193
+ }
194
+ if (new Set(Object.values(dbIds)).size !== LEDGER_DB_KEYS.length) {
195
+ return refuse('the four ledger database ids are not distinct');
196
+ }
197
+ const carried = new Set(section.library.databases.map((d) => d.id));
198
+ for (const key of LEDGER_DB_KEYS) {
199
+ if (!carried.has(dbIds[key]))
200
+ return refuse(`the section does not carry the ${key} database it names`);
201
+ }
202
+ // ── Project row pages into entities (host pages — databaseId null — skipped).
203
+ const accounts = [];
204
+ const txRows = [];
205
+ const postingRows = [];
206
+ const reconciliations = [];
207
+ const seenIds = new Set();
208
+ for (const page of section.library.pages) {
209
+ if (!page.databaseId)
210
+ continue; // a host page carries no entity
211
+ if (seenIds.has(page.id))
212
+ return refuse(`duplicate row id ${page.id}`);
213
+ seenIds.add(page.id);
214
+ const props = isRecord(page.properties) ? page.properties : {};
215
+ if (page.databaseId === dbIds.accounts) {
216
+ const type = props[LEDGER_PROP.account.type];
217
+ const status = props[LEDGER_PROP.account.status] ?? 'open';
218
+ const name = asStr(page.name);
219
+ if (!isValidLedgerAccountName(name))
220
+ return refuse(`account ${page.id} has an invalid name ${JSON.stringify(page.name)}`);
221
+ if (!oneOf(type, LEDGER_ACCOUNT_TYPES))
222
+ return refuse(`account ${name} has an invalid type ${JSON.stringify(type)}`);
223
+ if (!oneOf(status, LEDGER_ACCOUNT_STATUSES))
224
+ return refuse(`account ${name} has an invalid status ${JSON.stringify(status)}`);
225
+ const currency = asStr(props[LEDGER_PROP.account.currency]) || 'USD';
226
+ if (!isValidCurrencyCode(currency))
227
+ return refuse(`account ${name} has an invalid currency ${JSON.stringify(currency)}`);
228
+ accounts.push({
229
+ id: page.id,
230
+ name,
231
+ type,
232
+ status,
233
+ currency,
234
+ evidenceRequired: props[LEDGER_PROP.account.evidenceRequired] === true,
235
+ });
236
+ }
237
+ else if (page.databaseId === dbIds.transactions) {
238
+ txRows.push({ page, props });
239
+ }
240
+ else if (page.databaseId === dbIds.postings) {
241
+ postingRows.push({ page, props });
242
+ }
243
+ else if (page.databaseId === dbIds.reconciliations) {
244
+ const status = props[LEDGER_PROP.reconciliation.status] ?? 'open';
245
+ const balance = props[LEDGER_PROP.reconciliation.statementBalance];
246
+ const statementDate = props[LEDGER_PROP.reconciliation.statementDate];
247
+ if (!oneOf(status, LEDGER_RECONCILIATION_STATUSES))
248
+ return refuse(`reconciliation ${page.id} has an invalid status`);
249
+ if (!isValidLedgerDate(statementDate))
250
+ return refuse(`reconciliation ${page.id} has an invalid statement date`);
251
+ if (!isValidMinor(balance))
252
+ return refuse(`reconciliation ${page.id} has an invalid statement balance`);
253
+ reconciliations.push({
254
+ id: page.id,
255
+ accountId: asStr(props[LEDGER_PROP.reconciliation.account]),
256
+ statementDate,
257
+ statementBalanceMinor: balance,
258
+ status,
259
+ createdAt: asStr(page.createdAt),
260
+ });
261
+ }
262
+ else {
263
+ return refuse(`row ${page.id} belongs to database ${page.databaseId}, which is not one of the four ledger databases`);
264
+ }
265
+ }
266
+ if (txRows.length > LEDGER_MAX_TRANSACTION_LIMIT) {
267
+ return refuse(`the section carries ${txRows.length} journal entries — over the ${LEDGER_MAX_TRANSACTION_LIMIT}-entry ceiling an export section may hold (a book that size travels in a backup bundle, not a document export)`);
268
+ }
269
+ const accountById = new Map(accounts.map((a) => [a.id, a]));
270
+ const recById = new Map(reconciliations.map((r) => [r.id, r]));
271
+ // ── Postings, grouped under their transactions (order: `position`, the
272
+ // stored sibling key — posting order feeds the audited content hash).
273
+ const postingsByTx = new Map();
274
+ for (const { page, props } of postingRows) {
275
+ const txId = asStr(props[LEDGER_PROP.posting.transaction]);
276
+ const accountId = asStr(props[LEDGER_PROP.posting.account]);
277
+ const amount = props[LEDGER_PROP.posting.amount];
278
+ const cleared = props[LEDGER_PROP.posting.cleared] ?? 'pending';
279
+ if (!accountById.has(accountId))
280
+ return refuse(`posting ${page.id} references unknown account ${accountId || '(none)'}`);
281
+ if (!isValidMinor(amount))
282
+ return refuse(`posting ${page.id} has an invalid amount`);
283
+ if (!oneOf(cleared, LEDGER_CLEARED_STATES))
284
+ return refuse(`posting ${page.id} has an invalid cleared state`);
285
+ const reconciliationId = asStrOrNull(props[LEDGER_PROP.posting.reconciliation]);
286
+ if (reconciliationId !== null && !recById.has(reconciliationId)) {
287
+ return refuse(`posting ${page.id} references unknown reconciliation ${reconciliationId}`);
288
+ }
289
+ // Invariant 4, both directions: `reconciled` means frozen by a FINISHED
290
+ // reconciliation on the posting's own account, and nothing else does.
291
+ if ((cleared === 'reconciled') !== (reconciliationId !== null)) {
292
+ return refuse(`posting ${page.id} breaks the reconciled↔frozen invariant`);
293
+ }
294
+ if (reconciliationId !== null) {
295
+ const rec = recById.get(reconciliationId);
296
+ if (rec.status !== 'finished')
297
+ return refuse(`posting ${page.id} is frozen by reconciliation ${rec.id}, which is not finished`);
298
+ if (rec.accountId !== accountId)
299
+ return refuse(`posting ${page.id} is frozen by a reconciliation on another account`);
300
+ }
301
+ const memo = props[LEDGER_PROP.posting.memo];
302
+ if (memo !== undefined && memo !== null && typeof memo !== 'string')
303
+ return refuse(`posting ${page.id} has a non-string memo`);
304
+ if (typeof memo === 'string' && memo.length > SECTION_MAX_TEXT)
305
+ return refuse(`posting ${page.id} has a memo over the ${SECTION_MAX_TEXT}-character cap`);
306
+ const list = postingsByTx.get(txId) ?? [];
307
+ list.push({
308
+ posting: { id: page.id, accountId, amountMinor: amount, cleared, reconciliationId, memo: asStrOrNull(memo) },
309
+ position: typeof page.position === 'number' && Number.isFinite(page.position) ? page.position : list.length,
310
+ });
311
+ postingsByTx.set(txId, list);
312
+ }
313
+ // ── Transactions.
314
+ const transactions = [];
315
+ for (const { page, props } of txRows) {
316
+ const date = props[LEDGER_PROP.transaction.date];
317
+ const state = props[LEDGER_PROP.transaction.state] ?? 'draft';
318
+ if (!isValidLedgerDate(date))
319
+ return refuse(`journal entry ${page.id} has an invalid date`);
320
+ if (!oneOf(state, LEDGER_TRANSACTION_STATES))
321
+ return refuse(`journal entry ${page.id} has an invalid state`);
322
+ const entryNoRaw = props[LEDGER_PROP.transaction.entryNo];
323
+ const entryNo = typeof entryNoRaw === 'number' && Number.isFinite(entryNoRaw) ? entryNoRaw : null;
324
+ const kind = props[LEDGER_PROP.transaction.kind] === 'closing' ? 'closing' : null;
325
+ const evidence = props[LEDGER_PROP.transaction.evidence];
326
+ const description = asStr(props[LEDGER_PROP.transaction.description]);
327
+ if (description.length > SECTION_MAX_TEXT)
328
+ return refuse(`journal entry ${page.id} has a description over the ${SECTION_MAX_TEXT}-character cap`);
329
+ const ordered = (postingsByTx.get(page.id) ?? []).sort((a, b) => a.position - b.position).map((p) => p.posting);
330
+ postingsByTx.delete(page.id);
331
+ if (ordered.length > SECTION_MAX_POSTINGS)
332
+ return refuse(`journal entry ${page.id} has more than ${SECTION_MAX_POSTINGS} postings`);
333
+ if (state !== 'draft') {
334
+ if (entryNo === null)
335
+ return refuse(`${state} entry ${page.id} has no entry number`);
336
+ if (ordered.length < 2)
337
+ return refuse(`${state} entry ${page.id} has fewer than 2 postings`);
338
+ let balance = 0;
339
+ for (const p of ordered) {
340
+ balance = addMinor(balance, p.amountMinor);
341
+ if (balance === null)
342
+ return refuse(`${state} entry ${page.id} postings overflow the safe integer range`);
343
+ }
344
+ if (balance !== 0)
345
+ return refuse(`${state} entry ${page.id} does not balance to zero`);
346
+ }
347
+ else if (ordered.some((p) => p.cleared === 'reconciled')) {
348
+ return refuse(`draft entry ${page.id} carries a reconciled posting`);
349
+ }
350
+ if (kind === 'closing' && state === 'draft')
351
+ return refuse(`closing entry ${page.id} is a draft`);
352
+ transactions.push({
353
+ id: page.id,
354
+ date,
355
+ description,
356
+ state,
357
+ reverses: asStrOrNull(props[LEDGER_PROP.transaction.reverses]),
358
+ entryNo,
359
+ kind,
360
+ evidenceCount: Array.isArray(evidence) ? evidence.length : 0,
361
+ postings: ordered,
362
+ createdAt: asStr(page.createdAt),
363
+ });
364
+ }
365
+ if (postingsByTx.size > 0) {
366
+ const [orphanTx] = postingsByTx.keys();
367
+ return refuse(`postings reference journal entry ${orphanTx}, which the section does not carry`);
368
+ }
369
+ const txById = new Map(transactions.map((t) => [t.id, t]));
370
+ // ── Reversal graph: every void entry has exactly one reversal, and every
371
+ // reversal negates its original leg for leg (the writer will regenerate the
372
+ // reversal from the original, so a section claiming otherwise cannot replay
373
+ // faithfully and is refused rather than silently rewritten).
374
+ const reversalsOf = new Map();
375
+ for (const tx of transactions) {
376
+ if (tx.reverses === null)
377
+ continue;
378
+ const original = txById.get(tx.reverses);
379
+ if (!original)
380
+ return refuse(`reversal ${tx.id} reverses unknown entry ${tx.reverses}`);
381
+ if (tx.state === 'draft')
382
+ return refuse(`reversal ${tx.id} is a draft`);
383
+ if (original.state !== 'void')
384
+ return refuse(`reversal ${tx.id} reverses entry ${original.id}, which is ${original.state}, not void`);
385
+ const legs = new Map();
386
+ for (const p of [...original.postings, ...tx.postings]) {
387
+ const next = addMinor(legs.get(p.accountId) ?? 0, p.amountMinor);
388
+ if (next === null)
389
+ return refuse(`reversal ${tx.id} postings overflow the safe integer range`);
390
+ legs.set(p.accountId, next);
391
+ }
392
+ if ([...legs.values()].some((v) => v !== 0)) {
393
+ return refuse(`reversal ${tx.id} does not negate entry ${original.id} leg for leg`);
394
+ }
395
+ reversalsOf.set(original.id, [...(reversalsOf.get(original.id) ?? []), tx]);
396
+ }
397
+ for (const tx of transactions) {
398
+ if (tx.state === 'void' && (reversalsOf.get(tx.id) ?? []).length !== 1) {
399
+ return refuse(`void entry ${tx.id} does not have exactly one reversal`);
400
+ }
401
+ }
402
+ // ── Reconciliations: at most one OPEN per account; accounts resolve.
403
+ const openByAccount = new Set();
404
+ for (const rec of reconciliations) {
405
+ if (!accountById.has(rec.accountId))
406
+ return refuse(`reconciliation ${rec.id} references unknown account ${rec.accountId || '(none)'}`);
407
+ if (rec.status === 'open') {
408
+ if (openByAccount.has(rec.accountId))
409
+ return refuse(`account ${rec.accountId} has more than one open reconciliation`);
410
+ openByAccount.add(rec.accountId);
411
+ }
412
+ }
413
+ // ── Periods (from settings.ledgerPeriods — the stored row, verbatim).
414
+ const rawPeriods = section.settings?.['ledgerPeriods'];
415
+ const periods = [];
416
+ if (rawPeriods !== undefined && rawPeriods !== null) {
417
+ if (!Array.isArray(rawPeriods))
418
+ return refuse('ledgerPeriods is not an array');
419
+ for (const raw of rawPeriods) {
420
+ if (!isRecord(raw))
421
+ return refuse('a period record is not an object');
422
+ const { id, start, end, status, closingEntryId, reopenEntryId } = raw;
423
+ if (typeof id !== 'string' || id === '')
424
+ return refuse('a period record has no id');
425
+ if (!isValidLedgerDate(start) || !isValidLedgerDate(end) || end < start)
426
+ return refuse(`period ${id} has an invalid date range`);
427
+ if (!oneOf(status, LEDGER_PERIOD_STATUSES))
428
+ return refuse(`period ${id} has an invalid status`);
429
+ const closing = asStrOrNull(closingEntryId ?? null);
430
+ const reopen = asStrOrNull(reopenEntryId ?? null);
431
+ if (closing !== null) {
432
+ const entry = txById.get(closing);
433
+ if (!entry || entry.kind !== 'closing')
434
+ return refuse(`period ${id} names closing entry ${closing}, which the section does not carry as a closing entry`);
435
+ const expectedState = status === 'closed' ? 'posted' : 'void';
436
+ if (entry.state !== expectedState)
437
+ return refuse(`period ${id} is ${status} but its closing entry ${closing} is ${entry.state}`);
438
+ }
439
+ if (status === 'reopened') {
440
+ if (closing !== null && (reopen === null || txById.get(reopen)?.reverses !== closing)) {
441
+ return refuse(`period ${id} was reopened but its reversal entry is missing or does not reverse its closing entry`);
442
+ }
443
+ }
444
+ else if (reopen !== null) {
445
+ return refuse(`period ${id} is closed but records a reopen entry`);
446
+ }
447
+ periods.push({
448
+ id,
449
+ start,
450
+ end,
451
+ status,
452
+ closingEntryId: closing,
453
+ reopenEntryId: reopen,
454
+ closedAt: asStr(raw.closedAt),
455
+ closedBy: asStr(raw.closedBy),
456
+ reopenedAt: asStrOrNull(raw.reopenedAt),
457
+ reopenedBy: asStrOrNull(raw.reopenedBy),
458
+ });
459
+ }
460
+ // Closed ranges must not overlap (the store enforces this live; a section
461
+ // claiming otherwise could never have come from the writer).
462
+ const closed = periods.filter((p) => p.status === 'closed').sort((a, b) => (a.start < b.start ? -1 : 1));
463
+ for (let i = 1; i < closed.length; i += 1) {
464
+ if (closed[i].start <= closed[i - 1].end)
465
+ return refuse(`closed periods ${closed[i - 1].id} and ${closed[i].id} overlap`);
466
+ }
467
+ }
468
+ // Every closing entry belongs to exactly one period record.
469
+ const claimedClosings = new Set(periods.map((p) => p.closingEntryId).filter((id) => id !== null));
470
+ for (const tx of transactions) {
471
+ if (tx.kind === 'closing' && !claimedClosings.has(tx.id)) {
472
+ return refuse(`closing entry ${tx.id} is not referenced by any period record`);
473
+ }
474
+ }
475
+ // ── Period entries must be workflow-PRISTINE (Quinn 1). The restore
476
+ // REGENERATES closing entries and reopen reversals through
477
+ // closePeriod/reopenPeriod, whose legs are always born `pending`/unowned —
478
+ // a cleared tick on one would be silently dropped, and a leg frozen by a
479
+ // finished reconciliation could not be re-frozen at all (its posting is
480
+ // minted after the reconciliation pass). Either way the section cannot
481
+ // replay faithfully: refuse totally, and point at the lane that can.
482
+ const closingIds = new Set(transactions.filter((t) => t.kind === 'closing').map((t) => t.id));
483
+ for (const tx of transactions) {
484
+ const isPeriodEntry = tx.kind === 'closing' || (tx.reverses !== null && closingIds.has(tx.reverses));
485
+ if (!isPeriodEntry)
486
+ continue;
487
+ for (const p of tx.postings) {
488
+ if (p.cleared !== 'pending' || p.reconciliationId !== null) {
489
+ return refuse(`period entry ${tx.id} carries workflow state on a posting (a cleared tick or a reconciliation freeze) that a document-export restore cannot replay — restore from a backup bundle instead`);
490
+ }
491
+ }
492
+ }
493
+ // ── The closing sweeps must REPLAY to what the section records (Quinn 2).
494
+ // The restore's closePeriod recomputes each sweep over the FULLY-replayed
495
+ // books, while the source computed it over the books as they stood at close
496
+ // time — and the store legally admits entries dated in or before a period
497
+ // that were posted after its close (the date lock only covers dates INSIDE
498
+ // a closed range). Simulate every close in the replay's own chronology and
499
+ // refuse totally on any divergence, so per-account balances can never
500
+ // silently differ after a "successful" restore.
501
+ if (periods.length > 0) {
502
+ const incomeIds = new Set(accounts.filter((a) => isIncomeStatementAccountType(a.type)).map((a) => a.id));
503
+ const periodEntryIds = new Set();
504
+ for (const p of periods) {
505
+ if (p.closingEntryId)
506
+ periodEntryIds.add(p.closingEntryId);
507
+ if (p.reopenEntryId)
508
+ periodEntryIds.add(p.reopenEntryId);
509
+ }
510
+ // What exists when the period replay starts: every ordinary posted/void
511
+ // entry (the replay lands them all first). Period entries join as their
512
+ // close/reopen events are replayed. State (posted vs void) is irrelevant —
513
+ // the store's sweep counts BOTH (a void original is offset by its posted
514
+ // reversal), so existence alone decides.
515
+ const onBooks = new Set(transactions.filter((t) => t.state !== 'draft' && !periodEntryIds.has(t.id)).map((t) => t.id));
516
+ const events = [];
517
+ for (const p of periods) {
518
+ events.push({ at: p.closedAt || '', kind: 'close', period: p });
519
+ if (p.status === 'reopened')
520
+ events.push({ at: p.reopenedAt || p.closedAt || '', kind: 'reopen', period: p });
521
+ }
522
+ events.sort((a, b) => (a.at < b.at ? -1 : a.at > b.at ? 1 : a.kind === b.kind ? 0 : a.kind === 'close' ? -1 : 1));
523
+ for (const ev of events) {
524
+ if (ev.kind === 'reopen') {
525
+ if (ev.period.reopenEntryId)
526
+ onBooks.add(ev.period.reopenEntryId);
527
+ continue;
528
+ }
529
+ // The sweep closePeriod will regenerate: every income account's
530
+ // cumulative balance over on-the-books entries dated ≤ end.
531
+ const balances = new Map();
532
+ for (const tx of transactions) {
533
+ if (!onBooks.has(tx.id) || tx.date > ev.period.end)
534
+ continue;
535
+ for (const p of tx.postings) {
536
+ if (!incomeIds.has(p.accountId))
537
+ continue;
538
+ const next = addMinor(balances.get(p.accountId) ?? 0, p.amountMinor);
539
+ if (next === null)
540
+ return refuse(`the income sweep for period ${ev.period.id} overflows the safe integer range`);
541
+ balances.set(p.accountId, next);
542
+ }
543
+ }
544
+ for (const [accountId, balance] of balances) {
545
+ if (balance === 0)
546
+ balances.delete(accountId);
547
+ }
548
+ const mismatch = () => refuse(`the closing entry recorded for period ${ev.period.start} – ${ev.period.end} does not match the sweep a restore would regenerate — entries dated in or before the period were posted after it was closed. This book cannot round-trip through a document export; restore from a backup bundle instead`);
549
+ const closing = ev.period.closingEntryId === null ? undefined : txById.get(ev.period.closingEntryId);
550
+ if (!closing) {
551
+ if (balances.size > 0)
552
+ return mismatch();
553
+ continue; // nothing to sweep, nothing recorded — consistent
554
+ }
555
+ // Recorded legs, netted per account; must be exactly: one leg per
556
+ // nonzero income balance (negated) plus ONE non-income (retained-
557
+ // earnings) leg carrying the sweep total.
558
+ const legs = new Map();
559
+ for (const p of closing.postings) {
560
+ const next = addMinor(legs.get(p.accountId) ?? 0, p.amountMinor);
561
+ if (next === null)
562
+ return refuse(`closing entry ${closing.id} postings overflow the safe integer range`);
563
+ legs.set(p.accountId, next);
564
+ }
565
+ let total = 0;
566
+ for (const [accountId, balance] of balances) {
567
+ if (legs.get(accountId) !== -balance)
568
+ return mismatch();
569
+ legs.delete(accountId);
570
+ total = addMinor(total, balance);
571
+ if (total === null)
572
+ return refuse(`the income sweep for period ${ev.period.id} overflows the safe integer range`);
573
+ }
574
+ const rest = [...legs.entries()];
575
+ if (rest.length !== 1 || incomeIds.has(rest[0][0]) || rest[0][1] !== total)
576
+ return mismatch();
577
+ onBooks.add(closing.id);
578
+ }
579
+ }
580
+ // ── Replay order: posted/void by entry number, then drafts by creation.
581
+ transactions.sort((a, b) => {
582
+ const an = a.entryNo ?? Number.MAX_SAFE_INTEGER;
583
+ const bn = b.entryNo ?? Number.MAX_SAFE_INTEGER;
584
+ if (an !== bn)
585
+ return an - bn;
586
+ return a.createdAt < b.createdAt ? -1 : a.createdAt > b.createdAt ? 1 : a.id < b.id ? -1 : 1;
587
+ });
588
+ const evidenceDropped = transactions.reduce((n, t) => n + t.evidenceCount, 0);
589
+ return {
590
+ ok: true,
591
+ book: { accounts, transactions, reconciliations, periods, auditHead, evidenceDropped },
592
+ };
593
+ }
594
+ //# sourceMappingURL=ledgerExportSection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledgerExportSection.js","sourceRoot":"","sources":["../src/ledgerExportSection.ts"],"names":[],"mappings":"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"}