@noy-db/hub 0.2.0-pre.17 → 0.2.0-pre.19

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 (301) hide show
  1. package/dist/aggregate/index.cjs +227 -3
  2. package/dist/aggregate/index.cjs.map +1 -1
  3. package/dist/aggregate/index.d.cts +3 -3
  4. package/dist/aggregate/index.d.ts +3 -3
  5. package/dist/aggregate/index.js +5 -4
  6. package/dist/aggregate/index.js.map +1 -1
  7. package/dist/attestation/index.cjs.map +1 -1
  8. package/dist/attestation/index.d.cts +5 -5
  9. package/dist/attestation/index.d.ts +5 -5
  10. package/dist/attestation/index.js +6 -6
  11. package/dist/blobs/index.cjs +4 -10
  12. package/dist/blobs/index.cjs.map +1 -1
  13. package/dist/blobs/index.d.cts +6 -6
  14. package/dist/blobs/index.d.ts +6 -6
  15. package/dist/blobs/index.js +6 -6
  16. package/dist/bundle/index.cjs +1587 -392
  17. package/dist/bundle/index.cjs.map +1 -1
  18. package/dist/bundle/index.d.cts +7 -7
  19. package/dist/bundle/index.d.ts +7 -7
  20. package/dist/bundle/index.js +10 -10
  21. package/dist/{chunk-NBBMMJ2H.js → chunk-3FSMVWBN.js} +4 -4
  22. package/dist/{chunk-HGVSHKZW.js → chunk-3Q2AOPLT.js} +100 -29
  23. package/dist/chunk-3Q2AOPLT.js.map +1 -0
  24. package/dist/{chunk-SHX5QBCI.js → chunk-4ULLGYPA.js} +3 -3
  25. package/dist/{chunk-CD2AVTEM.js → chunk-5IGWRMEC.js} +5 -5
  26. package/dist/{chunk-QO6RGLLD.js → chunk-6KESZO5D.js} +35 -7
  27. package/dist/chunk-6KESZO5D.js.map +1 -0
  28. package/dist/{chunk-GP3SDSH2.js → chunk-6OSOE6BY.js} +15 -2
  29. package/dist/chunk-6OSOE6BY.js.map +1 -0
  30. package/dist/{chunk-F4G63NTZ.js → chunk-7C6VFNIY.js} +2 -2
  31. package/dist/{chunk-XJV6OB4D.js → chunk-7HD67R6U.js} +2 -2
  32. package/dist/{chunk-UMLVJTYV.js → chunk-ADB7GPM3.js} +7 -4
  33. package/dist/chunk-ADB7GPM3.js.map +1 -0
  34. package/dist/{chunk-NYSYPFXJ.js → chunk-B6E5IRPJ.js} +3 -3
  35. package/dist/chunk-CYNTFU2D.js +129 -0
  36. package/dist/chunk-CYNTFU2D.js.map +1 -0
  37. package/dist/{chunk-ZEGSDPB7.js → chunk-DJF3FXW5.js} +35 -1
  38. package/dist/chunk-DJF3FXW5.js.map +1 -0
  39. package/dist/{chunk-3G3W65EQ.js → chunk-DY3EOJEN.js} +2 -2
  40. package/dist/{chunk-YYVZYTWW.js → chunk-E66DSTJP.js} +3 -3
  41. package/dist/{chunk-5LIROIDM.js → chunk-FBLAWK6A.js} +2 -2
  42. package/dist/{chunk-E77UKJYL.js → chunk-FPHRTW2Z.js} +5 -5
  43. package/dist/{state-vault-W2OEABNO.js → chunk-G4PYA575.js} +24 -7
  44. package/dist/chunk-G4PYA575.js.map +1 -0
  45. package/dist/{chunk-U5QCMH3W.js → chunk-GKQAU52M.js} +4 -4
  46. package/dist/{chunk-2FU2FTXD.js → chunk-GYAWXHFO.js} +2 -2
  47. package/dist/{chunk-ROPJVUG3.js → chunk-H42KZXNV.js} +5 -210
  48. package/dist/chunk-H42KZXNV.js.map +1 -0
  49. package/dist/{chunk-XPIHJ34I.js → chunk-IBVTH4JR.js} +4 -4
  50. package/dist/{chunk-C3HYQPV4.js → chunk-IVP5IVON.js} +2 -2
  51. package/dist/{chunk-BL5GYANC.js → chunk-KEDJDWWQ.js} +3 -3
  52. package/dist/{chunk-I5IUYN7B.js → chunk-KNKNOJFS.js} +3 -3
  53. package/dist/chunk-KNKNOJFS.js.map +1 -0
  54. package/dist/{chunk-D77ZQSQQ.js → chunk-KYGGXXT6.js} +829 -170
  55. package/dist/chunk-KYGGXXT6.js.map +1 -0
  56. package/dist/{chunk-J7RWBXFY.js → chunk-LSIIPKYT.js} +2 -2
  57. package/dist/{chunk-BSZOCSDZ.js → chunk-M3FPNTO2.js} +4 -4
  58. package/dist/{chunk-XMVHEWF6.js → chunk-MI36HL5G.js} +4 -4
  59. package/dist/{chunk-ROVO6NPJ.js → chunk-NN6IISZO.js} +58 -3
  60. package/dist/chunk-NN6IISZO.js.map +1 -0
  61. package/dist/{chunk-7H2GEJ3O.js → chunk-OBMYMKGO.js} +29 -6
  62. package/dist/{chunk-7H2GEJ3O.js.map → chunk-OBMYMKGO.js.map} +1 -1
  63. package/dist/{chunk-UNTGHX5A.js → chunk-OKOKPYWH.js} +2 -2
  64. package/dist/{chunk-WV7WV6JO.js → chunk-OY7RX2VL.js} +9 -15
  65. package/dist/chunk-OY7RX2VL.js.map +1 -0
  66. package/dist/{chunk-H2MRGONI.js → chunk-PTGQPWMV.js} +2 -2
  67. package/dist/{chunk-BJSLBUJ7.js → chunk-PWFTQHYX.js} +2 -2
  68. package/dist/{chunk-5AXTH4QZ.js → chunk-Q5MCHUXZ.js} +2 -2
  69. package/dist/{chunk-QHM6XEAH.js → chunk-S22UOMHM.js} +6 -6
  70. package/dist/{chunk-WIAOUFFB.js → chunk-S3XA7G35.js} +2 -2
  71. package/dist/{chunk-SISBMAPO.js → chunk-SHIUFIPW.js} +1 -1
  72. package/dist/chunk-SHIUFIPW.js.map +1 -0
  73. package/dist/{chunk-KCEHMDZF.js → chunk-U7JNBSS3.js} +3 -3
  74. package/dist/{chunk-ZNGPEV5J.js → chunk-V3VIRTTE.js} +3 -3
  75. package/dist/{chunk-TIDXB5DF.js → chunk-V5FZWQNN.js} +4 -4
  76. package/dist/chunk-VEIVAYJ7.js +361 -0
  77. package/dist/chunk-VEIVAYJ7.js.map +1 -0
  78. package/dist/{chunk-AEIKD3PP.js → chunk-VNUE6FHP.js} +3 -3
  79. package/dist/{chunk-DYYYUW5D.js → chunk-WFK2EVYU.js} +10 -2
  80. package/dist/chunk-WFK2EVYU.js.map +1 -0
  81. package/dist/{chunk-XMHUK5PN.js → chunk-X7FJMKT3.js} +2 -2
  82. package/dist/{chunk-FEJDVE3Z.js → chunk-XPH3FWME.js} +7 -2
  83. package/dist/{chunk-FEJDVE3Z.js.map → chunk-XPH3FWME.js.map} +1 -1
  84. package/dist/{chunk-SNMJ7SB3.js → chunk-Y5J63SMF.js} +5 -5
  85. package/dist/{chunk-M476FOQ7.js → chunk-YLRRU72W.js} +2 -2
  86. package/dist/{chunk-DWEBTE2W.js → chunk-YX333DPS.js} +4 -4
  87. package/dist/{chunk-BH3X5L6A.js → chunk-YZE6C3TQ.js} +3 -3
  88. package/dist/consent/index.cjs.map +1 -1
  89. package/dist/consent/index.d.cts +6 -6
  90. package/dist/consent/index.d.ts +6 -6
  91. package/dist/consent/index.js +3 -3
  92. package/dist/{crypto-7BN2HDWG.js → crypto-B46VNH6X.js} +3 -3
  93. package/dist/{delegation-MGH5SODX.js → delegation-5HON72PV.js} +5 -5
  94. package/dist/derivations/index.cjs +82 -2
  95. package/dist/derivations/index.cjs.map +1 -1
  96. package/dist/derivations/index.d.cts +7 -7
  97. package/dist/derivations/index.d.ts +7 -7
  98. package/dist/derivations/index.js +8 -6
  99. package/dist/{dev-unlock-iXbYFAWl.d.cts → dev-unlock-BR1rMOS-.d.cts} +1 -1
  100. package/dist/{dev-unlock-CI1ijTML.d.ts → dev-unlock-whL49sxV.d.ts} +1 -1
  101. package/dist/{errors-Dz64FA65.d.cts → errors-DL-zTrrF.d.cts} +29 -1
  102. package/dist/{errors-Dz64FA65.d.ts → errors-DL-zTrrF.d.ts} +29 -1
  103. package/dist/executor-44R5CUS2.js +12 -0
  104. package/dist/executor-AOACUK7Z.js +8 -0
  105. package/dist/executor-OKFLQCDW.js +8 -0
  106. package/dist/{fanout-sidecar-FIJJ46YG.js → fanout-sidecar-DCQWJQ6S.js} +2 -2
  107. package/dist/forget/index.cjs.map +1 -1
  108. package/dist/forget/index.d.cts +1 -1
  109. package/dist/forget/index.d.ts +1 -1
  110. package/dist/forget/index.js +4 -4
  111. package/dist/guards/index.cjs +80 -3
  112. package/dist/guards/index.cjs.map +1 -1
  113. package/dist/guards/index.d.cts +7 -7
  114. package/dist/guards/index.d.ts +7 -7
  115. package/dist/guards/index.js +8 -4
  116. package/dist/{hash-tEcM5fnv.d.cts → hash-BEUBmmI4.d.cts} +1 -1
  117. package/dist/{hash-blk7Bkes.d.ts → hash-Dtb7FwWd.d.ts} +1 -1
  118. package/dist/history/index.cjs.map +1 -1
  119. package/dist/history/index.d.cts +7 -7
  120. package/dist/history/index.d.ts +7 -7
  121. package/dist/history/index.js +5 -5
  122. package/dist/i18n/index.cjs +149 -132
  123. package/dist/i18n/index.cjs.map +1 -1
  124. package/dist/i18n/index.d.cts +6 -6
  125. package/dist/i18n/index.d.ts +6 -6
  126. package/dist/i18n/index.js +14 -14
  127. package/dist/{index-u-kWzSrL.d.cts → index-BM7O48Ur.d.cts} +85 -9
  128. package/dist/{index-C-SSRIxP.d.cts → index-BMmajblo.d.cts} +14 -0
  129. package/dist/{index-C-SSRIxP.d.ts → index-BMmajblo.d.ts} +14 -0
  130. package/dist/{index-DpU6KWof.d.ts → index-BelbyUwz.d.ts} +85 -9
  131. package/dist/index.cjs +2206 -992
  132. package/dist/index.cjs.map +1 -1
  133. package/dist/index.d.cts +29 -16
  134. package/dist/index.d.ts +29 -16
  135. package/dist/index.js +76 -54
  136. package/dist/index.js.map +1 -1
  137. package/dist/indexing/index.cjs.map +1 -1
  138. package/dist/indexing/index.js +4 -4
  139. package/dist/issue-EPA2PSWP.js +12 -0
  140. package/dist/{ledger-LFVLHE5H.js → ledger-LS6GXCBP.js} +5 -5
  141. package/dist/materialized-views/index.cjs +257 -4
  142. package/dist/materialized-views/index.cjs.map +1 -1
  143. package/dist/materialized-views/index.d.cts +7 -7
  144. package/dist/materialized-views/index.d.ts +7 -7
  145. package/dist/materialized-views/index.js +8 -7
  146. package/dist/noydb-BVKFP74P.js +38 -0
  147. package/dist/overlay-views/index.cjs.map +1 -1
  148. package/dist/overlay-views/index.d.cts +7 -7
  149. package/dist/overlay-views/index.d.ts +7 -7
  150. package/dist/overlay-views/index.js +4 -4
  151. package/dist/periods/index.cjs.map +1 -1
  152. package/dist/periods/index.d.cts +6 -6
  153. package/dist/periods/index.d.ts +6 -6
  154. package/dist/periods/index.js +5 -5
  155. package/dist/{public-envelope-RXZNP3V6.js → public-envelope-AGU6SS4Z.js} +4 -4
  156. package/dist/query/index.cjs +320 -28
  157. package/dist/query/index.cjs.map +1 -1
  158. package/dist/query/index.d.cts +3 -3
  159. package/dist/query/index.d.ts +3 -3
  160. package/dist/query/index.js +7 -6
  161. package/dist/read-only-facade-EX6WZZBP.js +7 -0
  162. package/dist/registry-ERNAMRDE.js +8 -0
  163. package/dist/registry-EXTHSXQW.js +8 -0
  164. package/dist/{registry-SECUWSGY.js → registry-RDPTFXQ7.js} +3 -3
  165. package/dist/{revoke-B54H2S2W.js → revoke-IFLXEZA5.js} +6 -6
  166. package/dist/sealed-record/index.cjs.map +1 -1
  167. package/dist/sealed-record/index.d.cts +1 -1
  168. package/dist/sealed-record/index.d.ts +1 -1
  169. package/dist/sealed-record/index.js +2 -2
  170. package/dist/session/index.cjs.map +1 -1
  171. package/dist/session/index.d.cts +7 -7
  172. package/dist/session/index.d.ts +7 -7
  173. package/dist/session/index.js +3 -3
  174. package/dist/shadow/index.cjs.map +1 -1
  175. package/dist/shadow/index.d.cts +6 -6
  176. package/dist/shadow/index.d.ts +6 -6
  177. package/dist/shadow/index.js +2 -2
  178. package/dist/{signer-YSXZT574.js → signer-UNWOUJAK.js} +5 -5
  179. package/dist/snapshots/index.cjs.map +1 -1
  180. package/dist/snapshots/index.d.cts +6 -6
  181. package/dist/snapshots/index.d.ts +6 -6
  182. package/dist/snapshots/index.js +4 -4
  183. package/dist/{stale-TOA36SRK.js → stale-NTEV5SLX.js} +2 -2
  184. package/dist/state-vault-TUTFRTOA.js +14 -0
  185. package/dist/state-vault-TUTFRTOA.js.map +1 -0
  186. package/dist/store/index.cjs +8 -0
  187. package/dist/store/index.cjs.map +1 -1
  188. package/dist/store/index.d.cts +13 -6
  189. package/dist/store/index.d.ts +13 -6
  190. package/dist/store/index.js +2 -2
  191. package/dist/{strategy-4M9jo172.d.ts → strategy-BDxQnnTX.d.ts} +315 -4
  192. package/dist/{strategy-CLC1j79g.d.cts → strategy-C5ol6NdV.d.cts} +315 -4
  193. package/dist/sync/index.cjs.map +1 -1
  194. package/dist/sync/index.d.cts +5 -5
  195. package/dist/sync/index.d.ts +5 -5
  196. package/dist/sync/index.js +4 -4
  197. package/dist/team/index.cjs.map +1 -1
  198. package/dist/team/index.d.cts +6 -6
  199. package/dist/team/index.d.ts +6 -6
  200. package/dist/team/index.js +8 -8
  201. package/dist/transition-guard-B1N82hMf.d.cts +165 -0
  202. package/dist/transition-guard-C__YeF3_.d.ts +165 -0
  203. package/dist/tx/index.cjs.map +1 -1
  204. package/dist/tx/index.d.cts +6 -6
  205. package/dist/tx/index.d.ts +6 -6
  206. package/dist/tx/index.js +3 -3
  207. package/dist/{types-CljIHm_J.d.ts → types-CraiZOyO.d.ts} +609 -305
  208. package/dist/{types-CrSpRDuG.d.cts → types-D-gr5t0G.d.cts} +609 -305
  209. package/dist/{ulid-CrI7PPbA.d.cts → ulid-DQnSAP5W.d.cts} +1 -1
  210. package/dist/{ulid-CWfL2Vfv.d.ts → ulid-FFRRHkVf.d.ts} +1 -1
  211. package/dist/util/index.cjs.map +1 -1
  212. package/dist/util/index.js +1 -1
  213. package/dist/{vault-group-DHAHFX2A.js → vault-group-27EV7KB4.js} +205 -8
  214. package/dist/vault-group-27EV7KB4.js.map +1 -0
  215. package/dist/{with-materialized-view-NzF71cG_.d.cts → with-materialized-view-BboqxyV3.d.cts} +1 -1
  216. package/dist/{with-materialized-view-B892zYZV.d.ts → with-materialized-view-CguCeVcT.d.ts} +1 -1
  217. package/dist/{with-overlayed-view-CR6m7CHe.d.ts → with-overlayed-view-DO08u_tx.d.ts} +1 -1
  218. package/dist/{with-overlayed-view-UI8qSGL4.d.cts → with-overlayed-view-mmsg5Of3.d.cts} +1 -1
  219. package/dist/with-rollup-_TyBzz3T.d.ts +47 -0
  220. package/dist/with-rollup-aaxOZcIb.d.cts +47 -0
  221. package/package.json +3 -3
  222. package/dist/chunk-D77ZQSQQ.js.map +0 -1
  223. package/dist/chunk-DYYYUW5D.js.map +0 -1
  224. package/dist/chunk-GP3SDSH2.js.map +0 -1
  225. package/dist/chunk-HGVSHKZW.js.map +0 -1
  226. package/dist/chunk-I5IUYN7B.js.map +0 -1
  227. package/dist/chunk-JDWE6JMX.js +0 -139
  228. package/dist/chunk-JDWE6JMX.js.map +0 -1
  229. package/dist/chunk-PDULVIBY.js +0 -63
  230. package/dist/chunk-PDULVIBY.js.map +0 -1
  231. package/dist/chunk-QO6RGLLD.js.map +0 -1
  232. package/dist/chunk-ROPJVUG3.js.map +0 -1
  233. package/dist/chunk-ROVO6NPJ.js.map +0 -1
  234. package/dist/chunk-SISBMAPO.js.map +0 -1
  235. package/dist/chunk-UMLVJTYV.js.map +0 -1
  236. package/dist/chunk-WV7WV6JO.js.map +0 -1
  237. package/dist/chunk-ZEGSDPB7.js.map +0 -1
  238. package/dist/executor-3W63Y44O.js +0 -11
  239. package/dist/executor-CFFWPWBJ.js +0 -8
  240. package/dist/executor-VDQQOR4F.js +0 -8
  241. package/dist/immutable-guard-B5M95nbq.d.ts +0 -82
  242. package/dist/immutable-guard-qN3zF8o1.d.cts +0 -82
  243. package/dist/issue-TTMGHQ2J.js +0 -12
  244. package/dist/noydb-36S6GQNC.js +0 -37
  245. package/dist/read-only-facade-ITU6L7BL.js +0 -7
  246. package/dist/registry-3YFLZ7WD.js +0 -8
  247. package/dist/registry-TGZISEWC.js +0 -8
  248. package/dist/state-vault-W2OEABNO.js.map +0 -1
  249. package/dist/vault-group-DHAHFX2A.js.map +0 -1
  250. package/dist/with-derivation-BZ2y4bzF.d.ts +0 -13
  251. package/dist/with-derivation-Bozs8DmD.d.cts +0 -13
  252. /package/dist/{chunk-NBBMMJ2H.js.map → chunk-3FSMVWBN.js.map} +0 -0
  253. /package/dist/{chunk-SHX5QBCI.js.map → chunk-4ULLGYPA.js.map} +0 -0
  254. /package/dist/{chunk-CD2AVTEM.js.map → chunk-5IGWRMEC.js.map} +0 -0
  255. /package/dist/{chunk-F4G63NTZ.js.map → chunk-7C6VFNIY.js.map} +0 -0
  256. /package/dist/{chunk-XJV6OB4D.js.map → chunk-7HD67R6U.js.map} +0 -0
  257. /package/dist/{chunk-NYSYPFXJ.js.map → chunk-B6E5IRPJ.js.map} +0 -0
  258. /package/dist/{chunk-3G3W65EQ.js.map → chunk-DY3EOJEN.js.map} +0 -0
  259. /package/dist/{chunk-YYVZYTWW.js.map → chunk-E66DSTJP.js.map} +0 -0
  260. /package/dist/{chunk-5LIROIDM.js.map → chunk-FBLAWK6A.js.map} +0 -0
  261. /package/dist/{chunk-E77UKJYL.js.map → chunk-FPHRTW2Z.js.map} +0 -0
  262. /package/dist/{chunk-U5QCMH3W.js.map → chunk-GKQAU52M.js.map} +0 -0
  263. /package/dist/{chunk-2FU2FTXD.js.map → chunk-GYAWXHFO.js.map} +0 -0
  264. /package/dist/{chunk-XPIHJ34I.js.map → chunk-IBVTH4JR.js.map} +0 -0
  265. /package/dist/{chunk-C3HYQPV4.js.map → chunk-IVP5IVON.js.map} +0 -0
  266. /package/dist/{chunk-BL5GYANC.js.map → chunk-KEDJDWWQ.js.map} +0 -0
  267. /package/dist/{chunk-J7RWBXFY.js.map → chunk-LSIIPKYT.js.map} +0 -0
  268. /package/dist/{chunk-BSZOCSDZ.js.map → chunk-M3FPNTO2.js.map} +0 -0
  269. /package/dist/{chunk-XMVHEWF6.js.map → chunk-MI36HL5G.js.map} +0 -0
  270. /package/dist/{chunk-UNTGHX5A.js.map → chunk-OKOKPYWH.js.map} +0 -0
  271. /package/dist/{chunk-H2MRGONI.js.map → chunk-PTGQPWMV.js.map} +0 -0
  272. /package/dist/{chunk-BJSLBUJ7.js.map → chunk-PWFTQHYX.js.map} +0 -0
  273. /package/dist/{chunk-5AXTH4QZ.js.map → chunk-Q5MCHUXZ.js.map} +0 -0
  274. /package/dist/{chunk-QHM6XEAH.js.map → chunk-S22UOMHM.js.map} +0 -0
  275. /package/dist/{chunk-WIAOUFFB.js.map → chunk-S3XA7G35.js.map} +0 -0
  276. /package/dist/{chunk-KCEHMDZF.js.map → chunk-U7JNBSS3.js.map} +0 -0
  277. /package/dist/{chunk-ZNGPEV5J.js.map → chunk-V3VIRTTE.js.map} +0 -0
  278. /package/dist/{chunk-TIDXB5DF.js.map → chunk-V5FZWQNN.js.map} +0 -0
  279. /package/dist/{chunk-AEIKD3PP.js.map → chunk-VNUE6FHP.js.map} +0 -0
  280. /package/dist/{chunk-XMHUK5PN.js.map → chunk-X7FJMKT3.js.map} +0 -0
  281. /package/dist/{chunk-SNMJ7SB3.js.map → chunk-Y5J63SMF.js.map} +0 -0
  282. /package/dist/{chunk-M476FOQ7.js.map → chunk-YLRRU72W.js.map} +0 -0
  283. /package/dist/{chunk-DWEBTE2W.js.map → chunk-YX333DPS.js.map} +0 -0
  284. /package/dist/{chunk-BH3X5L6A.js.map → chunk-YZE6C3TQ.js.map} +0 -0
  285. /package/dist/{crypto-7BN2HDWG.js.map → crypto-B46VNH6X.js.map} +0 -0
  286. /package/dist/{delegation-MGH5SODX.js.map → delegation-5HON72PV.js.map} +0 -0
  287. /package/dist/{executor-3W63Y44O.js.map → executor-44R5CUS2.js.map} +0 -0
  288. /package/dist/{executor-CFFWPWBJ.js.map → executor-AOACUK7Z.js.map} +0 -0
  289. /package/dist/{executor-VDQQOR4F.js.map → executor-OKFLQCDW.js.map} +0 -0
  290. /package/dist/{fanout-sidecar-FIJJ46YG.js.map → fanout-sidecar-DCQWJQ6S.js.map} +0 -0
  291. /package/dist/{issue-TTMGHQ2J.js.map → issue-EPA2PSWP.js.map} +0 -0
  292. /package/dist/{ledger-LFVLHE5H.js.map → ledger-LS6GXCBP.js.map} +0 -0
  293. /package/dist/{noydb-36S6GQNC.js.map → noydb-BVKFP74P.js.map} +0 -0
  294. /package/dist/{public-envelope-RXZNP3V6.js.map → public-envelope-AGU6SS4Z.js.map} +0 -0
  295. /package/dist/{read-only-facade-ITU6L7BL.js.map → read-only-facade-EX6WZZBP.js.map} +0 -0
  296. /package/dist/{registry-3YFLZ7WD.js.map → registry-ERNAMRDE.js.map} +0 -0
  297. /package/dist/{registry-SECUWSGY.js.map → registry-EXTHSXQW.js.map} +0 -0
  298. /package/dist/{registry-TGZISEWC.js.map → registry-RDPTFXQ7.js.map} +0 -0
  299. /package/dist/{revoke-B54H2S2W.js.map → revoke-IFLXEZA5.js.map} +0 -0
  300. /package/dist/{signer-YSXZT574.js.map → signer-UNWOUJAK.js.map} +0 -0
  301. /package/dist/{stale-TOA36SRK.js.map → stale-NTEV5SLX.js.map} +0 -0
@@ -7,10 +7,10 @@ import {
7
7
  import {
8
8
  TxContext,
9
9
  revertExecuted
10
- } from "./chunk-ZNGPEV5J.js";
10
+ } from "./chunk-V3VIRTTE.js";
11
11
  import {
12
12
  OverlayedCollection
13
- } from "./chunk-XMHUK5PN.js";
13
+ } from "./chunk-X7FJMKT3.js";
14
14
  import {
15
15
  NO_AGGREGATE,
16
16
  Query,
@@ -20,36 +20,36 @@ import {
20
20
  decodeMoneyFields,
21
21
  quantizeMoneyFields,
22
22
  validateMoneyFieldPaths
23
- } from "./chunk-HGVSHKZW.js";
23
+ } from "./chunk-3Q2AOPLT.js";
24
24
  import {
25
25
  EXPORT_AUDIT_COLLECTION,
26
26
  createExportBlobsHandle,
27
27
  runCompaction
28
- } from "./chunk-KCEHMDZF.js";
28
+ } from "./chunk-U7JNBSS3.js";
29
29
  import {
30
30
  LazyQuery,
31
31
  decodeIdxId,
32
32
  encodeIdxId
33
- } from "./chunk-NYSYPFXJ.js";
33
+ } from "./chunk-B6E5IRPJ.js";
34
34
  import {
35
35
  canonicalGroupKey
36
- } from "./chunk-7H2GEJ3O.js";
36
+ } from "./chunk-OBMYMKGO.js";
37
37
  import {
38
38
  readPath
39
- } from "./chunk-J7RWBXFY.js";
39
+ } from "./chunk-LSIIPKYT.js";
40
40
  import {
41
41
  SCHEMAS_COLLECTION,
42
42
  loadPersistedSchema,
43
43
  resolveManagedSecret,
44
44
  savePersistedSchema,
45
45
  saveSealedPassphrase
46
- } from "./chunk-AEIKD3PP.js";
46
+ } from "./chunk-VNUE6FHP.js";
47
47
  import {
48
48
  loadPublicEnvelope,
49
49
  readPublicEnvelope,
50
50
  savePublicEnvelope,
51
51
  validatePublicEnvelopeInput
52
- } from "./chunk-YYVZYTWW.js";
52
+ } from "./chunk-E66DSTJP.js";
53
53
  import {
54
54
  buildTombstone,
55
55
  isTombstone,
@@ -58,17 +58,19 @@ import {
58
58
  rewrapBodyToDek,
59
59
  rotateRecordCek,
60
60
  sealRecordToHost
61
- } from "./chunk-U5QCMH3W.js";
61
+ } from "./chunk-GKQAU52M.js";
62
62
  import {
63
63
  PERIODS_COLLECTION
64
- } from "./chunk-BH3X5L6A.js";
64
+ } from "./chunk-YZE6C3TQ.js";
65
65
  import {
66
- getAtPath,
67
66
  isDictCollectionName,
68
- isStaticDictDescriptor,
67
+ isStaticDictDescriptor
68
+ } from "./chunk-H42KZXNV.js";
69
+ import {
70
+ getAtPath,
69
71
  resolvePolicy,
70
72
  setAtPathInPlace
71
- } from "./chunk-ROPJVUG3.js";
73
+ } from "./chunk-VEIVAYJ7.js";
72
74
  import {
73
75
  ManagedRecoveryNotEnrolledError,
74
76
  PolicyDeniedError,
@@ -90,11 +92,11 @@ import {
90
92
  saveShamirRecoveryEntries,
91
93
  updateAuthenticator,
92
94
  writeMagicLinkGrant
93
- } from "./chunk-QHM6XEAH.js";
95
+ } from "./chunk-S22UOMHM.js";
94
96
  import {
95
97
  assertTierAccess,
96
98
  dekKey
97
- } from "./chunk-5LIROIDM.js";
99
+ } from "./chunk-FBLAWK6A.js";
98
100
  import {
99
101
  USER_ENVELOPE_COLLECTION,
100
102
  assertKeyringOpenAllowed,
@@ -119,7 +121,7 @@ import {
119
121
  rotateKeys,
120
122
  saveUserEnvelope,
121
123
  updateKeyringIdentity
122
- } from "./chunk-BSZOCSDZ.js";
124
+ } from "./chunk-M3FPNTO2.js";
123
125
  import {
124
126
  INDEXED_STORE_POLICY
125
127
  } from "./chunk-2QR2PQTT.js";
@@ -129,7 +131,7 @@ import {
129
131
  import {
130
132
  LEDGER_COLLECTION,
131
133
  LEDGER_DELTAS_COLLECTION
132
- } from "./chunk-DWEBTE2W.js";
134
+ } from "./chunk-YX333DPS.js";
133
135
  import {
134
136
  sha256Hex as sha256Hex2
135
137
  } from "./chunk-PDVP3C2I.js";
@@ -141,11 +143,11 @@ import {
141
143
  readDottedPath,
142
144
  rebuildSubjectIndex,
143
145
  removeSubjectRef
144
- } from "./chunk-I5IUYN7B.js";
146
+ } from "./chunk-KNKNOJFS.js";
145
147
  import {
146
148
  NOYDB_BACKUP_VERSION,
147
149
  NOYDB_FORMAT_VERSION
148
- } from "./chunk-SISBMAPO.js";
150
+ } from "./chunk-SHIUFIPW.js";
149
151
  import {
150
152
  decrypt,
151
153
  encrypt,
@@ -153,13 +155,14 @@ import {
153
155
  sha256Hex,
154
156
  unwrapCek,
155
157
  wrapCek
156
- } from "./chunk-UNTGHX5A.js";
158
+ } from "./chunk-OKOKPYWH.js";
157
159
  import {
158
160
  AlreadyElevatedError,
159
161
  AttestationError,
160
162
  BackupCorruptedError,
161
163
  BackupLedgerError,
162
164
  ConflictError,
165
+ DerivationCapExceededError,
163
166
  ElevationExpiredError,
164
167
  ExportCapabilityError,
165
168
  ForgetStrategyNotConfiguredError,
@@ -191,7 +194,7 @@ import {
191
194
  UnsupportedIndexOptionError,
192
195
  ValidationError,
193
196
  VaultTemplateNotFoundError
194
- } from "./chunk-ZEGSDPB7.js";
197
+ } from "./chunk-DJF3FXW5.js";
195
198
 
196
199
  // src/policy/storage.ts
197
200
  var META_COLLECTION = "_meta";
@@ -506,6 +509,74 @@ var DISABLED_STATE = {
506
509
  getPersistedIndexes: () => null
507
510
  };
508
511
 
512
+ // src/search/tokenize.ts
513
+ var WORD = /[\p{L}\p{N}]+/gu;
514
+ var tokenize = (text) => {
515
+ if (!text) return [];
516
+ return text.normalize("NFKC").toLowerCase().match(WORD) ?? [];
517
+ };
518
+
519
+ // src/search/scan.ts
520
+ var K1 = 1.2;
521
+ var B = 0.75;
522
+ function fieldText(record, field) {
523
+ const v = record[field];
524
+ if (typeof v === "string") return v;
525
+ if (v === null || v === void 0) return "";
526
+ if (typeof v === "number" || typeof v === "boolean") return String(v);
527
+ return "";
528
+ }
529
+ function searchScan(entries, field, query, opts = {}, tokenizer = tokenize) {
530
+ const queryTerms = tokenizer(query);
531
+ if (queryTerms.length === 0) return [];
532
+ const match = opts.match ?? "any";
533
+ const usePrefix = opts.prefix ?? false;
534
+ const exactTerms = usePrefix ? queryTerms.slice(0, -1) : queryTerms;
535
+ const prefixTerm = usePrefix ? queryTerms[queryTerms.length - 1] : void 0;
536
+ const docs = entries.map((e) => ({ id: e.id, record: e.record, terms: tokenizer(fieldText(e.record, field)) }));
537
+ const N = docs.length || 1;
538
+ const df = /* @__PURE__ */ new Map();
539
+ let totalLen = 0;
540
+ for (const d of docs) {
541
+ totalLen += d.terms.length;
542
+ for (const t of new Set(d.terms)) df.set(t, (df.get(t) ?? 0) + 1);
543
+ }
544
+ const avgdl = totalLen / N || 1;
545
+ let prefixDf = 0;
546
+ if (prefixTerm !== void 0) {
547
+ for (const d of docs) {
548
+ if (d.terms.some((t) => t.startsWith(prefixTerm))) prefixDf++;
549
+ }
550
+ }
551
+ const requiredCount = exactTerms.length + (prefixTerm !== void 0 ? 1 : 0);
552
+ const results = [];
553
+ for (const d of docs) {
554
+ const tf = /* @__PURE__ */ new Map();
555
+ for (const t of d.terms) tf.set(t, (tf.get(t) ?? 0) + 1);
556
+ const matched = [];
557
+ for (const qt of exactTerms) {
558
+ const c = tf.get(qt) ?? 0;
559
+ if (c > 0) matched.push({ tf: c, df: df.get(qt) ?? 0 });
560
+ }
561
+ if (prefixTerm !== void 0) {
562
+ let ptf = 0;
563
+ for (const [t, c] of tf) if (t.startsWith(prefixTerm)) ptf += c;
564
+ if (ptf > 0) matched.push({ tf: ptf, df: prefixDf });
565
+ }
566
+ if (matched.length === 0) continue;
567
+ if (match === "all" && matched.length < requiredCount) continue;
568
+ let score = 0;
569
+ for (const m of matched) {
570
+ const idf = Math.log(1 + (N - m.df + 0.5) / (m.df + 0.5));
571
+ const denom = m.tf + K1 * (1 - B + B * (d.terms.length / avgdl));
572
+ score += idf * (m.tf * (K1 + 1) / (denom || 1));
573
+ }
574
+ results.push({ id: d.id, score, record: d.record });
575
+ }
576
+ results.sort((a, b) => b.score - a.score);
577
+ return opts.limit !== void 0 ? results.slice(0, opts.limit) : results;
578
+ }
579
+
509
580
  // src/indexing/unique-constraints.ts
510
581
  var UniqueConstraintSet = class {
511
582
  constructor(collectionName, uniqueDefs) {
@@ -837,7 +908,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
837
908
  }
838
909
  const sourceWithId = { ...source, id };
839
910
  if (DerivationExecutor === null) {
840
- ({ DerivationExecutor } = await import("./executor-CFFWPWBJ.js"));
911
+ ({ DerivationExecutor } = await import("./executor-OKFLQCDW.js"));
841
912
  }
842
913
  const ctx = { vault: accessor.getReadOnlyFacade() };
843
914
  const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx);
@@ -875,6 +946,15 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
875
946
  }
876
947
 
877
948
  // src/collection.ts
949
+ function selfWriteFieldEqual(a, b) {
950
+ if (a === b) return true;
951
+ if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
952
+ try {
953
+ return JSON.stringify(a) === JSON.stringify(b);
954
+ } catch {
955
+ return false;
956
+ }
957
+ }
878
958
  var fallbackWarned = /* @__PURE__ */ new Set();
879
959
  function warnOnceFallback(adapterName) {
880
960
  if (fallbackWarned.has(adapterName)) return;
@@ -1373,7 +1453,7 @@ var Collection = class {
1373
1453
  }
1374
1454
  }
1375
1455
  if (this.materializedViewSource !== void 0) {
1376
- const { resolveStaleMVOnRead } = await import("./stale-TOA36SRK.js");
1456
+ const { resolveStaleMVOnRead } = await import("./stale-NTEV5SLX.js");
1377
1457
  await resolveStaleMVOnRead(this.materializedViewSource, this.name);
1378
1458
  }
1379
1459
  let record;
@@ -1783,7 +1863,7 @@ var Collection = class {
1783
1863
  if (mode === "eager") {
1784
1864
  if (executor === null) {
1785
1865
  ;
1786
- ({ MaterializedViewExecutor: executor } = await import("./executor-3W63Y44O.js"));
1866
+ ({ MaterializedViewExecutor: executor } = await import("./executor-44R5CUS2.js"));
1787
1867
  }
1788
1868
  await executor.refresh(reg, {
1789
1869
  getCollection: (name) => this.materializedViewSource.getCollection(name),
@@ -1792,7 +1872,7 @@ var Collection = class {
1792
1872
  });
1793
1873
  } else if (mode === "lazy") {
1794
1874
  if (staleHelpers === null) {
1795
- staleHelpers = await import("./stale-TOA36SRK.js");
1875
+ staleHelpers = await import("./stale-NTEV5SLX.js");
1796
1876
  }
1797
1877
  staleHelpers.markMVStale(registry, reg.spec.name);
1798
1878
  }
@@ -1809,6 +1889,111 @@ var Collection = class {
1809
1889
  * output (carries `_derivedFrom`) — defensive guard against missed
1810
1890
  * cycle detection.
1811
1891
  */
1892
+ /**
1893
+ * @internal #376 — the RAW stored record (canonical-money form, i18n maps
1894
+ * intact), WITHOUT the locale resolution `get()` applies. Used as the
1895
+ * patch base for self-write reverse-denorm so writing back never clobbers
1896
+ * an i18n map or re-quantizes money incorrectly. Returns null for
1897
+ * missing / tombstoned records.
1898
+ */
1899
+ async _getStoredRecord(id) {
1900
+ let raw;
1901
+ if (this.lazy && this.lru) {
1902
+ const cached = this.lru.get(id);
1903
+ if (cached) raw = cached.record;
1904
+ else {
1905
+ const env = await this.adapter.get(this.vault, this.name, id);
1906
+ if (!env || isTombstone(env, this.encrypted)) return null;
1907
+ raw = await this.decryptRecord(env, { id });
1908
+ if (raw === null) return null;
1909
+ this.lru.set(id, { record: raw, version: env._v }, estimateRecordBytes(raw));
1910
+ }
1911
+ } else {
1912
+ await this.ensureHydrated();
1913
+ raw = this.cache.get(id)?.record ?? null;
1914
+ }
1915
+ if (raw === null) return null;
1916
+ return canonicalizeStoredMoney(raw, this.moneyFields);
1917
+ }
1918
+ /**
1919
+ * @internal #376 — ids of records whose top-level `field` equals `value`.
1920
+ * Uses the FK index when the field is indexed (O(matches)); otherwise a
1921
+ * linear scan (O(N) — fine for small child sets; index the FK to scale).
1922
+ */
1923
+ async _findMatchingIds(field, value) {
1924
+ const hit = this.getIndexes()?.lookupEqual(field, value);
1925
+ if (hit) return [...hit];
1926
+ const target = String(value);
1927
+ const matches = (rec) => {
1928
+ const fv = rec[field];
1929
+ return (typeof fv === "string" || typeof fv === "number") && String(fv) === target;
1930
+ };
1931
+ if (!this.lazy) {
1932
+ await this.ensureHydrated();
1933
+ const out2 = [];
1934
+ for (const [rid, e] of this.cache) {
1935
+ if (matches(e.record)) out2.push(rid);
1936
+ }
1937
+ return out2;
1938
+ }
1939
+ const ids = await this.adapter.list(this.vault, this.name);
1940
+ const out = [];
1941
+ for (const rid of ids) {
1942
+ const raw = await this._getStoredRecord(rid);
1943
+ if (raw !== null && matches(raw)) out.push(rid);
1944
+ }
1945
+ return out;
1946
+ }
1947
+ /**
1948
+ * @internal #376 slice 2 — recompute a rollup aggregate onto the parent.
1949
+ * Gathers every child of `parentId`, runs `compute`, and patches only the
1950
+ * rollup `field` onto the parent's raw stored record (value-equality
1951
+ * guarded). No-op when the parent record does not exist.
1952
+ */
1953
+ async recomputeRollup(spec, parentId) {
1954
+ if (this.derivationSource === void 0 || spec.rollup === void 0) return;
1955
+ const { from, key, field, compute } = spec.rollup;
1956
+ const into = spec.source;
1957
+ const intoColl = this.derivationSource.getCollection(into);
1958
+ const base = await intoColl._getStoredRecord(parentId);
1959
+ if (base === null) return;
1960
+ const fromColl = this.derivationSource.getCollection(from);
1961
+ const childIds = await fromColl._findMatchingIds(key, parentId);
1962
+ const children = [];
1963
+ for (const cid of childIds) {
1964
+ const c = await fromColl.get(cid);
1965
+ if (c !== null && c !== void 0) children.push(c);
1966
+ }
1967
+ const newValue = compute(children);
1968
+ if (selfWriteFieldEqual(base[field], newValue)) return;
1969
+ const patched = { ...base, [field]: newValue };
1970
+ const txCtx = this.derivationSource.getActiveTxContext();
1971
+ if (txCtx !== null) {
1972
+ const prior = await this.adapter.get(this.vault, into, parentId);
1973
+ txCtx._executed.push({
1974
+ op: { type: "put", vaultName: this.vault, collectionName: into, id: parentId },
1975
+ priorEnvelope: prior
1976
+ });
1977
+ }
1978
+ await intoColl.put(parentId, patched);
1979
+ }
1980
+ /**
1981
+ * @internal #376 slice 2 — fire any rollups for which THIS collection is the
1982
+ * child `from`, recomputing the affected parent after a child delete. Called
1983
+ * from the delete path with the just-removed record's key value. Other
1984
+ * derivation kinds do not react to deletes (unchanged).
1985
+ */
1986
+ async dispatchRollupsOnDelete(deleted) {
1987
+ if (this.derivationSource === void 0) return;
1988
+ const registry = this.derivationSource.registry();
1989
+ const rec = deleted;
1990
+ for (const { spec } of registry.strategiesForSource(this.name)) {
1991
+ if (!spec.rollup || spec.rollup.from !== this.name) continue;
1992
+ const kv = rec[spec.rollup.key];
1993
+ if (typeof kv !== "string" && typeof kv !== "number") continue;
1994
+ await this.recomputeRollup(spec, String(kv));
1995
+ }
1996
+ }
1812
1997
  async dispatchDerivations(id, record, version) {
1813
1998
  if (this.derivationSource === void 0) return;
1814
1999
  const incoming = canonicalizeStoredMoney(record, this.moneyFields);
@@ -1819,29 +2004,60 @@ var Collection = class {
1819
2004
  let DerivationExecutor = null;
1820
2005
  for (const { spec, strategyHash } of strategies) {
1821
2006
  const mode = typeof spec.lifecycle === "string" ? spec.lifecycle : spec.lifecycle.mode;
1822
- if (mode === "eager") {
1823
- if (DerivationExecutor === null) {
1824
- ({ DerivationExecutor } = await import("./executor-CFFWPWBJ.js"));
1825
- }
1826
- let sourceWithId;
1827
- let sourceVersion = version;
1828
- if (spec.source === this.name) {
1829
- sourceWithId = { ...incoming, id };
2007
+ if (spec.rollup) {
2008
+ if (mode !== "eager") continue;
2009
+ let parentId;
2010
+ if (this.name === spec.rollup.from) {
2011
+ const kv = incoming[spec.rollup.key];
2012
+ parentId = typeof kv === "string" || typeof kv === "number" ? String(kv) : null;
1830
2013
  } else {
1831
- const primary = await this.derivationSource.getCollection(spec.source).get(id);
1832
- if (primary === null || primary === void 0) continue;
1833
- sourceWithId = { ...primary, id };
1834
- sourceVersion = 0;
2014
+ parentId = id;
2015
+ }
2016
+ if (parentId !== null) await this.recomputeRollup(spec, parentId);
2017
+ continue;
2018
+ }
2019
+ const isSource = spec.source === this.name;
2020
+ const isSibling = !isSource && (spec.sources?.includes(this.name) ?? false);
2021
+ const trigger = !isSource && !isSibling ? spec.triggerBy?.find((t) => t.collection === this.name) : void 0;
2022
+ const runs = [];
2023
+ if (isSource) {
2024
+ runs.push({ input: { ...incoming, id }, base: incoming, runId: id, version });
2025
+ } else if (isSibling) {
2026
+ const p = await this.derivationSource.getCollection(spec.source).get(id);
2027
+ if (p !== null && p !== void 0) {
2028
+ const raw = await this.derivationSource.getCollection(spec.source)._getStoredRecord(id);
2029
+ runs.push({ input: { ...p, id }, base: raw ?? p, runId: id, version: 0 });
2030
+ }
2031
+ } else if (trigger) {
2032
+ const srcColl = this.derivationSource.getCollection(spec.source);
2033
+ const ids = await srcColl._findMatchingIds(trigger.on, id);
2034
+ if (trigger.maxFanout !== void 0 && ids.length > trigger.maxFanout) {
2035
+ throw new DerivationCapExceededError(`triggerBy ${this.name}\u2192${spec.source}`, ids.length, trigger.maxFanout);
1835
2036
  }
2037
+ for (const sid of ids) {
2038
+ const raw = await srcColl._getStoredRecord(sid);
2039
+ if (raw === null) continue;
2040
+ runs.push({ input: { ...raw, id: sid }, base: raw, runId: sid, version: 0 });
2041
+ }
2042
+ }
2043
+ if (runs.length === 0) continue;
2044
+ if (mode !== "eager") {
2045
+ for (const run of runs) await markStale(registry, spec, run.runId);
2046
+ continue;
2047
+ }
2048
+ if (DerivationExecutor === null) {
2049
+ ({ DerivationExecutor } = await import("./executor-OKFLQCDW.js"));
2050
+ }
2051
+ for (const run of runs) {
1836
2052
  const ctx = { vault: this.derivationSource.getReadOnlyFacade() };
1837
- const result = await DerivationExecutor.run(spec, sourceWithId, sourceVersion, strategyHash, ctx);
2053
+ const result = await DerivationExecutor.run(spec, run.input, run.version, strategyHash, ctx);
1838
2054
  for (const key of Object.keys(spec.outputs)) {
1839
2055
  const out = result.outputs[key];
1840
2056
  if (!out) continue;
1841
2057
  if (out.kind === "failed") {
1842
2058
  const err = out.error;
1843
2059
  if (spec.strict) throw err;
1844
- console.warn(`[derivation] output "${key}" for source "${spec.source}" id="${id}" failed:`, err);
2060
+ console.warn(`[derivation] output "${key}" for source "${spec.source}" id="${run.runId}" failed:`, err);
1845
2061
  continue;
1846
2062
  }
1847
2063
  const outSpec = spec.outputs[key];
@@ -1849,12 +2065,12 @@ var Collection = class {
1849
2065
  const outputCollection = this.derivationSource.getCollection(outSpec.collection);
1850
2066
  const txCtx = this.derivationSource.getActiveTxContext();
1851
2067
  if (out.kind === "array") {
1852
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-FIJJ46YG.js");
2068
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-DCQWJQ6S.js");
1853
2069
  const prior = await loadFanoutSidecar(
1854
2070
  this.adapter,
1855
2071
  this.vault,
1856
2072
  spec.source,
1857
- id,
2073
+ run.runId,
1858
2074
  key
1859
2075
  );
1860
2076
  const prevKeys = new Set(prior?.keys ?? []);
@@ -1881,7 +2097,7 @@ var Collection = class {
1881
2097
  }
1882
2098
  await saveFanoutSidecar(this.adapter, this.vault, {
1883
2099
  source: spec.source,
1884
- sourceId: id,
2100
+ sourceId: run.runId,
1885
2101
  outputKey: key,
1886
2102
  outputCollection: outSpec.collection,
1887
2103
  keys: newKeysList
@@ -1889,25 +2105,44 @@ var Collection = class {
1889
2105
  continue;
1890
2106
  }
1891
2107
  if (out.skipped === true) {
1892
- await outputCollection._internalDelete(id, txCtx);
2108
+ await outputCollection._internalDelete(run.runId, txCtx);
2109
+ continue;
2110
+ }
2111
+ if (outSpec.shape === "record" && outSpec.denorm !== void 0 && outSpec.collection === spec.source) {
2112
+ const value = out.value;
2113
+ const patched = { ...run.base };
2114
+ let changed = false;
2115
+ for (const f of outSpec.denorm) {
2116
+ if (!selfWriteFieldEqual(run.base[f], value[f])) {
2117
+ patched[f] = value[f];
2118
+ changed = true;
2119
+ }
2120
+ }
2121
+ if (!changed) continue;
2122
+ if (txCtx !== null) {
2123
+ const prior = await this.adapter.get(this.vault, outSpec.collection, run.runId);
2124
+ txCtx._executed.push({
2125
+ op: { type: "put", vaultName: this.vault, collectionName: outSpec.collection, id: run.runId },
2126
+ priorEnvelope: prior
2127
+ });
2128
+ }
2129
+ await outputCollection.put(run.runId, patched);
1893
2130
  continue;
1894
2131
  }
1895
2132
  if (txCtx !== null) {
1896
- const prior = await this.adapter.get(this.vault, outSpec.collection, id);
2133
+ const prior = await this.adapter.get(this.vault, outSpec.collection, run.runId);
1897
2134
  txCtx._executed.push({
1898
2135
  op: {
1899
2136
  type: "put",
1900
2137
  vaultName: this.vault,
1901
2138
  collectionName: outSpec.collection,
1902
- id
2139
+ id: run.runId
1903
2140
  },
1904
2141
  priorEnvelope: prior
1905
2142
  });
1906
2143
  }
1907
- await outputCollection.put(id, out.value);
2144
+ await outputCollection.put(run.runId, out.value);
1908
2145
  }
1909
- } else {
1910
- await markStale(registry, spec, id);
1911
2146
  }
1912
2147
  }
1913
2148
  }
@@ -2124,6 +2359,7 @@ var Collection = class {
2124
2359
  if (!internal) {
2125
2360
  await this.dispatchMaterializedViewsOnDelete(id);
2126
2361
  await this.dispatchArrayDerivationsOnDelete(id);
2362
+ if (existing) await this.dispatchRollupsOnDelete(existing.record);
2127
2363
  }
2128
2364
  }
2129
2365
  /**
@@ -2192,7 +2428,7 @@ var Collection = class {
2192
2428
  for (const [outputKey, outSpec] of Object.entries(spec.outputs)) {
2193
2429
  if (outSpec.shape !== "array") continue;
2194
2430
  if (helpers === null) {
2195
- helpers = await import("./fanout-sidecar-FIJJ46YG.js");
2431
+ helpers = await import("./fanout-sidecar-DCQWJQ6S.js");
2196
2432
  }
2197
2433
  const sidecar = await helpers.loadFanoutSidecar(
2198
2434
  this.adapter,
@@ -2232,7 +2468,7 @@ var Collection = class {
2232
2468
  if (mode === "eager") {
2233
2469
  if (executor === null) {
2234
2470
  ;
2235
- ({ MaterializedViewExecutor: executor } = await import("./executor-3W63Y44O.js"));
2471
+ ({ MaterializedViewExecutor: executor } = await import("./executor-44R5CUS2.js"));
2236
2472
  }
2237
2473
  await executor.refresh(reg, {
2238
2474
  getCollection: (name) => this.materializedViewSource.getCollection(name),
@@ -2241,7 +2477,7 @@ var Collection = class {
2241
2477
  });
2242
2478
  } else if (mode === "lazy") {
2243
2479
  if (staleHelpers === null) {
2244
- staleHelpers = await import("./stale-TOA36SRK.js");
2480
+ staleHelpers = await import("./stale-NTEV5SLX.js");
2245
2481
  }
2246
2482
  staleHelpers.markMVStale(registry, reg.spec.name);
2247
2483
  }
@@ -2264,7 +2500,7 @@ var Collection = class {
2264
2500
  );
2265
2501
  }
2266
2502
  if (this.materializedViewSource !== void 0) {
2267
- const { resolveStaleMVOnRead } = await import("./stale-TOA36SRK.js");
2503
+ const { resolveStaleMVOnRead } = await import("./stale-NTEV5SLX.js");
2268
2504
  await resolveStaleMVOnRead(this.materializedViewSource, this.name);
2269
2505
  }
2270
2506
  await this.ensureHydrated();
@@ -2280,6 +2516,29 @@ var Collection = class {
2280
2516
  hasReadTransforms() {
2281
2517
  return this.moneyFields !== void 0 && Object.keys(this.moneyFields).length > 0 || this.i18nFields !== void 0 && Object.keys(this.i18nFields).length > 0 || this.dictKeyFields !== void 0 && Object.keys(this.dictKeyFields).length > 0;
2282
2518
  }
2519
+ /**
2520
+ * Scan-mode full-text search over a plain-text `field` (#308). Decrypts the
2521
+ * collection in memory and ranks records by BM25 against the tokenized query.
2522
+ * **Zero added store leakage** — pure client-side scan; nothing searchable is
2523
+ * written to the store. (A store-usable blind index for at-scale search is a
2524
+ * separate, gated opt-in — see the #308 design note.) Eager mode only.
2525
+ *
2526
+ * `opts.match` (`'any'` default | `'all'`), `opts.prefix` (last query term as
2527
+ * a prefix → typeahead), `opts.limit` (top-N). Returns `{ id, score, record }`
2528
+ * ranked by descending score. The default tokenizer is word-boundary based —
2529
+ * see `src/search/tokenize.ts` for the Thai/CJK caveat.
2530
+ */
2531
+ async search(field, query, opts = {}) {
2532
+ if (this.lazy) {
2533
+ throw new Error(
2534
+ `Collection "${this.name}": search() (scan mode) requires eager mode (prefetch: true). A store-usable blind index for lazy / at-scale search is a separate gated opt-in (#308).`
2535
+ );
2536
+ }
2537
+ await this.ensureHydrated();
2538
+ const entries = [];
2539
+ for (const [id, e] of this.cache) entries.push({ id, record: e.record });
2540
+ return searchScan(entries, field, query, opts);
2541
+ }
2283
2542
  // ─── Bulk operations ─────────────────────────────────────
2284
2543
  /**
2285
2544
  * Put many records in one call. Each item is processed sequentially
@@ -2457,6 +2716,10 @@ var Collection = class {
2457
2716
  leftCollection,
2458
2717
  resolveRef: (field) => resolver.resolveRef(leftCollection, field),
2459
2718
  resolveSource: (collectionName) => resolver.resolveSource(collectionName),
2719
+ // #285 §3 — flow the vault/collection default locale to joins so a
2720
+ // joined i18n field resolves like get()/list() when no per-call
2721
+ // locale is given; toArray({ locale }) overrides it.
2722
+ ...this.defaultLocale !== void 0 ? { defaultLocale: this.defaultLocale } : {},
2460
2723
  ...resolver.resolveDictSource ? { resolveDictSource: (field) => resolver.resolveDictSource(leftCollection, field) } : {}
2461
2724
  } : void 0;
2462
2725
  return new Query(source, void 0, joinContext, this.aggregateStrategy);
@@ -2545,7 +2808,10 @@ var Collection = class {
2545
2808
  };
2546
2809
  this.emitter.on("change", handler);
2547
2810
  return () => this.emitter.off("change", handler);
2548
- }
2811
+ },
2812
+ // #285 §3 — expose this (right-side) collection's i18nText descriptors so
2813
+ // the join executor can resolve joined i18n fields at the `join` layer.
2814
+ ...this.i18nFields !== void 0 ? { i18nFields: this.i18nFields } : {}
2549
2815
  };
2550
2816
  }
2551
2817
  /**
@@ -2778,6 +3044,10 @@ var Collection = class {
2778
3044
  leftCollection,
2779
3045
  resolveRef: (field) => resolver.resolveRef(leftCollection, field),
2780
3046
  resolveSource: (collectionName) => resolver.resolveSource(collectionName),
3047
+ // #285 §3 — flow the vault/collection default locale to joins so a
3048
+ // joined i18n field resolves like get()/list() when no per-call
3049
+ // locale is given; toArray({ locale }) overrides it.
3050
+ ...this.defaultLocale !== void 0 ? { defaultLocale: this.defaultLocale } : {},
2781
3051
  ...resolver.resolveDictSource ? { resolveDictSource: (field) => resolver.resolveDictSource(leftCollection, field) } : {}
2782
3052
  } : void 0;
2783
3053
  return new ScanBuilder(
@@ -3178,14 +3448,15 @@ var Collection = class {
3178
3448
  (d) => isStaticDictDescriptor(d) && d.displayLocale !== void 0
3179
3449
  );
3180
3450
  if (!locale && !hasStaticDisplay) return result;
3451
+ const layer = localeOpts?._layer ?? "read";
3181
3452
  if (locale && hasI18n && this.i18nFields) {
3182
- result = this.i18nStrategy.applyI18nLocale(result, this.i18nFields, locale, localeOpts?.fallback);
3453
+ result = this.i18nStrategy.applyI18nLocale(result, this.i18nFields, locale, localeOpts?.fallback, layer);
3183
3454
  }
3184
3455
  if (hasDict && this.dictKeyFields && this.dictLabelResolver && locale !== "raw") {
3185
3456
  const withLabels = { ...result };
3186
3457
  const resolver = this.dictLabelResolver;
3187
3458
  for (const [field, desc] of Object.entries(this.dictKeyFields)) {
3188
- const policy = desc.onMissing ? resolvePolicy(desc.onMissing, "read") : "null";
3459
+ const policy = desc.onMissing ? resolvePolicy(desc.onMissing, layer) : "null";
3189
3460
  const fallback = policy === "substitute" ? localeOpts?.fallback ?? desc.substitute : localeOpts?.fallback;
3190
3461
  const effLocale = locale ?? (isStaticDictDescriptor(desc) ? desc.displayLocale : void 0);
3191
3462
  const resolveKey = async (key) => {
@@ -3334,6 +3605,34 @@ var Collection = class {
3334
3605
  }
3335
3606
  }
3336
3607
  }
3608
+ /**
3609
+ * @internal — hard-delete this record's persisted `_idx/<field>/<recordId>`
3610
+ * side-cars for the erasure path (#401). `forget()` crypto-shreds the body but
3611
+ * keeps the collection DEK, under which these side-cars are encrypted — so
3612
+ * without this they leave the indexed field VALUES readable after a "forget".
3613
+ *
3614
+ * Content-free: the side-car id is `encodeIdxId(def.key, id)`, so it needs no
3615
+ * body decode (the body is being shredded). Eager mode has no durable side-car
3616
+ * → no-op. The in-memory mirror is left as-is: it is ephemeral (rebuilt from
3617
+ * the now-deleted side-cars on reopen) and live reads skip the tombstone, so a
3618
+ * stale mirror hit cannot surface the erased record. Returns the count deleted
3619
+ * + the `def.key`s whose delete FAILED (residue that still leaks the value).
3620
+ */
3621
+ async _purgePersistedIndexes(id) {
3622
+ const persisted = this.persistedIndexes;
3623
+ if (!persisted) return { purged: 0, residue: [] };
3624
+ let purged = 0;
3625
+ const residue = [];
3626
+ for (const def of persisted.definitions()) {
3627
+ try {
3628
+ await this.adapter.delete(this.vault, this.name, encodeIdxId(def.key, id));
3629
+ purged++;
3630
+ } catch {
3631
+ residue.push(def.key);
3632
+ }
3633
+ }
3634
+ return { purged, residue };
3635
+ }
3337
3636
  /**
3338
3637
  * Bulk-load the persisted-index mirror from `_idx/<field>/*` side-cars
3339
3638
  * on first lazy-mode query. Idempotent — subsequent calls short-circuit
@@ -4026,6 +4325,38 @@ function withArchive(opts) {
4026
4325
  // src/sequence/index.ts
4027
4326
  var SEQUENCE_COLLECTION = "_sequences";
4028
4327
  var MAX_NEXT_ATTEMPTS = 16;
4328
+ var SEQ_FORMAT_TOKEN = /\{([^{}]*)\}/g;
4329
+ var SEQ_PAD_TOKEN = /^seq:0(\d+)$/;
4330
+ var SEQ_PARTITION_TOKEN = /^partition\.(\d+)$/;
4331
+ function compileSequenceFormat(format, series, partition) {
4332
+ const parts = partition ?? [];
4333
+ for (const m of format.matchAll(SEQ_FORMAT_TOKEN)) {
4334
+ const token = m[1] ?? "";
4335
+ if (token === "seq") continue;
4336
+ if (SEQ_PAD_TOKEN.test(token)) continue;
4337
+ const partMatch = SEQ_PARTITION_TOKEN.exec(token);
4338
+ if (partMatch) {
4339
+ const idx = Number(partMatch[1]);
4340
+ if (idx >= parts.length) {
4341
+ throw new ValidationError(
4342
+ `sequence("${series}"): format token "{${token}}" references partition index ${idx}, but only ${parts.length} partition component(s) were supplied.`
4343
+ );
4344
+ }
4345
+ continue;
4346
+ }
4347
+ throw new ValidationError(
4348
+ `sequence("${series}"): format contains unknown token "{${token}}". Accepted tokens: {seq}, {seq:0N}, {partition.i}.`
4349
+ );
4350
+ }
4351
+ return (serial) => format.replace(SEQ_FORMAT_TOKEN, (full, token) => {
4352
+ if (token === "seq") return String(serial);
4353
+ const padMatch = SEQ_PAD_TOKEN.exec(token);
4354
+ if (padMatch) return String(serial).padStart(Number(padMatch[1]), "0");
4355
+ const partMatch = SEQ_PARTITION_TOKEN.exec(token);
4356
+ if (partMatch) return String(parts[Number(partMatch[1])]);
4357
+ return full;
4358
+ });
4359
+ }
4029
4360
  function resolveSequenceKey(series, opts) {
4030
4361
  const partition = opts?.partition;
4031
4362
  if (!partition || partition.length === 0) return series;
@@ -4345,6 +4676,9 @@ var NO_PERIODS = {
4345
4676
  };
4346
4677
 
4347
4678
  // src/refs.ts
4679
+ function isRefArray(desc) {
4680
+ return desc.isArray === true;
4681
+ }
4348
4682
  var RefIntegrityError = class extends NoydbError {
4349
4683
  collection;
4350
4684
  id;
@@ -4381,6 +4715,17 @@ function ref(target, mode = "strict") {
4381
4715
  }
4382
4716
  return { target, mode };
4383
4717
  }
4718
+ function refArray(target, mode = "strict") {
4719
+ if (target.includes("/")) {
4720
+ throw new RefScopeError(target);
4721
+ }
4722
+ if (!target || target.startsWith("_")) {
4723
+ throw new Error(
4724
+ `refArray(): target collection name must be non-empty and cannot start with '_' (reserved for internal collections). Got "${target}".`
4725
+ );
4726
+ }
4727
+ return { target, mode, isArray: true };
4728
+ }
4384
4729
  var RefRegistry = class {
4385
4730
  outbound = /* @__PURE__ */ new Map();
4386
4731
  inbound = /* @__PURE__ */ new Map();
@@ -4405,7 +4750,7 @@ var RefRegistry = class {
4405
4750
  for (const k of existingKeys) {
4406
4751
  const a = existing[k];
4407
4752
  const b = refs[k];
4408
- if (!a || !b || a.target !== b.target || a.mode !== b.mode) {
4753
+ if (!a || !b || a.target !== b.target || a.mode !== b.mode || a.isArray !== b.isArray) {
4409
4754
  throw new Error(
4410
4755
  `RefRegistry: conflicting ref declarations for collection "${collection}" field "${k}"`
4411
4756
  );
@@ -4416,7 +4761,7 @@ var RefRegistry = class {
4416
4761
  this.outbound.set(collection, { ...refs });
4417
4762
  for (const [field, desc] of Object.entries(refs)) {
4418
4763
  const list = this.inbound.get(desc.target) ?? [];
4419
- list.push({ collection, field, mode: desc.mode });
4764
+ list.push({ collection, field, mode: desc.mode, ...desc.isArray ? { isArray: true } : {} });
4420
4765
  this.inbound.set(desc.target, list);
4421
4766
  }
4422
4767
  }
@@ -4444,6 +4789,141 @@ var RefRegistry = class {
4444
4789
  }
4445
4790
  };
4446
4791
 
4792
+ // src/links/link-set.ts
4793
+ var LINK_COLLECTION_PREFIX = "_links_";
4794
+ function linkCollectionName(name) {
4795
+ return `${LINK_COLLECTION_PREFIX}${name}`;
4796
+ }
4797
+ function isLinkCollectionName(name) {
4798
+ return name.startsWith(LINK_COLLECTION_PREFIX);
4799
+ }
4800
+ function linkRowKey(aId, bId) {
4801
+ return `${encodeURIComponent(aId)}|${encodeURIComponent(bId)}`;
4802
+ }
4803
+ var LinkSet = class {
4804
+ constructor(adapter, vault, name, spec, encrypted, getDEK, actor, emitter, endpointExists) {
4805
+ this.adapter = adapter;
4806
+ this.vault = vault;
4807
+ this.name = name;
4808
+ this.spec = spec;
4809
+ this.encrypted = encrypted;
4810
+ this.getDEK = getDEK;
4811
+ this.actor = actor;
4812
+ this.emitter = emitter;
4813
+ this.endpointExists = endpointExists;
4814
+ this.collName = linkCollectionName(name);
4815
+ }
4816
+ adapter;
4817
+ vault;
4818
+ name;
4819
+ spec;
4820
+ encrypted;
4821
+ getDEK;
4822
+ actor;
4823
+ emitter;
4824
+ endpointExists;
4825
+ collName;
4826
+ dekPromise = null;
4827
+ dek() {
4828
+ if (!this.dekPromise) this.dekPromise = this.getDEK(this.collName);
4829
+ return this.dekPromise;
4830
+ }
4831
+ async encryptEntry(entry, version) {
4832
+ const json = JSON.stringify(entry);
4833
+ const base = { _noydb: NOYDB_FORMAT_VERSION, _v: version, _ts: (/* @__PURE__ */ new Date()).toISOString(), _by: this.actor };
4834
+ if (!this.encrypted) return { ...base, _iv: "", _data: json };
4835
+ const { iv, data } = await encrypt(json, await this.dek());
4836
+ return { ...base, _iv: iv, _data: data };
4837
+ }
4838
+ async decryptEntry(env) {
4839
+ const json = this.encrypted ? await decrypt(env._iv, env._data, await this.dek()) : env._data;
4840
+ return JSON.parse(json);
4841
+ }
4842
+ async connect(aId, bId, meta) {
4843
+ if (!await this.endpointExists(this.spec.a, aId)) {
4844
+ throw new LinkEndpointError(this.name, this.spec.a, aId);
4845
+ }
4846
+ if (!await this.endpointExists(this.spec.b, bId)) {
4847
+ throw new LinkEndpointError(this.name, this.spec.b, bId);
4848
+ }
4849
+ const key = linkRowKey(aId, bId);
4850
+ const entry = meta !== void 0 ? { a: aId, b: bId, meta } : { a: aId, b: bId };
4851
+ const existing = await this.adapter.get(this.vault, this.collName, key);
4852
+ const env = await this.encryptEntry(entry, (existing?._v ?? 0) + 1);
4853
+ await this.adapter.put(this.vault, this.collName, key, env, existing?._v);
4854
+ this.emitter.emit("change", { vault: this.vault, collection: this.collName, id: key, action: "put" });
4855
+ }
4856
+ async disconnect(aId, bId) {
4857
+ const key = linkRowKey(aId, bId);
4858
+ const existing = await this.adapter.get(this.vault, this.collName, key);
4859
+ if (!existing) return;
4860
+ await this.adapter.delete(this.vault, this.collName, key);
4861
+ this.emitter.emit("change", { vault: this.vault, collection: this.collName, id: key, action: "delete" });
4862
+ }
4863
+ async has(aId, bId) {
4864
+ return await this.adapter.get(this.vault, this.collName, linkRowKey(aId, bId)) !== null;
4865
+ }
4866
+ async of(id) {
4867
+ const rows = await this.list();
4868
+ return rows.filter((r) => r.a === id || r.b === id);
4869
+ }
4870
+ async list() {
4871
+ const keys = await this.adapter.list(this.vault, this.collName);
4872
+ const out = [];
4873
+ for (const key of keys) {
4874
+ const env = await this.adapter.get(this.vault, this.collName, key);
4875
+ if (!env) continue;
4876
+ const e = await this.decryptEntry(env);
4877
+ out.push(e.meta !== void 0 ? { a: e.a, b: e.b, meta: e.meta } : { a: e.a, b: e.b });
4878
+ }
4879
+ return out;
4880
+ }
4881
+ // ── Vault-internal cascade helpers ──────────────────────────────────
4882
+ /** @internal — rows where the deleted endpoint id matches the relevant slot. */
4883
+ async _rowsTouchingEndpoint(collection, id) {
4884
+ const rows = await this.list();
4885
+ return rows.filter(
4886
+ (r) => this.spec.a === collection && r.a === id || this.spec.b === collection && r.b === id
4887
+ );
4888
+ }
4889
+ /** @internal — the storage collection name (for tx pre-image capture). */
4890
+ get _collectionName() {
4891
+ return this.collName;
4892
+ }
4893
+ };
4894
+ var LinkEndpointError = class extends NoydbError {
4895
+ link;
4896
+ endpoint;
4897
+ missingId;
4898
+ constructor(link, endpoint, missingId) {
4899
+ super(
4900
+ "LINK_ENDPOINT",
4901
+ `link("${link}").connect: endpoint "${endpoint}" has no record "${missingId}".`
4902
+ );
4903
+ this.name = "LinkEndpointError";
4904
+ this.link = link;
4905
+ this.endpoint = endpoint;
4906
+ this.missingId = missingId;
4907
+ }
4908
+ };
4909
+ var LinkIntegrityError = class extends NoydbError {
4910
+ link;
4911
+ endpoint;
4912
+ id;
4913
+ count;
4914
+ constructor(link, endpoint, id, count) {
4915
+ super(
4916
+ "LINK_INTEGRITY",
4917
+ `Cannot delete "${endpoint}"/"${id}": ${count} link(s) in "${link}" still reference it (onDelete: 'strict').`
4918
+ );
4919
+ this.name = "LinkIntegrityError";
4920
+ this.link = link;
4921
+ this.endpoint = endpoint;
4922
+ this.id = id;
4923
+ this.count = count;
4924
+ }
4925
+ };
4926
+
4447
4927
  // src/meta/user-envelope/api.ts
4448
4928
  var UserApi = class {
4449
4929
  constructor(adapter, vaultName, writerKeyringId, getDek, checkGate2) {
@@ -5468,13 +5948,17 @@ var Vault = class {
5468
5948
  */
5469
5949
  overlayedViewRegistry = null;
5470
5950
  /**
5471
- * Cached read-only facade handed to guard callbacks via `ctx.vault`,
5472
- * and to derivation callbacks via `derive(source, ctx)`. Allocated
5473
- * eagerly inside `_initGuards()` and/or `_initDerivations()` so read
5951
+ * Cached read-only facades handed to guard callbacks via `ctx.vault`
5952
+ * and to derivation callbacks via `derive(source, ctx)`. Split by
5953
+ * resolution layer (#285): the guard facade reads at `layer:'guard'`,
5954
+ * the derivation facade at `layer:'derivation'`, so i18nText / dictKey
5955
+ * fields resolve under that layer's `onMissing` policy. Allocated
5956
+ * eagerly inside `_initGuards()` / `_initDerivations()` so read
5474
5957
  * accessors stay synchronous (callers in `tx/transaction.ts` rely on
5475
- * that). Stays `null` for vaults with neither subsystem configured.
5958
+ * that). Each stays `null` for vaults without that subsystem.
5476
5959
  */
5477
- readOnlyFacade = null;
5960
+ guardFacade = null;
5961
+ derivationFacade = null;
5478
5962
  getDEK;
5479
5963
  /**
5480
5964
  * Per-principal user envelope API.
@@ -5636,6 +6120,10 @@ var Vault = class {
5636
6120
  i18nFieldRegistry = /* @__PURE__ */ new Map();
5637
6121
  /** Cache of DictionaryHandle instances, one per dictionary name. */
5638
6122
  dictionaryCache = /* @__PURE__ */ new Map();
6123
+ /** Registered link specs (#377-B), keyed by link name; set by `vault.link()`. */
6124
+ linkRegistry = /* @__PURE__ */ new Map();
6125
+ /** Cache of LinkSet handles, one per link name. */
6126
+ linkSetCache = /* @__PURE__ */ new Map();
5639
6127
  /** — subscribers for cross-tier access events. */
5640
6128
  crossTierSubs = /* @__PURE__ */ new Set();
5641
6129
  /** — currently-active elevation, or null. One per vault. */
@@ -5752,6 +6240,9 @@ var Vault = class {
5752
6240
  if (collectionName === SEQUENCE_COLLECTION) {
5753
6241
  throw new ReservedCollectionNameError(collectionName);
5754
6242
  }
6243
+ if (isLinkCollectionName(collectionName)) {
6244
+ throw new ReservedCollectionNameError(collectionName);
6245
+ }
5755
6246
  let coll = this.collectionCache.get(collectionName);
5756
6247
  if (coll && options?.moneyFields) {
5757
6248
  coll._applyMoneyFields(options.moneyFields);
@@ -5823,6 +6314,7 @@ var Vault = class {
5823
6314
  }));
5824
6315
  schemaUpdateGate = new SchemaUpdateGate(work);
5825
6316
  }
6317
+ const effectiveHistoryConfig = options?.historyConfig ?? this.historyConfig;
5826
6318
  const collOpts = {
5827
6319
  adapter: this.adapter,
5828
6320
  vault: this.name,
@@ -5838,7 +6330,7 @@ var Vault = class {
5838
6330
  schemaFence: this.schemaFence,
5839
6331
  getDEK: this.getDEK,
5840
6332
  onDirty: this.onDirty,
5841
- historyConfig: this.historyConfig,
6333
+ historyConfig: effectiveHistoryConfig,
5842
6334
  // thread the vault-wide blob strategy into every
5843
6335
  // collection. `undefined` is intentionally preserved so the
5844
6336
  // Collection constructor uses its NO_BLOBS default.
@@ -5849,7 +6341,11 @@ var Vault = class {
5849
6341
  historyStrategy: this.historyStrategy,
5850
6342
  i18nStrategy: this.i18nStrategy,
5851
6343
  syncStrategy: this.syncStrategy,
5852
- ledger: this.getLedgerOrNull() ?? void 0,
6344
+ // Per-collection ledger opt-out (#361): when this collection sets
6345
+ // `historyConfig.ledger: false`, withhold the ledger reference so all
6346
+ // four `if (this.ledger)` append sites in Collection no-op. The chain
6347
+ // stays valid — it simply never receives this collection's entries.
6348
+ ledger: effectiveHistoryConfig.ledger === false ? void 0 : this.getLedgerOrNull() ?? void 0,
5853
6349
  refEnforcer: this,
5854
6350
  joinResolver: this,
5855
6351
  defaultLocale: this.locale,
@@ -6210,6 +6706,68 @@ var Vault = class {
6210
6706
  }
6211
6707
  return handle;
6212
6708
  }
6709
+ /**
6710
+ * Declare a managed many-to-many link set (#377-B). Registers a
6711
+ * `_links_<name>` junction between two endpoint collections; access its
6712
+ * rows via `vault.links(name)`. Idempotent for an identical re-declaration;
6713
+ * a conflicting one throws. See {@link links}.
6714
+ *
6715
+ * ```ts
6716
+ * vault.link('saleLineLinks', { a: ref('saleLines'), b: ref('purchaseLines'), onDelete: 'cascade' })
6717
+ * ```
6718
+ *
6719
+ * `a` / `b` accept either a collection name or a `ref(target)` descriptor
6720
+ * (only its `target` is used — links manage their own integrity). `onDelete`
6721
+ * governs what happens to link rows when an endpoint record is deleted
6722
+ * (`'cascade'` default, `'strict'`, `'warn'`).
6723
+ */
6724
+ link(name, spec) {
6725
+ const a = typeof spec.a === "string" ? spec.a : spec.a.target;
6726
+ const b = typeof spec.b === "string" ? spec.b : spec.b.target;
6727
+ for (const [slot, target] of [["a", a], ["b", b]]) {
6728
+ if (!target || target.startsWith("_") || target.includes("/")) {
6729
+ throw new ValidationError(
6730
+ `vault.link("${name}"): endpoint "${slot}" must be a simple collection name, got "${target}".`
6731
+ );
6732
+ }
6733
+ }
6734
+ const resolved = { a, b, ...spec.onDelete ? { onDelete: spec.onDelete } : {} };
6735
+ const existing = this.linkRegistry.get(name);
6736
+ if (existing) {
6737
+ if (existing.a !== resolved.a || existing.b !== resolved.b || (existing.onDelete ?? "cascade") !== (resolved.onDelete ?? "cascade")) {
6738
+ throw new ValidationError(`vault.link("${name}"): conflicting re-declaration.`);
6739
+ }
6740
+ return;
6741
+ }
6742
+ this.linkRegistry.set(name, resolved);
6743
+ }
6744
+ /**
6745
+ * Access a declared link set (#377-B). Throws if `name` was not first
6746
+ * declared via {@link link}. Returns a cached {@link LinkSetHandle}:
6747
+ * `connect(a, b, meta?)`, `disconnect(a, b)`, `has(a, b)`, `of(id)`, `list()`.
6748
+ */
6749
+ links(name) {
6750
+ let handle = this.linkSetCache.get(name);
6751
+ if (!handle) {
6752
+ const spec = this.linkRegistry.get(name);
6753
+ if (!spec) {
6754
+ throw new ValidationError(`vault.links("${name}"): not declared. Call vault.link("${name}", { a, b }) first.`);
6755
+ }
6756
+ handle = new LinkSet(
6757
+ this.adapter,
6758
+ this.name,
6759
+ name,
6760
+ spec,
6761
+ this.encrypted,
6762
+ this.getDEK,
6763
+ this.keyring.userId,
6764
+ this.emitter,
6765
+ async (collection, id) => await this.collection(collection).get(id) !== null
6766
+ );
6767
+ this.linkSetCache.set(name, handle);
6768
+ }
6769
+ return handle;
6770
+ }
6213
6771
  /**
6214
6772
  * Build a `JoinableSource` for a dictKey field, for use in dict joins
6215
6773
  *. Returns a source whose snapshot contains `{ key, ...labels }`
@@ -6369,65 +6927,16 @@ var Vault = class {
6369
6927
  });
6370
6928
  }
6371
6929
  }
6372
- /**
6373
- * Bulk blob extraction primitive.
6374
- *
6375
- * Returns an async-iterable handle over every blob attached to
6376
- * records in the vault. Single capability check (`plaintext/blob`)
6377
- * at handle creation; single audit entry to `_export_audit` before
6378
- * the first yield. Per-blob decryption happens lazily as the
6379
- * consumer pulls tuples.
6380
- *
6381
- * ```ts
6382
- * const handle = vault.exportBlobs({
6383
- * collections: ['invoiceScans'],
6384
- * where: (rec) => (rec as { clientId?: string }).clientId === 'c-123',
6385
- * })
6386
- * for await (const { bytes, meta, recordRef } of handle) {
6387
- * await uploadToColdStorage(bytes, recordRef)
6388
- * }
6389
- * ```
6390
- *
6391
- * @see `@noy-db/hub/store/export-blobs` for the full option surface.
6392
- */
6393
- /**
6394
- * Evict blob slots per the per-collection `blobFields` retention
6395
- * policy.
6396
- *
6397
- * Iterates every collection declared with `{ blobFields: {...} }`.
6398
- * For each record, checks every configured slot against its
6399
- * policy — `retainDays` (age-based TTL) and/or `evictWhen(record)`
6400
- * (predicate) — and evicts matching slots. Every eviction writes
6401
- * one entry to `_blob_eviction_audit` (actor + eTag + reason +
6402
- * timestamp, no plaintext). Consumer-scheduled; noy-db never runs
6403
- * this on its own.
6404
- *
6405
- * ```ts
6406
- * await vault.compact() // run full pass
6407
- * await vault.compact({ dryRun: true }) // preview counts
6408
- * await vault.compact({ maxEvictions: 1000 }) // cap batch
6409
- * ```
6410
- */
6411
- /**
6412
- * Atomic, gap-free numbering. `vault.sequence('invoice-2026').next()`
6413
- * returns 1, 2, 3, … with no gaps or duplicates under concurrency, via
6414
- * an optimistic-CAS counter at `_sequences/<name>`. Each name is an
6415
- * independent sequence.
6416
- *
6417
- * **Online-only:** `next()` throws `SequenceOfflineError` unless the
6418
- * store advertises `capabilities.casAtomic` — gap-free numbering cannot
6419
- * be serialized by an offline / non-CAS writer.
6420
- *
6421
- * ```ts
6422
- * const n = await vault.sequence('invoice-2026').next() // 1, then 2, …
6423
- * const cur = await vault.sequence('invoice-2026').peek() // current value, no allocation
6424
- * ```
6425
- */
6426
6930
  sequence(series, opts) {
6427
6931
  if (series.includes("\0")) {
6428
6932
  throw new ValidationError(`sequence("${series}"): series name must not contain a null byte (\\x00).`);
6429
6933
  }
6430
6934
  if (this.numberingConfigs.has(series)) {
6935
+ if (opts?.format !== void 0) {
6936
+ throw new ValidationError(
6937
+ `sequence("${series}") is a deferred-numbering series; the format option applies to CAS sequences only.`
6938
+ );
6939
+ }
6431
6940
  const eng = this.deferred();
6432
6941
  return {
6433
6942
  next: async (nextOpts) => {
@@ -6451,7 +6960,17 @@ var Vault = class {
6451
6960
  actor: this.keyring.userId
6452
6961
  });
6453
6962
  }
6454
- return this.sequenceStore.handle(resolveSequenceKey(series, opts));
6963
+ const handle = this.sequenceStore.handle(resolveSequenceKey(series, opts));
6964
+ if (opts?.format === void 0) return handle;
6965
+ const render = compileSequenceFormat(opts.format, series, opts.partition);
6966
+ return {
6967
+ next: async (nextOpts) => {
6968
+ const serial = await handle.next(nextOpts);
6969
+ return { serial, formatted: render(serial) };
6970
+ },
6971
+ peek: () => handle.peek(),
6972
+ seedTo: (n) => handle.seedTo(n)
6973
+ };
6455
6974
  }
6456
6975
  /** @internal — lazily build the deferred-numbering engine with a cache-coherent stamp. */
6457
6976
  deferred() {
@@ -6566,12 +7085,12 @@ var Vault = class {
6566
7085
  if (!fieldSchema) {
6567
7086
  throw new AttestationError(`issueAttestation: collection '${collectionName}' has no attestation field-schema. Declare it via vault.collection('${collectionName}', { attestation: { fields: [...] } }).`);
6568
7087
  }
6569
- const { issueAttestationCore } = await import("./issue-TTMGHQ2J.js");
7088
+ const { issueAttestationCore } = await import("./issue-EPA2PSWP.js");
6570
7089
  const out = await issueAttestationCore(this.makeIssueContext(), { collection: collectionName, id, fieldSchema });
6571
7090
  return { docId: out.docId, qr: out.qr, keyId: out.keyId, publicKeyB64: out.publicKeyB64 };
6572
7091
  }
6573
7092
  async getDocumentSigningPublicKey() {
6574
- const { loadSigner, loadOrCreateSigner } = await import("./signer-YSXZT574.js");
7093
+ const { loadSigner, loadOrCreateSigner } = await import("./signer-UNWOUJAK.js");
6575
7094
  const existing = await loadSigner(this.adapter, this.name, this.getDEK);
6576
7095
  if (existing) return { keyId: existing.keyId, publicKeyB64: existing.publicKeyB64 };
6577
7096
  if (this.keyring.role !== "owner") {
@@ -6597,19 +7116,19 @@ var Vault = class {
6597
7116
  };
6598
7117
  }
6599
7118
  async revokeAttestation(docId) {
6600
- const { revokeDocCore } = await import("./revoke-B54H2S2W.js");
7119
+ const { revokeDocCore } = await import("./revoke-IFLXEZA5.js");
6601
7120
  await revokeDocCore(this.makeRevokeContext(), docId);
6602
7121
  }
6603
7122
  async unrevokeAttestation(docId) {
6604
- const { unrevokeDocCore } = await import("./revoke-B54H2S2W.js");
7123
+ const { unrevokeDocCore } = await import("./revoke-IFLXEZA5.js");
6605
7124
  await unrevokeDocCore(this.makeRevokeContext(), docId);
6606
7125
  }
6607
7126
  async getRevokedDocIds() {
6608
- const { getRevokedDocIdsCore } = await import("./revoke-B54H2S2W.js");
7127
+ const { getRevokedDocIdsCore } = await import("./revoke-IFLXEZA5.js");
6609
7128
  return getRevokedDocIdsCore(this.makeRevokeContext());
6610
7129
  }
6611
7130
  async publishRevocationList() {
6612
- const { publishRevocationListCore } = await import("./revoke-B54H2S2W.js");
7131
+ const { publishRevocationListCore } = await import("./revoke-IFLXEZA5.js");
6613
7132
  return publishRevocationListCore(this.makeRevokeContext());
6614
7133
  }
6615
7134
  makeRevokeContext() {
@@ -6678,6 +7197,43 @@ var Vault = class {
6678
7197
  if (descriptor.mode !== "strict") continue;
6679
7198
  const rawId = obj[field];
6680
7199
  if (rawId === null || rawId === void 0) continue;
7200
+ if (isRefArray(descriptor)) {
7201
+ if (!Array.isArray(rawId)) {
7202
+ throw new RefIntegrityError({
7203
+ collection: collectionName,
7204
+ id: obj["id"] ?? "<unknown>",
7205
+ field,
7206
+ refTo: descriptor.target,
7207
+ refId: null,
7208
+ message: `Array ref field "${collectionName}.${field}" must be an array, got ${typeof rawId}.`
7209
+ });
7210
+ }
7211
+ const arrTarget = this.collection(descriptor.target);
7212
+ for (const el of rawId) {
7213
+ if (typeof el !== "string" && typeof el !== "number") {
7214
+ throw new RefIntegrityError({
7215
+ collection: collectionName,
7216
+ id: obj["id"] ?? "<unknown>",
7217
+ field,
7218
+ refTo: descriptor.target,
7219
+ refId: null,
7220
+ message: `Array ref "${collectionName}.${field}" elements must be strings or numbers, got ${typeof el}.`
7221
+ });
7222
+ }
7223
+ const elId = String(el);
7224
+ if (!await arrTarget.get(elId)) {
7225
+ throw new RefIntegrityError({
7226
+ collection: collectionName,
7227
+ id: obj["id"] ?? "<unknown>",
7228
+ field,
7229
+ refTo: descriptor.target,
7230
+ refId: elId,
7231
+ message: `Strict array ref "${collectionName}.${field}" \u2192 "${descriptor.target}" cannot be satisfied: element id "${elId}" not found in "${descriptor.target}".`
7232
+ });
7233
+ }
7234
+ }
7235
+ continue;
7236
+ }
6681
7237
  if (typeof rawId !== "string" && typeof rawId !== "number") {
6682
7238
  throw new RefIntegrityError({
6683
7239
  collection: collectionName,
@@ -6727,6 +7283,11 @@ var Vault = class {
6727
7283
  const allRecords = await fromCollection.list();
6728
7284
  const matches = allRecords.filter((rec) => {
6729
7285
  const raw = rec[rule.field];
7286
+ if (rule.isArray) {
7287
+ return Array.isArray(raw) && raw.some(
7288
+ (el) => (typeof el === "string" || typeof el === "number") && String(el) === id
7289
+ );
7290
+ }
6730
7291
  if (typeof raw !== "string" && typeof raw !== "number") return false;
6731
7292
  return String(raw) === id;
6732
7293
  });
@@ -6765,10 +7326,45 @@ var Vault = class {
6765
7326
  }
6766
7327
  }
6767
7328
  }
7329
+ await this.enforceLinksOnDelete(collectionName, id);
6768
7330
  } finally {
6769
7331
  this.cascadeInProgress.delete(key);
6770
7332
  }
6771
7333
  }
7334
+ /**
7335
+ * @internal — apply link `onDelete` policy when an endpoint record is
7336
+ * deleted (#377-B). `'strict'` throws (blocks the delete), `'cascade'`
7337
+ * removes the touching link rows (tx-atomic when a transaction is active),
7338
+ * `'warn'` leaves orphans for `checkIntegrity()`.
7339
+ */
7340
+ async enforceLinksOnDelete(collectionName, id) {
7341
+ for (const [name, spec] of this.linkRegistry) {
7342
+ if (spec.a !== collectionName && spec.b !== collectionName) continue;
7343
+ const handle = this.links(name);
7344
+ const touching = await handle._rowsTouchingEndpoint(collectionName, id);
7345
+ if (touching.length === 0) continue;
7346
+ const mode = spec.onDelete ?? "cascade";
7347
+ if (mode === "warn") continue;
7348
+ if (mode === "strict") {
7349
+ throw new LinkIntegrityError(name, collectionName, id, touching.length);
7350
+ }
7351
+ const linkColl = handle._collectionName;
7352
+ const txCtx = this.noydb._activeTxContextOrNull;
7353
+ for (const row of touching) {
7354
+ const rowKey = linkRowKey(row.a, row.b);
7355
+ if (txCtx !== null) {
7356
+ const prior = await this.adapter.get(this.name, linkColl, rowKey);
7357
+ if (prior !== null) {
7358
+ txCtx._executed.push({
7359
+ op: { type: "delete", vaultName: this.name, collectionName: linkColl, id: rowKey },
7360
+ priorEnvelope: prior
7361
+ });
7362
+ }
7363
+ }
7364
+ await handle.disconnect(row.a, row.b);
7365
+ }
7366
+ }
7367
+ }
6772
7368
  // ─── Join resolver) ────────────────────
6773
7369
  /**
6774
7370
  * Look up the `RefDescriptor` the left collection declared for a
@@ -6829,6 +7425,23 @@ var Vault = class {
6829
7425
  for (const [field, descriptor] of Object.entries(refs)) {
6830
7426
  const rawId = record[field];
6831
7427
  if (rawId === null || rawId === void 0) continue;
7428
+ const target = this.collection(descriptor.target);
7429
+ if (isRefArray(descriptor)) {
7430
+ if (!Array.isArray(rawId)) {
7431
+ violations.push({ collection: collectionName, id: recId, field, refTo: descriptor.target, refId: rawId, mode: descriptor.mode });
7432
+ continue;
7433
+ }
7434
+ for (const el of rawId) {
7435
+ if (typeof el !== "string" && typeof el !== "number") {
7436
+ violations.push({ collection: collectionName, id: recId, field, refTo: descriptor.target, refId: el, mode: descriptor.mode });
7437
+ continue;
7438
+ }
7439
+ if (!await target.get(String(el))) {
7440
+ violations.push({ collection: collectionName, id: recId, field, refTo: descriptor.target, refId: el, mode: descriptor.mode });
7441
+ }
7442
+ }
7443
+ continue;
7444
+ }
6832
7445
  if (typeof rawId !== "string" && typeof rawId !== "number") {
6833
7446
  violations.push({
6834
7447
  collection: collectionName,
@@ -6841,7 +7454,6 @@ var Vault = class {
6841
7454
  continue;
6842
7455
  }
6843
7456
  const refId = String(rawId);
6844
- const target = this.collection(descriptor.target);
6845
7457
  const exists = await target.get(refId);
6846
7458
  if (!exists) {
6847
7459
  violations.push({
@@ -6856,6 +7468,19 @@ var Vault = class {
6856
7468
  }
6857
7469
  }
6858
7470
  }
7471
+ for (const [name, spec] of this.linkRegistry) {
7472
+ const linkColl = linkCollectionName(name);
7473
+ const rows = await this.links(name).list();
7474
+ for (const row of rows) {
7475
+ const rowKey = linkRowKey(row.a, row.b);
7476
+ if (await this.collection(spec.a).get(row.a) === null) {
7477
+ violations.push({ collection: linkColl, id: rowKey, field: "a", refTo: spec.a, refId: row.a, mode: spec.onDelete ?? "cascade" });
7478
+ }
7479
+ if (await this.collection(spec.b).get(row.b) === null) {
7480
+ violations.push({ collection: linkColl, id: rowKey, field: "b", refTo: spec.b, refId: row.b, mode: spec.onDelete ?? "cascade" });
7481
+ }
7482
+ }
7483
+ }
6859
7484
  return { violations };
6860
7485
  }
6861
7486
  /**
@@ -6962,6 +7587,8 @@ var Vault = class {
6962
7587
  const blobResidueCollections = /* @__PURE__ */ new Set();
6963
7588
  let blobsShredded = 0;
6964
7589
  let blobsRetainedShared = 0;
7590
+ let indexPostingsPurged = 0;
7591
+ const indexResidue = [];
6965
7592
  const blobsEnabled = this.blobStrategy !== void 0;
6966
7593
  const actor = this.keyring.userId;
6967
7594
  for (const ref2 of refs) {
@@ -6983,6 +7610,9 @@ var Vault = class {
6983
7610
  ref2.id,
6984
7611
  actor
6985
7612
  );
7613
+ const idxPurge = await coll._purgePersistedIndexes(ref2.id);
7614
+ indexPostingsPurged += idxPurge.purged;
7615
+ for (const field of idxPurge.residue) indexResidue.push(`${ref2.collection}:${ref2.id}:${field}`);
6986
7616
  if (blobsEnabled) {
6987
7617
  const r = await this.collection(ref2.collection).blob(ref2.id).shredAllForRecord();
6988
7618
  blobsShredded += r.shredded.length;
@@ -7018,7 +7648,9 @@ var Vault = class {
7018
7648
  unmigratedCount: unmigratedRecords.length,
7019
7649
  blobsShredded,
7020
7650
  blobsRetainedShared,
7021
- blobResidueCollections: [...blobResidueCollections]
7651
+ blobResidueCollections: [...blobResidueCollections],
7652
+ indexPostingsPurged,
7653
+ indexResidueCount: indexResidue.length
7022
7654
  })
7023
7655
  });
7024
7656
  return {
@@ -7030,6 +7662,8 @@ var Vault = class {
7030
7662
  blobsShredded,
7031
7663
  blobsRetainedShared,
7032
7664
  blobResidueCollections: [...blobResidueCollections],
7665
+ indexPostingsPurged,
7666
+ indexResidue,
7033
7667
  ledgerEntry
7034
7668
  };
7035
7669
  }
@@ -7126,12 +7760,12 @@ var Vault = class {
7126
7760
  if (handles.length === 0) return;
7127
7761
  const [{ GuardRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
7128
7762
  import("./registry-DKEXOJVO.js"),
7129
- import("./read-only-facade-ITU6L7BL.js")
7763
+ import("./read-only-facade-EX6WZZBP.js")
7130
7764
  ]);
7131
7765
  const registry = new GuardRegistry();
7132
7766
  for (const h of handles) registry.register(h.spec);
7133
7767
  this.guardRegistry = registry;
7134
- this.readOnlyFacade = new ReadOnlyVaultFacade(this);
7768
+ this.guardFacade = new ReadOnlyVaultFacade(this, "guard");
7135
7769
  }
7136
7770
  /**
7137
7771
  * @internal — The gate handler in Noydb.#registerGuardGate calls into
@@ -7153,8 +7787,8 @@ var Vault = class {
7153
7787
  async _initDerivations(handles) {
7154
7788
  if (handles.length === 0) return;
7155
7789
  const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
7156
- import("./registry-TGZISEWC.js"),
7157
- import("./read-only-facade-ITU6L7BL.js")
7790
+ import("./registry-ERNAMRDE.js"),
7791
+ import("./read-only-facade-EX6WZZBP.js")
7158
7792
  ]);
7159
7793
  const registry = new DerivationRegistry();
7160
7794
  for (const h of handles) {
@@ -7162,8 +7796,8 @@ var Vault = class {
7162
7796
  }
7163
7797
  registry.validate();
7164
7798
  this.derivationRegistry = registry;
7165
- if (this.readOnlyFacade === null) {
7166
- this.readOnlyFacade = new ReadOnlyVaultFacade(this);
7799
+ if (this.derivationFacade === null) {
7800
+ this.derivationFacade = new ReadOnlyVaultFacade(this, "derivation");
7167
7801
  }
7168
7802
  }
7169
7803
  /**
@@ -7184,7 +7818,7 @@ var Vault = class {
7184
7818
  */
7185
7819
  async _initMaterializedViews(handles) {
7186
7820
  if (handles.length === 0) return;
7187
- const { MaterializedViewRegistry } = await import("./registry-SECUWSGY.js");
7821
+ const { MaterializedViewRegistry } = await import("./registry-RDPTFXQ7.js");
7188
7822
  const registry = new MaterializedViewRegistry();
7189
7823
  this.materializedViewRegistry = registry;
7190
7824
  const db = this;
@@ -7208,7 +7842,7 @@ var Vault = class {
7208
7842
  */
7209
7843
  async _initOverlayedViews(handles) {
7210
7844
  if (handles.length === 0) return;
7211
- const { OverlayedViewRegistry } = await import("./registry-3YFLZ7WD.js");
7845
+ const { OverlayedViewRegistry } = await import("./registry-EXTHSXQW.js");
7212
7846
  const registry = new OverlayedViewRegistry();
7213
7847
  const mvRegistry = this.materializedViewRegistry;
7214
7848
  const overlayNames = /* @__PURE__ */ new Set();
@@ -7255,13 +7889,13 @@ var Vault = class {
7255
7889
  if (!reg) {
7256
7890
  throw new Error(`refreshView: no MV registered with name "${name}"`);
7257
7891
  }
7258
- const { MaterializedViewExecutor } = await import("./executor-3W63Y44O.js");
7892
+ const { MaterializedViewExecutor } = await import("./executor-44R5CUS2.js");
7259
7893
  const result = await MaterializedViewExecutor.refresh(reg, {
7260
7894
  getCollection: (n) => this.collection(n),
7261
7895
  getActiveTxContext: () => this.noydb._activeTxContextOrNull,
7262
7896
  getQueryContext: () => this
7263
7897
  });
7264
- const { clearMVStale } = await import("./stale-TOA36SRK.js");
7898
+ const { clearMVStale } = await import("./stale-NTEV5SLX.js");
7265
7899
  clearMVStale(registry, name);
7266
7900
  return result;
7267
7901
  }
@@ -7277,10 +7911,10 @@ var Vault = class {
7277
7911
  if (registry === null) return { derived: 0, failed: 0 };
7278
7912
  const strategies = registry.strategiesForSource(sourceCollection);
7279
7913
  if (strategies.length === 0) return { derived: 0, failed: 0 };
7280
- const { DerivationExecutor } = await import("./executor-CFFWPWBJ.js");
7914
+ const { DerivationExecutor } = await import("./executor-OKFLQCDW.js");
7281
7915
  const sourceColl = this.collection(sourceCollection);
7282
7916
  const records = await sourceColl.list();
7283
- const ctx = { vault: this.readOnlyFacade ?? new (await import("./read-only-facade-ITU6L7BL.js")).ReadOnlyVaultFacade(this) };
7917
+ const ctx = { vault: this.derivationFacade ?? new (await import("./read-only-facade-EX6WZZBP.js")).ReadOnlyVaultFacade(this, "derivation") };
7284
7918
  let derived = 0;
7285
7919
  let failed = 0;
7286
7920
  for (const record of records) {
@@ -7302,7 +7936,7 @@ var Vault = class {
7302
7936
  if (!outSpec) continue;
7303
7937
  const outputColl = this.collection(outSpec.collection);
7304
7938
  if (out.kind === "array") {
7305
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-FIJJ46YG.js");
7939
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-DCQWJQ6S.js");
7306
7940
  const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key);
7307
7941
  const prevKeys = new Set(prior?.keys ?? []);
7308
7942
  const newKeysList = out.entries.map((e) => e.key);
@@ -7345,17 +7979,18 @@ var Vault = class {
7345
7979
  * never see null).
7346
7980
  */
7347
7981
  _getReadOnlyFacade() {
7348
- return this.readOnlyFacade;
7982
+ return this.guardFacade;
7349
7983
  }
7350
7984
  /**
7351
- * Internal lazy-allocator for the read-only facade. Used as a
7352
- * defensive fallback; in practice `_initGuards()` eagerly
7353
- * instantiates this, so the lazy path is a no-op.
7985
+ * Internal lazy-allocator for the derivation read-only facade
7986
+ * (`layer:'derivation'`). Used as a defensive fallback; in practice
7987
+ * `_initDerivations()` eagerly instantiates this, so the lazy path is
7988
+ * a no-op.
7354
7989
  */
7355
7990
  _ensureReadOnlyFacade() {
7356
- if (this.readOnlyFacade !== null) return this.readOnlyFacade;
7991
+ if (this.derivationFacade !== null) return this.derivationFacade;
7357
7992
  throw new Error(
7358
- "Vault: guard hook fired before _initGuards() completed. This typically means the vault was opened via the sync fallback path (Noydb.vault(name)) without first calling await db.openVault(name). See issue #132."
7993
+ "Vault: derivation hook fired before _initDerivations() completed. This typically means the vault was opened via the sync fallback path (Noydb.vault(name)) without first calling await db.openVault(name). See issue #132."
7359
7994
  );
7360
7995
  }
7361
7996
  /**
@@ -7523,7 +8158,7 @@ var Vault = class {
7523
8158
  * collection.
7524
8159
  */
7525
8160
  async delegate(opts) {
7526
- const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-MGH5SODX.js");
8161
+ const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-5HON72PV.js");
7527
8162
  if (!this.keyring.kek) {
7528
8163
  throw new ValidationError(
7529
8164
  "issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (passphrase) first."
@@ -7545,7 +8180,7 @@ var Vault = class {
7545
8180
  * if the id does not exist.
7546
8181
  */
7547
8182
  async revokeDelegation(id) {
7548
- const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-MGH5SODX.js");
8183
+ const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-5HON72PV.js");
7549
8184
  await revokeDelegation(this.adapter, this.name, id);
7550
8185
  void DELEGATIONS_COLLECTION;
7551
8186
  }
@@ -8014,7 +8649,7 @@ var Vault = class {
8014
8649
  * @see docs/subsystems/public-envelope.md
8015
8650
  */
8016
8651
  async getPublicEnvelope(opts = {}) {
8017
- const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-RXZNP3V6.js");
8652
+ const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-AGU6SS4Z.js");
8018
8653
  return readPublicEnvelope2(this.adapter, this.name, opts);
8019
8654
  }
8020
8655
  /**
@@ -8291,6 +8926,8 @@ var Vault = class {
8291
8926
  */
8292
8927
  async *exportStream(opts = {}) {
8293
8928
  const granularity = opts.granularity ?? "collection";
8929
+ const exportLocale = opts.resolveLabels;
8930
+ const localeOpts = exportLocale !== void 0 ? { locale: exportLocale, _layer: "export" } : void 0;
8294
8931
  const snapshot = await this.adapter.loadAll(this.name);
8295
8932
  const collectionNames = Object.keys(snapshot).sort();
8296
8933
  const ledgerHead = opts.withLedgerHead ? await (async () => {
@@ -8300,19 +8937,21 @@ var Vault = class {
8300
8937
  return head ? { hash: head.hash, index: head.entry.index, ts: head.entry.ts } : void 0;
8301
8938
  })() : void 0;
8302
8939
  const dictSnapshotCache = /* @__PURE__ */ new Map();
8303
- for (const collectionName of collectionNames) {
8304
- const dictFields = this.dictKeyFieldRegistry.get(collectionName);
8305
- if (dictFields && Object.keys(dictFields).length > 0) {
8306
- const snap = {};
8307
- for (const [fieldName, dictName] of Object.entries(dictFields)) {
8308
- const entries = await this.dictionary(dictName).list();
8309
- const keyMap = {};
8310
- for (const entry of entries) {
8311
- keyMap[entry.key] = entry.labels;
8940
+ if (exportLocale === void 0) {
8941
+ for (const collectionName of collectionNames) {
8942
+ const dictFields = this.dictKeyFieldRegistry.get(collectionName);
8943
+ if (dictFields && Object.keys(dictFields).length > 0) {
8944
+ const snap = {};
8945
+ for (const [fieldName, dictName] of Object.entries(dictFields)) {
8946
+ const entries = await this.dictionary(dictName).list();
8947
+ const keyMap = {};
8948
+ for (const entry of entries) {
8949
+ keyMap[entry.key] = entry.labels;
8950
+ }
8951
+ snap[fieldName] = keyMap;
8312
8952
  }
8313
- snap[fieldName] = keyMap;
8953
+ dictSnapshotCache.set(collectionName, snap);
8314
8954
  }
8315
- dictSnapshotCache.set(collectionName, snap);
8316
8955
  }
8317
8956
  }
8318
8957
  for (const collectionName of collectionNames) {
@@ -8325,7 +8964,7 @@ var Vault = class {
8325
8964
  if (granularity === "collection") {
8326
8965
  const records = [];
8327
8966
  for (const id of ids) {
8328
- const record = await coll.get(id);
8967
+ const record = await coll.get(id, localeOpts);
8329
8968
  if (record !== null) records.push(record);
8330
8969
  }
8331
8970
  const chunk = {
@@ -8339,7 +8978,7 @@ var Vault = class {
8339
8978
  yield chunk;
8340
8979
  } else {
8341
8980
  for (const id of ids) {
8342
- const record = await coll.get(id);
8981
+ const record = await coll.get(id, localeOpts);
8343
8982
  if (record === null) continue;
8344
8983
  const chunk = {
8345
8984
  collection: collectionName,
@@ -8443,7 +9082,10 @@ var Vault = class {
8443
9082
  const allDictionaries = {};
8444
9083
  for await (const chunk of this.exportStream({
8445
9084
  granularity: "collection",
8446
- withLedgerHead: opts.withLedgerHead === true
9085
+ withLedgerHead: opts.withLedgerHead === true,
9086
+ // #285 export layer: thread the export locale so records are read at the
9087
+ // `export` layer (i18nText collapsed + dictKey/staticDict labels resolved).
9088
+ ...opts.resolveLabels !== void 0 ? { resolveLabels: opts.resolveLabels } : {}
8447
9089
  })) {
8448
9090
  collections[chunk.collection] = {
8449
9091
  schema: null,
@@ -9679,7 +10321,7 @@ var Noydb = class {
9679
10321
  if (!facade) return;
9680
10322
  const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
9681
10323
  await registry.runChecks(e.collection, incoming, ctx);
9682
- const { GuardExecutor } = await import("./executor-VDQQOR4F.js");
10324
+ const { GuardExecutor } = await import("./executor-AOACUK7Z.js");
9683
10325
  for (const g of guards) {
9684
10326
  await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming, e.computedFieldNames);
9685
10327
  }
@@ -10280,11 +10922,11 @@ var Noydb = class {
10280
10922
  if (name === STATE_VAULT_NAME) throw new ReservedVaultNameError(name);
10281
10923
  const template = this.vaultTemplates.get(opts.sharding.vaultTemplate);
10282
10924
  if (!template) throw new VaultTemplateNotFoundError(opts.sharding.vaultTemplate);
10283
- const { VaultGroup } = await import("./vault-group-DHAHFX2A.js");
10284
- const { StateManagementVault } = await import("./state-vault-W2OEABNO.js");
10925
+ const { VaultGroup } = await import("./vault-group-27EV7KB4.js");
10926
+ const { StateManagementVault } = await import("./state-vault-TUTFRTOA.js");
10285
10927
  const stateVault = opts.registry ? void 0 : await StateManagementVault.open(this);
10286
10928
  const registry = opts.registry ?? stateVault.registry;
10287
- const group = new VaultGroup(this, name, registry, opts.sharding, template);
10929
+ const group = new VaultGroup(this, name, registry, opts.sharding, template, opts.migrateOnOpen ?? false);
10288
10930
  if (stateVault) {
10289
10931
  group._attachStateVault(stateVault);
10290
10932
  await stateVault.recordManifest(opts.sharding.vaultTemplate, template);
@@ -10308,7 +10950,7 @@ var Noydb = class {
10308
10950
  */
10309
10951
  async openStateManagementVault() {
10310
10952
  if (this.closed) throw new ValidationError("Instance is closed");
10311
- const { StateManagementVault } = await import("./state-vault-W2OEABNO.js");
10953
+ const { StateManagementVault } = await import("./state-vault-TUTFRTOA.js");
10312
10954
  return StateManagementVault.open(this);
10313
10955
  }
10314
10956
  /**
@@ -10318,6 +10960,16 @@ var Noydb = class {
10318
10960
  async _shardVaultProvisioned(vaultId) {
10319
10961
  return (await this.options.store.list(vaultId, "_keyring")).length > 0;
10320
10962
  }
10963
+ /**
10964
+ * @internal — the physical backend store a vault id maps to. A
10965
+ * `routeStore` resolves the vault-prefix route via its `resolveBackend`;
10966
+ * a plain store is its own backend. Used by the federation data-residency
10967
+ * guard to read the placement backend's `capabilities.region` (#271).
10968
+ */
10969
+ _resolveBackend(vaultId) {
10970
+ const store = this.options.store;
10971
+ return store.resolveBackend ? store.resolveBackend(vaultId) : this.options.store;
10972
+ }
10321
10973
  /**
10322
10974
  * Change the current user's passphrase for a vault.
10323
10975
  *
@@ -11810,6 +12462,7 @@ function normalizeSyncTargets(sync) {
11810
12462
 
11811
12463
  export {
11812
12464
  withArchive,
12465
+ compileSequenceFormat,
11813
12466
  resolveSequenceKey,
11814
12467
  SequenceStore,
11815
12468
  validateSchemaInput,
@@ -11817,10 +12470,15 @@ export {
11817
12470
  isZodSchema,
11818
12471
  derivePersistedSchema,
11819
12472
  persistSchemaIfNeeded,
12473
+ isRefArray,
11820
12474
  RefIntegrityError,
11821
12475
  RefScopeError,
11822
12476
  ref,
12477
+ refArray,
11823
12478
  RefRegistry,
12479
+ isLinkCollectionName,
12480
+ LinkEndpointError,
12481
+ LinkIntegrityError,
11824
12482
  QuickUnlockStore,
11825
12483
  UserApi,
11826
12484
  META_COLLECTION,
@@ -11833,6 +12491,7 @@ export {
11833
12491
  describeAllUsersAuth,
11834
12492
  ComputedFieldError,
11835
12493
  evalComputedFields,
12494
+ tokenize,
11836
12495
  Lru,
11837
12496
  parseBytes,
11838
12497
  estimateRecordBytes,
@@ -11849,4 +12508,4 @@ export {
11849
12508
  Noydb,
11850
12509
  createNoydb
11851
12510
  };
11852
- //# sourceMappingURL=chunk-D77ZQSQQ.js.map
12511
+ //# sourceMappingURL=chunk-KYGGXXT6.js.map