@noy-db/hub 0.4.0-pre.4 → 0.4.0-pre.6

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 (470) hide show
  1. package/README.md +2 -2
  2. package/dist/api-5QVQX4HG.js +20 -0
  3. package/dist/attestation/index.js +18 -18
  4. package/dist/{backup-JL2GOTYQ.js → backup-USYSNCYM.js} +11 -11
  5. package/dist/blobs/index.js +15 -12
  6. package/dist/blobs/index.js.map +1 -1
  7. package/dist/broker/index.js +12 -12
  8. package/dist/cargo/index.js +34 -36
  9. package/dist/{chunk-JLHKBAFY.js → chunk-2BVW754E.js} +3 -3
  10. package/dist/{chunk-T7S4V52L.js → chunk-2PDBYF2O.js} +4 -4
  11. package/dist/{chunk-YGBIBOCR.js → chunk-2ZSC454H.js} +7 -7
  12. package/dist/{chunk-IGAIOGCN.js → chunk-32467U5J.js} +4 -4
  13. package/dist/{chunk-JA5O7UEZ.js → chunk-3GXDB3NQ.js} +6 -6
  14. package/dist/chunk-3GXDB3NQ.js.map +1 -0
  15. package/dist/{chunk-U73LHVPF.js → chunk-3S2YNMUS.js} +54 -6
  16. package/dist/chunk-3S2YNMUS.js.map +1 -0
  17. package/dist/{chunk-JW3XCZA2.js → chunk-3TZUC4WS.js} +11 -11
  18. package/dist/{chunk-JA5B3SLH.js → chunk-44Y3P5U6.js} +2 -2
  19. package/dist/{chunk-25G7U6RD.js → chunk-4B3DL75F.js} +2 -2
  20. package/dist/{chunk-L4OA7G5T.js → chunk-522MBPE5.js} +2 -2
  21. package/dist/chunk-5ABOFAHN.js +81 -0
  22. package/dist/chunk-5ABOFAHN.js.map +1 -0
  23. package/dist/chunk-5D2ALSM5.js +19 -0
  24. package/dist/chunk-5D2ALSM5.js.map +1 -0
  25. package/dist/{chunk-M25ZIEB2.js → chunk-5HSSTOOG.js} +2 -2
  26. package/dist/{chunk-LLVW4V7R.js → chunk-5WLDZZ6S.js} +3 -3
  27. package/dist/{chunk-BCOKZC4B.js → chunk-6SSWOUUS.js} +19 -19
  28. package/dist/chunk-6SSWOUUS.js.map +1 -0
  29. package/dist/{chunk-IGM563N5.js → chunk-6SYOHUHM.js} +6 -6
  30. package/dist/chunk-6SYOHUHM.js.map +1 -0
  31. package/dist/{chunk-7B4GPCX7.js → chunk-7IQWHYL2.js} +5 -5
  32. package/dist/{chunk-J3VW4J4E.js → chunk-7LP7FFJ2.js} +2 -2
  33. package/dist/chunk-7LP7FFJ2.js.map +1 -0
  34. package/dist/{chunk-5P5AAXYA.js → chunk-7U6AB7DZ.js} +7 -7
  35. package/dist/chunk-7U6AB7DZ.js.map +1 -0
  36. package/dist/chunk-AFHQATY4.js +47 -0
  37. package/dist/chunk-AFHQATY4.js.map +1 -0
  38. package/dist/{chunk-OWE4BNTM.js → chunk-AZXEOEQK.js} +4 -4
  39. package/dist/{chunk-GBEXTC6Z.js → chunk-BAAUFCJK.js} +3 -3
  40. package/dist/chunk-BAAUFCJK.js.map +1 -0
  41. package/dist/{chunk-BZEPJJOK.js → chunk-C2V7AJO2.js} +4 -4
  42. package/dist/chunk-CADUYBQD.js +151 -0
  43. package/dist/chunk-CADUYBQD.js.map +1 -0
  44. package/dist/{chunk-2JZ763FV.js → chunk-D4LAJ737.js} +2 -2
  45. package/dist/{chunk-5BHNQNBI.js → chunk-DOZFU7OZ.js} +1 -1
  46. package/dist/chunk-DOZFU7OZ.js.map +1 -0
  47. package/dist/{chunk-MEKAMERX.js → chunk-E7FSBI6I.js} +29 -29
  48. package/dist/chunk-E7FSBI6I.js.map +1 -0
  49. package/dist/{chunk-N4FZ6ITM.js → chunk-EGU4PWQW.js} +2 -2
  50. package/dist/chunk-EP5L47XV.js +22 -0
  51. package/dist/chunk-EP5L47XV.js.map +1 -0
  52. package/dist/{chunk-EW4HFWGJ.js → chunk-EPME33Y4.js} +6 -6
  53. package/dist/{chunk-W7TCXZWU.js → chunk-EWPS35AR.js} +794 -1045
  54. package/dist/chunk-EWPS35AR.js.map +1 -0
  55. package/dist/{chunk-JKWNG3TM.js → chunk-FHHYCBBP.js} +2 -2
  56. package/dist/{chunk-5BB3N4KU.js → chunk-G4MFQXYX.js} +2 -2
  57. package/dist/{chunk-KVHWEPT2.js → chunk-GHEMAVTN.js} +2 -2
  58. package/dist/{chunk-CGPO3ZYB.js → chunk-GQT6J4FJ.js} +15 -2
  59. package/dist/chunk-GQT6J4FJ.js.map +1 -0
  60. package/dist/{chunk-XW7NWO4A.js → chunk-GTNRMJYH.js} +2 -2
  61. package/dist/{chunk-YG2EG6CB.js → chunk-H5GMROCB.js} +4 -4
  62. package/dist/{chunk-JIMEB4C6.js → chunk-HA7P3BTB.js} +26 -177
  63. package/dist/chunk-HA7P3BTB.js.map +1 -0
  64. package/dist/{chunk-5KI3REO3.js → chunk-HDF5R2K6.js} +7 -7
  65. package/dist/{chunk-V3YB7RGR.js → chunk-HVPW6PCX.js} +3 -3
  66. package/dist/{chunk-2VUISNGP.js → chunk-HXVRRJBD.js} +5 -5
  67. package/dist/{chunk-ZJGZDOQO.js → chunk-ICYC5YNI.js} +6 -6
  68. package/dist/{chunk-KR5EGWI4.js → chunk-IUATR5UE.js} +27 -5
  69. package/dist/chunk-IUATR5UE.js.map +1 -0
  70. package/dist/{chunk-AFBJHD55.js → chunk-JGOKAZNB.js} +5 -5
  71. package/dist/{chunk-XGVDLQJE.js → chunk-JOCMXSR2.js} +3 -3
  72. package/dist/{chunk-XGVDLQJE.js.map → chunk-JOCMXSR2.js.map} +1 -1
  73. package/dist/{chunk-HGVFJL63.js → chunk-JTIPVW4J.js} +15 -5
  74. package/dist/{chunk-HGVFJL63.js.map → chunk-JTIPVW4J.js.map} +1 -1
  75. package/dist/{chunk-QXPOEAKR.js → chunk-KCZAFDP5.js} +2 -2
  76. package/dist/{chunk-MSO2C3KG.js → chunk-LC7DSMHR.js} +2 -2
  77. package/dist/{chunk-OVFCAS7U.js → chunk-LG2GUYRX.js} +9 -9
  78. package/dist/{chunk-2KL6NDD4.js → chunk-LN3MQFUE.js} +56 -4
  79. package/dist/chunk-LN3MQFUE.js.map +1 -0
  80. package/dist/{chunk-QUIG6BZT.js → chunk-M4GO4ZJK.js} +226 -36
  81. package/dist/chunk-M4GO4ZJK.js.map +1 -0
  82. package/dist/{chunk-QDNVHA2F.js → chunk-M7W2KYTL.js} +2 -2
  83. package/dist/{chunk-XULHFSHO.js → chunk-MLCTPWSO.js} +5 -5
  84. package/dist/chunk-MLCTPWSO.js.map +1 -0
  85. package/dist/{chunk-PEY6ZTCF.js → chunk-MMVQ3SUO.js} +9 -9
  86. package/dist/{chunk-PEY6ZTCF.js.map → chunk-MMVQ3SUO.js.map} +1 -1
  87. package/dist/{chunk-4X6DJZHY.js → chunk-MPPWL64H.js} +26 -43
  88. package/dist/chunk-MPPWL64H.js.map +1 -0
  89. package/dist/{chunk-QYJIOWKN.js → chunk-MQBFT2OT.js} +11 -9
  90. package/dist/chunk-MQBFT2OT.js.map +1 -0
  91. package/dist/{chunk-IUIVDVXM.js → chunk-MUPZ6IZX.js} +2 -2
  92. package/dist/{chunk-GZ2GKOF6.js → chunk-NA374QG7.js} +3 -3
  93. package/dist/chunk-NIKO2BBZ.js +23 -0
  94. package/dist/chunk-NIKO2BBZ.js.map +1 -0
  95. package/dist/{chunk-2U7Y7BNJ.js → chunk-ONB627HU.js} +2 -2
  96. package/dist/{chunk-GYB2QK5H.js → chunk-OWLZONGX.js} +2 -2
  97. package/dist/{chunk-YHPUDB7Q.js → chunk-OWOT7CFC.js} +2 -2
  98. package/dist/{chunk-VEX6G3YL.js → chunk-P4NUJVWL.js} +2 -2
  99. package/dist/chunk-PEOZ34EM.js +13 -0
  100. package/dist/chunk-PEOZ34EM.js.map +1 -0
  101. package/dist/{chunk-NM4LVUXH.js → chunk-PTT2NB46.js} +2 -2
  102. package/dist/chunk-PVEWA2DU.js +23 -0
  103. package/dist/chunk-PVEWA2DU.js.map +1 -0
  104. package/dist/{chunk-2ITLQZV5.js → chunk-PWWWMRT7.js} +2 -2
  105. package/dist/{chunk-FLHOTGOO.js → chunk-QVGEVZ5F.js} +3 -3
  106. package/dist/{chunk-HKR25MGX.js → chunk-QVIZDLAR.js} +10 -10
  107. package/dist/chunk-QVIZDLAR.js.map +1 -0
  108. package/dist/{chunk-OOTTXUNV.js → chunk-RM5EXCFF.js} +2 -2
  109. package/dist/{chunk-OOTTXUNV.js.map → chunk-RM5EXCFF.js.map} +1 -1
  110. package/dist/{chunk-OGFPMCSP.js → chunk-SBOHNJUD.js} +2 -2
  111. package/dist/{chunk-EDC6MLXV.js → chunk-SEU6QHH4.js} +2 -2
  112. package/dist/chunk-SMY5X46Z.js +14 -0
  113. package/dist/chunk-SMY5X46Z.js.map +1 -0
  114. package/dist/{chunk-F4COUZLL.js → chunk-TMR64XPL.js} +2 -2
  115. package/dist/{chunk-5OZCCLNC.js → chunk-TSNRZSRC.js} +2 -2
  116. package/dist/{chunk-2RMDVWGB.js → chunk-UNREYBZO.js} +2 -2
  117. package/dist/{chunk-BLB7P7LS.js → chunk-V2R2VWER.js} +176 -17
  118. package/dist/chunk-V2R2VWER.js.map +1 -0
  119. package/dist/{chunk-3XVOLB75.js → chunk-VDTWFN2P.js} +7 -5
  120. package/dist/chunk-VDTWFN2P.js.map +1 -0
  121. package/dist/chunk-VKQCVU2Z.js +21 -0
  122. package/dist/chunk-VKQCVU2Z.js.map +1 -0
  123. package/dist/{chunk-QCUH2G77.js → chunk-VNJMLOQS.js} +6 -6
  124. package/dist/{chunk-UEO5CHOP.js → chunk-WCJJQV2D.js} +13 -13
  125. package/dist/chunk-WCJJQV2D.js.map +1 -0
  126. package/dist/{chunk-25ZDB25Z.js → chunk-WWBC4KLB.js} +3 -3
  127. package/dist/chunk-WWBC4KLB.js.map +1 -0
  128. package/dist/{chunk-V7RGFJ3Z.js → chunk-XG7OZDOS.js} +6 -6
  129. package/dist/{chunk-GS3Q2KOZ.js → chunk-XONZGK6J.js} +2 -2
  130. package/dist/{chunk-5SZ24DL5.js → chunk-XSOGLHGY.js} +6 -6
  131. package/dist/{chunk-CCT4WZI6.js → chunk-XY6MNSAF.js} +5 -5
  132. package/dist/chunk-XY6MNSAF.js.map +1 -0
  133. package/dist/chunk-XZHEOSQ2.js +16 -0
  134. package/dist/chunk-XZHEOSQ2.js.map +1 -0
  135. package/dist/{chunk-NOT7XA7Q.js → chunk-YGMREQAK.js} +5 -5
  136. package/dist/{chunk-H4SMS4O2.js → chunk-YJ3TREAC.js} +2 -2
  137. package/dist/chunk-YMUFFJCO.js +23 -0
  138. package/dist/chunk-YMUFFJCO.js.map +1 -0
  139. package/dist/{chunk-E2R5NRZD.js → chunk-Z4D3YGAB.js} +2 -2
  140. package/dist/{chunk-WJDYZP3U.js → chunk-ZDFU34XY.js} +42 -39
  141. package/dist/chunk-ZDFU34XY.js.map +1 -0
  142. package/dist/{chunk-BZK6JEX4.js → chunk-ZF572E2M.js} +5 -5
  143. package/dist/{chunk-DEQ2JTBR.js → chunk-ZGEFBDPR.js} +4 -4
  144. package/dist/chunk-ZGEFBDPR.js.map +1 -0
  145. package/dist/{chunk-QAFWRGVD.js → chunk-ZHMUFYZF.js} +7 -7
  146. package/dist/{chunk-BVZGNMVM.js → chunk-ZHZ4PET5.js} +3 -3
  147. package/dist/{chunk-IZX3WZBF.js → chunk-ZM72UO3Y.js} +4 -4
  148. package/dist/{chunk-STR7WBOB.js → chunk-ZUDAK436.js} +2 -2
  149. package/dist/{chunk-ITI3SJRB.js → chunk-ZX5FNWH7.js} +2 -2
  150. package/dist/classified/index.js +5 -5
  151. package/dist/{classified-marker-7S5IEP6Q.js → classified-marker-SVDRXLD3.js} +3 -3
  152. package/dist/collection-facade-S5PPKZD5.js +44 -0
  153. package/dist/{computed-WZNKRLCY.js → computed-33DRJDOC.js} +3 -3
  154. package/dist/consent/index.js +13 -9
  155. package/dist/consent/index.js.map +1 -1
  156. package/dist/{cover-B5MY43CK.js → cover-ADBCTIKN.js} +4 -4
  157. package/dist/crdt/index.js +4 -0
  158. package/dist/crdt/index.js.map +1 -1
  159. package/dist/{dead-filter-KRRD57MR.js → dead-filter-HKDMTMVY.js} +2 -2
  160. package/dist/delegation-EV7LKJPH.js +25 -0
  161. package/dist/derivations/index.js +12 -12
  162. package/dist/derive-5LDJW76F.js +21 -0
  163. package/dist/dispatch-SPMYNXNW.js +194 -0
  164. package/dist/dispatch-SPMYNXNW.js.map +1 -0
  165. package/dist/dispatch-V5MSMQYX.js +72 -0
  166. package/dist/dispatch-V5MSMQYX.js.map +1 -0
  167. package/dist/{enclave-YFKA3GJT.js → enclave-ZA7C3H2L.js} +11 -11
  168. package/dist/executor-FCJEH3FU.js +9 -0
  169. package/dist/executor-OHET7TF7.js +9 -0
  170. package/dist/executor-SVHAJZ4A.js +28 -0
  171. package/dist/export-accessible-S35YKIBL.js +23 -0
  172. package/dist/extract-partition-UVHAM5WZ.js +38 -0
  173. package/dist/{fanout-sidecar-HJV3A7PM.js → fanout-sidecar-HRMHC34B.js} +9 -9
  174. package/dist/find-LEBUXVL7.js +11 -0
  175. package/dist/forget/index.js +9 -9
  176. package/dist/guards/index.js +3 -3
  177. package/dist/history/index.js +16 -12
  178. package/dist/history/index.js.map +1 -1
  179. package/dist/i18n/index.js +16 -14
  180. package/dist/i18n/index.js.map +1 -1
  181. package/dist/index.d.ts +17 -16
  182. package/dist/index.js +155 -211
  183. package/dist/index.js.map +1 -1
  184. package/dist/indexing/index.js +4 -2
  185. package/dist/indexing/index.js.map +1 -1
  186. package/dist/issue-5X3SMCF4.js +19 -0
  187. package/dist/kernel/collection.d.ts +0 -1
  188. package/dist/kernel/enclave/crypto.d.ts +8 -8
  189. package/dist/kernel/enclave/index.d.ts +2 -2
  190. package/dist/kernel/errors.d.ts +20 -20
  191. package/dist/kernel/lazy.d.ts +30 -0
  192. package/dist/kernel/noydb.d.ts +53 -101
  193. package/dist/kernel/query/builder.d.ts +10 -10
  194. package/dist/kernel/query/index.d.ts +0 -6
  195. package/dist/kernel/query/scan-builder.d.ts +4 -4
  196. package/dist/kernel/types.d.ts +87 -46
  197. package/dist/kernel/validation.d.ts +33 -33
  198. package/dist/kernel/vault.d.ts +12 -149
  199. package/dist/kernel/via/dispatch.d.ts +7 -0
  200. package/dist/{ledger-SW6QQOAV.js → ledger-K6JBFL3Z.js} +11 -11
  201. package/dist/liberate-NHTCKBU4.js +24 -0
  202. package/dist/{link-set-GNGGCFI4.js → link-set-XVZY2ODC.js} +11 -11
  203. package/dist/materialized-views/index.js +22 -19
  204. package/dist/noydb-TI3RFU6M.js +78 -0
  205. package/dist/overlay-views/index.js +4 -4
  206. package/dist/periods/index.js +15 -13
  207. package/dist/pod/index.js +11 -12
  208. package/dist/{policy-EAXSJNOT.js → policy-QWGJB7P7.js} +5 -5
  209. package/dist/port/with/collection-options.d.ts +171 -0
  210. package/dist/port/with/collection-registries.d.ts +62 -0
  211. package/dist/port/with/strategies.d.ts +2 -2
  212. package/dist/port/with/team-strategy.d.ts +3 -2
  213. package/dist/portability/index.js +8 -8
  214. package/dist/{post-register-A7HCFBP5.js → post-register-5VHHVFJY.js} +6 -6
  215. package/dist/query/index.js +6 -46
  216. package/dist/{aggregate → reduce}/index.js +24 -17
  217. package/dist/reduce/index.js.map +1 -0
  218. package/dist/register-CEX7R7NE.js +23 -0
  219. package/dist/registry-7CZWF3EQ.js +9 -0
  220. package/dist/registry-DIKMRXUC.js +19 -0
  221. package/dist/registry-EWIB5NTI.js +18 -0
  222. package/dist/request-withdrawal-AAG57QO4.js +31 -0
  223. package/dist/{reveal-PB3YG544.js → reveal-7OOT5XPD.js} +6 -6
  224. package/dist/revoke-U5LCIJMF.js +24 -0
  225. package/dist/satellites/index.js +1 -1
  226. package/dist/sealed-record/index.js +12 -12
  227. package/dist/{seed-EKF4DIBB.js → seed-GVOI6QP6.js} +12 -12
  228. package/dist/seed-GVOI6QP6.js.map +1 -0
  229. package/dist/session/index.js +13 -9
  230. package/dist/session/index.js.map +1 -1
  231. package/dist/shadow/index.js +6 -2
  232. package/dist/shadow/index.js.map +1 -1
  233. package/dist/signer-NAA2OX7H.js +25 -0
  234. package/dist/snapshots/index.js +14 -10
  235. package/dist/snapshots/index.js.map +1 -1
  236. package/dist/{stale-4UNPHWOU.js → stale-BJO2WIN7.js} +11 -10
  237. package/dist/storage-FL7XXZTN.js +23 -0
  238. package/dist/{store-coordination-provider-3AELCZ4Y.js → store-coordination-provider-DX5HECK3.js} +3 -3
  239. package/dist/sync/index.js +14 -10
  240. package/dist/sync/index.js.map +1 -1
  241. package/dist/team/index.js +26 -28
  242. package/dist/tiers/index.js +10 -10
  243. package/dist/to/index.js +1 -1
  244. package/dist/tx/index.js +7 -3
  245. package/dist/tx/index.js.map +1 -1
  246. package/dist/util/index.js +1 -1
  247. package/dist/{verify-MXN66IIH.js → verify-5X37OXRY.js} +5 -5
  248. package/dist/via/blob/index.d.ts +2 -0
  249. package/dist/via/i18n/core.d.ts +1 -1
  250. package/dist/via/i18n/index.d.ts +2 -0
  251. package/dist/via/money/money-reducer.d.ts +2 -2
  252. package/dist/{walk-H4YE52S2.js → walk-JXMWKKQW.js} +11 -11
  253. package/dist/with-audit/consent/index.d.ts +2 -0
  254. package/dist/with-audit/periods/index.d.ts +2 -0
  255. package/dist/with-audit/portability/export-accessible.d.ts +4 -4
  256. package/dist/with-audit/portability/request-withdrawal.d.ts +3 -3
  257. package/dist/with-audit/portability/withdraw-accessible.d.ts +2 -2
  258. package/dist/with-audit/sealed-record/strategy.d.ts +1 -1
  259. package/dist/with-cargo/adopt-partition.d.ts +7 -7
  260. package/dist/with-cargo/floor.d.ts +3 -3
  261. package/dist/with-cargo/index.d.ts +1 -1
  262. package/dist/with-commit/crdt/index.d.ts +2 -0
  263. package/dist/with-commit/history/index.d.ts +2 -0
  264. package/dist/with-commit/history/time-machine.d.ts +2 -2
  265. package/dist/with-fork/shadow/index.d.ts +2 -0
  266. package/dist/with-fork/snapshots/index.d.ts +2 -0
  267. package/dist/with-formula/derivations/dispatch.d.ts +98 -0
  268. package/dist/with-formula/materialized-views/dispatch.d.ts +75 -0
  269. package/dist/with-formula/materialized-views/types.d.ts +7 -7
  270. package/dist/with-lookup/indexing/index.d.ts +2 -0
  271. package/dist/with-lookup/{aggregate → reduce}/active.d.ts +8 -8
  272. package/dist/with-lookup/{aggregate → reduce}/groupby.d.ts +21 -21
  273. package/dist/with-lookup/reduce/index.d.ts +34 -0
  274. package/dist/with-lookup/{aggregate → reduce}/reducers.d.ts +10 -10
  275. package/dist/with-lookup/{aggregate/aggregation.d.ts → reduce/reduction.d.ts} +21 -21
  276. package/dist/with-lookup/{aggregate → reduce}/strategy.d.ts +15 -15
  277. package/dist/with-party/custody/liberate.d.ts +3 -3
  278. package/dist/with-party/session/dev-unlock.d.ts +2 -2
  279. package/dist/with-party/session/index.d.ts +2 -0
  280. package/dist/with-party/session/session.d.ts +2 -2
  281. package/dist/with-party/sync/index.d.ts +2 -0
  282. package/dist/with-party/team/deed.d.ts +8 -8
  283. package/dist/with-party/team/index.d.ts +2 -2
  284. package/dist/with-party/team/keyring.d.ts +39 -20
  285. package/dist/with-party/team/{managed-passphrase.d.ts → managed-secret.d.ts} +27 -27
  286. package/dist/with-party/team/noydb-facade.d.ts +43 -42
  287. package/dist/with-party/team/peer-recover.d.ts +13 -13
  288. package/dist/with-party/team/recovery.d.ts +5 -5
  289. package/dist/with-party/team/rotate-recover.d.ts +30 -30
  290. package/dist/with-pod/bundle.d.ts +30 -30
  291. package/dist/with-pod/format.d.ts +2 -2
  292. package/dist/withdraw-accessible-GO6KQJVM.js +28 -0
  293. package/package.json +6 -34
  294. package/dist/aggregate/index.js.map +0 -1
  295. package/dist/api-UPAT2O3M.js +0 -20
  296. package/dist/as/index.js +0 -30
  297. package/dist/at/index.js +0 -1
  298. package/dist/by/index.js +0 -11
  299. package/dist/chunk-25ZDB25Z.js.map +0 -1
  300. package/dist/chunk-2KL6NDD4.js.map +0 -1
  301. package/dist/chunk-2YELV6TV.js +0 -1
  302. package/dist/chunk-3O62PVDW.js +0 -205
  303. package/dist/chunk-3O62PVDW.js.map +0 -1
  304. package/dist/chunk-3XVOLB75.js.map +0 -1
  305. package/dist/chunk-4X6DJZHY.js.map +0 -1
  306. package/dist/chunk-5BHNQNBI.js.map +0 -1
  307. package/dist/chunk-5P5AAXYA.js.map +0 -1
  308. package/dist/chunk-BCOKZC4B.js.map +0 -1
  309. package/dist/chunk-BLB7P7LS.js.map +0 -1
  310. package/dist/chunk-CCT4WZI6.js.map +0 -1
  311. package/dist/chunk-CGPO3ZYB.js.map +0 -1
  312. package/dist/chunk-DEQ2JTBR.js.map +0 -1
  313. package/dist/chunk-GBEXTC6Z.js.map +0 -1
  314. package/dist/chunk-HKR25MGX.js.map +0 -1
  315. package/dist/chunk-IGM563N5.js.map +0 -1
  316. package/dist/chunk-J3VW4J4E.js.map +0 -1
  317. package/dist/chunk-JA5O7UEZ.js.map +0 -1
  318. package/dist/chunk-JIMEB4C6.js.map +0 -1
  319. package/dist/chunk-KMONEHDJ.js +0 -54
  320. package/dist/chunk-KMONEHDJ.js.map +0 -1
  321. package/dist/chunk-KR5EGWI4.js.map +0 -1
  322. package/dist/chunk-LB7FD65R.js +0 -163
  323. package/dist/chunk-LB7FD65R.js.map +0 -1
  324. package/dist/chunk-MEKAMERX.js.map +0 -1
  325. package/dist/chunk-QUIG6BZT.js.map +0 -1
  326. package/dist/chunk-QYJIOWKN.js.map +0 -1
  327. package/dist/chunk-U73LHVPF.js.map +0 -1
  328. package/dist/chunk-UEO5CHOP.js.map +0 -1
  329. package/dist/chunk-W7TCXZWU.js.map +0 -1
  330. package/dist/chunk-WEC3JGBA.js +0 -255
  331. package/dist/chunk-WEC3JGBA.js.map +0 -1
  332. package/dist/chunk-WJDYZP3U.js.map +0 -1
  333. package/dist/chunk-XULHFSHO.js.map +0 -1
  334. package/dist/collection-facade-CMZGQ6IS.js +0 -44
  335. package/dist/delegation-UT76AQIG.js +0 -25
  336. package/dist/derive-SGRCCKVP.js +0 -21
  337. package/dist/executor-TEZYRDN3.js +0 -9
  338. package/dist/executor-WQQRU6DO.js +0 -9
  339. package/dist/executor-YORMIBWV.js +0 -26
  340. package/dist/export-accessible-HXMKW5LJ.js +0 -23
  341. package/dist/extract-partition-QGQ2R42J.js +0 -38
  342. package/dist/find-VV6PBIHK.js +0 -11
  343. package/dist/in/index.js +0 -1
  344. package/dist/issue-7JJ4Z7E2.js +0 -19
  345. package/dist/liberate-FK7JI2QX.js +0 -24
  346. package/dist/noydb-N5IW6OFZ.js +0 -70
  347. package/dist/on/index.js +0 -17
  348. package/dist/port/as/index.d.ts +0 -26
  349. package/dist/port/at/index.d.ts +0 -18
  350. package/dist/port/in/index.d.ts +0 -21
  351. package/dist/port/on/index.d.ts +0 -27
  352. package/dist/port/ui/index.d.ts +0 -21
  353. package/dist/port/with/index.d.ts +0 -18
  354. package/dist/register-YBMRLZLO.js +0 -23
  355. package/dist/registry-3LXKNXWI.js +0 -9
  356. package/dist/registry-4V4YQCXJ.js +0 -19
  357. package/dist/registry-ZULMLCJK.js +0 -18
  358. package/dist/request-withdrawal-SEVUEUDG.js +0 -31
  359. package/dist/request-withdrawal-SEVUEUDG.js.map +0 -1
  360. package/dist/revoke-5QULL5GT.js +0 -24
  361. package/dist/revoke-5QULL5GT.js.map +0 -1
  362. package/dist/seed-EKF4DIBB.js.map +0 -1
  363. package/dist/signer-ZMH35FT4.js +0 -25
  364. package/dist/signer-ZMH35FT4.js.map +0 -1
  365. package/dist/stale-4UNPHWOU.js.map +0 -1
  366. package/dist/storage-QOZKQMID.js +0 -23
  367. package/dist/storage-QOZKQMID.js.map +0 -1
  368. package/dist/ui/index.js +0 -1
  369. package/dist/ui/index.js.map +0 -1
  370. package/dist/with/index.js +0 -31
  371. package/dist/with/index.js.map +0 -1
  372. package/dist/with-lookup/aggregate/index.d.ts +0 -23
  373. package/dist/withdraw-accessible-HPOVNG2G.js +0 -28
  374. package/dist/withdraw-accessible-HPOVNG2G.js.map +0 -1
  375. /package/dist/{api-UPAT2O3M.js.map → api-5QVQX4HG.js.map} +0 -0
  376. /package/dist/{backup-JL2GOTYQ.js.map → backup-USYSNCYM.js.map} +0 -0
  377. /package/dist/{chunk-JLHKBAFY.js.map → chunk-2BVW754E.js.map} +0 -0
  378. /package/dist/{chunk-T7S4V52L.js.map → chunk-2PDBYF2O.js.map} +0 -0
  379. /package/dist/{chunk-YGBIBOCR.js.map → chunk-2ZSC454H.js.map} +0 -0
  380. /package/dist/{chunk-IGAIOGCN.js.map → chunk-32467U5J.js.map} +0 -0
  381. /package/dist/{chunk-JW3XCZA2.js.map → chunk-3TZUC4WS.js.map} +0 -0
  382. /package/dist/{chunk-JA5B3SLH.js.map → chunk-44Y3P5U6.js.map} +0 -0
  383. /package/dist/{chunk-25G7U6RD.js.map → chunk-4B3DL75F.js.map} +0 -0
  384. /package/dist/{chunk-L4OA7G5T.js.map → chunk-522MBPE5.js.map} +0 -0
  385. /package/dist/{chunk-M25ZIEB2.js.map → chunk-5HSSTOOG.js.map} +0 -0
  386. /package/dist/{chunk-LLVW4V7R.js.map → chunk-5WLDZZ6S.js.map} +0 -0
  387. /package/dist/{chunk-7B4GPCX7.js.map → chunk-7IQWHYL2.js.map} +0 -0
  388. /package/dist/{chunk-OWE4BNTM.js.map → chunk-AZXEOEQK.js.map} +0 -0
  389. /package/dist/{chunk-BZEPJJOK.js.map → chunk-C2V7AJO2.js.map} +0 -0
  390. /package/dist/{chunk-2JZ763FV.js.map → chunk-D4LAJ737.js.map} +0 -0
  391. /package/dist/{chunk-N4FZ6ITM.js.map → chunk-EGU4PWQW.js.map} +0 -0
  392. /package/dist/{chunk-EW4HFWGJ.js.map → chunk-EPME33Y4.js.map} +0 -0
  393. /package/dist/{chunk-JKWNG3TM.js.map → chunk-FHHYCBBP.js.map} +0 -0
  394. /package/dist/{chunk-5BB3N4KU.js.map → chunk-G4MFQXYX.js.map} +0 -0
  395. /package/dist/{chunk-KVHWEPT2.js.map → chunk-GHEMAVTN.js.map} +0 -0
  396. /package/dist/{chunk-XW7NWO4A.js.map → chunk-GTNRMJYH.js.map} +0 -0
  397. /package/dist/{chunk-YG2EG6CB.js.map → chunk-H5GMROCB.js.map} +0 -0
  398. /package/dist/{chunk-5KI3REO3.js.map → chunk-HDF5R2K6.js.map} +0 -0
  399. /package/dist/{chunk-V3YB7RGR.js.map → chunk-HVPW6PCX.js.map} +0 -0
  400. /package/dist/{chunk-2VUISNGP.js.map → chunk-HXVRRJBD.js.map} +0 -0
  401. /package/dist/{chunk-ZJGZDOQO.js.map → chunk-ICYC5YNI.js.map} +0 -0
  402. /package/dist/{chunk-AFBJHD55.js.map → chunk-JGOKAZNB.js.map} +0 -0
  403. /package/dist/{chunk-QXPOEAKR.js.map → chunk-KCZAFDP5.js.map} +0 -0
  404. /package/dist/{chunk-MSO2C3KG.js.map → chunk-LC7DSMHR.js.map} +0 -0
  405. /package/dist/{chunk-OVFCAS7U.js.map → chunk-LG2GUYRX.js.map} +0 -0
  406. /package/dist/{chunk-QDNVHA2F.js.map → chunk-M7W2KYTL.js.map} +0 -0
  407. /package/dist/{chunk-IUIVDVXM.js.map → chunk-MUPZ6IZX.js.map} +0 -0
  408. /package/dist/{chunk-GZ2GKOF6.js.map → chunk-NA374QG7.js.map} +0 -0
  409. /package/dist/{chunk-2U7Y7BNJ.js.map → chunk-ONB627HU.js.map} +0 -0
  410. /package/dist/{chunk-GYB2QK5H.js.map → chunk-OWLZONGX.js.map} +0 -0
  411. /package/dist/{chunk-YHPUDB7Q.js.map → chunk-OWOT7CFC.js.map} +0 -0
  412. /package/dist/{chunk-VEX6G3YL.js.map → chunk-P4NUJVWL.js.map} +0 -0
  413. /package/dist/{chunk-NM4LVUXH.js.map → chunk-PTT2NB46.js.map} +0 -0
  414. /package/dist/{chunk-2ITLQZV5.js.map → chunk-PWWWMRT7.js.map} +0 -0
  415. /package/dist/{chunk-FLHOTGOO.js.map → chunk-QVGEVZ5F.js.map} +0 -0
  416. /package/dist/{chunk-OGFPMCSP.js.map → chunk-SBOHNJUD.js.map} +0 -0
  417. /package/dist/{chunk-EDC6MLXV.js.map → chunk-SEU6QHH4.js.map} +0 -0
  418. /package/dist/{chunk-F4COUZLL.js.map → chunk-TMR64XPL.js.map} +0 -0
  419. /package/dist/{chunk-5OZCCLNC.js.map → chunk-TSNRZSRC.js.map} +0 -0
  420. /package/dist/{chunk-2RMDVWGB.js.map → chunk-UNREYBZO.js.map} +0 -0
  421. /package/dist/{chunk-QCUH2G77.js.map → chunk-VNJMLOQS.js.map} +0 -0
  422. /package/dist/{chunk-V7RGFJ3Z.js.map → chunk-XG7OZDOS.js.map} +0 -0
  423. /package/dist/{chunk-GS3Q2KOZ.js.map → chunk-XONZGK6J.js.map} +0 -0
  424. /package/dist/{chunk-5SZ24DL5.js.map → chunk-XSOGLHGY.js.map} +0 -0
  425. /package/dist/{chunk-NOT7XA7Q.js.map → chunk-YGMREQAK.js.map} +0 -0
  426. /package/dist/{chunk-H4SMS4O2.js.map → chunk-YJ3TREAC.js.map} +0 -0
  427. /package/dist/{chunk-E2R5NRZD.js.map → chunk-Z4D3YGAB.js.map} +0 -0
  428. /package/dist/{chunk-BZK6JEX4.js.map → chunk-ZF572E2M.js.map} +0 -0
  429. /package/dist/{chunk-QAFWRGVD.js.map → chunk-ZHMUFYZF.js.map} +0 -0
  430. /package/dist/{chunk-BVZGNMVM.js.map → chunk-ZHZ4PET5.js.map} +0 -0
  431. /package/dist/{chunk-IZX3WZBF.js.map → chunk-ZM72UO3Y.js.map} +0 -0
  432. /package/dist/{chunk-STR7WBOB.js.map → chunk-ZUDAK436.js.map} +0 -0
  433. /package/dist/{chunk-ITI3SJRB.js.map → chunk-ZX5FNWH7.js.map} +0 -0
  434. /package/dist/{classified-marker-7S5IEP6Q.js.map → classified-marker-SVDRXLD3.js.map} +0 -0
  435. /package/dist/{as/index.js.map → collection-facade-S5PPKZD5.js.map} +0 -0
  436. /package/dist/{at/index.js.map → computed-33DRJDOC.js.map} +0 -0
  437. /package/dist/{by/index.js.map → cover-ADBCTIKN.js.map} +0 -0
  438. /package/dist/{dead-filter-KRRD57MR.js.map → dead-filter-HKDMTMVY.js.map} +0 -0
  439. /package/dist/{chunk-2YELV6TV.js.map → delegation-EV7LKJPH.js.map} +0 -0
  440. /package/dist/{collection-facade-CMZGQ6IS.js.map → derive-5LDJW76F.js.map} +0 -0
  441. /package/dist/{computed-WZNKRLCY.js.map → enclave-ZA7C3H2L.js.map} +0 -0
  442. /package/dist/{cover-B5MY43CK.js.map → executor-FCJEH3FU.js.map} +0 -0
  443. /package/dist/{delegation-UT76AQIG.js.map → executor-OHET7TF7.js.map} +0 -0
  444. /package/dist/{derive-SGRCCKVP.js.map → executor-SVHAJZ4A.js.map} +0 -0
  445. /package/dist/{enclave-YFKA3GJT.js.map → export-accessible-S35YKIBL.js.map} +0 -0
  446. /package/dist/{executor-TEZYRDN3.js.map → extract-partition-UVHAM5WZ.js.map} +0 -0
  447. /package/dist/{fanout-sidecar-HJV3A7PM.js.map → fanout-sidecar-HRMHC34B.js.map} +0 -0
  448. /package/dist/{executor-WQQRU6DO.js.map → find-LEBUXVL7.js.map} +0 -0
  449. /package/dist/{executor-YORMIBWV.js.map → issue-5X3SMCF4.js.map} +0 -0
  450. /package/dist/{export-accessible-HXMKW5LJ.js.map → ledger-K6JBFL3Z.js.map} +0 -0
  451. /package/dist/{extract-partition-QGQ2R42J.js.map → liberate-NHTCKBU4.js.map} +0 -0
  452. /package/dist/{find-VV6PBIHK.js.map → link-set-XVZY2ODC.js.map} +0 -0
  453. /package/dist/{in/index.js.map → noydb-TI3RFU6M.js.map} +0 -0
  454. /package/dist/{issue-7JJ4Z7E2.js.map → policy-QWGJB7P7.js.map} +0 -0
  455. /package/dist/{post-register-A7HCFBP5.js.map → post-register-5VHHVFJY.js.map} +0 -0
  456. /package/dist/{ledger-SW6QQOAV.js.map → register-CEX7R7NE.js.map} +0 -0
  457. /package/dist/{liberate-FK7JI2QX.js.map → registry-7CZWF3EQ.js.map} +0 -0
  458. /package/dist/{link-set-GNGGCFI4.js.map → registry-DIKMRXUC.js.map} +0 -0
  459. /package/dist/{noydb-N5IW6OFZ.js.map → registry-EWIB5NTI.js.map} +0 -0
  460. /package/dist/{on/index.js.map → request-withdrawal-AAG57QO4.js.map} +0 -0
  461. /package/dist/{reveal-PB3YG544.js.map → reveal-7OOT5XPD.js.map} +0 -0
  462. /package/dist/{policy-EAXSJNOT.js.map → revoke-U5LCIJMF.js.map} +0 -0
  463. /package/dist/{register-YBMRLZLO.js.map → signer-NAA2OX7H.js.map} +0 -0
  464. /package/dist/{registry-3LXKNXWI.js.map → stale-BJO2WIN7.js.map} +0 -0
  465. /package/dist/{registry-4V4YQCXJ.js.map → storage-FL7XXZTN.js.map} +0 -0
  466. /package/dist/{store-coordination-provider-3AELCZ4Y.js.map → store-coordination-provider-DX5HECK3.js.map} +0 -0
  467. /package/dist/{verify-MXN66IIH.js.map → verify-5X37OXRY.js.map} +0 -0
  468. /package/dist/{walk-H4YE52S2.js.map → walk-JXMWKKQW.js.map} +0 -0
  469. /package/dist/with-lookup/{aggregate → reduce}/canonical-key.d.ts +0 -0
  470. /package/dist/{registry-ZULMLCJK.js.map → withdraw-accessible-GO6KQJVM.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-formula/materialized-views/executor.ts"],"sourcesContent":["import type { Collection } from '../../kernel/collection.js'\nimport type { TxContext } from '../../with-commit/tx/transaction.js'\nimport type { EncryptedEnvelope } from '../../kernel/types.js'\nimport { MaterializedViewTooLargeError, MaterializedViewConfigError, LocaleNotSpecifiedError, JoinTooLargeError } from '../../kernel/errors.js'\nimport { DEFAULT_JOIN_MAX_ROWS } from '../../kernel/query/join.js'\nimport type { MaterializedFromMeta, MVQueryContext, MaterializedViewStrategy } from './types.js'\nimport type { RegisteredMV } from './registry.js'\nimport { wrapDbWithPredicates } from './registry.js'\nimport { groupAndReduce } from '../../with-lookup/reduce/groupby.js'\nimport { canonicalGroupKey } from '../../with-lookup/reduce/canonical-key.js'\nimport { applyI18nLocale, type I18nTextDescriptor } from '../../via/i18n/core.js'\nimport { putDerivedOutput, type PutDerivedOutputCtx } from '../../kernel/via/dispatch.js'\n\n/**\n * Accessor shape passed in from the owning Vault. Mirrors v1's\n * `DerivationStaleAccessor` — provides the per-collection resolver\n * and the active TxContext so refresh writes/tombstones register on\n * `_executed` for rollback symmetry.\n */\nexport interface MVExecutorAccessor {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getCollection(name: string): Collection<any>\n getActiveTxContext(): TxContext | null\n /**\n * Vault-shaped accessor passed to the MV's `query()` callback at\n * each refresh. Same instance the registry used at registration\n * time; threading through the executor lets the refresh path\n * re-evaluate the closure against the live vault state.\n */\n getQueryContext(): MVQueryContext\n /**\n * #638 Task 5 — ctx for `putDerivedOutput`'s frozen-period skip+audit. #641: the lazy\n * resolve-on-read caller (`stale.ts#resolveStaleMVOnRead`) now supplies one too — built at\n * the `Collection.get()`/`list()` entry point with a `'resolve-on-read'` sentinel id (no\n * real \"reacting write\" for a read-triggered materialize, mirroring `refreshView()`'s\n * `'refreshView'` sentinel). Still declared optional here since `MVExecutorAccessor` is a\n * general shape and a future caller could reasonably omit it.\n */\n dispatchCtx?: PutDerivedOutputCtx\n}\n\nexport interface RefreshResult {\n /** Rows newly written / overwritten. */\n written: number\n /** Rows tombstoned via `_internalDelete` (only when `onEmpty: 'delete'`). */\n deleted: number\n /** Failed row writes (non-strict mode). */\n failed: number\n /** #782/#785 — `outputCollection:id` entries from the tombstone pass whose ownership stamp\n * couldn't be decoded under the collection's default DEK (undecodable, mirroring\n * `invalidateMVAtRest`'s #776 posture) — ownership UNCONFIRMED. Only populated when\n * `onEmpty: 'delete'`. */\n residueUndecodable: string[]\n /** #782/#785 — `outputCollection:id` entries that decoded, stamp-matched this MV, but\n * `_internalDelete` declined (the #718 tier-elevation gate) — ownership CONFIRMED, a real\n * silent survival, surfaced rather than dropped. Only populated when `onEmpty: 'delete'`. */\n residueDeclined: string[]\n}\n\n/** Default cost ceiling — overridable per-MV via `spec.maxRows`. */\nconst DEFAULT_MAX_ROWS = 100_000\n\n/**\n * Materialize a query terminal that may be a `Query<T>` (call\n * `.toArray()`), an `Reduction<R>` (call `.run()` returning a\n * single object — wrap as a one-row array), or a `GroupedReduction<R>`\n * (call `.run()` returning an array of grouped rows). Branches on\n * available terminal at runtime — no type-discrimination at registration.\n */\nasync function materializeQueryResult(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n q: any,\n mvName: string,\n i18nLocale?: string,\n i18nFields?: Record<string, I18nTextDescriptor>,\n): Promise<ReadonlyArray<Record<string, unknown>>> {\n if (typeof q?.toArray === 'function') {\n // Query<T> — non-aggregate path. `.toArray()` returns Promise<T[]>.\n return await q.toArray()\n }\n if (typeof q?.run === 'function') {\n // Reduction<R> or GroupedReduction<R>. `.run()` is synchronous\n // and returns either a single object (Reduction) or an array of\n // rows (GroupedReduction). Promise.resolve() normalizes both\n // sync and async (future) variants.\n // Query-form MV grouping: when the MV declares i18nLocale, pass it +\n // i18nFields so a GroupedReduction resolves i18n group keys before\n // bucketing (the Reduction path ignores the extra arg).\n const runOpts = i18nLocale !== undefined ? { locale: i18nLocale, i18nFields } : undefined\n const result: unknown = await Promise.resolve(q.run(runOpts))\n if (Array.isArray(result)) {\n return result as ReadonlyArray<Record<string, unknown>>\n }\n // Single-aggregate result — wrap as one-row array. The consumer's\n // `rowKey()` should return a stable identity (often a literal\n // constant like `'total'`) since there's only one row.\n return [result as Record<string, unknown>]\n }\n throw new Error(\n `MV \"${mvName}\": query() must return a Query<T>, Reduction, or GroupedReduction. ` +\n `Got something without a .toArray() or .run() terminal.`,\n )\n}\n\n/**\n * Materialize a UNION-form MV: read every arm's source\n * collection, apply each arm's `map` to project rows into the unified\n * MV row shape, concatenate the mapped streams, then optionally run\n * `groupBy` + `aggregate` over the result.\n *\n * Modes (driven by `spec.groupBy` / `spec.aggregate`):\n *\n * - No `groupBy` → return the concatenated mapped rows unchanged.\n * - `groupBy` without `aggregate` → dedupe by composite group key,\n * keep the first row seen per key (later arms don't overwrite\n * earlier arms — Map insertion order rules).\n * - `groupBy` + `aggregate` → delegate to the shared `groupAndReduce`\n * pipeline used by `Query.groupBy().aggregate()`.\n *\n * Per-arm `map` is the schema-unification boundary; the strategy's\n * `TRow` type parameter enforces that every arm projects into the\n * same shape at compile time.\n *\n * @internal\n */\nasync function materializeUnionResult<TRow extends Record<string, unknown>>(\n spec: MaterializedViewStrategy<TRow>,\n db: MVQueryContext,\n): Promise<ReadonlyArray<Record<string, unknown>>> {\n const unified: TRow[] = []\n for (const arm of spec.unionSources!) {\n const coll = db.collection<Record<string, unknown>>(arm.collection)\n // Optional per-arm FK joins: chain `.join(field, { as, ... })` for\n // each declared leg before terminating. The aliased right-side\n // record lands at `sourceRow[leg.as]`, where the arm's `map` reads\n // it. Cast to `any` because the chained join widens the row type but\n // the executor treats every row as `Record<string, unknown>` — same\n // pattern the query-form join path uses.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let q: any = coll.query()\n if (arm.join?.length) {\n for (const leg of arm.join) {\n q = q.join(leg.field, { as: leg.as, maxRows: leg.maxRows, strategy: leg.strategy })\n }\n }\n const sourceRows = q.toArray() as ReadonlyArray<Record<string, unknown>>\n for (const r of sourceRows) {\n const mapped = arm.map(r)\n // null / undefined means \"omit this source row\" — skip without\n // pushing so groupBy/aggregate never see a null entry.\n if (mapped == null) continue\n unified.push(mapped)\n }\n }\n\n return finalizeMappedRows(spec, unified)\n}\n\n/**\n * Shared post-map tail for the UNION and projection (#810) forms:\n * optional `groupBy` (+ `aggregate`) over the mapped-row stream.\n * Extracted verbatim from `materializeUnionResult` so both forms feed\n * the identical grouping pipeline — i18n group-key resolution, the\n * object-group-key guard, dedup-without-aggregate, and the shared\n * `groupAndReduce` delegate.\n *\n * @internal\n */\nfunction finalizeMappedRows<TRow extends Record<string, unknown>>(\n spec: MaterializedViewStrategy<TRow>,\n unified: TRow[],\n): ReadonlyArray<Record<string, unknown>> {\n if (!spec.groupBy) return unified\n\n const groupFields: readonly string[] =\n typeof spec.groupBy === 'string' ? [spec.groupBy] : spec.groupBy\n\n // i18n-aware group keys. An `i18nText` group field carries a raw\n // `{ locale: string }` map, an unstable object key. When `i18nLocale` is\n // declared (with `i18nFields` describing those fields), resolve the declared\n // group-key i18n fields to it at the `mv` layer FIRST — the same unified-rows\n // boundary where money is threaded — so buckets are stable strings and the\n // `mv`-layer `onMissing` policy fires here.\n if (spec.i18nLocale !== undefined && spec.i18nFields !== undefined) {\n const groupI18n: Record<string, I18nTextDescriptor> = {}\n for (const f of groupFields) {\n const d = spec.i18nFields[f]\n if (d !== undefined) groupI18n[f] = d\n }\n if (Object.keys(groupI18n).length > 0) {\n for (let i = 0; i < unified.length; i++) {\n unified[i] = applyI18nLocale(unified[i] as Record<string, unknown>, groupI18n, spec.i18nLocale, undefined, 'mv') as TRow\n }\n }\n }\n // Guard (always): a remaining object-valued group key — an undeclared i18n\n // field or a locale-less MV — would bucket on a map. Refuse, don't bucket wrong.\n for (const f of groupFields) {\n for (const row of unified) {\n const v = (row as Record<string, unknown>)[f]\n if (v !== null && typeof v === 'object') {\n throw new LocaleNotSpecifiedError(\n f,\n `Materialized view \"${spec.name}\" groups by \"${f}\", whose value is a raw i18n locale map — ` +\n `an unstable object group key. Declare { i18nLocale, i18nFields } on the MV to resolve it at ` +\n `the 'mv' layer, or group by a dictKey/staticDict code (the stable key) and resolve the label at read time.`,\n )\n }\n }\n }\n\n // groupBy without aggregate — dedupe by composite key, keep first\n // seen row per key. Useful for cross-arm uniqueness (e.g. unify two\n // sibling collections, keeping one row per natural key).\n if (!spec.aggregate) {\n const seen = new Map<string, TRow>()\n for (const row of unified) {\n const k = canonicalGroupKey(groupFields, row as Record<string, unknown>)\n if (!seen.has(k)) seen.set(k, row)\n }\n return [...seen.values()]\n }\n\n // groupBy + aggregate — delegate to the shared pipeline used by\n // `Query.groupBy().aggregate()`. Result rows carry each grouped\n // field in declaration order followed by the spec's reducer outputs.\n return groupAndReduce<Record<string, unknown>>(unified, groupFields, spec.aggregate, spec.moneyFields)\n}\n\n/**\n * Materialize a projection-form MV (#810): hydrate the primary source\n * rows, resolve forward FK legs through the same `.join()` machinery\n * the UNION arms use, attach reverse \"collect\" legs via one\n * hash-grouped snapshot pass per leg, then run the projection `map`\n * (null / undefined omits the primary row) and the shared post-map\n * grouping tail.\n *\n * @internal\n */\nasync function materializeProjectionResult<TRow extends Record<string, unknown>>(\n spec: MaterializedViewStrategy<TRow>,\n db: MVQueryContext,\n): Promise<ReadonlyArray<Record<string, unknown>>> {\n const projection = spec.projection!\n const coll = db.collection<Record<string, unknown>>(projection.source)\n // Forward legs chain through the query builder exactly like UNION arm\n // joins — ref() resolution, dangling-mode semantics, presentation\n // dressing, and ceilings all ride the existing `.join()` path. Cast to\n // `any` for the same reason `materializeUnionResult` does.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let q: any = coll.query()\n for (const leg of projection.joins) {\n if ('collect' in leg) continue\n q = q.join(leg.field, { as: leg.as, maxRows: leg.maxRows, strategy: leg.strategy })\n }\n let rows = q.toArray() as Array<Record<string, unknown>>\n for (const leg of projection.joins) {\n if (!('collect' in leg)) continue\n rows = applyCollectLeg(rows, leg, spec.name, projection.source, db)\n }\n const mapped: TRow[] = []\n for (const r of rows) {\n const m = projection.map(r)\n // null / undefined means \"omit this primary row\" — same contract\n // as the UNION arm `map`.\n if (m == null) continue\n mapped.push(m)\n }\n return finalizeMappedRows(spec, mapped)\n}\n\n/**\n * Attach one reverse \"collect\" leg (#810): every row of `leg.collect`\n * whose `leg.on` field references a primary record's id lands in a\n * possibly-empty ARRAY under `leg.as` on that primary row. One\n * snapshot pass over the collect collection, hash-grouped by the `on`\n * FK — O(N+M), mirroring the forward hash-join fallback.\n *\n * Semantic check (first materialization, not factory time — parity\n * with join-time ref errors): `leg.on` must carry a `ref()` declared\n * on the collect collection targeting the projection `source`.\n *\n * @internal\n */\nfunction applyCollectLeg(\n primaryRows: ReadonlyArray<Record<string, unknown>>,\n leg: { readonly collect: string; readonly on: string; readonly as: string; readonly maxRows?: number },\n mvName: string,\n source: string,\n db: MVQueryContext,\n): Array<Record<string, unknown>> {\n const childColl = db.collection<Record<string, unknown>>(leg.collect)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const childQ = childColl.query() as any\n const refDesc = childQ._joinContext?.()?.resolveRef(leg.on) as { target: string } | null | undefined\n if (refDesc == null) {\n throw new MaterializedViewConfigError(\n `\"${mvName}\": projection collect leg \"${leg.as}\" requires a ref() on field \"${leg.on}\" of `\n + `collection \"${leg.collect}\" targeting \"${source}\" — declare `\n + `refs: { ${leg.on}: ref('${source}') } on collection \"${leg.collect}\", then retry`,\n )\n }\n if (refDesc.target !== source) {\n throw new MaterializedViewConfigError(\n `\"${mvName}\": projection collect leg \"${leg.as}\" expects field \"${leg.on}\" of collection `\n + `\"${leg.collect}\" to reference the projection source \"${source}\", but its ref() targets `\n + `\"${refDesc.target}\"`,\n )\n }\n const maxRows = leg.maxRows ?? DEFAULT_JOIN_MAX_ROWS\n const groups = new Map<string, Array<Record<string, unknown>>>()\n for (const child of childQ.toArray() as Array<Record<string, unknown>>) {\n const key = coerceCollectKey(child[leg.on])\n // Nullish / non-scalar FK values mean \"no reference\" — same\n // narrowing as the forward join path's key coercion.\n if (key === null) continue\n const bucket = groups.get(key)\n if (bucket) bucket.push(child)\n else groups.set(key, [child])\n }\n const out: Array<Record<string, unknown>> = []\n for (const row of primaryRows) {\n const key = coerceCollectKey(row.id)\n const children = key === null ? [] : groups.get(key) ?? []\n if (children.length > maxRows) {\n throw new JoinTooLargeError({\n leftRows: primaryRows.length,\n rightRows: children.length,\n maxRows,\n side: 'right',\n message:\n `projection MV \"${mvName}\": collect leg \"${leg.as}\" gathered ${children.length} ` +\n `\"${leg.collect}\" rows for one \"${source}\" record, exceeding the ${maxRows}-row ` +\n `per-primary-row ceiling. Raise the ceiling via { maxRows } on the leg if the ` +\n `fan-out genuinely fits in memory, or restructure the child collection.`,\n })\n }\n out.push({ ...row, [leg.as]: children })\n }\n return out\n}\n\n/**\n * Coerce an unknown FK value into a collect-grouping key. Same\n * narrowing as the join path's `coerceRefKey` (not exported from\n * there): strings and numbers are legitimate ref values; anything\n * else is \"no reference\" and returns `null`.\n *\n * @internal\n */\nfunction coerceCollectKey(value: unknown): string | null {\n if (value === null || value === undefined) return null\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'bigint') return String(value)\n return null\n}\n\n/**\n * Run an MV's `query()` and write the result rows to the output\n * collection. Same-DEK encryption: routes through the standard\n * `Collection.put` pipeline, so the output collection's DEK is what\n * gets used (matches the v2 spec's \"same DEK as the left-most source\"\n * invariant — `Collection.put` looks up the DEK by collection name,\n * and the output collection IS the MV's owned collection).\n *\n * Stamps `_materializedFrom` onto every emitted row.\n *\n * **Tombstoning:** when `spec.onEmpty: 'delete'` (default), rows\n * that existed in a prior refresh but no longer appear in the new\n * materialized result are deleted via `Collection._internalDelete` —\n * the housekeeping bypass primitive prevents user\n * `onDelete` guards on the output collection from firing on these\n * system-internal deletes. `onEmpty: 'keep'` opts out (rows from\n * prior refreshes linger even when the new result lacks them).\n *\n * **Cost ceiling:** if the materialized row count exceeds\n * `spec.maxRows` (default 100k), throws `MaterializedViewTooLargeError`\n * before any writes hit the store — so strict-mode rollback is\n * clean.\n *\n * **Strict mode:** `spec.strict === true` re-throws on any\n * row-write failure; the active TxContext registration means the\n * source-write rolls back atomically via `revertExecuted`.\n *\n * @internal\n */\nexport const MaterializedViewExecutor = {\n async refresh(\n reg: RegisteredMV,\n accessor: MVExecutorAccessor,\n ): Promise<RefreshResult> {\n const spec = reg.spec\n const outputColl = accessor.getCollection(reg.outputCollection)\n const maxRows = spec.maxRows ?? DEFAULT_MAX_ROWS\n const onEmpty = spec.onEmpty ?? 'delete'\n const strict = spec.strict ?? false\n\n // 1. Materialize the query (branches on terminal shape). If the\n // MV declared predicates, wrap the query context the same way\n // the registry did at registration time so `.wherePredicate()`\n // calls resolve to the registered functions.\n const baseCtx = accessor.getQueryContext()\n const ctxForQuery: MVQueryContext = spec.predicates\n ? wrapDbWithPredicates(baseCtx, spec.predicates)\n : baseCtx\n // UNION-form strategies: read every arm, map to the unified\n // row shape, concatenate, then optionally groupBy + aggregate.\n // Projection-form strategies (#810): hydrate the primary source,\n // attach forward + collect legs, map, then the same optional\n // grouping tail. The single-source `query()` path is untouched.\n let rows: ReadonlyArray<Record<string, unknown>>\n if (spec.unionSources) {\n rows = await materializeUnionResult(spec, ctxForQuery)\n } else if (spec.projection) {\n rows = await materializeProjectionResult(spec, ctxForQuery)\n } else {\n const q = spec.query!(ctxForQuery)\n rows = await materializeQueryResult(q, spec.name, spec.i18nLocale, spec.i18nFields)\n }\n\n // #777 — exclude this MV's OWN previously-stamped output rows from the\n // input scan. A same-collection Query-form MV copies the whole source row\n // verbatim into its output, so a stale output row can itself satisfy the\n // MV's own input filter (when the filter is on a field disjoint from the\n // partition field) and get re-selected as if it were live source — the\n // row self-perpetuates after its true source is gone. Prior output is\n // never this MV's own source.\n rows = rows.filter((row) => {\n const stamp = row._materializedFrom as { mvName?: string } | undefined\n return stamp?.mvName !== spec.name\n })\n\n // 2. Cost ceiling check BEFORE any writes — keeps the rollback\n // clean if the source-write is wrapped in a transaction.\n if (rows.length > maxRows) {\n throw new MaterializedViewTooLargeError(spec.name, rows.length, maxRows)\n }\n\n const txCtx = accessor.getActiveTxContext()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const adapter = (outputColl as any).adapter as {\n get(v: string, c: string, i: string): Promise<EncryptedEnvelope | null>\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const vaultName = (outputColl as any).vault as string\n\n // 3. Compute the post-refresh id set so we can diff against the\n // prior-emitted id set for tombstoning (when onEmpty === 'delete').\n const newIds = new Set<string>()\n const enrichedRows: Array<{ id: string; record: Record<string, unknown> }> = []\n for (const row of rows) {\n const id = spec.rowKey(row)\n newIds.add(id)\n const meta: MaterializedFromMeta = {\n mvName: spec.name,\n queryHash: reg.queryHash,\n sourceVersions: {},\n materializedAt: new Date().toISOString(),\n }\n enrichedRows.push({ id, record: { ...row, _materializedFrom: meta } })\n }\n\n // 4. Write the new rows.\n let written = 0\n let failed = 0\n for (const { id, record } of enrichedRows) {\n try {\n if (txCtx !== null) {\n const prior = await adapter.get(vaultName, reg.outputCollection, id)\n txCtx._executed.push({\n op: { type: 'put', vaultName, collectionName: reg.outputCollection, id },\n priorEnvelope: prior,\n })\n }\n if (accessor.dispatchCtx) {\n if (await putDerivedOutput(outputColl, id, record, accessor.dispatchCtx) === 'written') written++\n } else {\n await outputColl.put(id, record)\n written++\n }\n } catch (err) {\n failed++\n if (strict) throw err\n \n console.warn(`[mv] \"${spec.name}\" row write failed:`, err)\n }\n }\n\n // 5. Tombstone rows that existed before but don't appear now.\n // `onEmpty: 'keep'` skips this pass entirely. Uses\n // `_internalDelete` so a user-registered `onDelete` on the\n // output collection does NOT fire on housekeeping (composition fix).\n let deleted = 0\n const residueUndecodable: string[] = []\n const residueDeclined: string[] = []\n if (onEmpty === 'delete') {\n const priorIds = await listOutputIds(outputColl)\n for (const priorId of priorIds) {\n if (newIds.has(priorId)) continue\n // #762 — a same-collection partition MV (`output: { collection: <source>, partition }`,\n // the DERIV-PP30-001 shape) writes INTO its own source collection, so `listOutputIds`\n // also returns untouched USER source rows here. Decode each candidate and only\n // tombstone rows THIS MV stamped via `_materializedFrom.mvName` — the exact discipline\n // `invalidateMVAtRest` uses (stale.ts:151-162). An unstamped row, or one stamped by a\n // different MV, is never this MV's to delete.\n const priorEnvelope = await adapter.get(vaultName, reg.outputCollection, priorId)\n if (priorEnvelope === null) continue\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const priorDecoded = await (outputColl as any)._decodeEnvelope(priorEnvelope, priorId)\n if (priorDecoded === null) {\n // #782 part a — ownership unknown (undecodable, e.g. elevated above tier 0 on a\n // tiered output collection): can't rule out this being THIS MV's own stamped row.\n // Surface it rather than silently skip (mirrors invalidateMVAtRest's #776 posture —\n // previously this leg had NO residue channel at all).\n residueUndecodable.push(`${reg.outputCollection}:${priorId}`)\n continue\n }\n const priorStampedBy =\n typeof priorDecoded === 'object'\n ? (priorDecoded as Record<string, unknown>)._materializedFrom as { mvName?: string } | undefined\n : undefined\n if (priorStampedBy?.mvName !== spec.name) continue\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const outAny = outputColl as any\n if (typeof outAny._internalDelete === 'function') {\n // #776 part b — gate on the boolean, matching invalidateMVAtRest's discipline\n // (stale.ts): `_internalDelete` returns `false` for a #718 elevated-skip (no\n // erasure happened), and that must not inflate the tombstone count.\n if (await outAny._internalDelete(priorId, txCtx)) {\n deleted++\n } else {\n // #782 part b — decoded AND stamp-owned, but erasure was declined (#718\n // tier-elevation gate). Ownership IS confirmed here — a real silent survival,\n // not a legit stamp-mismatch skip. Surface it too.\n residueDeclined.push(`${reg.outputCollection}:${priorId}`)\n }\n } else {\n // Defensive fallback — should never hit in real flow since\n // every Collection has `_internalDelete`.\n await outputColl.delete(priorId)\n deleted++\n }\n } catch (err) {\n failed++\n if (strict) throw err\n\n console.warn(`[mv] \"${spec.name}\" tombstone failed for id=\"${priorId}\":`, err)\n }\n }\n }\n\n return { written, deleted, failed, residueUndecodable, residueDeclined }\n },\n}\n\n/**\n * List ids currently present in the MV's output collection via the\n * adapter directly (avoids triggering the lazy resolve-on-read path\n * we're INSIDE). Returns an empty array if the collection doesn't\n * exist or the adapter doesn't surface a list method.\n *\n * @internal\n */\nasync function listOutputIds(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n outputColl: Collection<any>,\n): Promise<string[]> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const cAny = outputColl as any\n const adapter = cAny.adapter as { list?: (v: string, c: string) => Promise<readonly string[]> }\n const vault = cAny.vault as string\n const name = cAny.name as string\n if (typeof adapter?.list !== 'function') return []\n try {\n const ids = await adapter.list(vault, name)\n return [...ids]\n } catch {\n return []\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  NoydbError
3
- } from "./chunk-IGM563N5.js";
3
+ } from "./chunk-6SYOHUHM.js";
4
4
 
5
5
  // src/with-shape/links/names.ts
6
6
  var LINK_COLLECTION_PREFIX = "_links_";
@@ -38,4 +38,4 @@ export {
38
38
  linkRowKey,
39
39
  LinkIntegrityError
40
40
  };
41
- //# sourceMappingURL=chunk-IUIVDVXM.js.map
41
+ //# sourceMappingURL=chunk-MUPZ6IZX.js.map
@@ -4,10 +4,10 @@ import {
4
4
  persistUserVisibility,
5
5
  readUserVisibility,
6
6
  saveUserEnvelope
7
- } from "./chunk-7B4GPCX7.js";
7
+ } from "./chunk-7IQWHYL2.js";
8
8
  import {
9
9
  PolicyDeniedError
10
- } from "./chunk-IGM563N5.js";
10
+ } from "./chunk-6SYOHUHM.js";
11
11
 
12
12
  // src/with-party/directory/user-envelope/api.ts
13
13
  var UserApi = class {
@@ -379,4 +379,4 @@ export {
379
379
  UserApi,
380
380
  createUserApi
381
381
  };
382
- //# sourceMappingURL=chunk-GZ2GKOF6.js.map
382
+ //# sourceMappingURL=chunk-NA374QG7.js.map
@@ -0,0 +1,23 @@
1
+ // src/with-fork/snapshots/strategy.ts
2
+ var NOT_ENABLED = new Error(
3
+ 'Snapshots require the snapshot strategy. Import `{ withSnapshots }` from "@noy-db/hub/snapshots" and pass it to `createNoydb({ snapshotStrategy: withSnapshots({ store }) })`.'
4
+ );
5
+ var NO_SNAPSHOTS = {
6
+ async snapshot() {
7
+ throw NOT_ENABLED;
8
+ },
9
+ async listSnapshots() {
10
+ throw NOT_ENABLED;
11
+ },
12
+ async restoreSnapshot() {
13
+ throw NOT_ENABLED;
14
+ },
15
+ async autoSnapshot() {
16
+ throw NOT_ENABLED;
17
+ }
18
+ };
19
+
20
+ export {
21
+ NO_SNAPSHOTS
22
+ };
23
+ //# sourceMappingURL=chunk-NIKO2BBZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-fork/snapshots/strategy.ts"],"sourcesContent":["import type { SnapshotPolicy } from './policy.js'\n\nexport interface SnapshotMeta {\n readonly version: string\n readonly label?: string\n readonly note?: string\n readonly exportedAt: string\n readonly exportedBy: string\n readonly size: number\n /**\n * `'verified'` — bundle was produced by `writePod(vault, {})`, which embeds\n * ledgerHead metadata; `vault.load()` runs `verifyBackupIntegrity()` on restore.\n * `'legacy-unverifiable'` — reserved for v2 import paths that read pre-existing bundles\n * lacking a ledgerHead; not produced by the current engine.\n */\n readonly integrity: 'verified' | 'legacy-unverifiable'\n /** `true` for the rolling auto-snapshot; absent on on-demand checkpoints. */\n readonly auto?: true\n}\n\nexport interface RetentionPolicy {\n readonly keepLast?: number\n readonly maxAgeDays?: number\n readonly prune?: boolean\n}\n\n/** @internal */\nexport interface SnapshotIndex {\n snapshots: SnapshotMeta[]\n nextCounter: number\n /** Single rolling auto-snapshot slot, separate from the immutable `snapshots` pool. */\n auto?: SnapshotMeta\n}\n\n/** @internal */\nexport interface SnapshotStrategy {\n snapshot(vault: unknown, by: string, opts?: { label?: string; note?: string }): Promise<SnapshotMeta>\n listSnapshots(vaultId: string): Promise<SnapshotMeta[]>\n restoreSnapshot(vault: unknown, version: string): Promise<void>\n /** Rolling auto-snapshot to the fixed `<vault>__auto` key. */\n autoSnapshot(vault: unknown, by: string, opts?: { label?: string; note?: string }): Promise<SnapshotMeta>\n /** Configured cadence policy. Undefined or `mode:'manual'` ⇒ no scheduler is wired. */\n readonly policy?: SnapshotPolicy\n}\n\nconst NOT_ENABLED = new Error(\n 'Snapshots require the snapshot strategy. Import `{ withSnapshots }` from ' +\n '\"@noy-db/hub/snapshots\" and pass it to ' +\n '`createNoydb({ snapshotStrategy: withSnapshots({ store }) })`.',\n)\n\n/** No-op stub. @internal */\nexport const NO_SNAPSHOTS: SnapshotStrategy = {\n async snapshot() { throw NOT_ENABLED },\n async listSnapshots() { throw NOT_ENABLED },\n async restoreSnapshot() { throw NOT_ENABLED },\n async autoSnapshot() { throw NOT_ENABLED },\n}\n"],"mappings":";AA6CA,IAAM,cAAc,IAAI;AAAA,EACtB;AAGF;AAGO,IAAM,eAAiC;AAAA,EAC5C,MAAM,WAAW;AAAE,UAAM;AAAA,EAAY;AAAA,EACrC,MAAM,gBAAgB;AAAE,UAAM;AAAA,EAAY;AAAA,EAC1C,MAAM,kBAAkB;AAAE,UAAM;AAAA,EAAY;AAAA,EAC5C,MAAM,eAAe;AAAE,UAAM;AAAA,EAAY;AAC3C;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ReadOnlyFrameError
3
- } from "./chunk-IGM563N5.js";
3
+ } from "./chunk-6SYOHUHM.js";
4
4
 
5
5
  // src/with-fork/shadow/vault-frame.ts
6
6
  var VaultFrame = class {
@@ -71,4 +71,4 @@ export {
71
71
  VaultFrame,
72
72
  CollectionFrame
73
73
  };
74
- //# sourceMappingURL=chunk-2U7Y7BNJ.js.map
74
+ //# sourceMappingURL=chunk-ONB627HU.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PortabilityNotEnabledError
3
- } from "./chunk-IGM563N5.js";
3
+ } from "./chunk-6SYOHUHM.js";
4
4
 
5
5
  // src/with-audit/portability/strategy.ts
6
6
  var NO_PORTABILITY = {
@@ -27,4 +27,4 @@ var NO_PORTABILITY = {
27
27
  export {
28
28
  NO_PORTABILITY
29
29
  };
30
- //# sourceMappingURL=chunk-GYB2QK5H.js.map
30
+ //# sourceMappingURL=chunk-OWLZONGX.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ConflictError,
3
3
  PodVersionConflictError
4
- } from "./chunk-IGM563N5.js";
4
+ } from "./chunk-6SYOHUHM.js";
5
5
 
6
6
  // src/with-pod/pod-store.ts
7
7
  var BUNDLE_STORE_VERSION = 1;
@@ -152,4 +152,4 @@ export {
152
152
  wrapBundleStore,
153
153
  createBundleStore
154
154
  };
155
- //# sourceMappingURL=chunk-YHPUDB7Q.js.map
155
+ //# sourceMappingURL=chunk-OWOT7CFC.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BrokerNotEnabledError
3
- } from "./chunk-IGM563N5.js";
3
+ } from "./chunk-6SYOHUHM.js";
4
4
 
5
5
  // src/port/with/broker-strategy.ts
6
6
  var NO_BROKER = {
@@ -27,4 +27,4 @@ export {
27
27
  NO_BROKER,
28
28
  buildCredentialBrokerHandle
29
29
  };
30
- //# sourceMappingURL=chunk-VEX6G3YL.js.map
30
+ //# sourceMappingURL=chunk-P4NUJVWL.js.map
@@ -0,0 +1,13 @@
1
+ // src/with-audit/consent/strategy.ts
2
+ var NO_CONSENT = {
3
+ async write() {
4
+ },
5
+ async read() {
6
+ return [];
7
+ }
8
+ };
9
+
10
+ export {
11
+ NO_CONSENT
12
+ };
13
+ //# sourceMappingURL=chunk-PEOZ34EM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-audit/consent/strategy.ts"],"sourcesContent":["/**\n * Strategy seam for the optional consent-audit service. Core\n * imports `ConsentStrategy` as a TYPE-ONLY symbol and `NO_CONSENT`\n * as a tiny runtime stub.\n *\n * `writeConsentEntry` / `loadConsentEntries` are only reachable from\n * `withConsent()` in `./active.ts`, exported through\n * `@noy-db/hub/consent`. Applications without a consent scope ship\n * none of the ~194 LOC.\n *\n * @internal\n */\n\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { EnclaveKey } from '../../kernel/enclave/index.js'\nimport type {\n ConsentAuditEntry,\n ConsentAuditFilter,\n} from './consent.js'\n\n/**\n * @internal\n */\nexport interface ConsentStrategy {\n /**\n * Record one consent audit entry. No-op under NO_CONSENT.\n */\n write(\n adapter: NoydbStore,\n vault: string,\n encrypted: boolean,\n entry: Omit<ConsentAuditEntry, 'id' | 'timestamp'>,\n getDEK: (collectionName: string) => Promise<EnclaveKey>,\n ): Promise<void>\n\n /**\n * Read filtered consent entries. Returns `[]` under NO_CONSENT.\n */\n read(\n adapter: NoydbStore,\n vault: string,\n encrypted: boolean,\n getDEK: (collectionName: string) => Promise<EnclaveKey>,\n filter?: ConsentAuditFilter,\n ): Promise<ConsentAuditEntry[]>\n}\n\n/**\n * No-consent stub. `write` is a no-op (returns a resolved promise);\n * `read` returns `[]`. Consumers get a consistent API surface without\n * pulling the consent module into the bundle.\n *\n * @internal\n */\nexport const NO_CONSENT: ConsentStrategy = {\n async write() {},\n async read() { return [] },\n}\n"],"mappings":";AAsDO,IAAM,aAA8B;AAAA,EACzC,MAAM,QAAQ;AAAA,EAAC;AAAA,EACf,MAAM,OAAO;AAAE,WAAO,CAAC;AAAA,EAAE;AAC3B;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TierWriteRefusedError
3
- } from "./chunk-IGM563N5.js";
3
+ } from "./chunk-6SYOHUHM.js";
4
4
 
5
5
  // src/kernel/tier-visibility.ts
6
6
  async function peekLiveTier(adapter, vault, name, id) {
@@ -34,4 +34,4 @@ export {
34
34
  assertTierWritable,
35
35
  assertCutoverTierSafe
36
36
  };
37
- //# sourceMappingURL=chunk-NM4LVUXH.js.map
37
+ //# sourceMappingURL=chunk-PTT2NB46.js.map
@@ -0,0 +1,23 @@
1
+ // src/with-commit/crdt/strategy.ts
2
+ var NOT_ENABLED = new Error(
3
+ 'CRDT mode requires the CRDT strategy. Import `{ withCrdt }` from "@noy-db/hub/crdt" and pass it to `createNoydb({ crdtStrategy: withCrdt() })`.'
4
+ );
5
+ var NO_CRDT = {
6
+ buildLwwMapState() {
7
+ throw NOT_ENABLED;
8
+ },
9
+ buildRgaState() {
10
+ throw NOT_ENABLED;
11
+ },
12
+ mergeCrdtStates() {
13
+ throw NOT_ENABLED;
14
+ },
15
+ resolveCrdtSnapshot() {
16
+ throw NOT_ENABLED;
17
+ }
18
+ };
19
+
20
+ export {
21
+ NO_CRDT
22
+ };
23
+ //# sourceMappingURL=chunk-PVEWA2DU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-commit/crdt/strategy.ts"],"sourcesContent":["/**\n * Strategy seam between core Collection and the optional CRDT\n * service. Core imports `CrdtStrategy` as a TYPE-ONLY symbol and\n * `NO_CRDT` as a minimal runtime stub.\n *\n * The state-construction / merge / snapshot-resolution helpers —\n * `buildLwwMapState`, `buildRgaState`, `mergeCrdtStates`,\n * `resolveCrdtSnapshot` — are only reachable from `withCrdt()` in\n * `./active.ts`, which is only exported through the `@noy-db/hub/crdt`\n * subpath. Consumers without CRDT mode configured never pull the\n * ~221 LOC into their bundle.\n *\n * @internal\n */\n\n// Hoisted to kernel/types.ts (C3 — enclave self-containment: record-codec.ts\n// consumes this as a spine-owned contract type). Re-exported here so existing\n// importers of this module are unaffected.\nimport type { CrdtStrategy } from '../../kernel/types.js'\nexport type { CrdtStrategy } from '../../kernel/types.js'\n\nconst NOT_ENABLED = new Error(\n 'CRDT mode requires the CRDT strategy. Import `{ withCrdt }` from ' +\n '\"@noy-db/hub/crdt\" and pass it to `createNoydb({ crdtStrategy: withCrdt() })`.',\n)\n\n/**\n * No-CRDT stub. Every method throws with a pointer at the subpath.\n * If a Collection declares `crdt: '...'` without this strategy wired,\n * the first put/sync-merge/read that hits the CRDT path surfaces the\n * error immediately.\n *\n * @internal\n */\nexport const NO_CRDT: CrdtStrategy = {\n buildLwwMapState() { throw NOT_ENABLED },\n buildRgaState() { throw NOT_ENABLED },\n mergeCrdtStates() { throw NOT_ENABLED },\n resolveCrdtSnapshot() { throw NOT_ENABLED },\n}\n"],"mappings":";AAqBA,IAAM,cAAc,IAAI;AAAA,EACtB;AAEF;AAUO,IAAM,UAAwB;AAAA,EACnC,mBAAmB;AAAE,UAAM;AAAA,EAAY;AAAA,EACvC,gBAAgB;AAAE,UAAM;AAAA,EAAY;AAAA,EACpC,kBAAkB;AAAE,UAAM;AAAA,EAAY;AAAA,EACtC,sBAAsB;AAAE,UAAM;AAAA,EAAY;AAC5C;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  OverlayIdMismatchError
3
- } from "./chunk-IGM563N5.js";
3
+ } from "./chunk-6SYOHUHM.js";
4
4
 
5
5
  // src/with-formula/overlay-views/virtual-collection.ts
6
6
  var OverlayedCollection = class {
@@ -206,4 +206,4 @@ var OverlayedCollection = class {
206
206
  export {
207
207
  OverlayedCollection
208
208
  };
209
- //# sourceMappingURL=chunk-2ITLQZV5.js.map
209
+ //# sourceMappingURL=chunk-PWWWMRT7.js.map
@@ -6,7 +6,7 @@ import {
6
6
  ConflictError,
7
7
  InvariantError,
8
8
  ValidationError
9
- } from "./chunk-IGM563N5.js";
9
+ } from "./chunk-6SYOHUHM.js";
10
10
 
11
11
  // src/kernel/best-effort-revert.ts
12
12
  async function bestEffortRevert(executed, adapter, compensate) {
@@ -231,7 +231,7 @@ async function runTransaction(db, fn, options, txInvariants) {
231
231
  db._clearActiveTxContext(ctx);
232
232
  }
233
233
  if (ctx._amendment) {
234
- const { GuardExecutor } = await import("./executor-WQQRU6DO.js");
234
+ const { GuardExecutor } = await import("./executor-OHET7TF7.js");
235
235
  try {
236
236
  for (const [vaultName, v] of ctx._amendmentVaults) {
237
237
  const registry = v._getGuardRegistry();
@@ -368,4 +368,4 @@ export {
368
368
  runTransaction,
369
369
  revertExecuted
370
370
  };
371
- //# sourceMappingURL=chunk-FLHOTGOO.js.map
371
+ //# sourceMappingURL=chunk-QVGEVZ5F.js.map
@@ -1,27 +1,27 @@
1
1
  import {
2
2
  resolveManagedSecret
3
- } from "./chunk-BCOKZC4B.js";
3
+ } from "./chunk-6SSWOUUS.js";
4
4
  import {
5
5
  freezeSnapshotOnly
6
- } from "./chunk-XULHFSHO.js";
6
+ } from "./chunk-MLCTPWSO.js";
7
7
  import {
8
8
  createOwnerKeyring
9
- } from "./chunk-WJDYZP3U.js";
9
+ } from "./chunk-ZDFU34XY.js";
10
10
  import {
11
11
  wrapKey
12
- } from "./chunk-5P5AAXYA.js";
12
+ } from "./chunk-7U6AB7DZ.js";
13
13
  import {
14
14
  NOYDB_FORMAT_VERSION
15
- } from "./chunk-5BHNQNBI.js";
15
+ } from "./chunk-DOZFU7OZ.js";
16
16
  import {
17
17
  PermissionDeniedError
18
- } from "./chunk-IGM563N5.js";
18
+ } from "./chunk-6SYOHUHM.js";
19
19
 
20
20
  // src/with-party/team/deed.ts
21
21
  var DEED_RECORD_ID = "deed";
22
22
  async function createDeedOwner(store, vault, ownerUserId, sealing) {
23
- const passphrase = await resolveManagedSecret(store, vault, sealing);
24
- const keyring = await createOwnerKeyring(store, vault, ownerUserId, passphrase);
23
+ const secret = await resolveManagedSecret(store, vault, sealing);
24
+ const keyring = await createOwnerKeyring(store, vault, ownerUserId, secret);
25
25
  await saveDeedMarker(store, vault, {
26
26
  ownerUserId,
27
27
  sealedUnder: sealing.id,
@@ -88,7 +88,7 @@ async function liberateVault(vault, opts) {
88
88
  }
89
89
  const collections = await listOperationalCollections(vault);
90
90
  const snapshot = await freezeSnapshotOnly(vault, collections, { actorUserId: keyring.userId });
91
- const newOwner = await createOwnerKeyring(adapter, vaultName, opts.newOwnerId, opts.newOwnerPassphrase);
91
+ const newOwner = await createOwnerKeyring(adapter, vaultName, opts.newOwnerId, opts.newOwnerSecret);
92
92
  if (!newOwner.kek) {
93
93
  throw new PermissionDeniedError(
94
94
  `new owner keyring for "${opts.newOwnerId}" has no KEK to re-wrap the incumbent DEKs under`
@@ -132,4 +132,4 @@ export {
132
132
  isDeedVault,
133
133
  liberateVault
134
134
  };
135
- //# sourceMappingURL=chunk-HKR25MGX.js.map
135
+ //# sourceMappingURL=chunk-QVIZDLAR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-party/team/deed.ts","../src/with-party/custody/liberate.ts"],"sourcesContent":["/**\n * FR-6 — Deed: sealed / hidden-owner provisioning.\n *\n * A **Deed** is a vault owned by a *latent* principal who never\n * authenticates. The owner credential (the random secret that\n * derives `KEK_owner`) is minted machine-side and sealed under a\n * **non-firm** {@link SealingKeyProvider} — that sealing boundary is\n * the cryptographic *inalienability anchor*: whoever holds the\n * provider (the client / their KMS) is the only party that can ever\n * re-derive `KEK_owner`. A firm-side custodian operates the vault\n * fully but can never reach the owner key — there is deliberately NO\n * firm-controlled fallback.\n *\n * Provisioning reuses the managed-mode seam:\n * - {@link resolveManagedSecret} mints + seals + persists the random\n * secret at `_meta/sealed-secret` (and unseals it on every\n * subsequent open through the same provider).\n * - {@link createOwnerKeyring} derives `KEK_owner` from that\n * secret and writes the `_keyring/<ownerUserId>` file.\n *\n * On top of that, a Deed writes a `_meta/deed` **marker**. The marker\n * is PLAINTEXT metadata — it records WHO the latent owner is and WHICH\n * sealing boundary protects them, so it must be readable without\n * unlocking the vault (a custodian or auditor inspecting the vault must\n * be able to see \"this is a Deed vault, owner = X, sealed under Y\"\n * without any key). The marker itself is therefore never sealed; only\n * the owner *credential* is.\n *\n * @module\n */\n\nimport type { NoydbStore, EncryptedEnvelope } from '../../kernel/types.js'\nimport { NOYDB_FORMAT_VERSION } from '../../kernel/types.js'\nimport type { UnlockedKeyring } from './keyring.js'\nimport { createOwnerKeyring } from './keyring.js'\nimport type { SealingKeyProvider } from './managed-secret.js'\nimport { resolveManagedSecret } from './managed-secret.js'\n\n/** Reserved id for the Deed marker under `_meta`. */\nexport const DEED_RECORD_ID = 'deed' as const\n\n/**\n * Plaintext metadata recording a vault's latent-owner Deed. Persisted\n * at `_meta/deed`. Readable without unlocking the vault by design — it\n * carries no secret material, only the identity of the latent owner\n * and the sealing boundary that anchors inalienability.\n */\nexport interface DeedMarker {\n /** The latent owner principal — the user id of the `_keyring/<id>` owner file. */\n readonly ownerUserId: string\n /**\n * The `SealingKeyProvider.id` the owner credential is sealed under.\n * The inalienability anchor: only the holder of this (non-firm)\n * provider can re-derive `KEK_owner`. Audit metadata — never secret.\n */\n readonly sealedUnder: string\n /** Always `true` for a Deed — the owner never authenticates interactively. */\n readonly latent: true\n /** ISO-8601 timestamp the Deed was issued. */\n readonly issuedAt: string\n /**\n * ISO-8601 timestamp the vault was liberated (a new owner claimed it\n * via the audited Liberate ceremony), if any. Absent until liberation.\n */\n readonly liberatedAt?: string\n}\n\n/**\n * Wire-format payload stored inside the `_meta/deed` envelope. Carries\n * a magic marker for forensics + the {@link DeedMarker} fields. JSON,\n * AES-GCM bypassed (the marker is plaintext metadata by design).\n */\ninterface DeedEnvelopePayload extends DeedMarker {\n readonly _noydb_deed: 1\n}\n\n/**\n * Provision a Deed: a latent owner whose credential is sealed under\n * `sealing` (a NON-firm provider). Mints + seals the owner secret\n * via {@link resolveManagedSecret}, derives the owner keyring via\n * {@link createOwnerKeyring}, then writes the plaintext `_meta/deed`\n * marker. Returns the unlocked owner keyring.\n *\n * The returned keyring is the only in-memory window onto `KEK_owner`\n * for this call; the persistent re-entry point is the sealing provider\n * (re-run {@link resolveManagedSecret} with the same provider to\n * re-resolve the secret, then {@link createOwnerKeyring}/load to\n * unlock — no interactive secret is ever required).\n *\n * There is deliberately no firm-controlled fallback: the marker's\n * `sealedUnder` is the single cryptographic anchor of ownership.\n */\nexport async function createDeedOwner(\n store: NoydbStore,\n vault: string,\n ownerUserId: string,\n sealing: SealingKeyProvider,\n): Promise<UnlockedKeyring> {\n // 1. Mint + seal + persist the random owner secret under the\n // non-firm provider (writes _meta/sealed-secret).\n const secret = await resolveManagedSecret(store, vault, sealing)\n\n // 2. Derive KEK_owner from the (never-human-seen) secret and\n // write the owner keyring file.\n const keyring = await createOwnerKeyring(store, vault, ownerUserId, secret)\n\n // 3. Write the plaintext Deed marker. NOT sealed — it is audit\n // metadata that must be readable without unlocking.\n await saveDeedMarker(store, vault, {\n ownerUserId,\n sealedUnder: sealing.id,\n latent: true,\n issuedAt: new Date().toISOString(),\n })\n\n return keyring\n}\n\n/**\n * Read the {@link DeedMarker} from `_meta/deed`, or `null` if the vault\n * has no Deed marker (i.e. it is not a Deed vault). Plaintext read — no\n * unlocking required.\n */\nexport async function loadDeedMarker(\n store: NoydbStore,\n vault: string,\n): Promise<DeedMarker | null> {\n const envelope = await store.get(vault, '_meta', DEED_RECORD_ID)\n if (!envelope) return null\n let payload: unknown\n try {\n payload = JSON.parse(envelope._data)\n } catch {\n return null\n }\n if (typeof payload !== 'object' || payload === null) return null\n const r = payload as Record<string, unknown>\n if (r._noydb_deed !== 1) return null\n if (\n typeof r.ownerUserId !== 'string'\n || typeof r.sealedUnder !== 'string'\n || r.latent !== true\n || typeof r.issuedAt !== 'string'\n ) {\n return null\n }\n const marker: DeedMarker = {\n ownerUserId: r.ownerUserId,\n sealedUnder: r.sealedUnder,\n latent: true,\n issuedAt: r.issuedAt,\n ...(typeof r.liberatedAt === 'string' ? { liberatedAt: r.liberatedAt } : {}),\n }\n return marker\n}\n\n/** Whether `vault` carries a Deed marker (a sealed/latent owner). */\nexport async function isDeedVault(\n store: NoydbStore,\n vault: string,\n): Promise<boolean> {\n return (await loadDeedMarker(store, vault)) !== null\n}\n\n/**\n * Persist a {@link DeedMarker} at `_meta/deed`. Mirrors\n * `saveSealedSecret`'s envelope shape: a standard\n * {@link EncryptedEnvelope} with AES-GCM bypassed (`_iv: ''`), the\n * payload stored as plaintext JSON in `_data`. The marker is metadata,\n * not a secret — sealing it would defeat its purpose (auditors /\n * custodians must read it without a key).\n *\n * @internal — used by `createDeedOwner` and (later) the Liberate\n * ceremony to stamp `liberatedAt`.\n */\nexport async function saveDeedMarker(\n store: NoydbStore,\n vault: string,\n marker: DeedMarker,\n): Promise<void> {\n const persisted: DeedEnvelopePayload = { _noydb_deed: 1, ...marker }\n const prior = await store.get(vault, '_meta', DEED_RECORD_ID)\n const env: EncryptedEnvelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: (prior?._v ?? 0) + 1,\n _ts: new Date().toISOString(),\n // AES-GCM bypassed — the marker is plaintext audit metadata.\n _iv: '',\n _data: JSON.stringify(persisted),\n }\n await store.put(vault, '_meta', DEED_RECORD_ID, env)\n}\n","/**\n * `liberateVault` — the audited claim of ownership over a\n * sealed-owner (Deed) vault. The inverse of withdrawal.\n *\n * A **Deed** vault's owner credential is sealed under a non-firm provider, so\n * the firm-side **custodian** (which holds every collection DEK and operates\n * the vault fully) can never reach `KEK_owner`. Liberation is the ONLY route\n * by which a custodian assumes ownership, and it is deliberately a manual,\n * audited ceremony:\n *\n * 1. gate `'liberate-vault'` (fail-closed)\n * 2. caller MUST be the `custodian` (the de-facto authority holding the DEKs)\n * 3. freeze a PRE-liberation EVIDENCE snapshot (hash-pinned in the ledger) —\n * but PRESERVE the live data for the new owner (see the freeze decision\n * below)\n * 4. mint a NEW owner keyring re-wrapping the incumbent DEKs under the new\n * owner's KEK\n * 5. lifecycle ledger `liberation-claimed:<newOwnerId>:<legalBasis>`\n * 6. stamp the `_meta/deed` marker with `liberatedAt`\n *\n * ## Security: the inalienability floor\n *\n * Liberation **mints a new owner from the custodian's DEKs** — it does NOT\n * unseal the original sealed owner. The old sealed-owner credential is left\n * untouched and ORPHANED (its `_keyring/<id>` file remains, its KEK is still\n * sealed under the non-firm provider), never impersonated. The new owner is a\n * DISTINCT principal under a fresh KEK derived from `newOwnerSecret`. This\n * preserves the inalienability floor: the act of claiming ownership is itself\n * auditable and produces a different principal, rather than silently assuming\n * the latent owner's identity.\n *\n * ## Freeze decision: snapshot-only, not freeze-and-delete\n *\n * `freezeAndDeleteClosure` (withdraw-accessible.ts) writes a hash-pinned\n * snapshot and THEN delete-closures the live records — correct for a\n * destructive withdrawal, WRONG for liberation. Liberation transfers\n * operational continuity; it must leave the live data intact for the new\n * owner. We therefore call the snapshot-only core `freezeSnapshotOnly`\n * (factored out of that module; the freeze-AND-delete withdrawal path is\n * unchanged) to pin the evidence snapshot while preserving the records.\n *\n * @module\n */\n\nimport type { Vault } from '../../kernel/vault.js'\nimport type { FactorProofBundle, KeyringFile } from '../../kernel/types.js'\nimport { PermissionDeniedError } from '../../kernel/errors.js'\nimport { wrapKey } from '../../kernel/enclave/index.js'\nimport { createOwnerKeyring } from '../team/keyring.js'\nimport type { FrozenSnapshotRef } from '../../with-audit/portability/withdraw-accessible.js'\nimport { freezeSnapshotOnly } from '../../with-audit/portability/withdraw-accessible.js'\nimport { loadDeedMarker, saveDeedMarker } from '../team/deed.js'\n\nexport interface LiberateOptions {\n /** The id of the new owner principal the custodian mints by claiming ownership. */\n readonly newOwnerId: string\n /** The secret that derives the new owner's KEK (the DEKs are re-wrapped under it). */\n readonly newOwnerSecret: string\n /** Legal/contractual basis recorded in the audit (e.g. 'contractual-handover'). */\n readonly legalBasis: string\n readonly factors?: FactorProofBundle\n}\n\nexport interface LiberateResult {\n /** The hash-pinned pre-liberation evidence snapshot. */\n readonly snapshot: FrozenSnapshotRef\n}\n\n/**\n * Audited claim of ownership over a sealed-owner vault by its custodian. See\n * the module doc for the full ceremony + security rationale.\n */\nexport async function liberateVault(\n vault: Vault,\n opts: LiberateOptions,\n): Promise<LiberateResult> {\n // 1. gate — fail-closed `liberate-vault`.\n await vault.noydb.checkGate(vault.name, 'liberate-vault', opts.factors)\n\n // 2. caller must be the custodian (the de-facto authority holding the DEKs).\n const { name: vaultName, adapter, keyring } = vault._introspectState()\n if (keyring.role !== 'custodian') {\n throw new PermissionDeniedError(\n 'liberation is claimed only by the custodian (the de-facto authority holding the DEKs)',\n )\n }\n\n // Refuse to clobber an existing principal: the new owner must be a FRESH id.\n // (Checked before any side effect so a colliding id never leaves a half-run\n // ceremony — no orphan snapshot, no partial keyring overwrite.)\n const existing = await adapter.get(vaultName, '_keyring', opts.newOwnerId)\n if (existing) {\n throw new PermissionDeniedError(\n `liberateVault: newOwnerId \"${opts.newOwnerId}\" already exists as a principal; choose a fresh id (liberation mints a distinct owner, it never overwrites an existing keyring)`,\n )\n }\n\n // 3. Pre-liberation EVIDENCE snapshot of every operational collection —\n // snapshot-only (live data preserved for the new owner; liberation\n // transfers operational continuity, it does not erase).\n const collections = await listOperationalCollections(vault)\n const snapshot = await freezeSnapshotOnly(vault, collections, { actorUserId: keyring.userId })\n\n // 4. Mint a NEW owner keyring, re-wrapping the incumbent DEKs under the new\n // owner's fresh KEK. The old sealed owner is NOT unsealed — a DISTINCT\n // principal is minted and the original owner credential is left orphaned\n // (inalienability floor). Mirrors adopt-partition.ts's DEK re-wrap.\n const newOwner = await createOwnerKeyring(adapter, vaultName, opts.newOwnerId, opts.newOwnerSecret)\n if (!newOwner.kek) {\n throw new PermissionDeniedError(\n `new owner keyring for \"${opts.newOwnerId}\" has no KEK to re-wrap the incumbent DEKs under`,\n )\n }\n const env = await adapter.get(vaultName, '_keyring', opts.newOwnerId)\n if (!env) {\n throw new PermissionDeniedError(`new owner keyring for \"${opts.newOwnerId}\" did not persist`)\n }\n const keyringFile = JSON.parse(env._data) as KeyringFile\n const mergedDeks: Record<string, string> = { ...keyringFile.deks }\n for (const [collection, dek] of keyring.deks) {\n mergedDeks[collection] = await wrapKey(dek, newOwner.kek)\n }\n const mergedFile: KeyringFile = { ...keyringFile, deks: mergedDeks }\n await adapter.put(vaultName, '_keyring', opts.newOwnerId, { ...env, _data: JSON.stringify(mergedFile) })\n\n // 5. Lifecycle ledger audit (no-op if the history strategy is absent).\n await vault._getLedgerOrNull()?.append({\n op: 'lifecycle', collection: '', id: '', version: 0, actor: opts.newOwnerId, payloadHash: '',\n reason: `liberation-claimed:${opts.newOwnerId}:${opts.legalBasis}`,\n })\n\n // 6. Stamp the Deed marker with `liberatedAt` (if a marker exists).\n const marker = await loadDeedMarker(adapter, vaultName)\n if (marker) {\n await saveDeedMarker(adapter, vaultName, { ...marker, liberatedAt: new Date().toISOString() })\n }\n\n return { snapshot }\n}\n\n/**\n * Enumerate the vault's operational (user-facing) collections — those carried\n * by the caller's keyring DEK map, minus the reserved internal collections\n * (`_*`). These are the collections frozen into the evidence snapshot.\n */\nasync function listOperationalCollections(vault: Vault): Promise<readonly string[]> {\n const { keyring } = vault._introspectState()\n return [...keyring.deks.keys()].filter((c) => !c.startsWith('_'))\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  MaterializedViewConfigError,
3
3
  ValidationError
4
- } from "./chunk-IGM563N5.js";
4
+ } from "./chunk-6SYOHUHM.js";
5
5
 
6
6
  // src/with-formula/materialized-views/with-materialized-view.ts
7
7
  function withMaterializedView(spec) {
@@ -177,4 +177,4 @@ function withMaterializedView(spec) {
177
177
  export {
178
178
  withMaterializedView
179
179
  };
180
- //# sourceMappingURL=chunk-OOTTXUNV.js.map
180
+ //# sourceMappingURL=chunk-RM5EXCFF.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/with-formula/materialized-views/with-materialized-view.ts"],"sourcesContent":["import { MaterializedViewConfigError, ValidationError } from '../../kernel/errors.js'\nimport type { MaterializedViewStrategy, MaterializedViewStrategyHandle } from './types.js'\n\n/**\n * Register a materialized view: a declared query whose result is\n * persisted as a queryable collection and kept fresh as sources\n * change. Writes go through the standard `Collection.put` pipeline;\n * refresh-driven deletes route through `Collection._internalDelete` so\n * user `onDelete` guards on the output collection aren't tripped by\n * housekeeping.\n *\n * Three registration modes:\n * - **single-source** — declare `query: (db) => Query<TRow>`; the\n * dependency analyzer derives source collections from the plan.\n * - **UNION** — declare `unionSources: [{ collection, map }, ...]`\n * plus optional `groupBy` + `aggregate`; the executor reads each\n * arm, maps to the unified row shape, concatenates, then groups\n * and aggregates.\n * - **projection** (#810) — declare `projection: { source, joins,\n * map }`; one output row per primary record, enriched with\n * forward FK legs and reverse \"collect\" legs before `map` runs.\n *\n * The three modes are mutually exclusive — exactly one of `query` /\n * `unionSources` / `projection` must be set at registration time.\n *\n * See docs/superpowers/specs/2026-05-20-dim14-mv-v2-design.md (single-source v2),\n * docs/superpowers/specs/2026-05-21-dim14-mv-multikey-and-union.md (UNION),\n * and docs/superpowers/specs/2026-07-25-join-projection-mv-design.md (projection).\n */\nexport function withMaterializedView<TRow extends Record<string, unknown>>(\n spec: MaterializedViewStrategy<TRow>,\n): MaterializedViewStrategyHandle {\n if (!spec.name || spec.name.length === 0) {\n throw new ValidationError('withMaterializedView: name is required')\n }\n // Mutual exclusion: exactly one of the three forms must be declared.\n const declaredForms = [spec.query, spec.unionSources, spec.projection]\n .filter((f) => f !== undefined).length\n if (declaredForms > 1) {\n throw new MaterializedViewConfigError(\n 'query, unionSources, and projection are mutually exclusive — pick one',\n )\n }\n if (declaredForms === 0) {\n throw new MaterializedViewConfigError(\n 'strategy must declare exactly one of query, unionSources, or projection',\n )\n }\n if (spec.query !== undefined && typeof spec.query !== 'function') {\n throw new ValidationError('withMaterializedView: query must be a function returning a Query<T>')\n }\n // UNION-form invariants.\n if (spec.unionSources) {\n // A single arm is a deliberate shape: map→group→aggregate over\n // ONE collection with a COMPUTED bucket key (e.g. month sliced from a\n // date field) — something the query form's stored-field groupBy cannot\n // express. The executor and dependency analyzer are arm-count-agnostic.\n if (spec.unionSources.length < 1) {\n throw new MaterializedViewConfigError(\n 'unionSources requires at least 1 source collection',\n )\n }\n const seen = new Set<string>()\n for (const s of spec.unionSources) {\n if (typeof s?.collection !== 'string' || s.collection.length === 0) {\n throw new MaterializedViewConfigError(\n 'each unionSources entry must declare a non-empty `collection` string',\n )\n }\n if (typeof s.map !== 'function') {\n throw new MaterializedViewConfigError(\n `unionSources entry for \"${s.collection}\" is missing a \\`map\\` function`,\n )\n }\n if (seen.has(s.collection)) {\n throw new MaterializedViewConfigError(\n `unionSources must reference distinct collections (duplicate: \"${s.collection}\")`,\n )\n }\n seen.add(s.collection)\n }\n if (Array.isArray(spec.groupBy) && spec.groupBy.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": groupBy must not be an empty array — omit it or provide at least one field name`,\n )\n }\n if (spec.aggregate && !spec.groupBy) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": UNION strategy with aggregate requires groupBy — `\n + `use groupBy to declare the bucketing keys, or remove aggregate for a pure dedup MV`,\n )\n }\n // `moneyFields` only has meaning when there's an aggregate to\n // money-rewrite — it keys reducer outputs, so declaring it without\n // `aggregate` is a no-op config mistake.\n if (spec.moneyFields && !spec.aggregate) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": moneyFields requires aggregate — `\n + `moneyFields rewrites sum/min/max reducers over money output fields, `\n + `so it is meaningless without an aggregate spec`,\n )\n }\n // Per-arm joins resolve right-side collections that the union\n // dependency set (built from arm `collection`s alone) does NOT\n // include. The consumer must list those right-side collections in\n // `sources` so writes to them trigger MV refresh.\n if (spec.unionSources.some(s => s.join && s.join.length > 0) && (!spec.sources || spec.sources.length === 0)) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a unionSources arm declares join(s) but `\n + `no \\`sources\\` are listed — declare sources: [...] with the right-side `\n + `(join-target) collection names so writes to them trigger MV refresh`,\n )\n }\n if (spec.predicates) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": predicates are not supported on UNION strategies — `\n + `UNION mode does not use a Query<T> chain, so .wherePredicate() cannot fire. `\n + `Use the query() form, or open an issue if per-arm predicates are needed`,\n )\n }\n }\n // Projection-form invariants (#810). Shape checks only — the\n // semantic ref() check on collect legs (the `on` field must carry a\n // ref() targeting the projection source) runs at first\n // materialization, parity with join-time ref errors.\n if (spec.projection) {\n const projection = spec.projection\n if (typeof projection.source !== 'string' || projection.source.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection.source must be a non-empty collection name`,\n )\n }\n if (typeof projection.map !== 'function') {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection is missing a \\`map\\` function`,\n )\n }\n if (!Array.isArray(projection.joins) || projection.joins.length < 1) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection.joins must declare at least 1 leg — `\n + `a leg-less single-source MV is the query() form's job`,\n )\n }\n const seenAs = new Set<string>()\n for (const leg of projection.joins) {\n const l = leg as { field?: unknown; collect?: unknown; on?: unknown; as?: unknown }\n const isForward = l.field !== undefined\n const isCollect = l.collect !== undefined\n if (isForward && isCollect) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a projection leg cannot declare both \\`field\\` `\n + `(forward) and \\`collect\\` (reverse) — split it into two legs`,\n )\n }\n if (!isForward && !isCollect) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": each projection leg must declare either \\`field\\` `\n + `(forward FK) or \\`collect\\` (reverse one-to-many)`,\n )\n }\n if (isForward && (typeof l.field !== 'string' || l.field.length === 0)) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a forward projection leg must declare a non-empty \\`field\\``,\n )\n }\n if (isCollect) {\n if (typeof l.collect !== 'string' || l.collect.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a collect projection leg must declare a non-empty \\`collect\\` collection name`,\n )\n }\n if (typeof l.on !== 'string' || l.on.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": collect leg for \"${l.collect}\" must declare a non-empty \\`on\\` FK field`,\n )\n }\n }\n if (typeof l.as !== 'string' || l.as.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": each projection leg must declare a non-empty \\`as\\` alias`,\n )\n }\n if (seenAs.has(l.as)) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection legs must attach under distinct \\`as\\` aliases (duplicate: \"${l.as}\")`,\n )\n }\n seenAs.add(l.as)\n }\n // Post-map grouping invariants — same rules as UNION (the mapped\n // stream feeds the same shared groupAndReduce tail).\n if (Array.isArray(spec.groupBy) && spec.groupBy.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": groupBy must not be an empty array — omit it or provide at least one field name`,\n )\n }\n if (spec.aggregate && !spec.groupBy) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection strategy with aggregate requires groupBy — `\n + `use groupBy to declare the bucketing keys, or remove aggregate for a row-per-primary-record MV`,\n )\n }\n if (spec.moneyFields && !spec.aggregate) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": moneyFields requires aggregate — `\n + `moneyFields rewrites sum/min/max reducers over money output fields, `\n + `so it is meaningless without an aggregate spec`,\n )\n }\n if (spec.predicates) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": predicates are not supported on projection strategies — `\n + `projection mode does not use a Query<T> chain, so .wherePredicate() cannot fire. `\n + `Filter inside projection.map (return null to omit) instead`,\n )\n }\n }\n // i18nLocale + i18nFields drive compute-time i18n resolution of group-key\n // i18nText fields before bucketing — UNION mode (resolved on the unified rows)\n // AND query mode (resolved in GroupedAggregation.run before groupAndReduce).\n // i18nLocale without i18nFields cannot resolve anything, so reject it early.\n if (spec.i18nLocale !== undefined && spec.i18nFields === undefined) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": i18nLocale requires i18nFields — `\n + `declare the i18nText descriptors of the group-key fields so they can be `\n + `resolved at the mv layer before bucketing.`,\n )\n }\n if (typeof spec.rowKey !== 'function') {\n throw new ValidationError('withMaterializedView: rowKey is required (no default; see spec § Type surface)')\n }\n if (spec.refresh !== 'eager' && spec.refresh !== 'lazy' && spec.refresh !== 'manual') {\n throw new ValidationError(\n `withMaterializedView: refresh must be 'eager' | 'lazy' | 'manual', got \"${String(spec.refresh)}\"`,\n )\n }\n return {\n __noydb_strategy: 'materialized-view',\n spec,\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/with-formula/materialized-views/with-materialized-view.ts"],"sourcesContent":["import { MaterializedViewConfigError, ValidationError } from '../../kernel/errors.js'\nimport type { MaterializedViewStrategy, MaterializedViewStrategyHandle } from './types.js'\n\n/**\n * Register a materialized view: a declared query whose result is\n * persisted as a queryable collection and kept fresh as sources\n * change. Writes go through the standard `Collection.put` pipeline;\n * refresh-driven deletes route through `Collection._internalDelete` so\n * user `onDelete` guards on the output collection aren't tripped by\n * housekeeping.\n *\n * Three registration modes:\n * - **single-source** — declare `query: (db) => Query<TRow>`; the\n * dependency analyzer derives source collections from the plan.\n * - **UNION** — declare `unionSources: [{ collection, map }, ...]`\n * plus optional `groupBy` + `aggregate`; the executor reads each\n * arm, maps to the unified row shape, concatenates, then groups\n * and aggregates.\n * - **projection** (#810) — declare `projection: { source, joins,\n * map }`; one output row per primary record, enriched with\n * forward FK legs and reverse \"collect\" legs before `map` runs.\n *\n * The three modes are mutually exclusive — exactly one of `query` /\n * `unionSources` / `projection` must be set at registration time.\n *\n * See docs/superpowers/specs/2026-05-20-dim14-mv-v2-design.md (single-source v2),\n * docs/superpowers/specs/2026-05-21-dim14-mv-multikey-and-union.md (UNION),\n * and docs/superpowers/specs/2026-07-25-join-projection-mv-design.md (projection).\n */\nexport function withMaterializedView<TRow extends Record<string, unknown>>(\n spec: MaterializedViewStrategy<TRow>,\n): MaterializedViewStrategyHandle {\n if (!spec.name || spec.name.length === 0) {\n throw new ValidationError('withMaterializedView: name is required')\n }\n // Mutual exclusion: exactly one of the three forms must be declared.\n const declaredForms = [spec.query, spec.unionSources, spec.projection]\n .filter((f) => f !== undefined).length\n if (declaredForms > 1) {\n throw new MaterializedViewConfigError(\n 'query, unionSources, and projection are mutually exclusive — pick one',\n )\n }\n if (declaredForms === 0) {\n throw new MaterializedViewConfigError(\n 'strategy must declare exactly one of query, unionSources, or projection',\n )\n }\n if (spec.query !== undefined && typeof spec.query !== 'function') {\n throw new ValidationError('withMaterializedView: query must be a function returning a Query<T>')\n }\n // UNION-form invariants.\n if (spec.unionSources) {\n // A single arm is a deliberate shape: map→group→aggregate over\n // ONE collection with a COMPUTED bucket key (e.g. month sliced from a\n // date field) — something the query form's stored-field groupBy cannot\n // express. The executor and dependency analyzer are arm-count-agnostic.\n if (spec.unionSources.length < 1) {\n throw new MaterializedViewConfigError(\n 'unionSources requires at least 1 source collection',\n )\n }\n const seen = new Set<string>()\n for (const s of spec.unionSources) {\n if (typeof s?.collection !== 'string' || s.collection.length === 0) {\n throw new MaterializedViewConfigError(\n 'each unionSources entry must declare a non-empty `collection` string',\n )\n }\n if (typeof s.map !== 'function') {\n throw new MaterializedViewConfigError(\n `unionSources entry for \"${s.collection}\" is missing a \\`map\\` function`,\n )\n }\n if (seen.has(s.collection)) {\n throw new MaterializedViewConfigError(\n `unionSources must reference distinct collections (duplicate: \"${s.collection}\")`,\n )\n }\n seen.add(s.collection)\n }\n if (Array.isArray(spec.groupBy) && spec.groupBy.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": groupBy must not be an empty array — omit it or provide at least one field name`,\n )\n }\n if (spec.aggregate && !spec.groupBy) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": UNION strategy with aggregate requires groupBy — `\n + `use groupBy to declare the bucketing keys, or remove aggregate for a pure dedup MV`,\n )\n }\n // `moneyFields` only has meaning when there's an aggregate to\n // money-rewrite — it keys reducer outputs, so declaring it without\n // `aggregate` is a no-op config mistake.\n if (spec.moneyFields && !spec.aggregate) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": moneyFields requires aggregate — `\n + `moneyFields rewrites sum/min/max reducers over money output fields, `\n + `so it is meaningless without an aggregate spec`,\n )\n }\n // Per-arm joins resolve right-side collections that the union\n // dependency set (built from arm `collection`s alone) does NOT\n // include. The consumer must list those right-side collections in\n // `sources` so writes to them trigger MV refresh.\n if (spec.unionSources.some(s => s.join && s.join.length > 0) && (!spec.sources || spec.sources.length === 0)) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a unionSources arm declares join(s) but `\n + `no \\`sources\\` are listed — declare sources: [...] with the right-side `\n + `(join-target) collection names so writes to them trigger MV refresh`,\n )\n }\n if (spec.predicates) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": predicates are not supported on UNION strategies — `\n + `UNION mode does not use a Query<T> chain, so .wherePredicate() cannot fire. `\n + `Use the query() form, or open an issue if per-arm predicates are needed`,\n )\n }\n }\n // Projection-form invariants (#810). Shape checks only — the\n // semantic ref() check on collect legs (the `on` field must carry a\n // ref() targeting the projection source) runs at first\n // materialization, parity with join-time ref errors.\n if (spec.projection) {\n const projection = spec.projection\n if (typeof projection.source !== 'string' || projection.source.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection.source must be a non-empty collection name`,\n )\n }\n if (typeof projection.map !== 'function') {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection is missing a \\`map\\` function`,\n )\n }\n if (!Array.isArray(projection.joins) || projection.joins.length < 1) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection.joins must declare at least 1 leg — `\n + `a leg-less single-source MV is the query() form's job`,\n )\n }\n const seenAs = new Set<string>()\n for (const leg of projection.joins) {\n const l = leg as { field?: unknown; collect?: unknown; on?: unknown; as?: unknown }\n const isForward = l.field !== undefined\n const isCollect = l.collect !== undefined\n if (isForward && isCollect) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a projection leg cannot declare both \\`field\\` `\n + `(forward) and \\`collect\\` (reverse) — split it into two legs`,\n )\n }\n if (!isForward && !isCollect) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": each projection leg must declare either \\`field\\` `\n + `(forward FK) or \\`collect\\` (reverse one-to-many)`,\n )\n }\n if (isForward && (typeof l.field !== 'string' || l.field.length === 0)) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a forward projection leg must declare a non-empty \\`field\\``,\n )\n }\n if (isCollect) {\n if (typeof l.collect !== 'string' || l.collect.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a collect projection leg must declare a non-empty \\`collect\\` collection name`,\n )\n }\n if (typeof l.on !== 'string' || l.on.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": collect leg for \"${l.collect}\" must declare a non-empty \\`on\\` FK field`,\n )\n }\n }\n if (typeof l.as !== 'string' || l.as.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": each projection leg must declare a non-empty \\`as\\` alias`,\n )\n }\n if (seenAs.has(l.as)) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection legs must attach under distinct \\`as\\` aliases (duplicate: \"${l.as}\")`,\n )\n }\n seenAs.add(l.as)\n }\n // Post-map grouping invariants — same rules as UNION (the mapped\n // stream feeds the same shared groupAndReduce tail).\n if (Array.isArray(spec.groupBy) && spec.groupBy.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": groupBy must not be an empty array — omit it or provide at least one field name`,\n )\n }\n if (spec.aggregate && !spec.groupBy) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection strategy with aggregate requires groupBy — `\n + `use groupBy to declare the bucketing keys, or remove aggregate for a row-per-primary-record MV`,\n )\n }\n if (spec.moneyFields && !spec.aggregate) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": moneyFields requires aggregate — `\n + `moneyFields rewrites sum/min/max reducers over money output fields, `\n + `so it is meaningless without an aggregate spec`,\n )\n }\n if (spec.predicates) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": predicates are not supported on projection strategies — `\n + `projection mode does not use a Query<T> chain, so .wherePredicate() cannot fire. `\n + `Filter inside projection.map (return null to omit) instead`,\n )\n }\n }\n // i18nLocale + i18nFields drive compute-time i18n resolution of group-key\n // i18nText fields before bucketing — UNION mode (resolved on the unified rows)\n // AND query mode (resolved in GroupedReduction.run before groupAndReduce).\n // i18nLocale without i18nFields cannot resolve anything, so reject it early.\n if (spec.i18nLocale !== undefined && spec.i18nFields === undefined) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": i18nLocale requires i18nFields — `\n + `declare the i18nText descriptors of the group-key fields so they can be `\n + `resolved at the mv layer before bucketing.`,\n )\n }\n if (typeof spec.rowKey !== 'function') {\n throw new ValidationError('withMaterializedView: rowKey is required (no default; see spec § Type surface)')\n }\n if (spec.refresh !== 'eager' && spec.refresh !== 'lazy' && spec.refresh !== 'manual') {\n throw new ValidationError(\n `withMaterializedView: refresh must be 'eager' | 'lazy' | 'manual', got \"${String(spec.refresh)}\"`,\n )\n }\n return {\n __noydb_strategy: 'materialized-view',\n spec,\n }\n}\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  DanglingReferenceError,
6
6
  JoinTooLargeError
7
- } from "./chunk-IGM563N5.js";
7
+ } from "./chunk-6SYOHUHM.js";
8
8
 
9
9
  // src/kernel/query/join.ts
10
10
  var DEFAULT_JOIN_MAX_ROWS = 5e4;
@@ -170,4 +170,4 @@ export {
170
170
  applyJoins,
171
171
  resetJoinWarnings
172
172
  };
173
- //# sourceMappingURL=chunk-OGFPMCSP.js.map
173
+ //# sourceMappingURL=chunk-SBOHNJUD.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sha256Hex
3
- } from "./chunk-5P5AAXYA.js";
3
+ } from "./chunk-7U6AB7DZ.js";
4
4
 
5
5
  // src/with-shape/persisted-schemas/canonicalize.ts
6
6
  function canonicalize(value) {
@@ -91,4 +91,4 @@ export {
91
91
  isZod4Schema,
92
92
  derivePersistedSchema
93
93
  };
94
- //# sourceMappingURL=chunk-EDC6MLXV.js.map
94
+ //# sourceMappingURL=chunk-SEU6QHH4.js.map
@@ -0,0 +1,14 @@
1
+ // src/with-fork/shadow/strategy.ts
2
+ var NOT_ENABLED = new Error(
3
+ 'VaultFrame requires the shadow strategy. Import `{ withShadow }` from "@noy-db/hub/shadow" and pass it to `createNoydb({ shadowStrategy: withShadow() })`.'
4
+ );
5
+ var NO_SHADOW = {
6
+ buildFrame() {
7
+ throw NOT_ENABLED;
8
+ }
9
+ };
10
+
11
+ export {
12
+ NO_SHADOW
13
+ };
14
+ //# sourceMappingURL=chunk-SMY5X46Z.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-fork/shadow/strategy.ts"],"sourcesContent":["/**\n * Strategy seam for the optional VaultFrame snapshot primitive.\n * Core imports `ShadowStrategy` as TYPE-ONLY and `NO_SHADOW` as a\n * 4-line stub. `VaultFrame` is only constructed inside `withShadow()`\n * — consumers who never import `@noy-db/hub/shadow` ship none of\n * the ~129 LOC.\n *\n * @internal\n */\n\nimport type { VaultFrame } from './vault-frame.js'\n\n/**\n * @internal\n */\nexport interface ShadowStrategy {\n /**\n * Build a `VaultFrame` bound to the given vault. The factory type\n * is kept loose (`unknown`) to avoid a core → shadow type\n * dependency — the consumer always calls this through\n * `vault.frame()`, which returns `VaultFrame` at its surface.\n */\n buildFrame(vault: unknown): VaultFrame\n}\n\nconst NOT_ENABLED = new Error(\n 'VaultFrame requires the shadow strategy. Import `{ withShadow }` ' +\n 'from \"@noy-db/hub/shadow\" and pass it to ' +\n '`createNoydb({ shadowStrategy: withShadow() })`.',\n)\n\n/**\n * No-shadow stub.\n *\n * @internal\n */\nexport const NO_SHADOW: ShadowStrategy = {\n buildFrame() { throw NOT_ENABLED },\n}\n"],"mappings":";AAyBA,IAAM,cAAc,IAAI;AAAA,EACtB;AAGF;AAOO,IAAM,YAA4B;AAAA,EACvC,aAAa;AAAE,UAAM;AAAA,EAAY;AACnC;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ValidationError
3
- } from "./chunk-IGM563N5.js";
3
+ } from "./chunk-6SYOHUHM.js";
4
4
 
5
5
  // src/with-audit/periods/window.ts
6
6
  var PERIODS_COLLECTION = "_periods";
@@ -21,4 +21,4 @@ export {
21
21
  PERIOD_TARGET_PURGES_COLLECTION,
22
22
  periodExclusiveUpperBound
23
23
  };
24
- //# sourceMappingURL=chunk-F4COUZLL.js.map
24
+ //# sourceMappingURL=chunk-TMR64XPL.js.map
@@ -2,7 +2,7 @@ import {
2
2
  IllegalTransitionError,
3
3
  RecordLockedError,
4
4
  ValidationError
5
- } from "./chunk-IGM563N5.js";
5
+ } from "./chunk-6SYOHUHM.js";
6
6
 
7
7
  // src/with-audit/guards/with-guard.ts
8
8
  function withGuard(strategy) {
@@ -120,4 +120,4 @@ export {
120
120
  immutableGuard,
121
121
  transitionGuard
122
122
  };
123
- //# sourceMappingURL=chunk-5OZCCLNC.js.map
123
+ //# sourceMappingURL=chunk-TSNRZSRC.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  LookupHandle
3
- } from "./chunk-BZEPJJOK.js";
3
+ } from "./chunk-C2V7AJO2.js";
4
4
 
5
5
  // src/via/lookup/active.ts
6
6
  function withLookup() {
@@ -33,4 +33,4 @@ function withLookup() {
33
33
  export {
34
34
  withLookup
35
35
  };
36
- //# sourceMappingURL=chunk-2RMDVWGB.js.map
36
+ //# sourceMappingURL=chunk-UNREYBZO.js.map