@noy-db/hub 0.6.0-pre.7 → 0.6.0-pre.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/cargo/index.js +1 -1
  2. package/dist/{chunk-YM75S6N6.js → chunk-2GAJGUNM.js} +139 -11
  3. package/dist/chunk-2GAJGUNM.js.map +1 -0
  4. package/dist/{chunk-PXCBVDFY.js → chunk-5O5HRRTV.js} +35 -2
  5. package/dist/chunk-5O5HRRTV.js.map +1 -0
  6. package/dist/{chunk-XBRNBG4Z.js → chunk-BEFVYAR5.js} +2 -2
  7. package/dist/{chunk-J7FM3RAU.js → chunk-BRVW2GS5.js} +2 -2
  8. package/dist/{chunk-4R55OPT2.js → chunk-BWVKEOPE.js} +2 -2
  9. package/dist/{chunk-ZMSE2ZZ4.js → chunk-GAG7QOVO.js} +6 -6
  10. package/dist/chunk-GAG7QOVO.js.map +1 -0
  11. package/dist/{chunk-JXIDGFKS.js → chunk-HPLWFNG4.js} +3 -1
  12. package/dist/chunk-HPLWFNG4.js.map +1 -0
  13. package/dist/{chunk-GOLN6LQ5.js → chunk-N35NC4JH.js} +2 -2
  14. package/dist/{chunk-WNFZI3I5.js → chunk-RV3ARMPN.js} +2 -2
  15. package/dist/{chunk-NNYENE7N.js → chunk-RXYYFSBB.js} +36 -2
  16. package/dist/chunk-RXYYFSBB.js.map +1 -0
  17. package/dist/{dispatch-4NSDG6EP.js → dispatch-FZEAWKVM.js} +5 -5
  18. package/dist/{executor-HYQBNG6J.js → executor-YIQB2S6N.js} +3 -3
  19. package/dist/index.js +10 -10
  20. package/dist/kernel/vault.d.ts +8 -2
  21. package/dist/materialized-views/index.js +3 -3
  22. package/dist/money/index.js +2 -2
  23. package/dist/{noydb-LYIAD4CW.js → noydb-ASEXNJS6.js} +4 -4
  24. package/dist/periods/index.js +8 -2
  25. package/dist/pod/index.js +4 -4
  26. package/dist/{stale-C27ICSB4.js → stale-ARHFVL5U.js} +2 -2
  27. package/dist/sync/index.js +2 -2
  28. package/dist/via/money/normalize.d.ts +20 -0
  29. package/dist/with-audit/periods/index.d.ts +3 -3
  30. package/dist/with-audit/periods/periods.d.ts +81 -1
  31. package/dist/with-audit/periods/vault-facade.d.ts +54 -1
  32. package/dist/with-audit/periods/window.d.ts +10 -0
  33. package/dist/with-shape/introspection/index.d.ts +1 -0
  34. package/package.json +3 -3
  35. package/dist/chunk-JXIDGFKS.js.map +0 -1
  36. package/dist/chunk-NNYENE7N.js.map +0 -1
  37. package/dist/chunk-PXCBVDFY.js.map +0 -1
  38. package/dist/chunk-YM75S6N6.js.map +0 -1
  39. package/dist/chunk-ZMSE2ZZ4.js.map +0 -1
  40. /package/dist/{chunk-XBRNBG4Z.js.map → chunk-BEFVYAR5.js.map} +0 -0
  41. /package/dist/{chunk-J7FM3RAU.js.map → chunk-BRVW2GS5.js.map} +0 -0
  42. /package/dist/{chunk-4R55OPT2.js.map → chunk-BWVKEOPE.js.map} +0 -0
  43. /package/dist/{chunk-GOLN6LQ5.js.map → chunk-N35NC4JH.js.map} +0 -0
  44. /package/dist/{chunk-WNFZI3I5.js.map → chunk-RV3ARMPN.js.map} +0 -0
  45. /package/dist/{dispatch-4NSDG6EP.js.map → dispatch-FZEAWKVM.js.map} +0 -0
  46. /package/dist/{executor-HYQBNG6J.js.map → executor-YIQB2S6N.js.map} +0 -0
  47. /package/dist/{noydb-LYIAD4CW.js.map → noydb-ASEXNJS6.js.map} +0 -0
  48. /package/dist/{stale-C27ICSB4.js.map → stale-ARHFVL5U.js.map} +0 -0
@@ -6,7 +6,7 @@ import {
6
6
  diffVault,
7
7
  unsealDeks,
8
8
  withCargo
9
- } from "../chunk-WNFZI3I5.js";
9
+ } from "../chunk-RV3ARMPN.js";
10
10
  import {
11
11
  extractPartition,
12
12
  walkClosure
@@ -109,17 +109,20 @@ import {
109
109
  } from "./chunk-PEOZ34EM.js";
110
110
  import {
111
111
  NO_PERIODS,
112
+ isEffectivelyReopened,
112
113
  purgeMarkersOn,
113
114
  resolvePeriodKey,
115
+ resolveReopenState,
114
116
  samePartition
115
- } from "./chunk-PXCBVDFY.js";
117
+ } from "./chunk-5O5HRRTV.js";
116
118
  import {
117
119
  PERIODS_COLLECTION,
118
120
  PERIOD_ARCHIVES_COLLECTION,
119
121
  PERIOD_FREEZES_COLLECTION,
122
+ PERIOD_REOPENS_COLLECTION,
120
123
  PERIOD_TARGET_PURGES_COLLECTION,
121
124
  periodExclusiveUpperBound
122
- } from "./chunk-JXIDGFKS.js";
125
+ } from "./chunk-HPLWFNG4.js";
123
126
  import {
124
127
  NO_SHADOW
125
128
  } from "./chunk-SMY5X46Z.js";
@@ -3406,7 +3409,7 @@ var Collection = class {
3406
3409
  }
3407
3410
  }
3408
3411
  if (this.materializedViewSource !== void 0) {
3409
- const { resolveStaleMVOnRead } = await import("./stale-C27ICSB4.js");
3412
+ const { resolveStaleMVOnRead } = await import("./stale-ARHFVL5U.js");
3410
3413
  await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: "resolve-on-read" }));
3411
3414
  }
3412
3415
  let record;
@@ -3936,7 +3939,7 @@ var Collection = class {
3936
3939
  */
3937
3940
  async dispatchMaterializedViews(id, record, wave) {
3938
3941
  if (this.materializedViewSource === void 0) return;
3939
- const { dispatchMaterializedViews } = await import("./dispatch-4NSDG6EP.js");
3942
+ const { dispatchMaterializedViews } = await import("./dispatch-FZEAWKVM.js");
3940
3943
  return dispatchMaterializedViews(this.#mvDispatchCtx(this.materializedViewSource), id, record, wave);
3941
3944
  }
3942
3945
  /**
@@ -4438,7 +4441,7 @@ var Collection = class {
4438
4441
  */
4439
4442
  async dispatchMaterializedViewsOnDelete(id) {
4440
4443
  if (this.materializedViewSource === void 0) return { deleted: 0, residueUndecodable: [], residueDeclined: [] };
4441
- const { dispatchMaterializedViewsOnDelete } = await import("./dispatch-4NSDG6EP.js");
4444
+ const { dispatchMaterializedViewsOnDelete } = await import("./dispatch-FZEAWKVM.js");
4442
4445
  return dispatchMaterializedViewsOnDelete(this.#mvDispatchCtx(this.materializedViewSource), id);
4443
4446
  }
4444
4447
  /**
@@ -4458,7 +4461,7 @@ var Collection = class {
4458
4461
  );
4459
4462
  }
4460
4463
  if (this.materializedViewSource !== void 0) {
4461
- const { resolveStaleMVOnRead } = await import("./stale-C27ICSB4.js");
4464
+ const { resolveStaleMVOnRead } = await import("./stale-ARHFVL5U.js");
4462
4465
  await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: "resolve-on-read" }));
4463
4466
  }
4464
4467
  await this.ensureHydrated();
@@ -6417,7 +6420,8 @@ var VaultPeriods = class {
6417
6420
  if (tp) targetPurges.set(tp.period, tp);
6418
6421
  }
6419
6422
  const scoped = options === void 0 ? all : all.filter((p) => samePartition(p.partition, options.partition));
6420
- return scoped.map((p) => {
6423
+ const withReopen = await this.mergeReopenState(scoped);
6424
+ return withReopen.map((p) => {
6421
6425
  const f = freezes.get(p.name);
6422
6426
  let merged = f ? this.mergeFreeze(p, f) : p;
6423
6427
  const a = archives.get(p.name);
@@ -6447,8 +6451,119 @@ var VaultPeriods = class {
6447
6451
  if (archive) merged = this.mergeArchive(merged, archive);
6448
6452
  const targetPurge = await this.readReserved(PERIOD_TARGET_PURGES_COLLECTION, key);
6449
6453
  if (targetPurge) merged = this.mergeTargetPurge(merged, targetPurge);
6454
+ const reopenLog = await this.readReserved(PERIOD_REOPENS_COLLECTION, key);
6455
+ if (reopenLog) merged = { ...merged, ...resolveReopenState(reopenLog.events) };
6450
6456
  return merged;
6451
6457
  }
6458
+ /**
6459
+ * The full append-only reopen/reclose log for one period (#1022) — the record
6460
+ * an audit actually asks for, in order. `[]` when never reopened.
6461
+ */
6462
+ async listPeriodReopens(name, options) {
6463
+ const key = resolvePeriodKey(name, options?.partition);
6464
+ const log = await this.readReserved(PERIOD_REOPENS_COLLECTION, key);
6465
+ return log?.events ?? [];
6466
+ }
6467
+ /**
6468
+ * Return a closed period to a writable state (#1022).
6469
+ *
6470
+ * Close is a three-state lifecycle in practice — open / closed / reopened —
6471
+ * because a month gets closed and then a missing invoice arrives, or a filing
6472
+ * is rejected and must be amended. That is routine, and it is supposed to
6473
+ * leave a trail.
6474
+ *
6475
+ * The `_periods/<key>` record is NOT touched: the reopen is appended to a
6476
+ * companion log, so the inter-period hash chain that proves the close
6477
+ * happened survives the reopen intact. The chain reads *closed at T1,
6478
+ * reopened at T2 by U, reclosed at T3*.
6479
+ *
6480
+ * A reopen withdraws the PERIOD's veto and nothing else. Record-level rules —
6481
+ * an `immutableGuard` on a sent receipt, a frozen field — are separate gate
6482
+ * handlers registered ahead of the period gate, so a reopened month cannot
6483
+ * resurrect a document that is independently locked. Period state can only
6484
+ * ever widen what the record-level rule already permits.
6485
+ *
6486
+ * Reopening an already-open window is allowed and appends another event: that
6487
+ * is how a window gets extended, and the log keeps both.
6488
+ */
6489
+ async reopenPeriod(name, options) {
6490
+ const existing = await this.loadPeriodsCache();
6491
+ const period = this.findPeriod(existing, name, options);
6492
+ if (!period) throw new ValidationError(`reopenPeriod: no period named "${name}"${scopeSuffix(options)}.`);
6493
+ if (period.kind !== "closed") {
6494
+ throw new ValidationError(
6495
+ `reopenPeriod: period "${name}" is "${period.kind}"; only a closed period can be reopened.`
6496
+ );
6497
+ }
6498
+ if (options?.until !== void 0 && Number.isNaN(Date.parse(options.until))) {
6499
+ throw new ValidationError(`reopenPeriod: unparseable \`until\` "${options.until}".`);
6500
+ }
6501
+ return this.appendReopenEvent(period, options, {
6502
+ op: "reopen",
6503
+ at: (/* @__PURE__ */ new Date()).toISOString(),
6504
+ by: this.deps.userId(),
6505
+ ...options?.until !== void 0 && { until: options.until },
6506
+ ...options?.reason !== void 0 && { reason: options.reason }
6507
+ });
6508
+ }
6509
+ /**
6510
+ * Seal a reopened period again (#1022), ending the window explicitly rather
6511
+ * than waiting for an `until` to lapse. Appends to the same log, so the
6512
+ * close → reopen → reclose sequence is recoverable in order.
6513
+ */
6514
+ async reclosePeriod(name, options) {
6515
+ const existing = await this.loadPeriodsCache();
6516
+ const period = this.findPeriod(existing, name, options);
6517
+ if (!period) throw new ValidationError(`reclosePeriod: no period named "${name}"${scopeSuffix(options)}.`);
6518
+ const merged = await this.mergeReopenState([period]);
6519
+ if (!isEffectivelyReopened(merged[0], (/* @__PURE__ */ new Date()).toISOString())) {
6520
+ throw new ValidationError(
6521
+ `reclosePeriod: period "${name}"${scopeSuffix(options)} is not currently reopened \u2014 nothing to reclose. A period whose \`until\` has already lapsed re-sealed on its own.`
6522
+ );
6523
+ }
6524
+ return this.appendReopenEvent(period, options, {
6525
+ op: "reclose",
6526
+ at: (/* @__PURE__ */ new Date()).toISOString(),
6527
+ by: this.deps.userId(),
6528
+ ...options?.reason !== void 0 && { reason: options.reason }
6529
+ });
6530
+ }
6531
+ /** Append one entry to a period's reopen log, ledger it, and invalidate the guard's view. */
6532
+ async appendReopenEvent(period, scope, event) {
6533
+ const key = resolvePeriodKey(period.name, period.partition);
6534
+ const prior = await this.readReserved(PERIOD_REOPENS_COLLECTION, key);
6535
+ const record = {
6536
+ period: period.name,
6537
+ ...hasPartition(period.partition) && { partition: period.partition },
6538
+ events: [...prior?.events ?? [], event]
6539
+ };
6540
+ const envelope = await this.writeReserved(PERIOD_REOPENS_COLLECTION, key, record);
6541
+ await this.deps.strategy.appendPeriodLedgerEntry(
6542
+ this.deps.getLedgerOrNull(),
6543
+ this.deps.userId(),
6544
+ envelope,
6545
+ key,
6546
+ PERIOD_REOPENS_COLLECTION
6547
+ );
6548
+ this.periodCache = null;
6549
+ void scope;
6550
+ return { ...period, ...resolveReopenState(record.events) };
6551
+ }
6552
+ /** Merge each period's reopen log onto it. One adapter listing, not one per period. */
6553
+ async mergeReopenState(periods) {
6554
+ if (periods.length === 0) return [];
6555
+ const ids = await this.deps.adapter.list(this.deps.vault, PERIOD_REOPENS_COLLECTION);
6556
+ if (ids.length === 0) return [...periods];
6557
+ const byKey = /* @__PURE__ */ new Map();
6558
+ for (const id of ids) {
6559
+ const r = await this.readReserved(PERIOD_REOPENS_COLLECTION, id);
6560
+ if (r) byKey.set(id, r);
6561
+ }
6562
+ return periods.map((p) => {
6563
+ const log = byKey.get(resolvePeriodKey(p.name, p.partition));
6564
+ return log ? { ...p, ...resolveReopenState(log.events) } : p;
6565
+ });
6566
+ }
6452
6567
  /** Resolve one period within the timeline named by `options` (vault-wide when absent). */
6453
6568
  findPeriod(all, name, options) {
6454
6569
  return all.find((p) => p.name === name && samePartition(p.partition, options?.partition));
@@ -6457,11 +6572,12 @@ var VaultPeriods = class {
6457
6572
  async assertTsWritable(existing, incoming, collection) {
6458
6573
  if (existing === null && incoming === null) return;
6459
6574
  if (this.periodCache === null) {
6460
- this.periodCache = await this.deps.strategy.loadPeriods(
6575
+ const loaded = await this.deps.strategy.loadPeriods(
6461
6576
  this.deps.adapter,
6462
6577
  this.deps.vault,
6463
6578
  (env) => this.decryptPeriodRecord(env)
6464
6579
  );
6580
+ this.periodCache = await this.mergeReopenState(loaded);
6465
6581
  }
6466
6582
  if (this.periodCache.length === 0) return;
6467
6583
  this.deps.strategy.assertTsWritable(
@@ -10184,14 +10300,14 @@ var Vault = class {
10184
10300
  if (!reg) {
10185
10301
  throw new Error(`refreshView: no MV registered with name "${name}"`);
10186
10302
  }
10187
- const { MaterializedViewExecutor } = await import("./executor-HYQBNG6J.js");
10303
+ const { MaterializedViewExecutor } = await import("./executor-YIQB2S6N.js");
10188
10304
  const result = await MaterializedViewExecutor.refresh(reg, {
10189
10305
  getCollection: (n) => this.collection(n),
10190
10306
  getActiveTxContext: () => this.noydb._activeTxContextOrNull,
10191
10307
  getQueryContext: () => this,
10192
10308
  dispatchCtx: this._dispatchCtx({ collection: name, id: "refreshView" })
10193
10309
  });
10194
- const { clearMVStaleFully } = await import("./stale-C27ICSB4.js");
10310
+ const { clearMVStaleFully } = await import("./stale-ARHFVL5U.js");
10195
10311
  await clearMVStaleFully(this.adapter, this.name, registry, name);
10196
10312
  return result;
10197
10313
  }
@@ -10699,6 +10815,18 @@ var Vault = class {
10699
10815
  async purgePeriodTargets(name, options) {
10700
10816
  return this.periods.purgePeriodTargets(name, options);
10701
10817
  }
10818
+ /** Return a closed period to writable (#1022); logged append-only, close chain untouched. */
10819
+ async reopenPeriod(name, options) {
10820
+ return this.periods.reopenPeriod(name, options);
10821
+ }
10822
+ /** Seal a reopened period again (#1022) rather than waiting for its `until` to lapse. */
10823
+ async reclosePeriod(name, options) {
10824
+ return this.periods.reclosePeriod(name, options);
10825
+ }
10826
+ /** The append-only reopen/reclose log for one period (#1022), in order. */
10827
+ async listPeriodReopens(name, options) {
10828
+ return this.periods.listPeriodReopens(name, options);
10829
+ }
10702
10830
  /** @internal — called by the gate bus before put/delete. */
10703
10831
  async _assertTsWritable(existing, incoming, collection) {
10704
10832
  return this.periods.assertTsWritable(existing, incoming, collection);
@@ -14414,4 +14542,4 @@ export {
14414
14542
  Noydb,
14415
14543
  createNoydb
14416
14544
  };
14417
- //# sourceMappingURL=chunk-YM75S6N6.js.map
14545
+ //# sourceMappingURL=chunk-2GAJGUNM.js.map