@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,3 +1,8 @@
1
+ import {
2
+ StoreCoordinationProvider,
3
+ loadFence,
4
+ runDrainBarrier
5
+ } from "./chunk-Z3BJF7SF.js";
1
6
  import {
2
7
  resolveSchema
3
8
  } from "./chunk-EMIGCR7X.js";
@@ -22,7 +27,7 @@ import {
22
27
  EXPORT_AUDIT_COLLECTION,
23
28
  createExportBlobsHandle,
24
29
  runCompaction
25
- } from "./chunk-ZCBJIDT4.js";
30
+ } from "./chunk-RRCRITDM.js";
26
31
  import {
27
32
  LazyQuery,
28
33
  decodeIdxId,
@@ -40,16 +45,16 @@ import {
40
45
  resolveManagedSecret,
41
46
  savePersistedSchema,
42
47
  saveSealedPassphrase
43
- } from "./chunk-YP2AYE5W.js";
48
+ } from "./chunk-SID2NJNF.js";
44
49
  import {
45
50
  writeNoydbBundle
46
- } from "./chunk-N4EXCKWP.js";
51
+ } from "./chunk-6ZKXFMUG.js";
47
52
  import {
48
53
  loadPublicEnvelope,
49
54
  readPublicEnvelope,
50
55
  savePublicEnvelope,
51
56
  validatePublicEnvelopeInput
52
- } from "./chunk-HUXDQIVU.js";
57
+ } from "./chunk-2NYVA6FW.js";
53
58
  import {
54
59
  buildTombstone,
55
60
  isTombstone,
@@ -58,14 +63,14 @@ import {
58
63
  rewrapBodyToDek,
59
64
  rotateRecordCek,
60
65
  sealRecordToHost
61
- } from "./chunk-Y5CTT6K5.js";
66
+ } from "./chunk-K6PCTYAH.js";
62
67
  import {
63
68
  PERIODS_COLLECTION
64
- } from "./chunk-FCIZXX56.js";
69
+ } from "./chunk-BOMH3637.js";
65
70
  import {
66
71
  isDictCollectionName,
67
72
  isStaticDictDescriptor
68
- } from "./chunk-JJKXJAH2.js";
73
+ } from "./chunk-PFKAT4NT.js";
69
74
  import {
70
75
  getAtPath,
71
76
  resolvePolicy,
@@ -92,7 +97,7 @@ import {
92
97
  saveShamirRecoveryEntries,
93
98
  updateAuthenticator,
94
99
  writeMagicLinkGrant
95
- } from "./chunk-2RHBFCWQ.js";
100
+ } from "./chunk-IWGVH2RR.js";
96
101
  import {
97
102
  assertTierAccess,
98
103
  dekKey
@@ -121,7 +126,7 @@ import {
121
126
  rotateKeys,
122
127
  saveUserEnvelope,
123
128
  updateKeyringIdentity
124
- } from "./chunk-UNBX2HMA.js";
129
+ } from "./chunk-LXA2E3VI.js";
125
130
  import {
126
131
  INDEXED_STORE_POLICY
127
132
  } from "./chunk-2QR2PQTT.js";
@@ -131,7 +136,7 @@ import {
131
136
  import {
132
137
  LEDGER_COLLECTION,
133
138
  LEDGER_DELTAS_COLLECTION
134
- } from "./chunk-EYZJULEN.js";
139
+ } from "./chunk-6H4CAHMQ.js";
135
140
  import {
136
141
  sha256Hex as sha256Hex2
137
142
  } from "./chunk-PDVP3C2I.js";
@@ -143,11 +148,11 @@ import {
143
148
  readDottedPath,
144
149
  rebuildSubjectIndex,
145
150
  removeSubjectRef
146
- } from "./chunk-TSUICI5N.js";
151
+ } from "./chunk-BMDVFBCL.js";
147
152
  import {
148
153
  NOYDB_BACKUP_VERSION,
149
154
  NOYDB_FORMAT_VERSION
150
- } from "./chunk-LR7CODVN.js";
155
+ } from "./chunk-AD6RNBAW.js";
151
156
  import {
152
157
  decrypt,
153
158
  encrypt,
@@ -179,7 +184,6 @@ import {
179
184
  NoydbError,
180
185
  NumberingUncertaintyError,
181
186
  PermissionDeniedError,
182
- QuiesceTimeoutError,
183
187
  ReadOnlyError,
184
188
  ReservedCollectionNameError,
185
189
  SchemaFenceError,
@@ -2127,7 +2131,7 @@ var Collection = class {
2127
2131
  const outputCollection = this.derivationSource.getCollection(outSpec.collection);
2128
2132
  const txCtx = this.derivationSource.getActiveTxContext();
2129
2133
  if (out.kind === "array") {
2130
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-ZQT4Y7PF.js");
2134
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-OC4QVTS2.js");
2131
2135
  const prior = await loadFanoutSidecar(
2132
2136
  this.adapter,
2133
2137
  this.vault,
@@ -2490,7 +2494,7 @@ var Collection = class {
2490
2494
  for (const [outputKey, outSpec] of Object.entries(spec.outputs)) {
2491
2495
  if (outSpec.shape !== "array") continue;
2492
2496
  if (helpers === null) {
2493
- helpers = await import("./fanout-sidecar-ZQT4Y7PF.js");
2497
+ helpers = await import("./fanout-sidecar-OC4QVTS2.js");
2494
2498
  }
2495
2499
  const sidecar = await helpers.loadFanoutSidecar(
2496
2500
  this.adapter,
@@ -5932,84 +5936,12 @@ var SchemaUpdateGate = class {
5932
5936
  }
5933
5937
  };
5934
5938
 
5935
- // src/schema-update/fence.ts
5936
- var FENCE_RECORD_ID = "schema-fence";
5937
- var META_COLLECTION2 = "_meta";
5938
- var DEFAULT_FENCE = { currentSchemaVersion: 0, fenceState: "normal" };
5939
- async function loadFence(store, vault) {
5940
- const envelope = await store.get(vault, META_COLLECTION2, FENCE_RECORD_ID);
5941
- if (!envelope) return DEFAULT_FENCE;
5942
- try {
5943
- const parsed = JSON.parse(envelope._data);
5944
- if (!isFenceDoc(parsed)) return DEFAULT_FENCE;
5945
- return parsed;
5946
- } catch {
5947
- return DEFAULT_FENCE;
5948
- }
5949
- }
5950
- async function saveFence(store, vault, fence) {
5951
- const envelope = {
5952
- _noydb: NOYDB_FORMAT_VERSION,
5953
- _v: 1,
5954
- _ts: (/* @__PURE__ */ new Date()).toISOString(),
5955
- _iv: "",
5956
- _data: JSON.stringify(fence)
5957
- };
5958
- await store.put(vault, META_COLLECTION2, FENCE_RECORD_ID, envelope);
5959
- }
5960
- function isFenceDoc(x) {
5961
- if (x === null || typeof x !== "object") return false;
5962
- const o = x;
5963
- return typeof o["currentSchemaVersion"] === "number" && (o["fenceState"] === "normal" || o["fenceState"] === "draining" || o["fenceState"] === "migrating" || o["fenceState"] === "complete");
5964
- }
5965
-
5966
- // src/schema-update/client-registry.ts
5967
- var META_COLLECTION3 = "_meta";
5968
- var CLIENT_PREFIX = "schema-fence:client:";
5969
- async function writeClientDoc(store, vault, clientId, doc) {
5970
- const envelope = {
5971
- _noydb: NOYDB_FORMAT_VERSION,
5972
- _v: 1,
5973
- _ts: (/* @__PURE__ */ new Date()).toISOString(),
5974
- _iv: "",
5975
- _data: JSON.stringify({ clientId, ...doc })
5976
- };
5977
- await store.put(vault, META_COLLECTION3, `${CLIENT_PREFIX}${clientId}`, envelope);
5978
- }
5979
- async function listClientDocs(store, vault) {
5980
- const ids = await store.list(vault, META_COLLECTION3);
5981
- const out = [];
5982
- for (const id of ids) {
5983
- if (!id.startsWith(CLIENT_PREFIX)) continue;
5984
- const env = await store.get(vault, META_COLLECTION3, id);
5985
- if (!env) continue;
5986
- try {
5987
- const parsed = JSON.parse(env._data);
5988
- if (isClientDoc(parsed)) out.push(parsed);
5989
- } catch {
5990
- }
5991
- }
5992
- return out;
5993
- }
5994
- async function activeQuiesced(store, vault, opts) {
5995
- const docs = await listClientDocs(store, vault);
5996
- const active = docs.filter(
5997
- (d) => d.lastSeen >= opts.now - opts.staleMs && d.clientId !== opts.excludeClientId
5998
- );
5999
- return active.every((d) => d.quiescedAtVersion === opts.generation);
6000
- }
6001
- function isClientDoc(x) {
6002
- if (x === null || typeof x !== "object") return false;
6003
- const o = x;
6004
- return typeof o["clientId"] === "string" && typeof o["lastSeen"] === "number" && (o["quiescedAtVersion"] === null || typeof o["quiescedAtVersion"] === "number");
6005
- }
6006
-
6007
5939
  // src/schema-update/fence-controller.ts
6008
5940
  var SchemaFenceController = class {
6009
- #store;
5941
+ #coordination;
6010
5942
  #vault;
6011
5943
  #onFlush;
6012
- #clientId;
5944
+ #writerId;
6013
5945
  #now;
6014
5946
  #staleMs;
6015
5947
  #quiesceTimeoutMs;
@@ -6017,10 +5949,10 @@ var SchemaFenceController = class {
6017
5949
  #snapshot = 0;
6018
5950
  #pending = /* @__PURE__ */ new Map();
6019
5951
  constructor(opts) {
6020
- this.#store = opts.store;
5952
+ this.#coordination = opts.coordination;
6021
5953
  this.#vault = opts.vault;
6022
5954
  this.#onFlush = opts.onFlush;
6023
- this.#clientId = opts.clientId ?? "migrator";
5955
+ this.#writerId = opts.clientId ?? "migrator";
6024
5956
  this.#now = opts.now ?? (() => Date.now());
6025
5957
  this.#staleMs = opts.staleMs ?? 3e4;
6026
5958
  this.#quiesceTimeoutMs = opts.quiesceTimeoutMs ?? 6e4;
@@ -6029,7 +5961,7 @@ var SchemaFenceController = class {
6029
5961
  }
6030
5962
  /** Capture the generation snapshot at vault-open. */
6031
5963
  async init() {
6032
- this.#snapshot = (await loadFence(this.#store, this.#vault)).currentSchemaVersion;
5964
+ this.#snapshot = (await this.#coordination.readFence(this.#vault)).currentSchemaVersion;
6033
5965
  }
6034
5966
  /** Record a per-collection pending cutover (from a registration `cutover` decision). */
6035
5967
  registerPendingCutover(collection, transform) {
@@ -6037,7 +5969,7 @@ var SchemaFenceController = class {
6037
5969
  }
6038
5970
  /** Write-path gate. Throws when behind, fenced, or this collection is cutover-pending. */
6039
5971
  async assertWritable(collection) {
6040
- const fence = await loadFence(this.#store, this.#vault);
5972
+ const fence = await this.#coordination.readFence(this.#vault);
6041
5973
  if (fence.currentSchemaVersion > this.#snapshot) {
6042
5974
  throw new MigrationRequiredError(
6043
5975
  `Vault "${this.#vault}" advanced to schema generation ${fence.currentSchemaVersion} (this client opened at ${this.#snapshot}). Reload to continue.`
@@ -6056,61 +5988,59 @@ var SchemaFenceController = class {
6056
5988
  * Admin trigger. Drain → wait for the active set to quiesce (or time out)
6057
5989
  * → migrate each pending transform → bump → complete → normal. The
6058
5990
  * migrator excludes itself from the barrier (it drained synchronously
6059
- * here). `onPoll` (tests) advances other clients between barrier checks;
6060
- * production falls back to a short real delay.
5991
+ * inside {@link runDrainBarrier}). `onPoll` (tests) advances other clients
5992
+ * between barrier checks; production falls back to a short real delay.
6061
5993
  */
6062
5994
  async runCutover(run, opts) {
6063
5995
  if (this.#pending.size === 0) return { migrated: 0 };
6064
- const base = await loadFence(this.#store, this.#vault);
5996
+ const base = await this.#coordination.readFence(this.#vault);
6065
5997
  const generation = base.currentSchemaVersion;
6066
- await this.#setState(generation, "draining");
6067
- await this.#onFlush();
6068
- const deadline = this.#now() + this.#quiesceTimeoutMs;
6069
- while (!await activeQuiesced(this.#store, this.#vault, {
6070
- generation,
6071
- now: this.#now(),
6072
- staleMs: this.#staleMs,
6073
- excludeClientId: this.#clientId
6074
- })) {
6075
- if (this.#now() >= deadline) {
6076
- throw new QuiesceTimeoutError(
6077
- `Cutover on "${this.#vault}" timed out waiting for clients to quiesce at generation ${generation}.`
6078
- );
6079
- }
6080
- await (opts?.onPoll ? opts.onPoll() : delay(50));
6081
- }
6082
- await this.#setState(generation, "migrating");
5998
+ this.#emit({ currentSchemaVersion: generation, fenceState: "draining" });
6083
5999
  let migrated = 0;
6084
- for (const [collection, transform] of this.#pending) {
6085
- await run(collection, transform);
6086
- migrated++;
6087
- }
6088
- const nextVersion = generation + 1;
6089
- await this.#setState(nextVersion, "complete");
6090
- this.#pending.clear();
6091
- await this.#setState(nextVersion, "normal");
6092
- this.#snapshot = nextVersion;
6000
+ await runDrainBarrier(
6001
+ this.#coordination,
6002
+ {
6003
+ vault: this.#vault,
6004
+ generation,
6005
+ writerId: this.#writerId,
6006
+ onFlush: this.#onFlush,
6007
+ staleMs: this.#staleMs,
6008
+ quiesceTimeoutMs: this.#quiesceTimeoutMs,
6009
+ now: this.#now,
6010
+ ...opts?.onPoll ? { onPoll: opts.onPoll } : {}
6011
+ },
6012
+ async () => {
6013
+ await this.#setState(generation, "migrating");
6014
+ for (const [collection, transform] of this.#pending) {
6015
+ await run(collection, transform);
6016
+ migrated++;
6017
+ }
6018
+ const nextVersion = generation + 1;
6019
+ await this.#setState(nextVersion, "complete");
6020
+ this.#pending.clear();
6021
+ await this.#setState(nextVersion, "normal");
6022
+ this.#snapshot = nextVersion;
6023
+ }
6024
+ );
6093
6025
  return { migrated };
6094
6026
  }
6095
6027
  /** Recover a stuck drain: reset fenceState to normal at the current version (no bump). */
6096
6028
  async abort() {
6097
- const fence = await loadFence(this.#store, this.#vault);
6029
+ const fence = await this.#coordination.readFence(this.#vault);
6098
6030
  await this.#setState(fence.currentSchemaVersion, "normal");
6099
6031
  }
6100
6032
  async #setState(currentSchemaVersion, fenceState) {
6101
- await saveFence(this.#store, this.#vault, { currentSchemaVersion, fenceState });
6033
+ await this.#coordination.setFence(this.#vault, { currentSchemaVersion, fenceState });
6102
6034
  this.#emit({ currentSchemaVersion, fenceState });
6103
6035
  }
6104
6036
  };
6105
- function delay(ms) {
6106
- return new Promise((resolve) => setTimeout(resolve, ms));
6107
- }
6108
6037
 
6109
6038
  // src/schema-update/fence-watcher.ts
6110
6039
  var FenceWatcher = class {
6111
- #store;
6040
+ #coordination;
6112
6041
  #vault;
6113
- #clientId;
6042
+ #writerId;
6043
+ #sessionId;
6114
6044
  #onFlush;
6115
6045
  #now;
6116
6046
  #emit;
@@ -6118,9 +6048,10 @@ var FenceWatcher = class {
6118
6048
  #quiescedAtVersion = null;
6119
6049
  #timer;
6120
6050
  constructor(opts) {
6121
- this.#store = opts.store;
6051
+ this.#coordination = opts.coordination;
6122
6052
  this.#vault = opts.vault;
6123
- this.#clientId = opts.clientId;
6053
+ this.#writerId = opts.clientId;
6054
+ this.#sessionId = opts.sessionId ?? opts.clientId;
6124
6055
  this.#onFlush = opts.onFlush;
6125
6056
  this.#now = opts.now ?? (() => Date.now());
6126
6057
  this.#emit = opts.emit ?? (() => {
@@ -6128,14 +6059,16 @@ var FenceWatcher = class {
6128
6059
  }
6129
6060
  /** Publish liveness (and the current ack) without changing quiesce state. */
6130
6061
  async beat() {
6131
- await writeClientDoc(this.#store, this.#vault, this.#clientId, {
6062
+ await this.#coordination.reportPresence(this.#vault, {
6063
+ writerId: this.#writerId,
6064
+ sessionId: this.#sessionId,
6132
6065
  lastSeen: this.#now(),
6133
6066
  quiescedAtVersion: this.#quiescedAtVersion
6134
6067
  });
6135
6068
  }
6136
6069
  /** Poll the fence; quiesce on draining; emit on transitions. */
6137
6070
  async check() {
6138
- const fence = await loadFence(this.#store, this.#vault);
6071
+ const fence = await this.#coordination.readFence(this.#vault);
6139
6072
  if (fence.fenceState !== this.#lastState) {
6140
6073
  this.#lastState = fence.fenceState;
6141
6074
  this.#emit({ currentSchemaVersion: fence.currentSchemaVersion, fenceState: fence.fenceState });
@@ -6752,10 +6685,11 @@ var Vault = class {
6752
6685
  this.keyring = opts.keyring;
6753
6686
  this.encrypted = opts.encrypted;
6754
6687
  this.schemaFence = new SchemaFenceController({
6755
- store: this.adapter,
6688
+ coordination: this.noydb.coordination,
6756
6689
  vault: this.name,
6757
6690
  onFlush: () => this.noydb._writeQueueTracker.onFlush(),
6758
6691
  clientId: this.noydb._clientId,
6692
+ sessionId: this.noydb._sessionId,
6759
6693
  emit: (e) => this.emitter.emit("schema:fence-changed", { vault: this.name, ...e })
6760
6694
  });
6761
6695
  this.emitter = opts.emitter;
@@ -7151,9 +7085,10 @@ var Vault = class {
7151
7085
  if (this.#fenceCoordinationStarted) return;
7152
7086
  this.#fenceCoordinationStarted = true;
7153
7087
  this.#fenceWatcher = new FenceWatcher({
7154
- store: this.adapter,
7088
+ coordination: this.noydb.coordination,
7155
7089
  vault: this.name,
7156
7090
  clientId: this.noydb._clientId,
7091
+ sessionId: this.noydb._sessionId,
7157
7092
  onFlush: () => this.noydb._writeQueueTracker.onFlush(),
7158
7093
  emit: (e) => this.emitter.emit("schema:fence-changed", { vault: this.name, ...e })
7159
7094
  });
@@ -7711,12 +7646,12 @@ var Vault = class {
7711
7646
  if (!fieldSchema) {
7712
7647
  throw new AttestationError(`issueAttestation: collection '${collectionName}' has no attestation field-schema. Declare it via vault.collection('${collectionName}', { attestation: { fields: [...] } }).`);
7713
7648
  }
7714
- const { issueAttestationCore } = await import("./issue-LEBPVF3Y.js");
7649
+ const { issueAttestationCore } = await import("./issue-ZZ2XPOGP.js");
7715
7650
  const out = await issueAttestationCore(this.makeIssueContext(), { collection: collectionName, id, fieldSchema });
7716
7651
  return { docId: out.docId, qr: out.qr, keyId: out.keyId, publicKeyB64: out.publicKeyB64 };
7717
7652
  }
7718
7653
  async getDocumentSigningPublicKey() {
7719
- const { loadSigner, loadOrCreateSigner } = await import("./signer-NEQPCHMW.js");
7654
+ const { loadSigner, loadOrCreateSigner } = await import("./signer-SCJ6C6HQ.js");
7720
7655
  const existing = await loadSigner(this.adapter, this.name, this.getDEK);
7721
7656
  if (existing) return { keyId: existing.keyId, publicKeyB64: existing.publicKeyB64 };
7722
7657
  if (this.keyring.role !== "owner") {
@@ -7742,19 +7677,19 @@ var Vault = class {
7742
7677
  };
7743
7678
  }
7744
7679
  async revokeAttestation(docId) {
7745
- const { revokeDocCore } = await import("./revoke-P5D3UTRX.js");
7680
+ const { revokeDocCore } = await import("./revoke-QJ2HUM4W.js");
7746
7681
  await revokeDocCore(this.makeRevokeContext(), docId);
7747
7682
  }
7748
7683
  async unrevokeAttestation(docId) {
7749
- const { unrevokeDocCore } = await import("./revoke-P5D3UTRX.js");
7684
+ const { unrevokeDocCore } = await import("./revoke-QJ2HUM4W.js");
7750
7685
  await unrevokeDocCore(this.makeRevokeContext(), docId);
7751
7686
  }
7752
7687
  async getRevokedDocIds() {
7753
- const { getRevokedDocIdsCore } = await import("./revoke-P5D3UTRX.js");
7688
+ const { getRevokedDocIdsCore } = await import("./revoke-QJ2HUM4W.js");
7754
7689
  return getRevokedDocIdsCore(this.makeRevokeContext());
7755
7690
  }
7756
7691
  async publishRevocationList() {
7757
- const { publishRevocationListCore } = await import("./revoke-P5D3UTRX.js");
7692
+ const { publishRevocationListCore } = await import("./revoke-QJ2HUM4W.js");
7758
7693
  return publishRevocationListCore(this.makeRevokeContext());
7759
7694
  }
7760
7695
  makeRevokeContext() {
@@ -8562,7 +8497,7 @@ var Vault = class {
8562
8497
  if (!outSpec) continue;
8563
8498
  const outputColl = this.collection(outSpec.collection);
8564
8499
  if (out.kind === "array") {
8565
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-ZQT4Y7PF.js");
8500
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-OC4QVTS2.js");
8566
8501
  const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key);
8567
8502
  const prevKeys = new Set(prior?.keys ?? []);
8568
8503
  const newKeysList = out.entries.map((e) => e.key);
@@ -9276,7 +9211,7 @@ var Vault = class {
9276
9211
  * @see docs/subsystems/public-envelope.md
9277
9212
  */
9278
9213
  async getPublicEnvelope(opts = {}) {
9279
- const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-DBKJEBBF.js");
9214
+ const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-O6X6AUUS.js");
9280
9215
  return readPublicEnvelope2(this.adapter, this.name, opts);
9281
9216
  }
9282
9217
  /**
@@ -10822,6 +10757,10 @@ var Noydb = class {
10822
10757
  writeHooks = new WriteHookRegistry();
10823
10758
  subsystemBus = new SubsystemBus();
10824
10759
  clientId = generateULID();
10760
+ /** Session that owns this instance's writers (one user's writers across vaults). */
10761
+ sessionId;
10762
+ /** Drain-barrier coordination transport for the schema fence (#469). */
10763
+ coordinationProvider;
10825
10764
  vaultCache = /* @__PURE__ */ new Map();
10826
10765
  keyringCache = /* @__PURE__ */ new Map();
10827
10766
  syncEngines = /* @__PURE__ */ new Map();
@@ -10896,6 +10835,8 @@ var Noydb = class {
10896
10835
  "[noydb] debugPlaintext is ON \u2014 records are stored UNENCRYPTED and laid out for native store inspection. NEVER use this for production or client data."
10897
10836
  );
10898
10837
  }
10838
+ this.sessionId = options.sessionId ?? generateULID();
10839
+ this.coordinationProvider = options.coordinationStrategy ?? new StoreCoordinationProvider(options.store);
10899
10840
  this.txStrategy = options.txStrategy ?? NO_TX;
10900
10841
  this.forgetStrategy = options.forgetStrategy ?? NO_FORGET;
10901
10842
  this.sessionStrategy = options.sessionStrategy ?? NO_SESSION;
@@ -11949,6 +11890,18 @@ var Noydb = class {
11949
11890
  get _clientId() {
11950
11891
  return this.clientId;
11951
11892
  }
11893
+ /** @internal Session that owns this instance's writers (#469). */
11894
+ get _sessionId() {
11895
+ return this.sessionId;
11896
+ }
11897
+ /**
11898
+ * @internal Drain-barrier coordination transport for the schema fence (#469).
11899
+ * The default store-backed provider reproduces today's fence behavior; a
11900
+ * `by-*` real-time transport is injected via `coordinationStrategy`.
11901
+ */
11902
+ get coordination() {
11903
+ return this.coordinationProvider;
11904
+ }
11952
11905
  /**
11953
11906
  * Soft-lock a single vault: clear its in-memory keyring, DEKs, vault
11954
11907
  * instance, sync engine, policy enforcer, and active-tier entry —
@@ -13184,4 +13137,4 @@ export {
13184
13137
  Noydb,
13185
13138
  createNoydb
13186
13139
  };
13187
- //# sourceMappingURL=chunk-56ENKU46.js.map
13140
+ //# sourceMappingURL=chunk-KSKKLVPA.js.map