@noy-db/hub 0.2.0-pre.25 → 0.2.0-pre.27

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 (147) hide show
  1. package/dist/attestation/index.cjs.map +1 -1
  2. package/dist/attestation/index.d.cts +1 -1
  3. package/dist/attestation/index.d.ts +1 -1
  4. package/dist/attestation/index.js +4 -4
  5. package/dist/blobs/index.cjs.map +1 -1
  6. package/dist/blobs/index.d.cts +3 -3
  7. package/dist/blobs/index.d.ts +3 -3
  8. package/dist/blobs/index.js +4 -4
  9. package/dist/bundle/index.cjs +320 -144
  10. package/dist/bundle/index.cjs.map +1 -1
  11. package/dist/bundle/index.d.cts +3 -3
  12. package/dist/bundle/index.d.ts +3 -3
  13. package/dist/bundle/index.js +8 -8
  14. package/dist/{chunk-HUXDQIVU.js → chunk-2NYVA6FW.js} +2 -2
  15. package/dist/{chunk-OCRDV3NU.js → chunk-5EITJMUJ.js} +3 -3
  16. package/dist/{chunk-EYZJULEN.js → chunk-6H4CAHMQ.js} +2 -2
  17. package/dist/{chunk-VGAN5RLD.js → chunk-6M5JKTUQ.js} +2 -2
  18. package/dist/{chunk-N4EXCKWP.js → chunk-6ZKXFMUG.js} +2 -2
  19. package/dist/{chunk-KJ37E3R5.js → chunk-7DDTFGXY.js} +2 -2
  20. package/dist/{chunk-LR7CODVN.js → chunk-AD6RNBAW.js} +1 -1
  21. package/dist/chunk-AD6RNBAW.js.map +1 -0
  22. package/dist/{chunk-TSUICI5N.js → chunk-BMDVFBCL.js} +2 -2
  23. package/dist/{chunk-FCIZXX56.js → chunk-BOMH3637.js} +2 -2
  24. package/dist/{chunk-RZOGD7IF.js → chunk-CVTPNW2Y.js} +6 -6
  25. package/dist/{chunk-GPZHHTJU.js → chunk-DONPLWRC.js} +2 -2
  26. package/dist/{chunk-GHXOVGTX.js → chunk-HAKEZTA7.js} +3 -3
  27. package/dist/{chunk-QYQRAOEF.js → chunk-I2RX62RX.js} +2 -2
  28. package/dist/{chunk-2RHBFCWQ.js → chunk-IWGVH2RR.js} +3 -3
  29. package/dist/{chunk-Y5CTT6K5.js → chunk-K6PCTYAH.js} +2 -2
  30. package/dist/{chunk-ANLOD6IS.js → chunk-KA5A5CSD.js} +3 -3
  31. package/dist/{chunk-56ENKU46.js → chunk-KSKKLVPA.js} +97 -144
  32. package/dist/chunk-KSKKLVPA.js.map +1 -0
  33. package/dist/{chunk-UNBX2HMA.js → chunk-LXA2E3VI.js} +2 -2
  34. package/dist/{chunk-JJKXJAH2.js → chunk-PFKAT4NT.js} +3 -3
  35. package/dist/{chunk-ZCBJIDT4.js → chunk-RRCRITDM.js} +2 -2
  36. package/dist/{chunk-YP2AYE5W.js → chunk-SID2NJNF.js} +2 -2
  37. package/dist/chunk-Z3BJF7SF.js +220 -0
  38. package/dist/chunk-Z3BJF7SF.js.map +1 -0
  39. package/dist/consent/index.d.cts +2 -2
  40. package/dist/consent/index.d.ts +2 -2
  41. package/dist/{decrypt-partition-CyyJUWLR.d.ts → decrypt-partition-CptDdcCx.d.ts} +1 -1
  42. package/dist/{decrypt-partition-C71vhnND.d.cts → decrypt-partition-DmkeOB4I.d.cts} +1 -1
  43. package/dist/derivations/index.d.cts +3 -3
  44. package/dist/derivations/index.d.ts +3 -3
  45. package/dist/{dev-unlock-BdrE0kbS.d.cts → dev-unlock-DUTLA3Sc.d.cts} +1 -1
  46. package/dist/{dev-unlock-ByBkl99-.d.ts → dev-unlock-Y9znMkQ2.d.ts} +1 -1
  47. package/dist/{fanout-sidecar-ZQT4Y7PF.js → fanout-sidecar-OC4QVTS2.js} +2 -2
  48. package/dist/forget/index.js +2 -2
  49. package/dist/guards/index.d.cts +3 -3
  50. package/dist/guards/index.d.ts +3 -3
  51. package/dist/{hash-CZxVv8RH.d.ts → hash-Btl9IvQS.d.ts} +1 -1
  52. package/dist/{hash-BUkDp_8Q.d.cts → hash-DFK7cGdo.d.cts} +1 -1
  53. package/dist/history/index.cjs.map +1 -1
  54. package/dist/history/index.d.cts +3 -3
  55. package/dist/history/index.d.ts +3 -3
  56. package/dist/history/index.js +3 -3
  57. package/dist/i18n/index.cjs.map +1 -1
  58. package/dist/i18n/index.d.cts +2 -2
  59. package/dist/i18n/index.d.ts +2 -2
  60. package/dist/i18n/index.js +3 -3
  61. package/dist/{index-CBUhOmrM.d.cts → index-CqzZml-D.d.cts} +1 -1
  62. package/dist/{index-DFhKV-6A.d.ts → index-wRwJVVJQ.d.ts} +1 -1
  63. package/dist/index.cjs +316 -140
  64. package/dist/index.cjs.map +1 -1
  65. package/dist/index.d.cts +11 -11
  66. package/dist/index.d.ts +11 -11
  67. package/dist/index.js +19 -18
  68. package/dist/index.js.map +1 -1
  69. package/dist/{issue-LEBPVF3Y.js → issue-ZZ2XPOGP.js} +4 -4
  70. package/dist/kernel/index.cjs +61 -0
  71. package/dist/kernel/index.cjs.map +1 -1
  72. package/dist/kernel/index.d.cts +2 -2
  73. package/dist/kernel/index.d.ts +2 -2
  74. package/dist/kernel/index.js +7 -0
  75. package/dist/{ledger-FLRTSOYH.js → ledger-XQ4KVFQ6.js} +3 -3
  76. package/dist/materialized-views/index.d.cts +3 -3
  77. package/dist/materialized-views/index.d.ts +3 -3
  78. package/dist/{mime-magic-BAhLjkHw.d.cts → mime-magic-Co4Pyj-O.d.cts} +1 -1
  79. package/dist/{mime-magic-C1UbcBxP.d.ts → mime-magic-OiPT1qed.d.ts} +1 -1
  80. package/dist/{noydb-6FA46A4M.js → noydb-EY52NVH4.js} +15 -14
  81. package/dist/overlay-views/index.d.cts +3 -3
  82. package/dist/overlay-views/index.d.ts +3 -3
  83. package/dist/periods/index.cjs.map +1 -1
  84. package/dist/periods/index.d.cts +2 -2
  85. package/dist/periods/index.d.ts +2 -2
  86. package/dist/periods/index.js +3 -3
  87. package/dist/{public-envelope-DBKJEBBF.js → public-envelope-O6X6AUUS.js} +3 -3
  88. package/dist/{revoke-P5D3UTRX.js → revoke-QJ2HUM4W.js} +4 -4
  89. package/dist/session/index.d.cts +3 -3
  90. package/dist/session/index.d.ts +3 -3
  91. package/dist/shadow/index.d.cts +2 -2
  92. package/dist/shadow/index.d.ts +2 -2
  93. package/dist/{signer-NEQPCHMW.js → signer-SCJ6C6HQ.js} +3 -3
  94. package/dist/snapshots/index.d.cts +2 -2
  95. package/dist/snapshots/index.d.ts +2 -2
  96. package/dist/snapshots/index.js +3 -3
  97. package/dist/store/index.d.cts +2 -2
  98. package/dist/store/index.d.ts +2 -2
  99. package/dist/sync/index.cjs.map +1 -1
  100. package/dist/sync/index.d.cts +1 -1
  101. package/dist/sync/index.d.ts +1 -1
  102. package/dist/sync/index.js +2 -2
  103. package/dist/team/index.cjs.map +1 -1
  104. package/dist/team/index.d.cts +2 -2
  105. package/dist/team/index.d.ts +2 -2
  106. package/dist/team/index.js +5 -5
  107. package/dist/{transition-guard-BSLdikC_.d.ts → transition-guard-CJmb8O8q.d.ts} +1 -1
  108. package/dist/{transition-guard-DPs6al8h.d.cts → transition-guard-Dzj68JWC.d.cts} +1 -1
  109. package/dist/tx/index.d.cts +2 -2
  110. package/dist/tx/index.d.ts +2 -2
  111. package/dist/{types-CCq0WHh9.d.ts → types-CkSWJt0H.d.ts} +137 -7
  112. package/dist/{types-BCYvhKzr.d.cts → types-CwrTuYFI.d.cts} +137 -7
  113. package/dist/{with-materialized-view-DiD41wQp.d.ts → with-materialized-view-BVfcPlaE.d.ts} +1 -1
  114. package/dist/{with-materialized-view-CTHe6uh9.d.cts → with-materialized-view-dPG213gd.d.cts} +1 -1
  115. package/dist/{with-overlayed-view-Dlz5hcM8.d.cts → with-overlayed-view-CJ2UDBol.d.cts} +1 -1
  116. package/dist/{with-overlayed-view-DlbsJMhF.d.ts → with-overlayed-view-zYPQzGGh.d.ts} +1 -1
  117. package/dist/{with-rollup-BBWdrCvu.d.cts → with-rollup-B_zbRi3f.d.cts} +1 -1
  118. package/dist/{with-rollup-mT4_CWaU.d.ts → with-rollup-BvaJefEs.d.ts} +1 -1
  119. package/package.json +3 -3
  120. package/dist/chunk-56ENKU46.js.map +0 -1
  121. package/dist/chunk-LR7CODVN.js.map +0 -1
  122. /package/dist/{chunk-HUXDQIVU.js.map → chunk-2NYVA6FW.js.map} +0 -0
  123. /package/dist/{chunk-OCRDV3NU.js.map → chunk-5EITJMUJ.js.map} +0 -0
  124. /package/dist/{chunk-EYZJULEN.js.map → chunk-6H4CAHMQ.js.map} +0 -0
  125. /package/dist/{chunk-VGAN5RLD.js.map → chunk-6M5JKTUQ.js.map} +0 -0
  126. /package/dist/{chunk-N4EXCKWP.js.map → chunk-6ZKXFMUG.js.map} +0 -0
  127. /package/dist/{chunk-KJ37E3R5.js.map → chunk-7DDTFGXY.js.map} +0 -0
  128. /package/dist/{chunk-TSUICI5N.js.map → chunk-BMDVFBCL.js.map} +0 -0
  129. /package/dist/{chunk-FCIZXX56.js.map → chunk-BOMH3637.js.map} +0 -0
  130. /package/dist/{chunk-RZOGD7IF.js.map → chunk-CVTPNW2Y.js.map} +0 -0
  131. /package/dist/{chunk-GPZHHTJU.js.map → chunk-DONPLWRC.js.map} +0 -0
  132. /package/dist/{chunk-GHXOVGTX.js.map → chunk-HAKEZTA7.js.map} +0 -0
  133. /package/dist/{chunk-QYQRAOEF.js.map → chunk-I2RX62RX.js.map} +0 -0
  134. /package/dist/{chunk-2RHBFCWQ.js.map → chunk-IWGVH2RR.js.map} +0 -0
  135. /package/dist/{chunk-Y5CTT6K5.js.map → chunk-K6PCTYAH.js.map} +0 -0
  136. /package/dist/{chunk-ANLOD6IS.js.map → chunk-KA5A5CSD.js.map} +0 -0
  137. /package/dist/{chunk-UNBX2HMA.js.map → chunk-LXA2E3VI.js.map} +0 -0
  138. /package/dist/{chunk-JJKXJAH2.js.map → chunk-PFKAT4NT.js.map} +0 -0
  139. /package/dist/{chunk-ZCBJIDT4.js.map → chunk-RRCRITDM.js.map} +0 -0
  140. /package/dist/{chunk-YP2AYE5W.js.map → chunk-SID2NJNF.js.map} +0 -0
  141. /package/dist/{fanout-sidecar-ZQT4Y7PF.js.map → fanout-sidecar-OC4QVTS2.js.map} +0 -0
  142. /package/dist/{issue-LEBPVF3Y.js.map → issue-ZZ2XPOGP.js.map} +0 -0
  143. /package/dist/{ledger-FLRTSOYH.js.map → ledger-XQ4KVFQ6.js.map} +0 -0
  144. /package/dist/{noydb-6FA46A4M.js.map → noydb-EY52NVH4.js.map} +0 -0
  145. /package/dist/{public-envelope-DBKJEBBF.js.map → public-envelope-O6X6AUUS.js.map} +0 -0
  146. /package/dist/{revoke-P5D3UTRX.js.map → revoke-QJ2HUM4W.js.map} +0 -0
  147. /package/dist/{signer-NEQPCHMW.js.map → signer-SCJ6C6HQ.js.map} +0 -0
@@ -1,6 +1,6 @@
1
- import { B as BlobStrategy } from '../types-BCYvhKzr.cjs';
2
- export { o as BLOB_CHUNKS_COLLECTION, p as BLOB_COLLECTION, q as BLOB_EVICTION_AUDIT_COLLECTION, r as BLOB_INDEX_COLLECTION, t as BLOB_SLOTS_PREFIX, u as BLOB_VERSIONS_PREFIX, w as BlobEvictionEntry, x as BlobFieldPolicy, y as BlobFieldsConfig, z as BlobObject, A as BlobPutOptions, C as BlobResponseOptions, E as BlobSet, F as BlobStrategyOpenArgs, G as CompactRunOptions, H as CompactionContext, J as CompactionResult, K as DEFAULT_CHUNK_SIZE, L as EXPORT_AUDIT_COLLECTION, M as ExportBlobsAbortedError, N as ExportBlobsAuditEntry, O as ExportBlobsHandle, Q as ExportBlobsOptions, R as ExportedBlob, T as ObjectListEntry, U as ObjectMeta, V as ObjectProjection, W as ObjectUrlOptions, X as PutObjectOptions, Y as PutUrlOptions, Z as SlotInfo, _ as SlotRecord, $ as VersionRecord, a0 as createExportBlobsHandle, a1 as memoryObjectProjection, a2 as runCompaction } from '../types-BCYvhKzr.cjs';
3
- export { I as ImportExternalOptions, a as ImportExternalResult, b as ImportableCollection, d as detectMagic, c as detectMimeType, i as importExternalObjects, e as isPreCompressed } from '../mime-magic-BAhLjkHw.cjs';
1
+ import { B as BlobStrategy } from '../types-CwrTuYFI.cjs';
2
+ export { o as BLOB_CHUNKS_COLLECTION, p as BLOB_COLLECTION, q as BLOB_EVICTION_AUDIT_COLLECTION, r as BLOB_INDEX_COLLECTION, t as BLOB_SLOTS_PREFIX, u as BLOB_VERSIONS_PREFIX, w as BlobEvictionEntry, x as BlobFieldPolicy, y as BlobFieldsConfig, z as BlobObject, A as BlobPutOptions, C as BlobResponseOptions, E as BlobSet, F as BlobStrategyOpenArgs, G as CompactRunOptions, H as CompactionContext, J as CompactionResult, K as DEFAULT_CHUNK_SIZE, L as EXPORT_AUDIT_COLLECTION, M as ExportBlobsAbortedError, N as ExportBlobsAuditEntry, O as ExportBlobsHandle, Q as ExportBlobsOptions, R as ExportedBlob, T as ObjectListEntry, U as ObjectMeta, V as ObjectProjection, W as ObjectUrlOptions, X as PutObjectOptions, Y as PutUrlOptions, Z as SlotInfo, _ as SlotRecord, $ as VersionRecord, a0 as createExportBlobsHandle, a1 as memoryObjectProjection, a2 as runCompaction } from '../types-CwrTuYFI.cjs';
3
+ export { I as ImportExternalOptions, a as ImportExternalResult, b as ImportableCollection, d as detectMagic, c as detectMimeType, i as importExternalObjects, e as isPreCompressed } from '../mime-magic-Co4Pyj-O.cjs';
4
4
  import '../lazy-builder-eYZzLEL1.cjs';
5
5
  import '../predicate-BmhBSPCH.cjs';
6
6
  import '../strategy-D1zjEV3n.cjs';
@@ -1,6 +1,6 @@
1
- import { B as BlobStrategy } from '../types-CCq0WHh9.js';
2
- export { o as BLOB_CHUNKS_COLLECTION, p as BLOB_COLLECTION, q as BLOB_EVICTION_AUDIT_COLLECTION, r as BLOB_INDEX_COLLECTION, t as BLOB_SLOTS_PREFIX, u as BLOB_VERSIONS_PREFIX, w as BlobEvictionEntry, x as BlobFieldPolicy, y as BlobFieldsConfig, z as BlobObject, A as BlobPutOptions, C as BlobResponseOptions, E as BlobSet, F as BlobStrategyOpenArgs, G as CompactRunOptions, H as CompactionContext, J as CompactionResult, K as DEFAULT_CHUNK_SIZE, L as EXPORT_AUDIT_COLLECTION, M as ExportBlobsAbortedError, N as ExportBlobsAuditEntry, O as ExportBlobsHandle, Q as ExportBlobsOptions, R as ExportedBlob, T as ObjectListEntry, U as ObjectMeta, V as ObjectProjection, W as ObjectUrlOptions, X as PutObjectOptions, Y as PutUrlOptions, Z as SlotInfo, _ as SlotRecord, $ as VersionRecord, a0 as createExportBlobsHandle, a1 as memoryObjectProjection, a2 as runCompaction } from '../types-CCq0WHh9.js';
3
- export { I as ImportExternalOptions, a as ImportExternalResult, b as ImportableCollection, d as detectMagic, c as detectMimeType, i as importExternalObjects, e as isPreCompressed } from '../mime-magic-C1UbcBxP.js';
1
+ import { B as BlobStrategy } from '../types-CkSWJt0H.js';
2
+ export { o as BLOB_CHUNKS_COLLECTION, p as BLOB_COLLECTION, q as BLOB_EVICTION_AUDIT_COLLECTION, r as BLOB_INDEX_COLLECTION, t as BLOB_SLOTS_PREFIX, u as BLOB_VERSIONS_PREFIX, w as BlobEvictionEntry, x as BlobFieldPolicy, y as BlobFieldsConfig, z as BlobObject, A as BlobPutOptions, C as BlobResponseOptions, E as BlobSet, F as BlobStrategyOpenArgs, G as CompactRunOptions, H as CompactionContext, J as CompactionResult, K as DEFAULT_CHUNK_SIZE, L as EXPORT_AUDIT_COLLECTION, M as ExportBlobsAbortedError, N as ExportBlobsAuditEntry, O as ExportBlobsHandle, Q as ExportBlobsOptions, R as ExportedBlob, T as ObjectListEntry, U as ObjectMeta, V as ObjectProjection, W as ObjectUrlOptions, X as PutObjectOptions, Y as PutUrlOptions, Z as SlotInfo, _ as SlotRecord, $ as VersionRecord, a0 as createExportBlobsHandle, a1 as memoryObjectProjection, a2 as runCompaction } from '../types-CkSWJt0H.js';
3
+ export { I as ImportExternalOptions, a as ImportExternalResult, b as ImportableCollection, d as detectMagic, c as detectMimeType, i as importExternalObjects, e as isPreCompressed } from '../mime-magic-OiPT1qed.js';
4
4
  import '../lazy-builder-ChSqcF5t.js';
5
5
  import '../predicate-BmhBSPCH.js';
6
6
  import '../strategy-YQ1qJWyq.js';
@@ -11,16 +11,16 @@ import {
11
11
  importExternalObjects,
12
12
  isPreCompressed,
13
13
  memoryObjectProjection
14
- } from "../chunk-KJ37E3R5.js";
14
+ } from "../chunk-7DDTFGXY.js";
15
15
  import {
16
16
  BLOB_EVICTION_AUDIT_COLLECTION,
17
17
  EXPORT_AUDIT_COLLECTION,
18
18
  ExportBlobsAbortedError,
19
19
  createExportBlobsHandle,
20
20
  runCompaction
21
- } from "../chunk-ZCBJIDT4.js";
22
- import "../chunk-Y5CTT6K5.js";
23
- import "../chunk-LR7CODVN.js";
21
+ } from "../chunk-RRCRITDM.js";
22
+ import "../chunk-K6PCTYAH.js";
23
+ import "../chunk-AD6RNBAW.js";
24
24
  import "../chunk-7JSP3E67.js";
25
25
  import "../chunk-DDOYOMAD.js";
26
26
 
@@ -4353,9 +4353,252 @@ var init_peer_recover = __esm({
4353
4353
  }
4354
4354
  });
4355
4355
 
4356
+ // src/coordination/types.ts
4357
+ function isQuorum(writers, generation, excludeWriterId) {
4358
+ return writers.filter((w) => w.writerId !== excludeWriterId).every((w) => w.quiescedAtVersion === generation);
4359
+ }
4360
+ async function runDrainBarrier(provider, o, run) {
4361
+ await provider.setFence(o.vault, { currentSchemaVersion: o.generation, fenceState: "draining" });
4362
+ await o.onFlush();
4363
+ const deadline = o.now() + o.quiesceTimeoutMs;
4364
+ const seeded = await provider.reachableWriters(o.vault, { staleMs: o.staleMs, now: o.now() });
4365
+ if (!isQuorum(seeded, o.generation, o.writerId)) {
4366
+ await new Promise((resolve, reject) => {
4367
+ let settled = false;
4368
+ const finish = (fn) => {
4369
+ if (!settled) {
4370
+ settled = true;
4371
+ unsub();
4372
+ fn();
4373
+ }
4374
+ };
4375
+ const unsub = provider.observePresence(o.vault, (writers) => {
4376
+ if (isQuorum(writers, o.generation, o.writerId)) finish(resolve);
4377
+ });
4378
+ const tick = async () => {
4379
+ if (settled) return;
4380
+ if (o.now() >= deadline) {
4381
+ finish(
4382
+ () => reject(
4383
+ new QuiesceTimeoutError(
4384
+ `Cutover of vault "${o.vault}" to generation ${o.generation} timed out after ${o.quiesceTimeoutMs}ms waiting for active writers to quiesce.`
4385
+ )
4386
+ )
4387
+ );
4388
+ return;
4389
+ }
4390
+ if (o.onPoll) await o.onPoll();
4391
+ const w = await provider.reachableWriters(o.vault, { staleMs: o.staleMs, now: o.now() });
4392
+ if (isQuorum(w, o.generation, o.writerId)) finish(resolve);
4393
+ else setTimeout(() => void tick(), 25);
4394
+ };
4395
+ void tick();
4396
+ });
4397
+ }
4398
+ await run();
4399
+ }
4400
+ var init_types3 = __esm({
4401
+ "src/coordination/types.ts"() {
4402
+ "use strict";
4403
+ init_errors();
4404
+ }
4405
+ });
4406
+
4407
+ // src/schema-update/fence.ts
4408
+ async function loadFence(store, vault) {
4409
+ const envelope = await store.get(vault, META_COLLECTION2, FENCE_RECORD_ID);
4410
+ if (!envelope) return DEFAULT_FENCE;
4411
+ try {
4412
+ const parsed = JSON.parse(envelope._data);
4413
+ if (!isFenceDoc(parsed)) return DEFAULT_FENCE;
4414
+ return parsed;
4415
+ } catch {
4416
+ return DEFAULT_FENCE;
4417
+ }
4418
+ }
4419
+ async function saveFence(store, vault, fence) {
4420
+ const envelope = {
4421
+ _noydb: NOYDB_FORMAT_VERSION,
4422
+ _v: 1,
4423
+ _ts: (/* @__PURE__ */ new Date()).toISOString(),
4424
+ _iv: "",
4425
+ _data: JSON.stringify(fence)
4426
+ };
4427
+ await store.put(vault, META_COLLECTION2, FENCE_RECORD_ID, envelope);
4428
+ }
4429
+ function isFenceDoc(x) {
4430
+ if (x === null || typeof x !== "object") return false;
4431
+ const o = x;
4432
+ return typeof o["currentSchemaVersion"] === "number" && (o["fenceState"] === "normal" || o["fenceState"] === "draining" || o["fenceState"] === "migrating" || o["fenceState"] === "complete");
4433
+ }
4434
+ var FENCE_RECORD_ID, META_COLLECTION2, DEFAULT_FENCE;
4435
+ var init_fence = __esm({
4436
+ "src/schema-update/fence.ts"() {
4437
+ "use strict";
4438
+ init_types();
4439
+ FENCE_RECORD_ID = "schema-fence";
4440
+ META_COLLECTION2 = "_meta";
4441
+ DEFAULT_FENCE = { currentSchemaVersion: 0, fenceState: "normal" };
4442
+ }
4443
+ });
4444
+
4445
+ // src/schema-update/client-registry.ts
4446
+ async function writeClientDoc(store, vault, clientId, doc) {
4447
+ const envelope = {
4448
+ _noydb: NOYDB_FORMAT_VERSION,
4449
+ _v: 1,
4450
+ _ts: (/* @__PURE__ */ new Date()).toISOString(),
4451
+ _iv: "",
4452
+ _data: JSON.stringify({ clientId, ...doc })
4453
+ };
4454
+ await store.put(vault, META_COLLECTION3, `${CLIENT_PREFIX}${clientId}`, envelope);
4455
+ }
4456
+ async function listClientDocs(store, vault) {
4457
+ const ids = await store.list(vault, META_COLLECTION3);
4458
+ const out = [];
4459
+ for (const id of ids) {
4460
+ if (!id.startsWith(CLIENT_PREFIX)) continue;
4461
+ const env = await store.get(vault, META_COLLECTION3, id);
4462
+ if (!env) continue;
4463
+ try {
4464
+ const parsed = JSON.parse(env._data);
4465
+ if (isClientDoc(parsed)) out.push(parsed);
4466
+ } catch {
4467
+ }
4468
+ }
4469
+ return out;
4470
+ }
4471
+ function isClientDoc(x) {
4472
+ if (x === null || typeof x !== "object") return false;
4473
+ const o = x;
4474
+ return typeof o["clientId"] === "string" && typeof o["lastSeen"] === "number" && (o["quiescedAtVersion"] === null || typeof o["quiescedAtVersion"] === "number") && (o["sessionId"] === void 0 || typeof o["sessionId"] === "string");
4475
+ }
4476
+ var META_COLLECTION3, CLIENT_PREFIX;
4477
+ var init_client_registry = __esm({
4478
+ "src/schema-update/client-registry.ts"() {
4479
+ "use strict";
4480
+ init_types();
4481
+ META_COLLECTION3 = "_meta";
4482
+ CLIENT_PREFIX = "schema-fence:client:";
4483
+ }
4484
+ });
4485
+
4486
+ // src/coordination/store-provider.ts
4487
+ function toPresence(doc) {
4488
+ return {
4489
+ writerId: doc.clientId,
4490
+ // Pre-#469 docs (and explicit empty) have no session — fall back to the
4491
+ // writerId so every presence is session-addressable.
4492
+ sessionId: doc.sessionId && doc.sessionId.length > 0 ? doc.sessionId : doc.clientId,
4493
+ lastSeen: doc.lastSeen,
4494
+ quiescedAtVersion: doc.quiescedAtVersion
4495
+ };
4496
+ }
4497
+ function fenceEqual(a, b) {
4498
+ return a.currentSchemaVersion === b.currentSchemaVersion && a.fenceState === b.fenceState;
4499
+ }
4500
+ function presenceListEqual(a, b) {
4501
+ if (a.length !== b.length) return false;
4502
+ const key = (w) => `${w.writerId}\0${w.sessionId}\0${w.lastSeen}\0${String(w.quiescedAtVersion)}`;
4503
+ const bk = new Set(b.map(key));
4504
+ return a.every((w) => bk.has(key(w)));
4505
+ }
4506
+ function unref(timer) {
4507
+ const t = timer;
4508
+ if (typeof t.unref === "function") t.unref();
4509
+ }
4510
+ var DEFAULT_POLL_INTERVAL_MS, StoreCoordinationProvider;
4511
+ var init_store_provider = __esm({
4512
+ "src/coordination/store-provider.ts"() {
4513
+ "use strict";
4514
+ init_fence();
4515
+ init_client_registry();
4516
+ DEFAULT_POLL_INTERVAL_MS = 50;
4517
+ StoreCoordinationProvider = class {
4518
+ #store;
4519
+ #pollIntervalMs;
4520
+ constructor(store, opts) {
4521
+ this.#store = store;
4522
+ this.#pollIntervalMs = opts?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
4523
+ }
4524
+ async setFence(vault, fence) {
4525
+ await saveFence(this.#store, vault, fence);
4526
+ }
4527
+ async readFence(vault) {
4528
+ return loadFence(this.#store, vault);
4529
+ }
4530
+ observeFence(vault, onChange) {
4531
+ let last = null;
4532
+ let busy = false;
4533
+ const poll = async () => {
4534
+ if (busy) return;
4535
+ busy = true;
4536
+ try {
4537
+ const fence = await loadFence(this.#store, vault);
4538
+ if (last === null || !fenceEqual(last, fence)) {
4539
+ last = fence;
4540
+ onChange(fence);
4541
+ }
4542
+ } catch {
4543
+ } finally {
4544
+ busy = false;
4545
+ }
4546
+ };
4547
+ void poll();
4548
+ const timer = setInterval(() => void poll(), this.#pollIntervalMs);
4549
+ unref(timer);
4550
+ return () => clearInterval(timer);
4551
+ }
4552
+ async reportPresence(vault, p) {
4553
+ await writeClientDoc(this.#store, vault, p.writerId, {
4554
+ lastSeen: p.lastSeen,
4555
+ quiescedAtVersion: p.quiescedAtVersion,
4556
+ sessionId: p.sessionId
4557
+ });
4558
+ }
4559
+ observePresence(vault, onChange) {
4560
+ let last = null;
4561
+ let busy = false;
4562
+ const poll = async () => {
4563
+ if (busy) return;
4564
+ busy = true;
4565
+ try {
4566
+ const docs = await listClientDocs(this.#store, vault);
4567
+ const writers = docs.map(toPresence);
4568
+ if (last === null || !presenceListEqual(last, writers)) {
4569
+ last = writers;
4570
+ onChange(writers);
4571
+ }
4572
+ } catch {
4573
+ } finally {
4574
+ busy = false;
4575
+ }
4576
+ };
4577
+ void poll();
4578
+ const timer = setInterval(() => void poll(), this.#pollIntervalMs);
4579
+ unref(timer);
4580
+ return () => clearInterval(timer);
4581
+ }
4582
+ async reachableWriters(vault, o) {
4583
+ const docs = await listClientDocs(this.#store, vault);
4584
+ return docs.map(toPresence).filter((w) => o.now - w.lastSeen <= o.staleMs);
4585
+ }
4586
+ };
4587
+ }
4588
+ });
4589
+
4590
+ // src/coordination/index.ts
4591
+ var init_coordination = __esm({
4592
+ "src/coordination/index.ts"() {
4593
+ "use strict";
4594
+ init_types3();
4595
+ init_store_provider();
4596
+ }
4597
+ });
4598
+
4356
4599
  // src/policy/storage.ts
4357
4600
  async function loadVaultPolicy(store, vault) {
4358
- const envelope = await store.get(vault, META_COLLECTION2, POLICY_RECORD_ID);
4601
+ const envelope = await store.get(vault, META_COLLECTION4, POLICY_RECORD_ID);
4359
4602
  if (!envelope) return void 0;
4360
4603
  try {
4361
4604
  const parsed = JSON.parse(envelope._data);
@@ -4373,7 +4616,7 @@ async function saveVaultPolicy(store, vault, policy) {
4373
4616
  _iv: "",
4374
4617
  _data: JSON.stringify(policy)
4375
4618
  };
4376
- await store.put(vault, META_COLLECTION2, POLICY_RECORD_ID, envelope);
4619
+ await store.put(vault, META_COLLECTION4, POLICY_RECORD_ID, envelope);
4377
4620
  }
4378
4621
  function isVaultPolicy(x) {
4379
4622
  if (x === null || typeof x !== "object") return false;
@@ -4381,12 +4624,12 @@ function isVaultPolicy(x) {
4381
4624
  const gates = x.gates;
4382
4625
  return gates !== null && typeof gates === "object";
4383
4626
  }
4384
- var META_COLLECTION2, POLICY_RECORD_ID;
4627
+ var META_COLLECTION4, POLICY_RECORD_ID;
4385
4628
  var init_storage5 = __esm({
4386
4629
  "src/policy/storage.ts"() {
4387
4630
  "use strict";
4388
4631
  init_types();
4389
- META_COLLECTION2 = "_meta";
4632
+ META_COLLECTION4 = "_meta";
4390
4633
  POLICY_RECORD_ID = "policy";
4391
4634
  }
4392
4635
  });
@@ -4541,7 +4784,7 @@ function resolveSchema(schema) {
4541
4784
  };
4542
4785
  }
4543
4786
  var PUBLIC_ENVELOPE_FIELDS, DEFAULT_PUBLIC_ENVELOPE_SCHEMA;
4544
- var init_types3 = __esm({
4787
+ var init_types4 = __esm({
4545
4788
  "src/meta/public-envelope/types.ts"() {
4546
4789
  "use strict";
4547
4790
  PUBLIC_ENVELOPE_FIELDS = [
@@ -4579,7 +4822,7 @@ __export(public_envelope_exports, {
4579
4822
  var init_public_envelope = __esm({
4580
4823
  "src/meta/public-envelope/index.ts"() {
4581
4824
  "use strict";
4582
- init_types3();
4825
+ init_types4();
4583
4826
  init_schema();
4584
4827
  init_storage();
4585
4828
  }
@@ -15134,108 +15377,18 @@ var init_gate = __esm({
15134
15377
  }
15135
15378
  });
15136
15379
 
15137
- // src/schema-update/fence.ts
15138
- async function loadFence(store, vault) {
15139
- const envelope = await store.get(vault, META_COLLECTION3, FENCE_RECORD_ID);
15140
- if (!envelope) return DEFAULT_FENCE;
15141
- try {
15142
- const parsed = JSON.parse(envelope._data);
15143
- if (!isFenceDoc(parsed)) return DEFAULT_FENCE;
15144
- return parsed;
15145
- } catch {
15146
- return DEFAULT_FENCE;
15147
- }
15148
- }
15149
- async function saveFence(store, vault, fence) {
15150
- const envelope = {
15151
- _noydb: NOYDB_FORMAT_VERSION,
15152
- _v: 1,
15153
- _ts: (/* @__PURE__ */ new Date()).toISOString(),
15154
- _iv: "",
15155
- _data: JSON.stringify(fence)
15156
- };
15157
- await store.put(vault, META_COLLECTION3, FENCE_RECORD_ID, envelope);
15158
- }
15159
- function isFenceDoc(x) {
15160
- if (x === null || typeof x !== "object") return false;
15161
- const o = x;
15162
- return typeof o["currentSchemaVersion"] === "number" && (o["fenceState"] === "normal" || o["fenceState"] === "draining" || o["fenceState"] === "migrating" || o["fenceState"] === "complete");
15163
- }
15164
- var FENCE_RECORD_ID, META_COLLECTION3, DEFAULT_FENCE;
15165
- var init_fence = __esm({
15166
- "src/schema-update/fence.ts"() {
15167
- "use strict";
15168
- init_types();
15169
- FENCE_RECORD_ID = "schema-fence";
15170
- META_COLLECTION3 = "_meta";
15171
- DEFAULT_FENCE = { currentSchemaVersion: 0, fenceState: "normal" };
15172
- }
15173
- });
15174
-
15175
- // src/schema-update/client-registry.ts
15176
- async function writeClientDoc(store, vault, clientId, doc) {
15177
- const envelope = {
15178
- _noydb: NOYDB_FORMAT_VERSION,
15179
- _v: 1,
15180
- _ts: (/* @__PURE__ */ new Date()).toISOString(),
15181
- _iv: "",
15182
- _data: JSON.stringify({ clientId, ...doc })
15183
- };
15184
- await store.put(vault, META_COLLECTION4, `${CLIENT_PREFIX}${clientId}`, envelope);
15185
- }
15186
- async function listClientDocs(store, vault) {
15187
- const ids = await store.list(vault, META_COLLECTION4);
15188
- const out = [];
15189
- for (const id of ids) {
15190
- if (!id.startsWith(CLIENT_PREFIX)) continue;
15191
- const env = await store.get(vault, META_COLLECTION4, id);
15192
- if (!env) continue;
15193
- try {
15194
- const parsed = JSON.parse(env._data);
15195
- if (isClientDoc(parsed)) out.push(parsed);
15196
- } catch {
15197
- }
15198
- }
15199
- return out;
15200
- }
15201
- async function activeQuiesced(store, vault, opts) {
15202
- const docs = await listClientDocs(store, vault);
15203
- const active = docs.filter(
15204
- (d) => d.lastSeen >= opts.now - opts.staleMs && d.clientId !== opts.excludeClientId
15205
- );
15206
- return active.every((d) => d.quiescedAtVersion === opts.generation);
15207
- }
15208
- function isClientDoc(x) {
15209
- if (x === null || typeof x !== "object") return false;
15210
- const o = x;
15211
- return typeof o["clientId"] === "string" && typeof o["lastSeen"] === "number" && (o["quiescedAtVersion"] === null || typeof o["quiescedAtVersion"] === "number");
15212
- }
15213
- var META_COLLECTION4, CLIENT_PREFIX;
15214
- var init_client_registry = __esm({
15215
- "src/schema-update/client-registry.ts"() {
15216
- "use strict";
15217
- init_types();
15218
- META_COLLECTION4 = "_meta";
15219
- CLIENT_PREFIX = "schema-fence:client:";
15220
- }
15221
- });
15222
-
15223
15380
  // src/schema-update/fence-controller.ts
15224
- function delay(ms) {
15225
- return new Promise((resolve) => setTimeout(resolve, ms));
15226
- }
15227
15381
  var SchemaFenceController;
15228
15382
  var init_fence_controller = __esm({
15229
15383
  "src/schema-update/fence-controller.ts"() {
15230
15384
  "use strict";
15231
- init_fence();
15232
15385
  init_errors();
15233
- init_client_registry();
15386
+ init_coordination();
15234
15387
  SchemaFenceController = class {
15235
- #store;
15388
+ #coordination;
15236
15389
  #vault;
15237
15390
  #onFlush;
15238
- #clientId;
15391
+ #writerId;
15239
15392
  #now;
15240
15393
  #staleMs;
15241
15394
  #quiesceTimeoutMs;
@@ -15243,10 +15396,10 @@ var init_fence_controller = __esm({
15243
15396
  #snapshot = 0;
15244
15397
  #pending = /* @__PURE__ */ new Map();
15245
15398
  constructor(opts) {
15246
- this.#store = opts.store;
15399
+ this.#coordination = opts.coordination;
15247
15400
  this.#vault = opts.vault;
15248
15401
  this.#onFlush = opts.onFlush;
15249
- this.#clientId = opts.clientId ?? "migrator";
15402
+ this.#writerId = opts.clientId ?? "migrator";
15250
15403
  this.#now = opts.now ?? (() => Date.now());
15251
15404
  this.#staleMs = opts.staleMs ?? 3e4;
15252
15405
  this.#quiesceTimeoutMs = opts.quiesceTimeoutMs ?? 6e4;
@@ -15255,7 +15408,7 @@ var init_fence_controller = __esm({
15255
15408
  }
15256
15409
  /** Capture the generation snapshot at vault-open. */
15257
15410
  async init() {
15258
- this.#snapshot = (await loadFence(this.#store, this.#vault)).currentSchemaVersion;
15411
+ this.#snapshot = (await this.#coordination.readFence(this.#vault)).currentSchemaVersion;
15259
15412
  }
15260
15413
  /** Record a per-collection pending cutover (from a registration `cutover` decision). */
15261
15414
  registerPendingCutover(collection, transform) {
@@ -15263,7 +15416,7 @@ var init_fence_controller = __esm({
15263
15416
  }
15264
15417
  /** Write-path gate. Throws when behind, fenced, or this collection is cutover-pending. */
15265
15418
  async assertWritable(collection) {
15266
- const fence = await loadFence(this.#store, this.#vault);
15419
+ const fence = await this.#coordination.readFence(this.#vault);
15267
15420
  if (fence.currentSchemaVersion > this.#snapshot) {
15268
15421
  throw new MigrationRequiredError(
15269
15422
  `Vault "${this.#vault}" advanced to schema generation ${fence.currentSchemaVersion} (this client opened at ${this.#snapshot}). Reload to continue.`
@@ -15282,49 +15435,49 @@ var init_fence_controller = __esm({
15282
15435
  * Admin trigger. Drain → wait for the active set to quiesce (or time out)
15283
15436
  * → migrate each pending transform → bump → complete → normal. The
15284
15437
  * migrator excludes itself from the barrier (it drained synchronously
15285
- * here). `onPoll` (tests) advances other clients between barrier checks;
15286
- * production falls back to a short real delay.
15438
+ * inside {@link runDrainBarrier}). `onPoll` (tests) advances other clients
15439
+ * between barrier checks; production falls back to a short real delay.
15287
15440
  */
15288
15441
  async runCutover(run, opts) {
15289
15442
  if (this.#pending.size === 0) return { migrated: 0 };
15290
- const base = await loadFence(this.#store, this.#vault);
15443
+ const base = await this.#coordination.readFence(this.#vault);
15291
15444
  const generation = base.currentSchemaVersion;
15292
- await this.#setState(generation, "draining");
15293
- await this.#onFlush();
15294
- const deadline = this.#now() + this.#quiesceTimeoutMs;
15295
- while (!await activeQuiesced(this.#store, this.#vault, {
15296
- generation,
15297
- now: this.#now(),
15298
- staleMs: this.#staleMs,
15299
- excludeClientId: this.#clientId
15300
- })) {
15301
- if (this.#now() >= deadline) {
15302
- throw new QuiesceTimeoutError(
15303
- `Cutover on "${this.#vault}" timed out waiting for clients to quiesce at generation ${generation}.`
15304
- );
15305
- }
15306
- await (opts?.onPoll ? opts.onPoll() : delay(50));
15307
- }
15308
- await this.#setState(generation, "migrating");
15445
+ this.#emit({ currentSchemaVersion: generation, fenceState: "draining" });
15309
15446
  let migrated = 0;
15310
- for (const [collection, transform] of this.#pending) {
15311
- await run(collection, transform);
15312
- migrated++;
15313
- }
15314
- const nextVersion = generation + 1;
15315
- await this.#setState(nextVersion, "complete");
15316
- this.#pending.clear();
15317
- await this.#setState(nextVersion, "normal");
15318
- this.#snapshot = nextVersion;
15447
+ await runDrainBarrier(
15448
+ this.#coordination,
15449
+ {
15450
+ vault: this.#vault,
15451
+ generation,
15452
+ writerId: this.#writerId,
15453
+ onFlush: this.#onFlush,
15454
+ staleMs: this.#staleMs,
15455
+ quiesceTimeoutMs: this.#quiesceTimeoutMs,
15456
+ now: this.#now,
15457
+ ...opts?.onPoll ? { onPoll: opts.onPoll } : {}
15458
+ },
15459
+ async () => {
15460
+ await this.#setState(generation, "migrating");
15461
+ for (const [collection, transform] of this.#pending) {
15462
+ await run(collection, transform);
15463
+ migrated++;
15464
+ }
15465
+ const nextVersion = generation + 1;
15466
+ await this.#setState(nextVersion, "complete");
15467
+ this.#pending.clear();
15468
+ await this.#setState(nextVersion, "normal");
15469
+ this.#snapshot = nextVersion;
15470
+ }
15471
+ );
15319
15472
  return { migrated };
15320
15473
  }
15321
15474
  /** Recover a stuck drain: reset fenceState to normal at the current version (no bump). */
15322
15475
  async abort() {
15323
- const fence = await loadFence(this.#store, this.#vault);
15476
+ const fence = await this.#coordination.readFence(this.#vault);
15324
15477
  await this.#setState(fence.currentSchemaVersion, "normal");
15325
15478
  }
15326
15479
  async #setState(currentSchemaVersion, fenceState) {
15327
- await saveFence(this.#store, this.#vault, { currentSchemaVersion, fenceState });
15480
+ await this.#coordination.setFence(this.#vault, { currentSchemaVersion, fenceState });
15328
15481
  this.#emit({ currentSchemaVersion, fenceState });
15329
15482
  }
15330
15483
  };
@@ -15336,12 +15489,11 @@ var FenceWatcher;
15336
15489
  var init_fence_watcher = __esm({
15337
15490
  "src/schema-update/fence-watcher.ts"() {
15338
15491
  "use strict";
15339
- init_fence();
15340
- init_client_registry();
15341
15492
  FenceWatcher = class {
15342
- #store;
15493
+ #coordination;
15343
15494
  #vault;
15344
- #clientId;
15495
+ #writerId;
15496
+ #sessionId;
15345
15497
  #onFlush;
15346
15498
  #now;
15347
15499
  #emit;
@@ -15349,9 +15501,10 @@ var init_fence_watcher = __esm({
15349
15501
  #quiescedAtVersion = null;
15350
15502
  #timer;
15351
15503
  constructor(opts) {
15352
- this.#store = opts.store;
15504
+ this.#coordination = opts.coordination;
15353
15505
  this.#vault = opts.vault;
15354
- this.#clientId = opts.clientId;
15506
+ this.#writerId = opts.clientId;
15507
+ this.#sessionId = opts.sessionId ?? opts.clientId;
15355
15508
  this.#onFlush = opts.onFlush;
15356
15509
  this.#now = opts.now ?? (() => Date.now());
15357
15510
  this.#emit = opts.emit ?? (() => {
@@ -15359,14 +15512,16 @@ var init_fence_watcher = __esm({
15359
15512
  }
15360
15513
  /** Publish liveness (and the current ack) without changing quiesce state. */
15361
15514
  async beat() {
15362
- await writeClientDoc(this.#store, this.#vault, this.#clientId, {
15515
+ await this.#coordination.reportPresence(this.#vault, {
15516
+ writerId: this.#writerId,
15517
+ sessionId: this.#sessionId,
15363
15518
  lastSeen: this.#now(),
15364
15519
  quiescedAtVersion: this.#quiescedAtVersion
15365
15520
  });
15366
15521
  }
15367
15522
  /** Poll the fence; quiesce on draining; emit on transitions. */
15368
15523
  async check() {
15369
- const fence = await loadFence(this.#store, this.#vault);
15524
+ const fence = await this.#coordination.readFence(this.#vault);
15370
15525
  if (fence.fenceState !== this.#lastState) {
15371
15526
  this.#lastState = fence.fenceState;
15372
15527
  this.#emit({ currentSchemaVersion: fence.currentSchemaVersion, fenceState: fence.fenceState });
@@ -16678,10 +16833,11 @@ var init_vault = __esm({
16678
16833
  this.keyring = opts.keyring;
16679
16834
  this.encrypted = opts.encrypted;
16680
16835
  this.schemaFence = new SchemaFenceController({
16681
- store: this.adapter,
16836
+ coordination: this.noydb.coordination,
16682
16837
  vault: this.name,
16683
16838
  onFlush: () => this.noydb._writeQueueTracker.onFlush(),
16684
16839
  clientId: this.noydb._clientId,
16840
+ sessionId: this.noydb._sessionId,
16685
16841
  emit: (e) => this.emitter.emit("schema:fence-changed", { vault: this.name, ...e })
16686
16842
  });
16687
16843
  this.emitter = opts.emitter;
@@ -17077,9 +17233,10 @@ var init_vault = __esm({
17077
17233
  if (this.#fenceCoordinationStarted) return;
17078
17234
  this.#fenceCoordinationStarted = true;
17079
17235
  this.#fenceWatcher = new FenceWatcher({
17080
- store: this.adapter,
17236
+ coordination: this.noydb.coordination,
17081
17237
  vault: this.name,
17082
17238
  clientId: this.noydb._clientId,
17239
+ sessionId: this.noydb._sessionId,
17083
17240
  onFlush: () => this.noydb._writeQueueTracker.onFlush(),
17084
17241
  emit: (e) => this.emitter.emit("schema:fence-changed", { vault: this.name, ...e })
17085
17242
  });
@@ -21043,6 +21200,7 @@ var init_noydb = __esm({
21043
21200
  init_recovery();
21044
21201
  init_managed_passphrase();
21045
21202
  init_ulid();
21203
+ init_coordination();
21046
21204
  init_errors2();
21047
21205
  init_auth_introspection();
21048
21206
  init_public_envelope();
@@ -21086,6 +21244,10 @@ var init_noydb = __esm({
21086
21244
  writeHooks = new WriteHookRegistry();
21087
21245
  subsystemBus = new SubsystemBus();
21088
21246
  clientId = generateULID();
21247
+ /** Session that owns this instance's writers (one user's writers across vaults). */
21248
+ sessionId;
21249
+ /** Drain-barrier coordination transport for the schema fence (#469). */
21250
+ coordinationProvider;
21089
21251
  vaultCache = /* @__PURE__ */ new Map();
21090
21252
  keyringCache = /* @__PURE__ */ new Map();
21091
21253
  syncEngines = /* @__PURE__ */ new Map();
@@ -21160,6 +21322,8 @@ var init_noydb = __esm({
21160
21322
  "[noydb] debugPlaintext is ON \u2014 records are stored UNENCRYPTED and laid out for native store inspection. NEVER use this for production or client data."
21161
21323
  );
21162
21324
  }
21325
+ this.sessionId = options.sessionId ?? generateULID();
21326
+ this.coordinationProvider = options.coordinationStrategy ?? new StoreCoordinationProvider(options.store);
21163
21327
  this.txStrategy = options.txStrategy ?? NO_TX;
21164
21328
  this.forgetStrategy = options.forgetStrategy ?? NO_FORGET;
21165
21329
  this.sessionStrategy = options.sessionStrategy ?? NO_SESSION;
@@ -22213,6 +22377,18 @@ var init_noydb = __esm({
22213
22377
  get _clientId() {
22214
22378
  return this.clientId;
22215
22379
  }
22380
+ /** @internal Session that owns this instance's writers (#469). */
22381
+ get _sessionId() {
22382
+ return this.sessionId;
22383
+ }
22384
+ /**
22385
+ * @internal Drain-barrier coordination transport for the schema fence (#469).
22386
+ * The default store-backed provider reproduces today's fence behavior; a
22387
+ * `by-*` real-time transport is injected via `coordinationStrategy`.
22388
+ */
22389
+ get coordination() {
22390
+ return this.coordinationProvider;
22391
+ }
22216
22392
  /**
22217
22393
  * Soft-lock a single vault: clear its in-memory keyring, DEKs, vault
22218
22394
  * instance, sync engine, policy enforcer, and active-tier entry —