@noy-db/hub 0.2.0-pre.3 → 0.2.0-pre.5

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 (280) hide show
  1. package/dist/aggregate/index.cjs.map +1 -1
  2. package/dist/aggregate/index.js +4 -4
  3. package/dist/attestation/index.cjs.map +1 -1
  4. package/dist/attestation/index.d.cts +4 -4
  5. package/dist/attestation/index.d.ts +4 -4
  6. package/dist/attestation/index.js +6 -6
  7. package/dist/blobs/index.cjs.map +1 -1
  8. package/dist/blobs/index.d.cts +5 -5
  9. package/dist/blobs/index.d.ts +5 -5
  10. package/dist/blobs/index.js +5 -5
  11. package/dist/bundle/index.cjs +443 -338
  12. package/dist/bundle/index.cjs.map +1 -1
  13. package/dist/bundle/index.d.cts +17 -17
  14. package/dist/bundle/index.d.ts +17 -17
  15. package/dist/bundle/index.js +10 -10
  16. package/dist/bundle/index.js.map +1 -1
  17. package/dist/{chunk-YL2DR3HY.js → chunk-25WFLKOH.js} +2 -2
  18. package/dist/chunk-25WFLKOH.js.map +1 -0
  19. package/dist/{chunk-EMEX37ZN.js → chunk-2GMRNNI3.js} +3 -3
  20. package/dist/chunk-2GMRNNI3.js.map +1 -0
  21. package/dist/{chunk-NGSPBLLE.js → chunk-34XGYMQT.js} +3 -3
  22. package/dist/chunk-34XGYMQT.js.map +1 -0
  23. package/dist/{chunk-FXQYZNOW.js → chunk-5OVIFUQE.js} +1 -1
  24. package/dist/chunk-5OVIFUQE.js.map +1 -0
  25. package/dist/{chunk-P6256WTJ.js → chunk-5QPF2MJ5.js} +3 -3
  26. package/dist/chunk-5QPF2MJ5.js.map +1 -0
  27. package/dist/{chunk-5ZGZ6HIZ.js → chunk-5VMTAX4Y.js} +2 -2
  28. package/dist/{chunk-74JEQFMT.js → chunk-6A4AMQ2H.js} +5 -5
  29. package/dist/chunk-6A4AMQ2H.js.map +1 -0
  30. package/dist/{chunk-YDLAFP36.js → chunk-6HJ2ZALB.js} +1 -1
  31. package/dist/chunk-6HJ2ZALB.js.map +1 -0
  32. package/dist/{chunk-GDTCGIPX.js → chunk-7TX7HN42.js} +2 -2
  33. package/dist/chunk-7TX7HN42.js.map +1 -0
  34. package/dist/{chunk-EPK6A3WJ.js → chunk-A3JMGXPG.js} +2 -2
  35. package/dist/chunk-A3JMGXPG.js.map +1 -0
  36. package/dist/{chunk-75QDHSE4.js → chunk-A4JNVBPF.js} +5 -5
  37. package/dist/{chunk-IS5HWQO7.js → chunk-ARZAHCCF.js} +3 -3
  38. package/dist/{chunk-T6HQMVML.js → chunk-BT7544RM.js} +399 -301
  39. package/dist/chunk-BT7544RM.js.map +1 -0
  40. package/dist/{chunk-4OQWR46B.js → chunk-CCC25PA7.js} +5 -5
  41. package/dist/{chunk-NSLTPGEN.js → chunk-CGJFCT3X.js} +2 -2
  42. package/dist/{chunk-YK72A4IT.js → chunk-CKH247ZR.js} +4 -4
  43. package/dist/{chunk-HGZ7DC5H.js → chunk-DFCINPB5.js} +2 -2
  44. package/dist/chunk-DFCINPB5.js.map +1 -0
  45. package/dist/{chunk-4X2S7PBF.js → chunk-E225X5CQ.js} +3 -3
  46. package/dist/chunk-E225X5CQ.js.map +1 -0
  47. package/dist/{chunk-5YHWBPOT.js → chunk-ED3E3OLO.js} +2 -2
  48. package/dist/{chunk-UOF74WQY.js → chunk-EKTOYEZ3.js} +2 -2
  49. package/dist/{chunk-SAVQ6E2O.js → chunk-G26QAQNI.js} +2 -2
  50. package/dist/{chunk-YMYK7US4.js → chunk-HIELMTUK.js} +2 -2
  51. package/dist/{chunk-MRIBLZL3.js → chunk-ICH4AIGL.js} +1 -1
  52. package/dist/chunk-ICH4AIGL.js.map +1 -0
  53. package/dist/{chunk-LOL725S4.js → chunk-JSYTGEX4.js} +3 -3
  54. package/dist/{chunk-FBMXWVGP.js → chunk-KGFV72WK.js} +5 -5
  55. package/dist/{chunk-GVXBHCZ2.js → chunk-LJO6Q3X6.js} +5 -5
  56. package/dist/chunk-LJO6Q3X6.js.map +1 -0
  57. package/dist/{chunk-ZC2AAE6J.js → chunk-LWFQYT4N.js} +2 -2
  58. package/dist/chunk-LWFQYT4N.js.map +1 -0
  59. package/dist/{chunk-K5PVGKE4.js → chunk-MDIC4FAU.js} +2 -2
  60. package/dist/{chunk-A6SWRXUQ.js → chunk-NONMIU6C.js} +2 -2
  61. package/dist/{chunk-ZUMGGHRB.js → chunk-OPD3PZOG.js} +4 -4
  62. package/dist/{chunk-LS3JLEIB.js → chunk-PS5G6A3Y.js} +4 -4
  63. package/dist/{chunk-KYKMKLJ6.js → chunk-PX3MJ6RB.js} +3 -3
  64. package/dist/{chunk-FCDO7UAO.js → chunk-R4LTCI6O.js} +2 -2
  65. package/dist/{chunk-BFI3RS42.js → chunk-R7JTYCRX.js} +2 -2
  66. package/dist/chunk-R7JTYCRX.js.map +1 -0
  67. package/dist/{chunk-WRLHNG6H.js → chunk-RIHZBSWJ.js} +4 -4
  68. package/dist/chunk-RIHZBSWJ.js.map +1 -0
  69. package/dist/{chunk-UVPGJXVO.js → chunk-SGSHQ4PH.js} +5 -5
  70. package/dist/{chunk-TLFUDXVV.js → chunk-T6MTNGBM.js} +5 -5
  71. package/dist/chunk-T6MTNGBM.js.map +1 -0
  72. package/dist/{chunk-6S3LLAQ5.js → chunk-TNBIWSQ7.js} +2 -2
  73. package/dist/{chunk-GD3BGKAR.js → chunk-UGVDIOY7.js} +2 -2
  74. package/dist/{chunk-FS7A4XNF.js → chunk-WEA4TDTJ.js} +3 -3
  75. package/dist/{chunk-4UBOTYP5.js → chunk-XDW37COG.js} +5 -5
  76. package/dist/chunk-XDW37COG.js.map +1 -0
  77. package/dist/{chunk-QAU5HM6Q.js → chunk-XVJFFGTG.js} +3 -3
  78. package/dist/{chunk-2EYC3WDT.js → chunk-Y3P5DEMZ.js} +6 -6
  79. package/dist/chunk-Y3P5DEMZ.js.map +1 -0
  80. package/dist/{chunk-G7PAZ3TD.js → chunk-YEHUEUNP.js} +4 -4
  81. package/dist/chunk-YEHUEUNP.js.map +1 -0
  82. package/dist/{chunk-2XLVPKXG.js → chunk-YJ46RFCD.js} +2 -2
  83. package/dist/{chunk-KMI2NBBF.js → chunk-YZ6JETII.js} +6 -6
  84. package/dist/{chunk-NCO2JGKK.js → chunk-Z6FNBOTC.js} +1 -1
  85. package/dist/chunk-Z6FNBOTC.js.map +1 -0
  86. package/dist/{chunk-GAUBWHAF.js → chunk-ZQMYB56Z.js} +4 -4
  87. package/dist/consent/index.cjs.map +1 -1
  88. package/dist/consent/index.d.cts +5 -5
  89. package/dist/consent/index.d.ts +5 -5
  90. package/dist/consent/index.js +3 -3
  91. package/dist/{crypto-H2Y3DDFW.js → crypto-5UDZZL26.js} +3 -3
  92. package/dist/{delegation-QSC7G5QC.js → delegation-42LO4WFO.js} +5 -5
  93. package/dist/derivations/index.cjs +1 -1
  94. package/dist/derivations/index.cjs.map +1 -1
  95. package/dist/derivations/index.d.cts +8 -8
  96. package/dist/derivations/index.d.ts +8 -8
  97. package/dist/derivations/index.js +4 -4
  98. package/dist/{dev-unlock-Cf2B7Kih.d.ts → dev-unlock--ahUTrhc.d.ts} +1 -1
  99. package/dist/{dev-unlock-De3mjQWv.d.cts → dev-unlock-BIwt2V3p.d.cts} +1 -1
  100. package/dist/executor-AWCHQ2KN.js +8 -0
  101. package/dist/executor-RWICJI7J.js +11 -0
  102. package/dist/executor-SOLEQVUB.js +8 -0
  103. package/dist/{fanout-sidecar-NRBWSLRK.js → fanout-sidecar-EVICRM46.js} +2 -2
  104. package/dist/fanout-sidecar-EVICRM46.js.map +1 -0
  105. package/dist/guards/index.cjs +1 -1
  106. package/dist/guards/index.cjs.map +1 -1
  107. package/dist/guards/index.d.cts +6 -6
  108. package/dist/guards/index.d.ts +6 -6
  109. package/dist/guards/index.js +4 -4
  110. package/dist/{hash-vBCB0-Ps.d.cts → hash-BQVrGV-t.d.cts} +1 -1
  111. package/dist/{hash-gVn_uKhp.d.ts → hash-CJEFQxSD.d.ts} +1 -1
  112. package/dist/history/index.cjs.map +1 -1
  113. package/dist/history/index.d.cts +6 -6
  114. package/dist/history/index.d.ts +6 -6
  115. package/dist/history/index.js +6 -6
  116. package/dist/i18n/index.cjs.map +1 -1
  117. package/dist/i18n/index.d.cts +5 -5
  118. package/dist/i18n/index.d.ts +5 -5
  119. package/dist/i18n/index.js +7 -7
  120. package/dist/{index-DVkvrgpm.d.cts → index-5I0MZ0jQ.d.cts} +12 -12
  121. package/dist/{index-BF1B2HB9.d.ts → index-fIPPh5dg.d.ts} +12 -12
  122. package/dist/index.cjs +362 -264
  123. package/dist/index.cjs.map +1 -1
  124. package/dist/index.d.cts +20 -22
  125. package/dist/index.d.ts +20 -22
  126. package/dist/index.js +45 -45
  127. package/dist/index.js.map +1 -1
  128. package/dist/indexing/index.cjs +1 -1
  129. package/dist/indexing/index.cjs.map +1 -1
  130. package/dist/indexing/index.d.cts +3 -3
  131. package/dist/indexing/index.d.ts +3 -3
  132. package/dist/indexing/index.js +4 -4
  133. package/dist/issue-IODMTPME.js +12 -0
  134. package/dist/{lazy-builder-Rpd-V3jP.d.ts → lazy-builder-D1MyR1qH.d.ts} +2 -2
  135. package/dist/{lazy-builder-C-rPfWG0.d.cts → lazy-builder-DXlSCNCJ.d.cts} +2 -2
  136. package/dist/{ledger-WOEJUYTP.js → ledger-UX4QIHWI.js} +6 -6
  137. package/dist/materialized-views/index.cjs.map +1 -1
  138. package/dist/materialized-views/index.d.cts +18 -18
  139. package/dist/materialized-views/index.d.ts +18 -18
  140. package/dist/materialized-views/index.js +7 -7
  141. package/dist/noydb-6TADQIYH.js +34 -0
  142. package/dist/overlay-views/index.cjs +1 -1
  143. package/dist/overlay-views/index.cjs.map +1 -1
  144. package/dist/overlay-views/index.d.cts +8 -8
  145. package/dist/overlay-views/index.d.ts +8 -8
  146. package/dist/overlay-views/index.js +4 -4
  147. package/dist/periods/index.cjs.map +1 -1
  148. package/dist/periods/index.d.cts +5 -5
  149. package/dist/periods/index.d.ts +5 -5
  150. package/dist/periods/index.js +6 -6
  151. package/dist/{predicate-Dnu81tsS.d.cts → predicate-B0IKeBXx.d.cts} +1 -1
  152. package/dist/{predicate-Dnu81tsS.d.ts → predicate-B0IKeBXx.d.ts} +1 -1
  153. package/dist/{public-envelope-OHQ5UZFM.js → public-envelope-YKHKP74C.js} +4 -4
  154. package/dist/query/index.cjs +2 -2
  155. package/dist/query/index.cjs.map +1 -1
  156. package/dist/query/index.d.cts +2 -2
  157. package/dist/query/index.d.ts +2 -2
  158. package/dist/query/index.js +6 -6
  159. package/dist/registry-446I2NMN.js +8 -0
  160. package/dist/{registry-CDHASH73.js → registry-4NEW7LQY.js} +3 -3
  161. package/dist/registry-524KJZG4.js +8 -0
  162. package/dist/registry-DKEXOJVO.js +7 -0
  163. package/dist/{revoke-7JOVLZFD.js → revoke-R5NIQ74J.js} +6 -6
  164. package/dist/session/index.cjs.map +1 -1
  165. package/dist/session/index.d.cts +6 -6
  166. package/dist/session/index.d.ts +6 -6
  167. package/dist/session/index.js +3 -3
  168. package/dist/shadow/index.cjs.map +1 -1
  169. package/dist/shadow/index.d.cts +5 -5
  170. package/dist/shadow/index.d.ts +5 -5
  171. package/dist/shadow/index.js +2 -2
  172. package/dist/{signer-M4K5HBLD.js → signer-WGDJNWSU.js} +5 -5
  173. package/dist/{stale-PAGCS4K5.js → stale-74WGLVZ2.js} +2 -2
  174. package/dist/store/index.cjs.map +1 -1
  175. package/dist/store/index.d.cts +5 -5
  176. package/dist/store/index.d.ts +5 -5
  177. package/dist/store/index.js +2 -2
  178. package/dist/sync/index.cjs.map +1 -1
  179. package/dist/sync/index.d.cts +4 -4
  180. package/dist/sync/index.d.ts +4 -4
  181. package/dist/sync/index.js +4 -4
  182. package/dist/team/index.cjs +1 -1
  183. package/dist/team/index.cjs.map +1 -1
  184. package/dist/team/index.d.cts +5 -5
  185. package/dist/team/index.d.ts +5 -5
  186. package/dist/team/index.js +8 -8
  187. package/dist/tx/index.cjs +2 -2
  188. package/dist/tx/index.cjs.map +1 -1
  189. package/dist/tx/index.d.cts +5 -5
  190. package/dist/tx/index.d.ts +5 -5
  191. package/dist/tx/index.js +3 -3
  192. package/dist/tx/index.js.map +1 -1
  193. package/dist/{types-D9eB0Rvh.d.ts → types-BV4AZKmx.d.ts} +340 -302
  194. package/dist/{types-CSLcfytP.d.cts → types-BeKi0hCx.d.cts} +340 -302
  195. package/dist/{ulid-CiM2OAeM.d.ts → ulid-CQc0eBxE.d.ts} +19 -19
  196. package/dist/{ulid-CG2YvAbg.d.cts → ulid-Cvljl7ZZ.d.cts} +19 -19
  197. package/dist/util/index.cjs.map +1 -1
  198. package/dist/util/index.js +1 -1
  199. package/dist/{with-derivation-Bzpj6UTv.d.ts → with-derivation-BWcwmevt.d.ts} +1 -1
  200. package/dist/{with-derivation-DWajFh4K.d.cts → with-derivation-BkOBDhsu.d.cts} +1 -1
  201. package/dist/{with-guard-DF_Ul3DT.d.cts → with-guard-BD4Hyu8s.d.cts} +1 -1
  202. package/dist/{with-guard-DR7U-l4v.d.ts → with-guard-Du54s3Ti.d.ts} +1 -1
  203. package/dist/{with-materialized-view-qtoJ3xKJ.d.ts → with-materialized-view-B5W4wFAC.d.ts} +2 -2
  204. package/dist/{with-materialized-view-_piodoIz.d.cts → with-materialized-view-BCPPZdjC.d.cts} +2 -2
  205. package/dist/{with-overlayed-view-DFaRfgMr.d.ts → with-overlayed-view-B8RrlLsG.d.cts} +2 -2
  206. package/dist/{with-overlayed-view-DwzCKxn2.d.cts → with-overlayed-view-Cw-h9p9N.d.ts} +2 -2
  207. package/package.json +3 -3
  208. package/dist/chunk-2EYC3WDT.js.map +0 -1
  209. package/dist/chunk-4UBOTYP5.js.map +0 -1
  210. package/dist/chunk-4X2S7PBF.js.map +0 -1
  211. package/dist/chunk-74JEQFMT.js.map +0 -1
  212. package/dist/chunk-BFI3RS42.js.map +0 -1
  213. package/dist/chunk-EMEX37ZN.js.map +0 -1
  214. package/dist/chunk-EPK6A3WJ.js.map +0 -1
  215. package/dist/chunk-FXQYZNOW.js.map +0 -1
  216. package/dist/chunk-G7PAZ3TD.js.map +0 -1
  217. package/dist/chunk-GDTCGIPX.js.map +0 -1
  218. package/dist/chunk-GVXBHCZ2.js.map +0 -1
  219. package/dist/chunk-HGZ7DC5H.js.map +0 -1
  220. package/dist/chunk-MRIBLZL3.js.map +0 -1
  221. package/dist/chunk-NCO2JGKK.js.map +0 -1
  222. package/dist/chunk-NGSPBLLE.js.map +0 -1
  223. package/dist/chunk-P6256WTJ.js.map +0 -1
  224. package/dist/chunk-T6HQMVML.js.map +0 -1
  225. package/dist/chunk-TLFUDXVV.js.map +0 -1
  226. package/dist/chunk-WRLHNG6H.js.map +0 -1
  227. package/dist/chunk-YDLAFP36.js.map +0 -1
  228. package/dist/chunk-YL2DR3HY.js.map +0 -1
  229. package/dist/chunk-ZC2AAE6J.js.map +0 -1
  230. package/dist/executor-BZKFZVRC.js +0 -8
  231. package/dist/executor-GFZFDQXV.js +0 -8
  232. package/dist/executor-KT2IOZVP.js +0 -11
  233. package/dist/fanout-sidecar-NRBWSLRK.js.map +0 -1
  234. package/dist/issue-BAJ7ZB4S.js +0 -12
  235. package/dist/noydb-XNQSKXGO.js +0 -34
  236. package/dist/registry-2IEARCGT.js +0 -7
  237. package/dist/registry-EMGLZGR6.js +0 -8
  238. package/dist/registry-NQALYR77.js +0 -8
  239. /package/dist/{chunk-5ZGZ6HIZ.js.map → chunk-5VMTAX4Y.js.map} +0 -0
  240. /package/dist/{chunk-75QDHSE4.js.map → chunk-A4JNVBPF.js.map} +0 -0
  241. /package/dist/{chunk-IS5HWQO7.js.map → chunk-ARZAHCCF.js.map} +0 -0
  242. /package/dist/{chunk-4OQWR46B.js.map → chunk-CCC25PA7.js.map} +0 -0
  243. /package/dist/{chunk-NSLTPGEN.js.map → chunk-CGJFCT3X.js.map} +0 -0
  244. /package/dist/{chunk-YK72A4IT.js.map → chunk-CKH247ZR.js.map} +0 -0
  245. /package/dist/{chunk-5YHWBPOT.js.map → chunk-ED3E3OLO.js.map} +0 -0
  246. /package/dist/{chunk-UOF74WQY.js.map → chunk-EKTOYEZ3.js.map} +0 -0
  247. /package/dist/{chunk-SAVQ6E2O.js.map → chunk-G26QAQNI.js.map} +0 -0
  248. /package/dist/{chunk-YMYK7US4.js.map → chunk-HIELMTUK.js.map} +0 -0
  249. /package/dist/{chunk-LOL725S4.js.map → chunk-JSYTGEX4.js.map} +0 -0
  250. /package/dist/{chunk-FBMXWVGP.js.map → chunk-KGFV72WK.js.map} +0 -0
  251. /package/dist/{chunk-K5PVGKE4.js.map → chunk-MDIC4FAU.js.map} +0 -0
  252. /package/dist/{chunk-A6SWRXUQ.js.map → chunk-NONMIU6C.js.map} +0 -0
  253. /package/dist/{chunk-ZUMGGHRB.js.map → chunk-OPD3PZOG.js.map} +0 -0
  254. /package/dist/{chunk-LS3JLEIB.js.map → chunk-PS5G6A3Y.js.map} +0 -0
  255. /package/dist/{chunk-KYKMKLJ6.js.map → chunk-PX3MJ6RB.js.map} +0 -0
  256. /package/dist/{chunk-FCDO7UAO.js.map → chunk-R4LTCI6O.js.map} +0 -0
  257. /package/dist/{chunk-UVPGJXVO.js.map → chunk-SGSHQ4PH.js.map} +0 -0
  258. /package/dist/{chunk-6S3LLAQ5.js.map → chunk-TNBIWSQ7.js.map} +0 -0
  259. /package/dist/{chunk-GD3BGKAR.js.map → chunk-UGVDIOY7.js.map} +0 -0
  260. /package/dist/{chunk-FS7A4XNF.js.map → chunk-WEA4TDTJ.js.map} +0 -0
  261. /package/dist/{chunk-QAU5HM6Q.js.map → chunk-XVJFFGTG.js.map} +0 -0
  262. /package/dist/{chunk-2XLVPKXG.js.map → chunk-YJ46RFCD.js.map} +0 -0
  263. /package/dist/{chunk-KMI2NBBF.js.map → chunk-YZ6JETII.js.map} +0 -0
  264. /package/dist/{chunk-GAUBWHAF.js.map → chunk-ZQMYB56Z.js.map} +0 -0
  265. /package/dist/{crypto-H2Y3DDFW.js.map → crypto-5UDZZL26.js.map} +0 -0
  266. /package/dist/{delegation-QSC7G5QC.js.map → delegation-42LO4WFO.js.map} +0 -0
  267. /package/dist/{executor-BZKFZVRC.js.map → executor-AWCHQ2KN.js.map} +0 -0
  268. /package/dist/{executor-GFZFDQXV.js.map → executor-RWICJI7J.js.map} +0 -0
  269. /package/dist/{executor-KT2IOZVP.js.map → executor-SOLEQVUB.js.map} +0 -0
  270. /package/dist/{issue-BAJ7ZB4S.js.map → issue-IODMTPME.js.map} +0 -0
  271. /package/dist/{ledger-WOEJUYTP.js.map → ledger-UX4QIHWI.js.map} +0 -0
  272. /package/dist/{noydb-XNQSKXGO.js.map → noydb-6TADQIYH.js.map} +0 -0
  273. /package/dist/{public-envelope-OHQ5UZFM.js.map → public-envelope-YKHKP74C.js.map} +0 -0
  274. /package/dist/{registry-2IEARCGT.js.map → registry-446I2NMN.js.map} +0 -0
  275. /package/dist/{registry-CDHASH73.js.map → registry-4NEW7LQY.js.map} +0 -0
  276. /package/dist/{registry-EMGLZGR6.js.map → registry-524KJZG4.js.map} +0 -0
  277. /package/dist/{registry-NQALYR77.js.map → registry-DKEXOJVO.js.map} +0 -0
  278. /package/dist/{revoke-7JOVLZFD.js.map → revoke-R5NIQ74J.js.map} +0 -0
  279. /package/dist/{signer-M4K5HBLD.js.map → signer-WGDJNWSU.js.map} +0 -0
  280. /package/dist/{stale-PAGCS4K5.js.map → stale-74WGLVZ2.js.map} +0 -0
@@ -4,34 +4,34 @@ import {
4
4
  import {
5
5
  TxContext,
6
6
  revertExecuted
7
- } from "./chunk-GVXBHCZ2.js";
7
+ } from "./chunk-LJO6Q3X6.js";
8
8
  import {
9
9
  OverlayedCollection
10
- } from "./chunk-NGSPBLLE.js";
10
+ } from "./chunk-34XGYMQT.js";
11
11
  import {
12
12
  LazyQuery,
13
13
  decodeIdxId,
14
14
  encodeIdxId
15
- } from "./chunk-WRLHNG6H.js";
15
+ } from "./chunk-RIHZBSWJ.js";
16
16
  import {
17
17
  SCHEMAS_COLLECTION,
18
18
  loadPersistedSchema,
19
19
  resolveManagedSecret,
20
20
  savePersistedSchema,
21
21
  saveSealedPassphrase
22
- } from "./chunk-4X2S7PBF.js";
22
+ } from "./chunk-E225X5CQ.js";
23
23
  import {
24
24
  loadPublicEnvelope,
25
25
  readPublicEnvelope,
26
26
  savePublicEnvelope,
27
27
  validatePublicEnvelopeInput
28
- } from "./chunk-FS7A4XNF.js";
28
+ } from "./chunk-WEA4TDTJ.js";
29
29
  import {
30
30
  PERIODS_COLLECTION
31
- } from "./chunk-GAUBWHAF.js";
31
+ } from "./chunk-ZQMYB56Z.js";
32
32
  import {
33
33
  isDictCollectionName
34
- } from "./chunk-KMI2NBBF.js";
34
+ } from "./chunk-YZ6JETII.js";
35
35
  import {
36
36
  ManagedRecoveryNotEnrolledError,
37
37
  PolicyDeniedError,
@@ -53,11 +53,11 @@ import {
53
53
  saveShamirRecoveryEntries,
54
54
  updateAuthenticator,
55
55
  writeMagicLinkGrant
56
- } from "./chunk-2EYC3WDT.js";
56
+ } from "./chunk-Y3P5DEMZ.js";
57
57
  import {
58
58
  assertTierAccess,
59
59
  dekKey
60
- } from "./chunk-6S3LLAQ5.js";
60
+ } from "./chunk-TNBIWSQ7.js";
61
61
  import {
62
62
  USER_ENVELOPE_COLLECTION,
63
63
  buildRecipientKeyringFile,
@@ -81,7 +81,7 @@ import {
81
81
  rotateKeys,
82
82
  saveUserEnvelope,
83
83
  updateKeyringIdentity
84
- } from "./chunk-TLFUDXVV.js";
84
+ } from "./chunk-T6MTNGBM.js";
85
85
  import {
86
86
  INDEXED_STORE_POLICY
87
87
  } from "./chunk-2QR2PQTT.js";
@@ -91,30 +91,30 @@ import {
91
91
  import {
92
92
  LEDGER_COLLECTION,
93
93
  LEDGER_DELTAS_COLLECTION
94
- } from "./chunk-74JEQFMT.js";
94
+ } from "./chunk-6A4AMQ2H.js";
95
95
  import {
96
96
  sha256Hex as sha256Hex2
97
- } from "./chunk-NCO2JGKK.js";
97
+ } from "./chunk-Z6FNBOTC.js";
98
98
  import {
99
99
  NO_AGGREGATE,
100
100
  Query,
101
101
  ScanBuilder
102
- } from "./chunk-4UBOTYP5.js";
102
+ } from "./chunk-XDW37COG.js";
103
103
  import {
104
104
  EXPORT_AUDIT_COLLECTION,
105
105
  createExportBlobsHandle,
106
106
  runCompaction
107
- } from "./chunk-LOL725S4.js";
107
+ } from "./chunk-JSYTGEX4.js";
108
108
  import {
109
109
  NOYDB_BACKUP_VERSION,
110
110
  NOYDB_FORMAT_VERSION
111
- } from "./chunk-FXQYZNOW.js";
111
+ } from "./chunk-5OVIFUQE.js";
112
112
  import {
113
113
  decrypt,
114
114
  encrypt,
115
115
  encryptDeterministic,
116
116
  sha256Hex
117
- } from "./chunk-UOF74WQY.js";
117
+ } from "./chunk-EKTOYEZ3.js";
118
118
  import {
119
119
  AlreadyElevatedError,
120
120
  AttestationError,
@@ -141,7 +141,7 @@ import {
141
141
  TierNotGrantedError,
142
142
  TranslatorNotConfiguredError,
143
143
  ValidationError
144
- } from "./chunk-YDLAFP36.js";
144
+ } from "./chunk-6HJ2ZALB.js";
145
145
 
146
146
  // src/policy/storage.ts
147
147
  var META_COLLECTION = "_meta";
@@ -644,7 +644,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
644
644
  }
645
645
  const sourceWithId = { ...source, id };
646
646
  if (DerivationExecutor === null) {
647
- ({ DerivationExecutor } = await import("./executor-GFZFDQXV.js"));
647
+ ({ DerivationExecutor } = await import("./executor-SOLEQVUB.js"));
648
648
  }
649
649
  const ctx = { vault: accessor.getReadOnlyFacade() };
650
650
  const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx);
@@ -664,7 +664,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
664
664
  }
665
665
  if (out.kind === "array") {
666
666
  console.warn(
667
- `[derivation] unexpected array-shape output "${key}" in lazy resolve path; array-shape derivations require lifecycle: "eager" (#200 slice 1).`
667
+ `[derivation] unexpected array-shape output "${key}" in lazy resolve path; array-shape derivations require lifecycle: "eager".`
668
668
  );
669
669
  continue;
670
670
  }
@@ -702,6 +702,7 @@ var Collection = class {
702
702
  schemaUpdateGate;
703
703
  schemaFence;
704
704
  writeHooks;
705
+ subsystemBus;
705
706
  activeTxId;
706
707
  getDEK;
707
708
  onDirty;
@@ -890,42 +891,14 @@ var Collection = class {
890
891
  syncAdapter;
891
892
  /** — consent-audit hook, no-op when no scope is active. */
892
893
  onAccess;
893
- /**
894
- * accounting-period write guard. Called BEFORE any
895
- * adapter write with:
896
- * - `existing` — the prior envelope's `_ts` and decrypted record
897
- * (or `null` if no prior envelope exists)
898
- * - `incoming` — the record being written (or `null` for delete)
899
- *
900
- * Throws `PeriodClosedError` if either side falls inside a closed
901
- * period. Installed by Vault; no-op when no period has been closed.
902
- * Async so the Vault can lazy-load the period list from the
903
- * adapter on first use.
904
- */
905
- periodGuard;
906
- /**
907
- * Optional back-reference to the owning vault's guard registry + a
908
- * read-only vault facade. When present, `Collection.put` and
909
- * `Collection.delete` consult the registry for guards declared
910
- * against this collection and run their `check` + `frozenFields`
911
- * before the adapter write. Absent in unit tests that construct
912
- * a Collection directly; production code always sets it via
913
- * `Vault.collection()`.
914
- *
915
- * Typed structurally rather than as `Vault` to avoid a circular
916
- * import (mirrors the `refEnforcer` / `joinResolver` pattern).
917
- */
918
- guardSource;
919
894
  /**
920
895
  * Vault-internal hook for derivation dispatch. When set,
921
896
  * `Collection.put` consults the registry after the source-write
922
897
  * commits and writes derived outputs through `getCollection(name).put`.
923
- * Same structural-interface pattern as `guardSource` to avoid a
924
- * circular Vault import.
925
898
  */
926
899
  derivationSource;
927
900
  /**
928
- * Vault-internal hook for materialized-view dispatch (#143/#150).
901
+ * Vault-internal hook for materialized-view dispatch.
929
902
  * Parallel to `derivationSource` — when set, `Collection.put` fires
930
903
  * `MaterializedViewRegistry.onSourceWrite` after the source-write
931
904
  * commits + after `dispatchDerivations` has run.
@@ -981,6 +954,7 @@ var Collection = class {
981
954
  this.schemaUpdateGate = opts.schemaUpdateGate;
982
955
  this.schemaFence = opts.schemaFence;
983
956
  this.writeHooks = opts.writeHooks;
957
+ this.subsystemBus = opts.subsystemBus;
984
958
  this.activeTxId = opts.activeTxId;
985
959
  this.blobStrategy = opts.blobStrategy ?? NO_BLOBS;
986
960
  this.aggregateStrategy = opts.aggregateStrategy ?? NO_AGGREGATE;
@@ -1005,8 +979,6 @@ var Collection = class {
1005
979
  this.crdtMode = opts.crdt;
1006
980
  this.syncAdapter = opts.syncAdapter;
1007
981
  this.onAccess = opts.onAccess;
1008
- this.periodGuard = opts.periodGuard;
1009
- this.guardSource = opts.guardSource;
1010
982
  this.derivationSource = opts.derivationSource;
1011
983
  this.materializedViewSource = opts.materializedViewSource;
1012
984
  this.tiers = opts.tiers && opts.tiers.length > 0 ? new Set(opts.tiers) : null;
@@ -1140,7 +1112,7 @@ var Collection = class {
1140
1112
  }
1141
1113
  }
1142
1114
  if (this.materializedViewSource !== void 0) {
1143
- const { resolveStaleMVOnRead } = await import("./stale-PAGCS4K5.js");
1115
+ const { resolveStaleMVOnRead } = await import("./stale-74WGLVZ2.js");
1144
1116
  await resolveStaleMVOnRead(this.materializedViewSource, this.name);
1145
1117
  }
1146
1118
  let record;
@@ -1208,21 +1180,23 @@ var Collection = class {
1208
1180
  }
1209
1181
  /**
1210
1182
  * Create or update a record. Runs inside the hub's write-queue tracker
1211
- * (#227) so `hub.writeQueue.pending` reflects this write.
1183
+ * so `hub.writeQueue.pending` reflects this write.
1212
1184
  *
1213
1185
  * @param id Record identifier.
1214
1186
  * @param record The record body (validated by the collection's schema
1215
1187
  * if one was attached at `vault.collection(...)` time).
1216
1188
  * @param options Optional metadata for audit + import workflows.
1217
1189
  * `reason` is stamped onto the resulting ledger entry
1218
- * (see #1) so audit consumers can filter via
1190
+ * so audit consumers can filter via
1219
1191
  * `entries.filter(e => e.reason?.startsWith('import:'))`.
1220
1192
  */
1221
1193
  async put(id, record, options) {
1222
1194
  await this.schemaUpdateGate?.assertWritable();
1223
1195
  await this.schemaFence?.assertWritable(this.name);
1196
+ const hooksActive = this.#hooksActive();
1197
+ const busAfterPut = (this.subsystemBus?.hasHandlers("afterPut") ?? false) && !(this.subsystemBus?.dispatching ?? false);
1224
1198
  let event;
1225
- if (this.#hooksActive()) {
1199
+ if (hooksActive || busAfterPut) {
1226
1200
  const prior = await this.#priorForHook(id);
1227
1201
  event = {
1228
1202
  op: prior.record === null ? "create" : "update",
@@ -1237,23 +1211,26 @@ var Collection = class {
1237
1211
  baseVersion: prior.version,
1238
1212
  version: prior.version + 1
1239
1213
  };
1240
- await this.writeHooks.runBefore(event);
1214
+ if (hooksActive) await this.writeHooks.runBefore(event);
1241
1215
  }
1242
1216
  if (this.writeQueue) await this.writeQueue.track(() => this.putInternal(id, record, options));
1243
1217
  else await this.putInternal(id, record, options);
1244
- if (event) await this.writeHooks.runAfter(event);
1218
+ if (event) {
1219
+ if (hooksActive) await this.writeHooks.runAfter(event);
1220
+ if (busAfterPut) await this.subsystemBus.dispatch("afterPut", event);
1221
+ }
1245
1222
  }
1246
- /** @internal #230 — true when hooks should fire for this write (handlers exist, not re-entrant). */
1223
+ /** @internal — true when hooks should fire for this write (handlers exist, not re-entrant). */
1247
1224
  #hooksActive() {
1248
1225
  return this.writeHooks !== void 0 && this.writeHooks.hasHandlers && !this.writeHooks.suppressed;
1249
1226
  }
1250
1227
  /**
1251
- * @internal #230/#228c — resolve the prior record for a hook's `before` and
1228
+ * @internal — resolve the prior record for a hook's `before` and
1252
1229
  * its version. Critically, this uses the SAME basis `putInternal` writes from
1253
1230
  * (the in-memory cache in eager mode; lru-then-adapter in lazy) — NOT a fresh
1254
1231
  * store read — so `baseVersion`/`version` match the version actually written.
1255
1232
  * A separate store read would diverge once another tab has advanced the shared
1256
- * store past this tab's cache, breaking #228c conflict detection.
1233
+ * store past this tab's cache, breaking cross-tab conflict detection.
1257
1234
  */
1258
1235
  async #priorForHook(id) {
1259
1236
  if (this.lazy && this.lru) {
@@ -1275,52 +1252,28 @@ var Collection = class {
1275
1252
  if (!hasWritePermission(this.keyring, this.name)) {
1276
1253
  throw new ReadOnlyError();
1277
1254
  }
1278
- if (this.guardSource) {
1279
- const registry = this.guardSource.registry();
1280
- const guards = registry.guardsFor(this.name);
1281
- if (guards.length > 0) {
1282
- const existingEnv = await this.adapter.get(this.vault, this.name, id);
1283
- let existingRecord = null;
1284
- if (existingEnv) {
1285
- try {
1286
- existingRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
1287
- } catch {
1288
- existingRecord = null;
1289
- }
1290
- }
1291
- const incomingRecord = record;
1292
- const ctx = {
1293
- existing: existingRecord,
1294
- vault: this.guardSource.readOnlyVault(),
1295
- userId: this.keyring.userId,
1296
- role: this.keyring.role
1297
- };
1298
- if (registry.isAmendmentActive()) {
1299
- const vBefore = existingEnv?._v ?? 0;
1300
- registry.collectChange(this.name, id, existingRecord, incomingRecord, vBefore, vBefore + 1);
1301
- } else {
1302
- await registry.runChecks(this.name, incomingRecord, ctx);
1303
- const { GuardExecutor } = await import("./executor-BZKFZVRC.js");
1304
- for (const g of guards) {
1305
- await GuardExecutor.checkFrozenFields(g, id, existingRecord, incomingRecord);
1306
- }
1307
- }
1308
- }
1309
- }
1310
- if (this.periodGuard !== void 0) {
1255
+ if (this.subsystemBus?.hasGateHandlers("beforePut")) {
1311
1256
  const existingEnv = await this.adapter.get(this.vault, this.name, id);
1312
- let priorRecord = null;
1257
+ let existingRecord = null;
1313
1258
  if (existingEnv) {
1314
1259
  try {
1315
- priorRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
1260
+ existingRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
1316
1261
  } catch {
1317
- priorRecord = null;
1262
+ existingRecord = null;
1318
1263
  }
1319
1264
  }
1320
- await this.periodGuard(
1321
- existingEnv ? { ts: existingEnv._ts, record: priorRecord } : null,
1322
- record
1323
- );
1265
+ await this.subsystemBus.dispatchGate("beforePut", {
1266
+ op: existingEnv ? "update" : "create",
1267
+ vault: this.vault,
1268
+ collection: this.name,
1269
+ docId: id,
1270
+ incoming: record,
1271
+ existing: existingRecord,
1272
+ existingVersion: existingEnv?._v ?? 0,
1273
+ existingTs: existingEnv?._ts,
1274
+ userId: this.keyring.userId,
1275
+ role: this.keyring.role
1276
+ });
1324
1277
  }
1325
1278
  if (this.schema !== void 0) {
1326
1279
  record = await validateSchemaInput(this.schema, record, `put(${id})`);
@@ -1506,7 +1459,7 @@ var Collection = class {
1506
1459
  * Fire registered MV strategies whose dependency set includes this
1507
1460
  * collection. Eager-mode MVs re-materialize inline via
1508
1461
  * `MaterializedViewExecutor.refresh`; lazy / manual modes are
1509
- * no-ops in the foundation (subtask #150) wired in #151.
1462
+ * no-ops in the foundation; wired in the lazy-mode implementation.
1510
1463
  *
1511
1464
  * Skips entirely when the record being written is itself an
1512
1465
  * MV-emitted row (carries `_materializedFrom`) — defensive guard
@@ -1529,7 +1482,7 @@ var Collection = class {
1529
1482
  if (mode === "eager") {
1530
1483
  if (executor === null) {
1531
1484
  ;
1532
- ({ MaterializedViewExecutor: executor } = await import("./executor-KT2IOZVP.js"));
1485
+ ({ MaterializedViewExecutor: executor } = await import("./executor-RWICJI7J.js"));
1533
1486
  }
1534
1487
  await executor.refresh(reg, {
1535
1488
  getCollection: (name) => this.materializedViewSource.getCollection(name),
@@ -1538,7 +1491,7 @@ var Collection = class {
1538
1491
  });
1539
1492
  } else if (mode === "lazy") {
1540
1493
  if (staleHelpers === null) {
1541
- staleHelpers = await import("./stale-PAGCS4K5.js");
1494
+ staleHelpers = await import("./stale-74WGLVZ2.js");
1542
1495
  }
1543
1496
  staleHelpers.markMVStale(registry, reg.spec.name);
1544
1497
  }
@@ -1567,7 +1520,7 @@ var Collection = class {
1567
1520
  const mode = typeof spec.lifecycle === "string" ? spec.lifecycle : spec.lifecycle.mode;
1568
1521
  if (mode === "eager") {
1569
1522
  if (DerivationExecutor === null) {
1570
- ({ DerivationExecutor } = await import("./executor-GFZFDQXV.js"));
1523
+ ({ DerivationExecutor } = await import("./executor-SOLEQVUB.js"));
1571
1524
  }
1572
1525
  const sourceWithId = { ...incoming, id };
1573
1526
  const ctx = { vault: this.derivationSource.getReadOnlyFacade() };
@@ -1586,7 +1539,7 @@ var Collection = class {
1586
1539
  const outputCollection = this.derivationSource.getCollection(outSpec.collection);
1587
1540
  const txCtx = this.derivationSource.getActiveTxContext();
1588
1541
  if (out.kind === "array") {
1589
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-NRBWSLRK.js");
1542
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-EVICRM46.js");
1590
1543
  const prior = await loadFanoutSidecar(
1591
1544
  this.adapter,
1592
1545
  this.vault,
@@ -1650,13 +1603,15 @@ var Collection = class {
1650
1603
  }
1651
1604
  /**
1652
1605
  * Delete a record by ID. Runs inside the hub's write-queue tracker
1653
- * (#227) so `hub.writeQueue.pending` reflects this write.
1606
+ * so `hub.writeQueue.pending` reflects this write.
1654
1607
  */
1655
1608
  async delete(id) {
1656
1609
  await this.schemaUpdateGate?.assertWritable();
1657
1610
  await this.schemaFence?.assertWritable(this.name);
1611
+ const hooksActive = this.#hooksActive();
1612
+ const busAfterDelete = (this.subsystemBus?.hasHandlers("afterDelete") ?? false) && !(this.subsystemBus?.dispatching ?? false);
1658
1613
  let event;
1659
- if (this.#hooksActive()) {
1614
+ if (hooksActive || busAfterDelete) {
1660
1615
  const prior = await this.#priorForHook(id);
1661
1616
  event = {
1662
1617
  op: "delete",
@@ -1671,14 +1626,17 @@ var Collection = class {
1671
1626
  baseVersion: prior.version,
1672
1627
  version: prior.version + 1
1673
1628
  };
1674
- await this.writeHooks.runBefore(event);
1629
+ if (hooksActive) await this.writeHooks.runBefore(event);
1675
1630
  }
1676
1631
  if (this.writeQueue) await this.writeQueue.track(() => this.deleteInternal(id));
1677
1632
  else await this.deleteInternal(id);
1678
- if (event) await this.writeHooks.runAfter(event);
1633
+ if (event) {
1634
+ if (hooksActive) await this.writeHooks.runAfter(event);
1635
+ if (busAfterDelete) await this.subsystemBus.dispatch("afterDelete", event);
1636
+ }
1679
1637
  }
1680
1638
  /**
1681
- * @internal #232 — bulk-rewrite every record through a cutover transform.
1639
+ * @internal — bulk-rewrite every record through a cutover transform.
1682
1640
  * Raw adapter path (bypasses the write gate + guards — the transform is
1683
1641
  * trusted and runs only during the `migrating` phase). Bumps each
1684
1642
  * record's `_v` and appends a ledger `op:'migration'` entry.
@@ -1717,8 +1675,7 @@ var Collection = class {
1717
1675
  }
1718
1676
  /**
1719
1677
  * @internal — system-internal delete that bypasses user-facing
1720
- * delete hooks (`onDelete`, accounting-period guard, FK ref
1721
- * enforcer). Used by derivation tombstones (#144) and MV refresh
1678
+ * delete hooks (`onDelete`, FK ref enforcer). Used by derivation tombstones and MV refresh
1722
1679
  * (Dim 14 v2) — system housekeeping shouldn't trip user invariants
1723
1680
  * registered against the output collection. The ledger entry and
1724
1681
  * history snapshot still fire so backup integrity and time-travel
@@ -1730,7 +1687,7 @@ var Collection = class {
1730
1687
  *
1731
1688
  * When a `txCtx` is supplied, the prior envelope is captured and
1732
1689
  * pushed onto `txCtx._executed` BEFORE the delete fires — mirrors
1733
- * the #133 rollback hardening for puts. Callers outside a
1690
+ * the rollback hardening for puts. Callers outside a
1734
1691
  * multi-record transaction pass `null` and skip the tracking.
1735
1692
  *
1736
1693
  * Amendment composition: if `_internalDelete` runs while a vault's
@@ -1773,58 +1730,27 @@ var Collection = class {
1773
1730
  if (!hasWritePermission(this.keyring, this.name)) {
1774
1731
  throw new ReadOnlyError();
1775
1732
  }
1776
- if (this.guardSource) {
1777
- const registry = this.guardSource.registry();
1778
- const guards = registry.guardsFor(this.name);
1779
- if (guards.length > 0) {
1780
- const existingEnv = await this.adapter.get(this.vault, this.name, id);
1781
- if (existingEnv) {
1782
- let existingRecord = null;
1783
- try {
1784
- existingRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
1785
- } catch {
1786
- existingRecord = null;
1787
- }
1788
- if (registry.isAmendmentActive()) {
1789
- const vBefore = existingEnv._v;
1790
- registry.collectChange(
1791
- this.name,
1792
- id,
1793
- existingRecord,
1794
- null,
1795
- vBefore,
1796
- vBefore
1797
- );
1798
- } else if (!internal) {
1799
- const ctx = {
1800
- existing: existingRecord,
1801
- vault: this.guardSource.readOnlyVault(),
1802
- userId: this.keyring.userId,
1803
- role: this.keyring.role
1804
- };
1805
- await registry.runOnDelete(
1806
- this.name,
1807
- existingRecord ?? {},
1808
- ctx
1809
- );
1810
- }
1811
- }
1812
- }
1813
- }
1814
- if (!internal && this.periodGuard !== void 0) {
1733
+ if (this.subsystemBus?.hasGateHandlers("beforeDelete")) {
1815
1734
  const existingEnv = await this.adapter.get(this.vault, this.name, id);
1816
- let priorRecord = null;
1817
1735
  if (existingEnv) {
1736
+ let existingRecord = null;
1818
1737
  try {
1819
- priorRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
1738
+ existingRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
1820
1739
  } catch {
1821
- priorRecord = null;
1740
+ existingRecord = null;
1822
1741
  }
1742
+ await this.subsystemBus.dispatchGate("beforeDelete", {
1743
+ vault: this.vault,
1744
+ collection: this.name,
1745
+ docId: id,
1746
+ existing: existingRecord,
1747
+ existingVersion: existingEnv._v,
1748
+ existingTs: existingEnv._ts,
1749
+ internal,
1750
+ userId: this.keyring.userId,
1751
+ role: this.keyring.role
1752
+ });
1823
1753
  }
1824
- await this.periodGuard(
1825
- existingEnv ? { ts: existingEnv._ts, record: priorRecord } : null,
1826
- null
1827
- );
1828
1754
  }
1829
1755
  if (!internal && this.refEnforcer !== void 0) {
1830
1756
  await this.refEnforcer.enforceRefsOnDelete(this.name, id);
@@ -1885,7 +1811,7 @@ var Collection = class {
1885
1811
  }
1886
1812
  /**
1887
1813
  * Cascade deletes of array-shape derived rows when a source row is
1888
- * deleted (#200). Reads each registered strategy's fanout sidecar
1814
+ * deleted. Reads each registered strategy's fanout sidecar
1889
1815
  * for this source id, deletes every listed derived row, then
1890
1816
  * deletes the sidecar itself.
1891
1817
  *
@@ -1905,7 +1831,7 @@ var Collection = class {
1905
1831
  for (const [outputKey, outSpec] of Object.entries(spec.outputs)) {
1906
1832
  if (outSpec.shape !== "array") continue;
1907
1833
  if (helpers === null) {
1908
- helpers = await import("./fanout-sidecar-NRBWSLRK.js");
1834
+ helpers = await import("./fanout-sidecar-EVICRM46.js");
1909
1835
  }
1910
1836
  const sidecar = await helpers.loadFanoutSidecar(
1911
1837
  this.adapter,
@@ -1924,8 +1850,8 @@ var Collection = class {
1924
1850
  }
1925
1851
  }
1926
1852
  /**
1927
- * Mirror of {@link dispatchMaterializedViews} for the delete path
1928
- * (#181). No record content is available (it's gone), so the
1853
+ * Mirror of {@link dispatchMaterializedViews} for the delete path.
1854
+ * No record content is available (it's gone), so the
1929
1855
  * `_materializedFrom` skip used by the put-side dispatch doesn't
1930
1856
  * apply here — instead, the recursion guard is the `internal` gate
1931
1857
  * at the `_doDelete` call site above.
@@ -1945,7 +1871,7 @@ var Collection = class {
1945
1871
  if (mode === "eager") {
1946
1872
  if (executor === null) {
1947
1873
  ;
1948
- ({ MaterializedViewExecutor: executor } = await import("./executor-KT2IOZVP.js"));
1874
+ ({ MaterializedViewExecutor: executor } = await import("./executor-RWICJI7J.js"));
1949
1875
  }
1950
1876
  await executor.refresh(reg, {
1951
1877
  getCollection: (name) => this.materializedViewSource.getCollection(name),
@@ -1954,7 +1880,7 @@ var Collection = class {
1954
1880
  });
1955
1881
  } else if (mode === "lazy") {
1956
1882
  if (staleHelpers === null) {
1957
- staleHelpers = await import("./stale-PAGCS4K5.js");
1883
+ staleHelpers = await import("./stale-74WGLVZ2.js");
1958
1884
  }
1959
1885
  staleHelpers.markMVStale(registry, reg.spec.name);
1960
1886
  }
@@ -1977,7 +1903,7 @@ var Collection = class {
1977
1903
  );
1978
1904
  }
1979
1905
  if (this.materializedViewSource !== void 0) {
1980
- const { resolveStaleMVOnRead } = await import("./stale-PAGCS4K5.js");
1906
+ const { resolveStaleMVOnRead } = await import("./stale-74WGLVZ2.js");
1981
1907
  await resolveStaleMVOnRead(this.materializedViewSource, this.name);
1982
1908
  }
1983
1909
  await this.ensureHydrated();
@@ -2455,7 +2381,7 @@ var Collection = class {
2455
2381
  * .aggregate({ total: sum('amount'), n: count() })
2456
2382
  * ```
2457
2383
  *
2458
- * **Lazy-MV gap (#157):** `scan()` is synchronous-build and does
2384
+ * **Lazy-MV gap:** `scan()` is synchronous-build and does
2459
2385
  * NOT trigger lazy materialized-view resolve-on-read. For lazy
2460
2386
  * MVs, call `list()` (which DOES resolve) or `vault.refreshView(name)`
2461
2387
  * before scanning. Same shape as the `query()` limitation.
@@ -2536,7 +2462,7 @@ var Collection = class {
2536
2462
  this.indexes?.upsert(id, record, previous ? previous.record : null);
2537
2463
  }
2538
2464
  /**
2539
- * #228b — apply a peer tab's committed write to THIS tab's in-memory view:
2465
+ * Apply a peer tab's committed write to THIS tab's in-memory view:
2540
2466
  * re-read the (already-persisted) envelope from the shared store + refresh
2541
2467
  * cache/indexes, then emit a `change` event so reactive consumers re-render.
2542
2468
  * Never writes to the store and never fires write hooks, so it cannot loop.
@@ -2545,7 +2471,7 @@ var Collection = class {
2545
2471
  await this._invalidateCacheEntry(id);
2546
2472
  this.emitter.emit("change", { vault: this.vault, collection: this.name, id, action });
2547
2473
  }
2548
- /** @internal #228c — the current in-memory record without a store read (for conflict capture). */
2474
+ /** @internal — the current in-memory record without a store read (for conflict capture). */
2549
2475
  _peekCached(id) {
2550
2476
  const entry = this.lazy && this.lru ? this.lru.get(id) : this.cache.get(id);
2551
2477
  return entry ? entry.record : null;
@@ -3648,7 +3574,7 @@ var UserApi = class {
3648
3574
  * the envelope on first call. Optimistic-concurrency safe — a stale
3649
3575
  * `_v` (parallel writer on another device) throws `ConflictError`.
3650
3576
  *
3651
- * Patch semantics (#57):
3577
+ * Patch semantics:
3652
3578
  * - `undefined` (or omitted key) — skip; existing value preserved
3653
3579
  * - `null` — delete the field from the merged result
3654
3580
  * - any other value — overwrite (deep-merge for plain objects,
@@ -3704,7 +3630,7 @@ var UserApi = class {
3704
3630
  this.fireChange(this.writerKeyringId, written);
3705
3631
  return written;
3706
3632
  }
3707
- // ─── Visibility (#122) ───────────────────────────────────────────────
3633
+ // ─── Visibility ──────────────────────────────────────────────────────
3708
3634
  /**
3709
3635
  * Read the current user's visibility flag from
3710
3636
  * `_meta/visibility/<keyringId>`. Returns `{ hidden: false }` when no
@@ -4554,23 +4480,23 @@ var Vault = class {
4554
4480
  * `null` for vaults that never register any guard strategy. The
4555
4481
  * runtime class is dynamic-imported on demand so consumers that
4556
4482
  * never use guards don't pull `GuardRegistry`/`GuardExecutor` into
4557
- * their bundle (#130).
4483
+ * their bundle.
4558
4484
  */
4559
4485
  guardRegistry = null;
4560
4486
  /**
4561
4487
  * Per-vault derivation registry. Same lazy-load contract as
4562
4488
  * `guardRegistry` — `null` until `_initDerivations()` runs with at
4563
- * least one strategy handle. See #130 for the bundle motivation.
4489
+ * least one strategy handle.
4564
4490
  */
4565
4491
  derivationRegistry = null;
4566
4492
  /**
4567
- * Per-vault materialized-view registry (#143/#150). Same lazy-load
4493
+ * Per-vault materialized-view registry. Same lazy-load
4568
4494
  * contract as `derivationRegistry` — `null` until
4569
4495
  * `_initMaterializedViews()` runs with at least one MV handle.
4570
4496
  */
4571
4497
  materializedViewRegistry = null;
4572
4498
  /**
4573
- * Per-vault overlay registry (#154). Same lazy-load contract as
4499
+ * Per-vault overlay registry. Same lazy-load contract as
4574
4500
  * `materializedViewRegistry` — `null` until `_initOverlayedViews()`
4575
4501
  * runs with at least one handle.
4576
4502
  */
@@ -4591,7 +4517,7 @@ var Vault = class {
4591
4517
  * target this vault session's keyringId. There is no method to write
4592
4518
  * another principal's envelope (own-only write rule, structural).
4593
4519
  * - Read-anyone: `get(keyringId)`, `list()` — read other principals'
4594
- * envelopes, subject to the `view-team-profiles` policy gate (#22).
4520
+ * envelopes, subject to the `view-team-profiles` policy gate.
4595
4521
  * - Reactive: `subscribe(id, cb)`, `live(id)` — fire on local writes.
4596
4522
  *
4597
4523
  * @see docs/superpowers/specs/2026-05-05-user-envelope-design.md
@@ -4611,12 +4537,12 @@ var Vault = class {
4611
4537
  */
4612
4538
  reloadKeyring;
4613
4539
  collectionCache = /* @__PURE__ */ new Map();
4614
- /** #232 — vault-level schema cutover fence/controller. */
4540
+ /** Vault-level schema cutover fence/controller. */
4615
4541
  schemaFence;
4616
- /** #232 — per-client heartbeat/watcher; started lazily on cutover registration. */
4542
+ /** Per-client heartbeat/watcher; started lazily on cutover registration. */
4617
4543
  #fenceWatcher;
4618
4544
  #fenceCoordinationStarted = false;
4619
- /** #229 — per-collection registered schema-update strategy names. */
4545
+ /** Per-collection registered schema-update strategy names. */
4620
4546
  #schemaUpdateNames = /* @__PURE__ */ new Map();
4621
4547
  /**
4622
4548
  * per-collection `blobFields` retention/TTL config.
@@ -4690,8 +4616,7 @@ var Vault = class {
4690
4616
  * Cache of closed/opened accounting periods.
4691
4617
  * Populated on first `closePeriod` / `openPeriod` / `listPeriods` /
4692
4618
  * per-collection write call. Kept in memory as an ordered list (by
4693
- * `closedAt`) so the `periodGuard` hook runs synchronously against
4694
- * each collection's put/delete path.
4619
+ * `closedAt`) so period checks run fast when the gate bus fires.
4695
4620
  *
4696
4621
  * Sentinel `null` means "not yet loaded" — the first consumer
4697
4622
  * triggers a one-time `loadPeriods()` pass. Every subsequent
@@ -4886,6 +4811,7 @@ var Vault = class {
4886
4811
  emitter: this.emitter,
4887
4812
  writeQueue: this.noydb._writeQueueTracker,
4888
4813
  writeHooks: this.noydb._writeHooks,
4814
+ subsystemBus: this.noydb._subsystemBus,
4889
4815
  activeTxId: () => this.noydb._activeTxContextOrNull?.txId ?? null,
4890
4816
  schemaUpdateGate,
4891
4817
  schemaFence: this.schemaFence,
@@ -4908,18 +4834,12 @@ var Vault = class {
4908
4834
  defaultLocale: this.locale,
4909
4835
  onRegisterConflictResolver: this.onRegisterConflictResolver,
4910
4836
  onAccess: (op, id) => this._logConsent(op, collectionName, id),
4911
- periodGuard: (existing, incoming) => this._assertTsWritable(existing, incoming),
4912
- // Guard / derivation sources are only wired when the
4913
- // corresponding registry has been initialised. Vaults without
4914
- // guards/derivations skip this entirely so `Collection.put`'s
4915
- // `if (this.guardSource)` / `if (this.derivationSource)`
4916
- // branches no-op without ever touching the subsystem code.
4917
- ...this.guardRegistry !== null ? {
4918
- guardSource: {
4919
- registry: () => this.guardRegistry,
4920
- readOnlyVault: () => this._ensureReadOnlyFacade()
4921
- }
4922
- } : {},
4837
+ // Derivation source is only wired when the corresponding registry
4838
+ // has been initialised. Guard source was removed in Track A slice 3b
4839
+ // guards now run via the gate bus in Noydb.#registerGuardGate.
4840
+ // Vaults without derivations skip this so `Collection.put`'s
4841
+ // `if (this.derivationSource)` branch no-ops without touching the
4842
+ // derivation subsystem code.
4923
4843
  ...this.derivationRegistry !== null ? {
4924
4844
  derivationSource: {
4925
4845
  registry: () => this.derivationRegistry,
@@ -5009,7 +4929,7 @@ var Vault = class {
5009
4929
  await Promise.allSettled(pending);
5010
4930
  }
5011
4931
  /**
5012
- * Run a coordinated schema cutover (#232). Drains pending writes, waits
4932
+ * Run a coordinated schema cutover. Drains pending writes, waits
5013
4933
  * for the active client set to quiesce (the ack-barrier), applies every
5014
4934
  * pending collection transform in bulk, bumps the vault schema generation,
5015
4935
  * and clears the fence. Returns the count of collections migrated.
@@ -5027,9 +4947,9 @@ var Vault = class {
5027
4947
  await coll._applyCutoverTransform(transform);
5028
4948
  }
5029
4949
  /**
5030
- * #228b — refresh a loaded collection's view of one document from a peer
4950
+ * Refresh a loaded collection's view of one document from a peer
5031
4951
  * tab's broadcast. No-op when the collection isn't loaded in this tab
5032
- * (it will read fresh on next open). Mirrors #runCutoverTransform's guard.
4952
+ * (it will read fresh on next open). Mirrors `#runCutoverTransform`'s guard.
5033
4953
  */
5034
4954
  async _applyRemoteWrite(collectionName, docId, action) {
5035
4955
  const coll = this.collectionCache.get(collectionName);
@@ -5037,9 +4957,9 @@ var Vault = class {
5037
4957
  await coll._applyRemoteChange(docId, action);
5038
4958
  }
5039
4959
  /**
5040
- * #228c — for a detected conflict: capture this tab's clobbered record,
4960
+ * For a detected conflict: capture this tab's clobbered record,
5041
4961
  * read the common ancestor from history, converge the cache to the store's
5042
- * authoritative value (the (b) re-read), and return all three for the
4962
+ * authoritative value (the re-read), and return all three for the
5043
4963
  * WriteConflict payload. Returns null when the collection isn't loaded.
5044
4964
  */
5045
4965
  async _captureAndConverge(collectionName, docId, action, baseV) {
@@ -5056,15 +4976,15 @@ var Vault = class {
5056
4976
  const remote = await coll.get(docId);
5057
4977
  return { local, remote, base };
5058
4978
  }
5059
- /** Recover a stuck cutover fence (#232) — reset to normal without bumping. */
4979
+ /** Recover a stuck cutover fence — reset to normal without bumping. */
5060
4980
  async abortSchemaCutover() {
5061
4981
  await this.schemaFence.abort();
5062
4982
  }
5063
- /** Current schema-cutover fence state for this vault (#232/#233). Thin live read. */
4983
+ /** Current schema-cutover fence state for this vault. Thin live read. */
5064
4984
  async schemaFenceState() {
5065
4985
  return loadFence(this.adapter, this.name);
5066
4986
  }
5067
- /** @internal Start the per-client heartbeat + fence watcher once a cutover is registered (#232). */
4987
+ /** @internal Start the per-client heartbeat + fence watcher once a cutover is registered. */
5068
4988
  _ensureFenceCoordination() {
5069
4989
  if (this.#fenceCoordinationStarted) return;
5070
4990
  this.#fenceCoordinationStarted = true;
@@ -5414,12 +5334,12 @@ var Vault = class {
5414
5334
  if (!fieldSchema) {
5415
5335
  throw new AttestationError(`issueAttestation: collection '${collectionName}' has no attestation field-schema. Declare it via vault.collection('${collectionName}', { attestation: { fields: [...] } }).`);
5416
5336
  }
5417
- const { issueAttestationCore } = await import("./issue-BAJ7ZB4S.js");
5337
+ const { issueAttestationCore } = await import("./issue-IODMTPME.js");
5418
5338
  const out = await issueAttestationCore(this.makeIssueContext(), { collection: collectionName, id, fieldSchema });
5419
5339
  return { docId: out.docId, qr: out.qr, keyId: out.keyId, publicKeyB64: out.publicKeyB64 };
5420
5340
  }
5421
5341
  async getDocumentSigningPublicKey() {
5422
- const { loadSigner, loadOrCreateSigner } = await import("./signer-M4K5HBLD.js");
5342
+ const { loadSigner, loadOrCreateSigner } = await import("./signer-WGDJNWSU.js");
5423
5343
  const existing = await loadSigner(this.adapter, this.name, this.getDEK);
5424
5344
  if (existing) return { keyId: existing.keyId, publicKeyB64: existing.publicKeyB64 };
5425
5345
  if (this.keyring.role !== "owner") {
@@ -5445,19 +5365,19 @@ var Vault = class {
5445
5365
  };
5446
5366
  }
5447
5367
  async revokeAttestation(docId) {
5448
- const { revokeDocCore } = await import("./revoke-7JOVLZFD.js");
5368
+ const { revokeDocCore } = await import("./revoke-R5NIQ74J.js");
5449
5369
  await revokeDocCore(this.makeRevokeContext(), docId);
5450
5370
  }
5451
5371
  async unrevokeAttestation(docId) {
5452
- const { unrevokeDocCore } = await import("./revoke-7JOVLZFD.js");
5372
+ const { unrevokeDocCore } = await import("./revoke-R5NIQ74J.js");
5453
5373
  await unrevokeDocCore(this.makeRevokeContext(), docId);
5454
5374
  }
5455
5375
  async getRevokedDocIds() {
5456
- const { getRevokedDocIdsCore } = await import("./revoke-7JOVLZFD.js");
5376
+ const { getRevokedDocIdsCore } = await import("./revoke-R5NIQ74J.js");
5457
5377
  return getRevokedDocIdsCore(this.makeRevokeContext());
5458
5378
  }
5459
5379
  async publishRevocationList() {
5460
- const { publishRevocationListCore } = await import("./revoke-7JOVLZFD.js");
5380
+ const { publishRevocationListCore } = await import("./revoke-R5NIQ74J.js");
5461
5381
  return publishRevocationListCore(this.makeRevokeContext());
5462
5382
  }
5463
5383
  makeRevokeContext() {
@@ -5737,7 +5657,7 @@ var Vault = class {
5737
5657
  * Dynamic-imports `GuardRegistry` + `ReadOnlyVaultFacade` and seeds
5738
5658
  * the registry with the supplied strategy handles. No-op when the
5739
5659
  * handles array is empty — keeps the guard subsystem out of the
5740
- * floor bundle for consumers that don't use guards (#130).
5660
+ * floor bundle for consumers that don't use guards.
5741
5661
  *
5742
5662
  * The read-only facade is eagerly instantiated here so the sync
5743
5663
  * accessor `_getReadOnlyFacade()` (called from the tx amendment
@@ -5746,7 +5666,7 @@ var Vault = class {
5746
5666
  async _initGuards(handles) {
5747
5667
  if (handles.length === 0) return;
5748
5668
  const [{ GuardRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
5749
- import("./registry-2IEARCGT.js"),
5669
+ import("./registry-DKEXOJVO.js"),
5750
5670
  import("./read-only-facade-ITU6L7BL.js")
5751
5671
  ]);
5752
5672
  const registry = new GuardRegistry();
@@ -5755,10 +5675,9 @@ var Vault = class {
5755
5675
  this.readOnlyFacade = new ReadOnlyVaultFacade(this);
5756
5676
  }
5757
5677
  /**
5758
- * @internal — Collection.put calls into this. Returns `null` for
5759
- * vaults that never registered any guard strategy. Callers MUST
5760
- * gate on null (the existing `if (this.guardSource)` branches in
5761
- * `Collection` already do this transitively).
5678
+ * @internal — The gate handler in Noydb.#registerGuardGate calls into
5679
+ * this. Returns `null` for vaults that never registered any guard
5680
+ * strategy. Callers MUST gate on null.
5762
5681
  */
5763
5682
  _getGuardRegistry() {
5764
5683
  return this.guardRegistry;
@@ -5769,13 +5688,13 @@ var Vault = class {
5769
5688
  * derivation strategies (async because `strategyHash` computation
5770
5689
  * goes through `crypto.subtle.digest`). No-op when the handles
5771
5690
  * array is empty — keeps the derivation subsystem out of the floor
5772
- * bundle for consumers that don't use derivations (#130). Throws
5691
+ * bundle for consumers that don't use derivations. Throws
5773
5692
  * `DerivationCycleError` if a cycle is detected after registration.
5774
5693
  */
5775
5694
  async _initDerivations(handles) {
5776
5695
  if (handles.length === 0) return;
5777
5696
  const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
5778
- import("./registry-EMGLZGR6.js"),
5697
+ import("./registry-446I2NMN.js"),
5779
5698
  import("./read-only-facade-ITU6L7BL.js")
5780
5699
  ]);
5781
5700
  const registry = new DerivationRegistry();
@@ -5801,12 +5720,12 @@ var Vault = class {
5801
5720
  * MV spec (which invokes its `query()` once for dependency
5802
5721
  * analysis), then runs the unified cycle detection across the MV +
5803
5722
  * derivation graphs. No-op when the handles array is empty — keeps
5804
- * the MV subsystem out of the floor bundle (mirrors v1 #130).
5723
+ * the MV subsystem out of the floor bundle (mirrors the derivation lazy-import pattern).
5805
5724
  * Throws `MaterializedViewCycleError` if a cycle is detected.
5806
5725
  */
5807
5726
  async _initMaterializedViews(handles) {
5808
5727
  if (handles.length === 0) return;
5809
- const { MaterializedViewRegistry } = await import("./registry-CDHASH73.js");
5728
+ const { MaterializedViewRegistry } = await import("./registry-4NEW7LQY.js");
5810
5729
  const registry = new MaterializedViewRegistry();
5811
5730
  this.materializedViewRegistry = registry;
5812
5731
  const db = this;
@@ -5830,7 +5749,7 @@ var Vault = class {
5830
5749
  */
5831
5750
  async _initOverlayedViews(handles) {
5832
5751
  if (handles.length === 0) return;
5833
- const { OverlayedViewRegistry } = await import("./registry-NQALYR77.js");
5752
+ const { OverlayedViewRegistry } = await import("./registry-524KJZG4.js");
5834
5753
  const registry = new OverlayedViewRegistry();
5835
5754
  const mvRegistry = this.materializedViewRegistry;
5836
5755
  const overlayNames = /* @__PURE__ */ new Set();
@@ -5858,13 +5777,13 @@ var Vault = class {
5858
5777
  return this.overlayedViewRegistry;
5859
5778
  }
5860
5779
  /**
5861
- * Manual re-materialize for a single registered MV (#151). Useful
5780
+ * Manual re-materialize for a single registered MV. Useful
5862
5781
  * for `refresh: 'manual'` MVs (whose consumer drives refreshes
5863
5782
  * externally), for stale-bit recovery on vault re-open, and as the
5864
5783
  * explicit bulk-recompute escape hatch after a strategy change.
5865
5784
  *
5866
- * Returns `{ written, deleted, failed }`. `deleted` is always 0 in
5867
- * foundation + this sub-issue — tombstoning lands in #152.
5785
+ * Returns `{ written, deleted, failed }`. `deleted` is always 0
5786
+ * when tombstoning is not enabled.
5868
5787
  *
5869
5788
  * Throws if `name` is not a registered MV.
5870
5789
  */
@@ -5877,13 +5796,13 @@ var Vault = class {
5877
5796
  if (!reg) {
5878
5797
  throw new Error(`refreshView: no MV registered with name "${name}"`);
5879
5798
  }
5880
- const { MaterializedViewExecutor } = await import("./executor-KT2IOZVP.js");
5799
+ const { MaterializedViewExecutor } = await import("./executor-RWICJI7J.js");
5881
5800
  const result = await MaterializedViewExecutor.refresh(reg, {
5882
5801
  getCollection: (n) => this.collection(n),
5883
5802
  getActiveTxContext: () => this.noydb._activeTxContextOrNull,
5884
5803
  getQueryContext: () => this
5885
5804
  });
5886
- const { clearMVStale } = await import("./stale-PAGCS4K5.js");
5805
+ const { clearMVStale } = await import("./stale-74WGLVZ2.js");
5887
5806
  clearMVStale(registry, name);
5888
5807
  return result;
5889
5808
  }
@@ -5899,7 +5818,7 @@ var Vault = class {
5899
5818
  if (registry === null) return { derived: 0, failed: 0 };
5900
5819
  const strategies = registry.strategiesForSource(sourceCollection);
5901
5820
  if (strategies.length === 0) return { derived: 0, failed: 0 };
5902
- const { DerivationExecutor } = await import("./executor-GFZFDQXV.js");
5821
+ const { DerivationExecutor } = await import("./executor-SOLEQVUB.js");
5903
5822
  const sourceColl = this.collection(sourceCollection);
5904
5823
  const records = await sourceColl.list();
5905
5824
  const ctx = { vault: this.readOnlyFacade ?? new (await import("./read-only-facade-ITU6L7BL.js")).ReadOnlyVaultFacade(this) };
@@ -5924,7 +5843,7 @@ var Vault = class {
5924
5843
  if (!outSpec) continue;
5925
5844
  const outputColl = this.collection(outSpec.collection);
5926
5845
  if (out.kind === "array") {
5927
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-NRBWSLRK.js");
5846
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-EVICRM46.js");
5928
5847
  const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key);
5929
5848
  const prevKeys = new Set(prior?.keys ?? []);
5930
5849
  const newKeysList = out.entries.map((e) => e.key);
@@ -5960,22 +5879,19 @@ var Vault = class {
5960
5879
  /**
5961
5880
  * @internal — exposed for `runTransaction({ amendment: true })` so
5962
5881
  * the amendment invariant runner can pass the SAME read-only vault
5963
- * facade that the per-record `Collection.put` guard hook uses
5964
- * (`guardSource.readOnlyVault()` above). Eagerly instantiated by
5965
- * `_initGuards()` so this accessor stays synchronous; returns
5966
- * `null` for vaults that never registered any guard (amendments
5967
- * require at least one guard, so the caller should never see null).
5882
+ * facade that the gate handler in Noydb.#registerGuardGate uses.
5883
+ * Eagerly instantiated by `_initGuards()` so this accessor stays
5884
+ * synchronous; returns `null` for vaults that never registered any
5885
+ * guard (amendments require at least one guard, so the caller should
5886
+ * never see null).
5968
5887
  */
5969
5888
  _getReadOnlyFacade() {
5970
5889
  return this.readOnlyFacade;
5971
5890
  }
5972
5891
  /**
5973
- * Internal lazy-allocator for the read-only facade. Used by the
5974
- * per-collection `guardSource.readOnlyVault` callback when guards
5975
- * ARE configured but `_initGuards()` raced with the first guard
5976
- * invocation (theoretically impossible — `Noydb.openVault` awaits
5977
- * `_initGuards` before returning — but we keep the defensive lazy
5978
- * path so the closure's contract stays "always returns a facade").
5892
+ * Internal lazy-allocator for the read-only facade. Used as a
5893
+ * defensive fallback; in practice `_initGuards()` eagerly
5894
+ * instantiates this, so the lazy path is a no-op.
5979
5895
  */
5980
5896
  _ensureReadOnlyFacade() {
5981
5897
  if (this.readOnlyFacade !== null) return this.readOnlyFacade;
@@ -6148,7 +6064,7 @@ var Vault = class {
6148
6064
  * collection.
6149
6065
  */
6150
6066
  async delegate(opts) {
6151
- const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-QSC7G5QC.js");
6067
+ const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-42LO4WFO.js");
6152
6068
  if (!this.keyring.kek) {
6153
6069
  throw new ValidationError(
6154
6070
  "issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (passphrase) first."
@@ -6170,7 +6086,7 @@ var Vault = class {
6170
6086
  * if the id does not exist.
6171
6087
  */
6172
6088
  async revokeDelegation(id) {
6173
- const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-QSC7G5QC.js");
6089
+ const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-42LO4WFO.js");
6174
6090
  await revokeDelegation(this.adapter, this.name, id);
6175
6091
  void DELEGATIONS_COLLECTION;
6176
6092
  }
@@ -6430,7 +6346,7 @@ var Vault = class {
6430
6346
  const all = await this._loadPeriodsCache();
6431
6347
  return all.find((p) => p.name === name) ?? null;
6432
6348
  }
6433
- /** @internal — periodGuard callback installed on every Collection. */
6349
+ /** @internal — called by the gate bus before put/delete. */
6434
6350
  async _assertTsWritable(existing, incoming) {
6435
6351
  if (existing === null && incoming === null) return;
6436
6352
  if (this.periodCache === null) {
@@ -6518,7 +6434,7 @@ var Vault = class {
6518
6434
  return dumpVaultSchema(this, opts);
6519
6435
  }
6520
6436
  /**
6521
- * Lightweight read of the vault's registered schema (#229): collections
6437
+ * Lightweight read of the vault's registered schema: collections
6522
6438
  * (+ doc counts), guards, materialized views, schema-update strategies,
6523
6439
  * and the unlocked user's grants. Cheap — one `adapter.list` per
6524
6440
  * collection, no decryption. For a full snapshot + stats use dumpSchema().
@@ -6639,7 +6555,7 @@ var Vault = class {
6639
6555
  * @see docs/subsystems/public-envelope.md
6640
6556
  */
6641
6557
  async getPublicEnvelope(opts = {}) {
6642
- const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-OHQ5UZFM.js");
6558
+ const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-YKHKP74C.js");
6643
6559
  return readPublicEnvelope2(this.adapter, this.name, opts);
6644
6560
  }
6645
6561
  /**
@@ -7305,6 +7221,110 @@ var WriteHookRegistry = class {
7305
7221
  }
7306
7222
  };
7307
7223
 
7224
+ // src/subsystem-bus.ts
7225
+ var SubsystemBus = class {
7226
+ #handlers = /* @__PURE__ */ new Map();
7227
+ #gateHandlers = /* @__PURE__ */ new Map();
7228
+ #depth = 0;
7229
+ /** Register a handler for an observe point. Returns an unsubscribe fn. */
7230
+ register(point, handler) {
7231
+ let arr = this.#handlers.get(point);
7232
+ if (!arr) {
7233
+ arr = [];
7234
+ this.#handlers.set(point, arr);
7235
+ }
7236
+ arr.push(handler);
7237
+ return () => {
7238
+ const a = this.#handlers.get(point);
7239
+ if (!a) return;
7240
+ const i = a.indexOf(handler);
7241
+ if (i >= 0) a.splice(i, 1);
7242
+ };
7243
+ }
7244
+ /** Cheap gate for the write path — true when any handler is registered for the point. */
7245
+ hasHandlers(point) {
7246
+ const a = this.#handlers.get(point);
7247
+ return a !== void 0 && a.length > 0;
7248
+ }
7249
+ /**
7250
+ * True while one or more dispatches are in flight. Backed by a depth counter
7251
+ * so that two concurrent async dispatches (`Promise.all([put('a'), put('b')])`
7252
+ * each captured `busAfterPut=true` at their respective put() tops while depth
7253
+ * was 0) both proceed independently — the counter stays > 0 until BOTH finish,
7254
+ * so any nested write attempted by a handler still sees `dispatching === true`
7255
+ * and is suppressed by the write-path gate in `collection.ts`
7256
+ * (`busAfterPut = hasHandlers('afterPut') && !dispatching`). Re-entrancy
7257
+ * suppression lives exclusively on that write-path gate; concurrent independent
7258
+ * dispatches must not drop each other's events.
7259
+ */
7260
+ get dispatching() {
7261
+ return this.#depth > 0;
7262
+ }
7263
+ /**
7264
+ * Dispatch in registration order, awaited. Per-handler errors are warned, not
7265
+ * thrown — an observe handler must never abort a completed write. A
7266
+ * re-entrancy guard suppresses nested firing so a handler that itself writes
7267
+ * cannot loop (same rationale as WriteHookRegistry.#suppressed).
7268
+ */
7269
+ async dispatch(point, event) {
7270
+ const a = this.#handlers.get(point);
7271
+ if (!a || a.length === 0) return;
7272
+ this.#depth++;
7273
+ try {
7274
+ for (const h of a.slice()) {
7275
+ try {
7276
+ await h(event);
7277
+ } catch (err) {
7278
+ console.warn(
7279
+ `[noy-db] subsystem observe handler failed at ${point}: ` + (err instanceof Error ? err.message : String(err))
7280
+ );
7281
+ }
7282
+ }
7283
+ } finally {
7284
+ this.#depth--;
7285
+ }
7286
+ }
7287
+ /** Register a write-gating handler. A throw from the handler ABORTS the write. Returns an unsubscribe fn. */
7288
+ registerGate(point, handler) {
7289
+ let arr = this.#gateHandlers.get(point);
7290
+ if (!arr) {
7291
+ arr = [];
7292
+ this.#gateHandlers.set(point, arr);
7293
+ }
7294
+ arr.push(handler);
7295
+ return () => {
7296
+ const a = this.#gateHandlers.get(point);
7297
+ if (!a) return;
7298
+ const i = a.indexOf(handler);
7299
+ if (i >= 0) a.splice(i, 1);
7300
+ };
7301
+ }
7302
+ /** Cheap gate for the write path — true when any gate handler is registered for the point. */
7303
+ hasGateHandlers(point) {
7304
+ const a = this.#gateHandlers.get(point);
7305
+ return a !== void 0 && a.length > 0;
7306
+ }
7307
+ /**
7308
+ * Run gate handlers in registration order, awaited. Unlike `dispatch`
7309
+ * (observe), a handler throw is NOT swallowed — it PROPAGATES, aborting the
7310
+ * write before it reaches the store. The first throw stops the remaining
7311
+ * handlers (fail-fast). This is the seam guards/periods migrate onto.
7312
+ *
7313
+ * Note: gate handlers are validators that read, not write. A gate handler
7314
+ * that writes back into the same collection would re-enter the write path
7315
+ * and re-dispatch this point; loop-suppression for that case is deferred to
7316
+ * the migration slice (contract: gate handlers must not perform writes that
7317
+ * re-trigger their own point).
7318
+ */
7319
+ async dispatchGate(point, event) {
7320
+ const a = this.#gateHandlers.get(point);
7321
+ if (!a || a.length === 0) return;
7322
+ for (const h of a.slice()) {
7323
+ await h(event);
7324
+ }
7325
+ }
7326
+ };
7327
+
7308
7328
  // src/tab-coordination.ts
7309
7329
  var TabCoordinator = class {
7310
7330
  tabId;
@@ -7661,9 +7681,9 @@ var PERSONAL_POLICY = Object.freeze({
7661
7681
  minTier: 1,
7662
7682
  enabled: true
7663
7683
  },
7664
- // rotate-recovery (#121): deliberate paper-sheet regeneration
7665
- // when the user remembers their passphrase. PERSONAL matches the
7666
- // pre-#121 low-level flow's bar — knowing the passphrase is enough.
7684
+ // rotate-recovery: deliberate paper-sheet regeneration
7685
+ // when the user remembers their passphrase. PERSONAL allows tier-1 —
7686
+ // knowing the passphrase is enough.
7667
7687
  "rotate-recovery": { minTier: 1 },
7668
7688
  "enroll-authenticator": { minTier: 1 },
7669
7689
  "remove-authenticator": { minTier: 1 },
@@ -7697,7 +7717,7 @@ var PERSONAL_POLICY = Object.freeze({
7697
7717
  minTier: 1,
7698
7718
  enabled: false
7699
7719
  },
7700
- // ─── User envelope gates (#22) ────────────────────────────────────
7720
+ // ─── User envelope gates ──────────────────────────────────────────
7701
7721
  // edit-own-profile: tier 3 floor — any active session can edit their
7702
7722
  // own profile/preferences. Tightening to require a TOTP for
7703
7723
  // profile changes is a one-line override.
@@ -7724,7 +7744,7 @@ var STRICT_POLICY = Object.freeze({
7724
7744
  minTier: 1,
7725
7745
  enabled: true
7726
7746
  },
7727
- // rotate-recovery (#121): STRICT requires an off-device factor —
7747
+ // rotate-recovery: STRICT requires an off-device factor —
7728
7748
  // rotating recovery is an off-site-trust event; a stolen unlocked
7729
7749
  // laptop must not be able to silently mint a new sheet for the
7730
7750
  // attacker. Matches the `peer-recover-user` STRICT default.
@@ -7797,7 +7817,7 @@ var STRICT_POLICY = Object.freeze({
7797
7817
  minTier: 1,
7798
7818
  enabled: false
7799
7819
  },
7800
- // ─── User envelope gates (#22) ────────────────────────────────────
7820
+ // ─── User envelope gates ──────────────────────────────────────────
7801
7821
  // STRICT: profile edits require a TOTP/email-OTP factor (typical
7802
7822
  // shared-workstation hardening — your name/avatar shouldn't change
7803
7823
  // without a fresh second-factor proof).
@@ -7908,13 +7928,14 @@ var Noydb = class {
7908
7928
  emitter = new NoydbEventEmitter();
7909
7929
  writeQueueTracker = new WriteQueueTracker();
7910
7930
  writeHooks = new WriteHookRegistry();
7931
+ subsystemBus = new SubsystemBus();
7911
7932
  clientId = generateULID();
7912
7933
  vaultCache = /* @__PURE__ */ new Map();
7913
7934
  keyringCache = /* @__PURE__ */ new Map();
7914
7935
  syncEngines = /* @__PURE__ */ new Map();
7915
7936
  /**
7916
7937
  * Per-vault active session tier — defaults to `1` after a passphrase
7917
- * unlock; tier-2 / tier-3 unlocks (issue #11) downgrade it. Used by
7938
+ * unlock; tier-2 / tier-3 unlocks downgrade it. Used by
7918
7939
  * {@link checkGate} to evaluate `gate.minTier`.
7919
7940
  */
7920
7941
  activeTier = /* @__PURE__ */ new Map();
@@ -7924,14 +7945,14 @@ var Noydb = class {
7924
7945
  */
7925
7946
  policyCache = /* @__PURE__ */ new Map();
7926
7947
  /**
7927
- * One-shot bypass for the managed-mode strong-recovery check (#195).
7948
+ * One-shot bypass for the managed-mode strong-recovery check.
7928
7949
  * Set true by {@link openVaultAndEnrollRecovery} for the duration of
7929
7950
  * the bootstrap window so the keyring can be created before the
7930
7951
  * strong recovery is enrolled. Always cleared (try/finally).
7931
7952
  * @internal
7932
7953
  */
7933
7954
  _skipNextManagedRecoveryCheck = false;
7934
- /** Per-vault tier-3 (PIN / quick-resume) state — issue #11. */
7955
+ /** Per-vault tier-3 (PIN / quick-resume) state. */
7935
7956
  quickUnlock = new QuickUnlockStore();
7936
7957
  /**
7937
7958
  * Resolved public-envelope schema. Lazily computed once from
@@ -7941,9 +7962,9 @@ var Noydb = class {
7941
7962
  publicEnvelopeSchema;
7942
7963
  closed = false;
7943
7964
  sessionTimer = null;
7944
- /** Same-device multi-tab coordinator (#228); created on `enableTabCoordination()`. */
7965
+ /** Same-device multi-tab coordinator; created on `enableTabCoordination()`. */
7945
7966
  tabCoordinator;
7946
- /** Cross-tab write relay (#228b); created on `enableTabCoordination()`. */
7967
+ /** Cross-tab write relay; created on `enableTabCoordination()`. */
7947
7968
  writeRelay;
7948
7969
  /** Per-vault policy enforcers. */
7949
7970
  policyEnforcers = /* @__PURE__ */ new Map();
@@ -7956,8 +7977,8 @@ var Noydb = class {
7956
7977
  * the same function's `finally` block. Side-effect writes triggered
7957
7978
  * during a staged op's `Collection.put` (today: eager derivation
7958
7979
  * outputs) register their pre-write envelope on `_executed` here so
7959
- * a mid-batch failure rolls them back alongside the main staged ops
7960
- * (#133). `null` outside of Phase 2.
7980
+ * a mid-batch failure rolls them back alongside the main staged ops.
7981
+ * `null` outside of Phase 2.
7961
7982
  * @internal
7962
7983
  */
7963
7984
  _activeTxContext = null;
@@ -7978,8 +7999,95 @@ var Noydb = class {
7978
7999
  if (options.sessionPolicy) {
7979
8000
  this.sessionStrategy.validateSessionPolicy(options.sessionPolicy);
7980
8001
  }
8002
+ this.#registerGuardGate();
8003
+ this.#registerPeriodGate();
7981
8004
  this.resetSessionTimer();
7982
8005
  }
8006
+ // Track A — guards migration. Registers record-lock / field-freeze / onDelete
8007
+ // / amendment-collect as gate-bus handlers (only when guards are opted in, so
8008
+ // the write path is zero-cost otherwise). Resolves the live vault's
8009
+ // GuardRegistry per dispatch. Registered BEFORE the period gate so guard
8010
+ // checks run first. The amendment branch is a side-effect (collectChange),
8011
+ // NOT a throw — and runs even for internal deletes (an amendment invariant
8012
+ // must see system housekeeping tombstones); onDelete/checks run only for
8013
+ // user (non-internal) operations.
8014
+ #registerGuardGate() {
8015
+ if (this.options.guardStrategies === void 0) return;
8016
+ this.subsystemBus.registerGate("beforePut", async (e) => {
8017
+ const v = this.vaultCache.get(e.vault);
8018
+ if (!v) return;
8019
+ const registry = v._getGuardRegistry();
8020
+ if (!registry) return;
8021
+ const guards = registry.guardsFor(e.collection);
8022
+ if (guards.length === 0) return;
8023
+ const existing = e.existing ?? null;
8024
+ const incoming = e.incoming;
8025
+ if (registry.isAmendmentActive()) {
8026
+ registry.collectChange(e.collection, e.docId, existing, incoming, e.existingVersion, e.existingVersion + 1);
8027
+ return;
8028
+ }
8029
+ const facade = v._getReadOnlyFacade();
8030
+ if (!facade) return;
8031
+ const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
8032
+ await registry.runChecks(e.collection, incoming, ctx);
8033
+ const { GuardExecutor } = await import("./executor-AWCHQ2KN.js");
8034
+ for (const g of guards) {
8035
+ await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming);
8036
+ }
8037
+ });
8038
+ this.subsystemBus.registerGate("beforeDelete", async (e) => {
8039
+ const v = this.vaultCache.get(e.vault);
8040
+ if (!v) return;
8041
+ const registry = v._getGuardRegistry();
8042
+ if (!registry) return;
8043
+ const guards = registry.guardsFor(e.collection);
8044
+ if (guards.length === 0) return;
8045
+ const existing = e.existing ?? null;
8046
+ if (registry.isAmendmentActive()) {
8047
+ registry.collectChange(e.collection, e.docId, existing, null, e.existingVersion, e.existingVersion);
8048
+ return;
8049
+ }
8050
+ if (e.internal) return;
8051
+ const facade = v._getReadOnlyFacade();
8052
+ if (!facade) return;
8053
+ const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
8054
+ await registry.runOnDelete(e.collection, existing ?? {}, ctx);
8055
+ });
8056
+ }
8057
+ /**
8058
+ * Register closed-period write guards on the subsystem bus when a
8059
+ * periodsStrategy is configured. Handlers resolve the live Vault from
8060
+ * vaultCache so they always use the up-to-date period cache.
8061
+ */
8062
+ // Track A — periods migration. Registers the closed-period write guard as a
8063
+ // gate-bus handler (only when periods is opted in, so the write path is
8064
+ // zero-cost otherwise). Each handler resolves the LIVE vault from the cache
8065
+ // per dispatch and delegates to its `_assertTsWritable`, which owns all
8066
+ // period logic. Resolving the live vault makes eviction/re-creation
8067
+ // transparent. Semantics note: if a write reaches the gate through a retained
8068
+ // collection handle whose vault has been evicted from `vaultCache` (e.g. a
8069
+ // post-revocation write on a stale handle), the period check is skipped — the
8070
+ // guard binds to the live vault, not a captured instance. Periods is a
8071
+ // write-integrity guard, not a security boundary, and a re-open reloads the
8072
+ // period cache; the trade-off is intentional.
8073
+ #registerPeriodGate() {
8074
+ if (this.options.periodsStrategy === void 0) return;
8075
+ this.subsystemBus.registerGate("beforePut", async (e) => {
8076
+ const v = this.vaultCache.get(e.vault);
8077
+ if (!v) return;
8078
+ const existing = e.op === "create" ? null : { ts: e.existingTs ?? null, record: e.existing ?? null };
8079
+ await v._assertTsWritable(existing, e.incoming);
8080
+ });
8081
+ this.subsystemBus.registerGate("beforeDelete", async (e) => {
8082
+ if (e.internal) return;
8083
+ const v = this.vaultCache.get(e.vault);
8084
+ if (!v) return;
8085
+ await v._assertTsWritable(
8086
+ { ts: e.existingTs ?? null, record: e.existing ?? null },
8087
+ null
8088
+ );
8089
+ });
8090
+ }
7983
8091
  resetSessionTimer() {
7984
8092
  if (this.sessionTimer) clearTimeout(this.sessionTimer);
7985
8093
  const idleMs = this.options.sessionPolicy?.idleTimeoutMs ?? this.options.sessionTimeout;
@@ -8269,8 +8377,6 @@ var Noydb = class {
8269
8377
  * @throws `NoAccessError` when no keyring exists for the target.
8270
8378
  * @throws `PermissionDeniedError` when the role hierarchy rejects.
8271
8379
  * @throws `ValidationError` when no field is provided.
8272
- *
8273
- * @see #54
8274
8380
  */
8275
8381
  async updateUser(vault, options, factors) {
8276
8382
  await this.checkGate(vault, "update-user", factors);
@@ -8606,7 +8712,7 @@ var Noydb = class {
8606
8712
  * Phase 2. `Collection.dispatchDerivations` consults this so a
8607
8713
  * recursive derived-output write inside `Collection.put` can register
8608
8714
  * its envelope onto `ctx._executed` and roll back with the main
8609
- * staged ops on mid-batch failure (#133).
8715
+ * staged ops on mid-batch failure.
8610
8716
  *
8611
8717
  * @internal
8612
8718
  */
@@ -8635,7 +8741,7 @@ var Noydb = class {
8635
8741
  * `Collection.putManyAtomic` (via `derivationSource.createTxContext`)
8636
8742
  * to publish an active context for the duration of its bulk-atomic
8637
8743
  * Phase 2 loop, so recursive derivation-output writes register on
8638
- * `ctx._executed` and roll back together with the source ops (#133).
8744
+ * `ctx._executed` and roll back together with the source ops.
8639
8745
  *
8640
8746
  * @internal
8641
8747
  */
@@ -8706,26 +8812,26 @@ var Noydb = class {
8706
8812
  return this.writeQueueTracker;
8707
8813
  }
8708
8814
  /**
8709
- * Register a hook that runs before each write (#230). Awaited; a throw
8815
+ * Register a hook that runs before each write. Awaited; a throw
8710
8816
  * aborts the write. Returns an unsubscribe function.
8711
8817
  */
8712
8818
  onBeforeWrite(handler) {
8713
8819
  return this.writeHooks.onBeforeWrite(handler);
8714
8820
  }
8715
8821
  /**
8716
- * Register a hook that runs after each committed write (#230). Awaited;
8822
+ * Register a hook that runs after each committed write. Awaited;
8717
8823
  * a handler error is warned, never rolled back. Returns an unsubscribe fn.
8718
8824
  */
8719
8825
  onAfterWrite(handler) {
8720
8826
  return this.writeHooks.onAfterWrite(handler);
8721
8827
  }
8722
- /** Subscribe to cross-tab write conflicts (#228c). Returns an unsubscribe. */
8828
+ /** Subscribe to cross-tab write conflicts. Returns an unsubscribe. */
8723
8829
  onWriteConflict(fn) {
8724
8830
  this.on("write:conflict", fn);
8725
8831
  return () => this.off("write:conflict", fn);
8726
8832
  }
8727
8833
  /**
8728
- * Enable same-device multi-tab coordination (#228): primary/secondary
8834
+ * Enable same-device multi-tab coordination: primary/secondary
8729
8835
  * election + presence. Browser-only — a graceful no-op (role 'unknown')
8730
8836
  * when Web Locks / BroadcastChannel are unavailable and nothing is
8731
8837
  * injected. Idempotent; returns a disposer.
@@ -8808,7 +8914,11 @@ var Noydb = class {
8808
8914
  get _writeHooks() {
8809
8915
  return this.writeHooks;
8810
8916
  }
8811
- /** @internal Stable per-instance id for schema-cutover coordination (#232). */
8917
+ /** @internal The observe bus, threaded into every Collection. */
8918
+ get _subsystemBus() {
8919
+ return this.subsystemBus;
8920
+ }
8921
+ /** @internal Stable per-instance id for schema-cutover coordination. */
8812
8922
  get _clientId() {
8813
8923
  return this.clientId;
8814
8924
  }
@@ -8828,10 +8938,6 @@ var Noydb = class {
8828
8938
  * survives lock; nothing about it changes when DEKs are scrubbed).
8829
8939
  *
8830
8940
  * No-op when `vault` is not currently in cache (idempotent).
8831
- *
8832
- * Unblocks vLannaAi/niwat#33.
8833
- *
8834
- * @see #17
8835
8941
  */
8836
8942
  lockVault(vault) {
8837
8943
  this.syncEngines.get(vault)?.stopAutoSync();
@@ -8946,7 +9052,7 @@ var Noydb = class {
8946
9052
  return merged;
8947
9053
  }
8948
9054
  /**
8949
- * Read the current vault-level user-directory toggle (#122). Returns
9055
+ * Read the current vault-level user-directory toggle. Returns
8950
9056
  * the default-on shape (`{ enabled: true }`) when no `_meta/directory`
8951
9057
  * document has been persisted yet.
8952
9058
  *
@@ -8958,7 +9064,7 @@ var Noydb = class {
8958
9064
  return persisted?.enabled ?? true;
8959
9065
  }
8960
9066
  /**
8961
- * Toggle the vault's user-directory listing on or off (#122).
9067
+ * Toggle the vault's user-directory listing on or off.
8962
9068
  * Owner-only. When disabled, `listUsersWithEnvelopes()` throws
8963
9069
  * {@link import('./errors.js').DirectoryDisabledError} for callers
8964
9070
  * whose role is neither `owner` nor `admin`.
@@ -9018,7 +9124,7 @@ var Noydb = class {
9018
9124
  *
9019
9125
  * Two enforcement modes:
9020
9126
  *
9021
- * 1. **Managed-mode mandatory strong-recovery (#195).** When
9127
+ * 1. **Managed-mode mandatory strong-recovery.** When
9022
9128
  * `passphraseMode === 'managed'`, the vault MUST have at least
9023
9129
  * one **strong** recovery profile (Shamir today). Paper alone is
9024
9130
  * rejected because under managed mode the user has no memorized
@@ -9052,14 +9158,14 @@ var Noydb = class {
9052
9158
  throw new RecoveryNotEnrolledError();
9053
9159
  }
9054
9160
  /**
9055
- * Internal accessor used by tier-2/tier-3 unlock paths (issue #11)
9161
+ * Internal accessor used by tier-2/tier-3 unlock paths
9056
9162
  * to mark the active session tier.
9057
9163
  * @internal
9058
9164
  */
9059
9165
  _setActiveTier(vault, tier) {
9060
9166
  this.activeTier.set(vault, tier);
9061
9167
  }
9062
- // ─── Tier-2 enroll / remove (issue #11) ────────────────────────
9168
+ // ─── Tier-2 enroll / remove ─────────────────────────────────────
9063
9169
  /**
9064
9170
  * Add a tier-2 authenticator slot to the calling user's keyring.
9065
9171
  * Each slot independently wraps the SAME KEK under a method-specific
@@ -9089,7 +9195,7 @@ var Noydb = class {
9089
9195
  const next = await removeAuthenticator(this.options.store, vault, keyring, slotId);
9090
9196
  this.keyringCache.set(vault, next);
9091
9197
  }
9092
- /** Read the slot list for a vault. Internal — `describeAuthConfig` (#13) consumes this. */
9198
+ /** Read the slot list for a vault. Internal — `describeAuthConfig` consumes this. */
9093
9199
  async listAuthenticators(vault) {
9094
9200
  const keyring = await this.getKeyringInternal(vault);
9095
9201
  return keyring.authenticators;
@@ -9101,7 +9207,7 @@ var Noydb = class {
9101
9207
  * are immutable through this method. Anti-slot-swap is structural,
9102
9208
  * not gate-driven.
9103
9209
  *
9104
- * `meta` patch semantics (#57-aligned):
9210
+ * `meta` patch semantics (top-level merge):
9105
9211
  * - Top-level merge — absent keys preserved
9106
9212
  * - `null` value — delete that meta key
9107
9213
  * - Other values — replace verbatim
@@ -9119,8 +9225,6 @@ var Noydb = class {
9119
9225
  *
9120
9226
  * @throws `NoAccessError` when no slot with the given id exists.
9121
9227
  * @throws `ValidationError` when no patch field is provided.
9122
- *
9123
- * @see #55
9124
9228
  */
9125
9229
  async updateAuthenticator(vault, slotId, options, factors) {
9126
9230
  await this.checkGate(vault, "update-authenticator", factors);
@@ -9129,7 +9233,7 @@ var Noydb = class {
9129
9233
  this.keyringCache.set(vault, next);
9130
9234
  }
9131
9235
  /**
9132
- * Native WebAuthn enrollment using the **real** internal keyring (#16).
9236
+ * Native WebAuthn enrollment using the **real** internal keyring.
9133
9237
  *
9134
9238
  * Why this exists: when a consumer is using `createNoydb({ secret })`,
9135
9239
  * they cannot reach the live `UnlockedKeyring` to feed it to
@@ -9172,8 +9276,6 @@ var Noydb = class {
9172
9276
  * a server-side allowlist).
9173
9277
  *
9174
9278
  * Gated by `enroll-authenticator` like `enrollAuthenticator()` itself.
9175
- *
9176
- * @see #16
9177
9279
  */
9178
9280
  async enrollWebAuthn(vault, ceremony, factors) {
9179
9281
  await this.checkGate(vault, "enroll-authenticator", factors);
@@ -9200,8 +9302,6 @@ var Noydb = class {
9200
9302
  * deciding when a new device prompt should appear. Identity is
9201
9303
  * `id` + `enrolled_at`; the `meta.credentialId` (base64) is used by
9202
9304
  * `allowCredentials` at unlock time.
9203
- *
9204
- * @see #16
9205
9305
  */
9206
9306
  async listWebAuthnSlots(vault) {
9207
9307
  const keyring = await this.getKeyringInternal(vault);
@@ -9283,7 +9383,7 @@ var Noydb = class {
9283
9383
  async getPublicEnvelope(vault, opts = {}) {
9284
9384
  return readPublicEnvelope(this.options.store, vault, opts);
9285
9385
  }
9286
- // ─── Auth introspection (issue #13) ────────────────────────────
9386
+ // ─── Auth introspection ─────────────────────────────────────────
9287
9387
  /** English summary of the configured auth model. */
9288
9388
  async describeAuthConfig(vault) {
9289
9389
  return describeAuthConfig(this.options.store, vault);
@@ -9306,7 +9406,7 @@ var Noydb = class {
9306
9406
  await this.checkGate(vault, "view-user-auth", factors);
9307
9407
  return describeAllUsersAuth(this.options.store, vault);
9308
9408
  }
9309
- // ─── Tier-1 change flows (issue #10) ───────────────────────────
9409
+ // ─── Tier-1 change flows ────────────────────────────────────────
9310
9410
  /**
9311
9411
  * Rotate the user's passphrase (user remembers old). Validates the
9312
9412
  * new phrase against the configured `passphrase` policy, runs the
@@ -9314,8 +9414,7 @@ var Noydb = class {
9314
9414
  *
9315
9415
  * Tier-2 authenticator slots are dropped — each slot wraps the old
9316
9416
  * KEK and would need its derivation key to be re-presented. Re-enrol
9317
- * via `db.enrollAuthenticator` after rotation. Tracked as a
9318
- * v0.1.0-pre.5 limitation.
9417
+ * via `db.enrollAuthenticator` after rotation.
9319
9418
  *
9320
9419
  * @throws `WeakPassphraseError` on a weak new phrase.
9321
9420
  * @throws `PolicyDeniedError` when the gate denies (missing factor, …).
@@ -9337,8 +9436,8 @@ var Noydb = class {
9337
9436
  }
9338
9437
  /**
9339
9438
  * Reset the passphrase using a recovery proof (user forgot the old).
9340
- * v0.1.0-pre.5 supports the `'paper'` profile end-to-end; the
9341
- * other three profiles throw {@link RecoveryProfileNotImplementedError}.
9439
+ * Currently supports the `'paper'` profile end-to-end; the
9440
+ * other profiles throw {@link RecoveryProfileNotImplementedError}.
9342
9441
  *
9343
9442
  * Burns the used recovery entry on success.
9344
9443
  */
@@ -9367,7 +9466,7 @@ var Noydb = class {
9367
9466
  return { newCodes: codes };
9368
9467
  }
9369
9468
  /**
9370
- * Deliberate paper-recovery-code regeneration (#121). User knows their
9469
+ * Deliberate paper-recovery-code regeneration. User knows their
9371
9470
  * passphrase but wants a fresh sheet — they lost the printout or
9372
9471
  * suspect compromise of the off-site copy.
9373
9472
  *
@@ -9377,7 +9476,7 @@ var Noydb = class {
9377
9476
  *
9378
9477
  * Gated by the `rotate-recovery` policy gate:
9379
9478
  * - PERSONAL_POLICY: `{ minTier: 1 }` — knowing the passphrase
9380
- * suffices, matching the pre-#121 low-level flow's bar.
9479
+ * suffices, matching the lower-level flow's bar.
9381
9480
  * - STRICT_POLICY: `{ minTier: 1, factors: [{ anyOf: ['totp',
9382
9481
  * 'email-otp', 'webauthn-roaming'] }] }` — rotation is an
9383
9482
  * off-site-trust event; require an off-device factor so a
@@ -9482,7 +9581,7 @@ var Noydb = class {
9482
9581
  return { newShares: shareStrings, entryId: targetEntryId };
9483
9582
  }
9484
9583
  /**
9485
- * **Atomic create-and-enroll for managed-mode vaults (#195).**
9584
+ * **Atomic create-and-enroll for managed-mode vaults.**
9486
9585
  *
9487
9586
  * Bootstraps a managed-mode vault and enrolls strong recovery in
9488
9587
  * a single ceremony. Under `passphraseMode: 'managed'`, every
@@ -9553,7 +9652,7 @@ var Noydb = class {
9553
9652
  return { vault: vaultHandle, recoveryEnrollments };
9554
9653
  }
9555
9654
  /**
9556
- * **Recovery flow under managed-passphrase mode (#195).**
9655
+ * **Recovery flow under managed-passphrase mode.**
9557
9656
  *
9558
9657
  * Replaces the sealed passphrase of a managed-mode vault with a
9559
9658
  * fresh 256-bit random, sealed under the configured
@@ -9570,7 +9669,7 @@ var Noydb = class {
9570
9669
  * 5. Drop the keyring cache so the next operation re-derives.
9571
9670
  *
9572
9671
  * The vault's strong-recovery enrollment is preserved across
9573
- * recovery (Shamir entries are not burned on use — see #196).
9672
+ * recovery (Shamir entries are not burned on use).
9574
9673
  *
9575
9674
  * @throws ValidationError if the Noydb instance is not in managed mode.
9576
9675
  */
@@ -9618,7 +9717,7 @@ var Noydb = class {
9618
9717
  }
9619
9718
  /**
9620
9719
  * Atomic peer-recovery — re-wraps an EXISTING user's keyring under
9621
- * a fresh temp passphrase in a single store write. Closes #34's
9720
+ * a fresh temp passphrase in a single store write. Closes the
9622
9721
  * partial-failure window (the previous compose-from-primitives
9623
9722
  * pattern was `db.revoke + db.grant`, two writes — if the issuer
9624
9723
  * cancelled between them the target was locked out entirely).
@@ -9628,7 +9727,7 @@ var Noydb = class {
9628
9727
  * - Same `userId`, role, permissions, capabilities preserved.
9629
9728
  * - DEKs unchanged → every other principal in the vault keeps
9630
9729
  * access. No key rotation.
9631
- * - Allows owner→owner natively (#33). The existing
9730
+ * - Allows owner→owner natively. The existing
9632
9731
  * `db.revoke` retains its block — peer-recovery is a separate,
9633
9732
  * intentionally-named operation.
9634
9733
  * - Tier-2 slots dropped (they wrap the old KEK).
@@ -9657,7 +9756,6 @@ var Noydb = class {
9657
9756
  * @throws `PrivilegeEscalationError` when the caller lacks a DEK
9658
9757
  * the target previously had access to.
9659
9758
  *
9660
- * @see #33 #34 — the issues this method closes.
9661
9759
  */
9662
9760
  async recoverUser(vault, options, factors) {
9663
9761
  await this.checkGate(vault, "peer-recover-user", factors);
@@ -9668,7 +9766,7 @@ var Noydb = class {
9668
9766
  }
9669
9767
  }
9670
9768
  /**
9671
- * Persist a recovery enrollment. v0.1.0-pre.5 accepts the `'paper'`
9769
+ * Persist a recovery enrollment. Accepts the `'paper'`
9672
9770
  * profile.
9673
9771
  *
9674
9772
  * The hub wraps the user's DEK set (not the KEK) under a code-derived
@@ -9688,7 +9786,7 @@ var Noydb = class {
9688
9786
  * showCodesToUser(codes)
9689
9787
  * ```
9690
9788
  *
9691
- * As of pre.8, `@noy-db/on-recovery`'s `generateRecoveryCodeSet`
9789
+ * `@noy-db/on-recovery`'s `generateRecoveryCodeSet`
9692
9790
  * delegates to `mintPaperRecoveryEntry` internally — its output is
9693
9791
  * fed directly to this API. Pick whichever fits your code-gen layer:
9694
9792
  *
@@ -9728,13 +9826,13 @@ var Noydb = class {
9728
9826
  "#196"
9729
9827
  );
9730
9828
  }
9731
- /** Read the persisted recovery entries (paper + Shamir). Used by `describeAuthConfig` (#13). */
9829
+ /** Read the persisted recovery entries (paper + Shamir). Used by `describeAuthConfig`. */
9732
9830
  async listRecoveryEntries(vault) {
9733
9831
  const paper = await loadPaperRecoveryEntries(this.options.store, vault);
9734
9832
  const shamir = await loadShamirRecoveryEntries(this.options.store, vault);
9735
9833
  return { paper, shamir };
9736
9834
  }
9737
- // ─── Tier-3 enroll / unlock (issue #11) ────────────────────────
9835
+ // ─── Tier-3 enroll / unlock ─────────────────────────────────────
9738
9836
  /**
9739
9837
  * Register a tier-3 quick-unlock state for the vault. The state is
9740
9838
  * an opaque blob produced by `@noy-db/on-pin/enrollPin` (or any
@@ -9770,11 +9868,11 @@ var Noydb = class {
9770
9868
  this.quickUnlock.delete(vault);
9771
9869
  }
9772
9870
  /**
9773
- * Public accessor for the unlocked keyring of a vault — issue #28.
9871
+ * Public accessor for the unlocked keyring of a vault.
9774
9872
  *
9775
9873
  * Returns a **defensive shallow copy** so consumers can read the DEK
9776
9874
  * map and authenticator list without the risk of mutating the hub's
9777
- * internal cache (#88). Internal hub code paths use a live reference
9875
+ * internal cache. Internal hub code paths use a live reference
9778
9876
  * via `getKeyringInternal`; ceremonies and external consumers always
9779
9877
  * get a snapshot.
9780
9878
  *
@@ -9957,4 +10055,4 @@ export {
9957
10055
  Noydb,
9958
10056
  createNoydb
9959
10057
  };
9960
- //# sourceMappingURL=chunk-T6HQMVML.js.map
10058
+ //# sourceMappingURL=chunk-BT7544RM.js.map