@noy-db/hub 0.8.0 → 0.9.0-pre.0

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 (533) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +8 -8
  3. package/codemods/0.4.0-pre.json +1 -1
  4. package/codemods/0.8.0-pre.json +1 -1
  5. package/dist/api-MSJXVYQG.js +18 -0
  6. package/dist/as/index.js +33 -23
  7. package/dist/as/index.js.map +1 -1
  8. package/dist/at/index.js +8 -8
  9. package/dist/attestation/index.js +18 -18
  10. package/dist/{backup-YE2VQ26S.js → backup-7RKNZMQO.js} +11 -11
  11. package/dist/blobs/index.js +12 -12
  12. package/dist/broker/index.js +19 -11
  13. package/dist/broker/index.js.map +1 -1
  14. package/dist/by/index.js +2 -2
  15. package/dist/capsule/contract.d.ts +1 -1
  16. package/dist/capsule/contract.js +6 -6
  17. package/dist/capsule/enclave-aes/broker/proof.d.ts +12 -3
  18. package/dist/capsule/enclave-aes/index.d.ts +1 -1
  19. package/dist/capsule/enclave-aes/index.js +40 -14
  20. package/dist/capsule/enclave-aes/index.js.map +1 -1
  21. package/dist/capsule/index.d.ts +1 -1
  22. package/dist/capsule/plumbing/record-codec.d.ts +7 -0
  23. package/dist/{capsule-VOLX3QRQ.js → capsule-57BDK7LG.js} +8 -8
  24. package/dist/cargo/index.js +32 -32
  25. package/dist/{chunk-A4XMIZT3.js → chunk-226V6XXJ.js} +41 -6
  26. package/dist/chunk-226V6XXJ.js.map +1 -0
  27. package/dist/{chunk-LNSVGRHO.js → chunk-2A56DSRI.js} +2 -2
  28. package/dist/chunk-2DX4JCRI.js +1 -0
  29. package/dist/{chunk-SV2PM2OY.js → chunk-2ELOCEXE.js} +1 -1
  30. package/dist/chunk-2ELOCEXE.js.map +1 -0
  31. package/dist/{chunk-6QVKPHBF.js → chunk-2WJKJZSO.js} +2 -2
  32. package/dist/{chunk-TKVUE4JF.js → chunk-2ZFD2UJC.js} +9 -9
  33. package/dist/{chunk-2AFX33YA.js → chunk-3V6LZHUO.js} +3 -3
  34. package/dist/chunk-3V6LZHUO.js.map +1 -0
  35. package/dist/{chunk-4JPMZTJY.js → chunk-3Y5JLSXS.js} +2 -2
  36. package/dist/{chunk-XSPFDUDG.js → chunk-45VHWE4C.js} +51 -16
  37. package/dist/chunk-45VHWE4C.js.map +1 -0
  38. package/dist/{chunk-LGNDFRYC.js → chunk-4CFHL5RY.js} +1 -1
  39. package/dist/chunk-4CFHL5RY.js.map +1 -0
  40. package/dist/{chunk-EZGV6F47.js → chunk-4J3MNVVX.js} +1 -1
  41. package/dist/{chunk-EZGV6F47.js.map → chunk-4J3MNVVX.js.map} +1 -1
  42. package/dist/{chunk-O2IMQSNA.js → chunk-4UIP3QNW.js} +2 -2
  43. package/dist/{chunk-EJLV62NI.js → chunk-55P6OBB7.js} +2 -2
  44. package/dist/{chunk-Y3LPTBG7.js → chunk-5HNW4ZTA.js} +6 -9
  45. package/dist/chunk-5HNW4ZTA.js.map +1 -0
  46. package/dist/{chunk-TEHHROZL.js → chunk-5LMCVBMY.js} +5 -5
  47. package/dist/{chunk-4V3Q35WG.js → chunk-5UUJE4FP.js} +3 -3
  48. package/dist/{chunk-JWWYRR4Q.js → chunk-5XONHAFD.js} +2 -2
  49. package/dist/{chunk-PD64727P.js → chunk-6QLCS7ET.js} +2 -2
  50. package/dist/chunk-6QLCS7ET.js.map +1 -0
  51. package/dist/{chunk-QBLT6POL.js → chunk-6WS35E6X.js} +2 -2
  52. package/dist/{chunk-IUBMZPHM.js → chunk-6Y5E4SJU.js} +5 -6
  53. package/dist/chunk-6Y5E4SJU.js.map +1 -0
  54. package/dist/{chunk-GZT3NQRA.js → chunk-72XBVN4J.js} +8 -2
  55. package/dist/{chunk-GZT3NQRA.js.map → chunk-72XBVN4J.js.map} +1 -1
  56. package/dist/{chunk-EYG2CY2X.js → chunk-7BMOS4JQ.js} +11 -11
  57. package/dist/chunk-7BMOS4JQ.js.map +1 -0
  58. package/dist/{chunk-UA372JHH.js → chunk-7CT6SX4M.js} +3 -3
  59. package/dist/chunk-7CT6SX4M.js.map +1 -0
  60. package/dist/{chunk-EZOAKKTB.js → chunk-ABU6A4Z5.js} +2 -2
  61. package/dist/{chunk-VKI2EB3N.js → chunk-AJFPAHMW.js} +3 -3
  62. package/dist/{chunk-DQESF6RP.js → chunk-APFFJN5T.js} +29 -16
  63. package/dist/chunk-APFFJN5T.js.map +1 -0
  64. package/dist/{chunk-2ODVB6LZ.js → chunk-B65CC6Z6.js} +2 -2
  65. package/dist/{chunk-MBMTND6D.js → chunk-BJH77UY2.js} +2 -2
  66. package/dist/{chunk-VAORSCSU.js → chunk-BMHQHH7Q.js} +2 -2
  67. package/dist/chunk-BMHQHH7Q.js.map +1 -0
  68. package/dist/{chunk-FFJFE4T7.js → chunk-BNFNQNEP.js} +2 -2
  69. package/dist/chunk-BU2ABHFW.js +74 -0
  70. package/dist/chunk-BU2ABHFW.js.map +1 -0
  71. package/dist/{chunk-5WWDGFOS.js → chunk-BUE7R3B5.js} +2 -2
  72. package/dist/{chunk-5FE75J4S.js → chunk-BVF3SXD7.js} +5 -5
  73. package/dist/{chunk-VFHCKG5M.js → chunk-BYHCKX73.js} +3 -3
  74. package/dist/{chunk-BVCUTXE3.js → chunk-C53ER7AG.js} +2 -2
  75. package/dist/{chunk-MILI22XQ.js → chunk-CAD7N6HQ.js} +3 -3
  76. package/dist/{chunk-5KC7QYEC.js → chunk-CB4467G3.js} +5 -5
  77. package/dist/{chunk-JIBUPZHA.js → chunk-D4V5JJAK.js} +4 -4
  78. package/dist/{chunk-DLD5LGDS.js → chunk-D5A3GCZ4.js} +3 -3
  79. package/dist/{chunk-FOEDQATO.js → chunk-DHU2AQ6T.js} +2 -2
  80. package/dist/{chunk-VHBKYN2J.js → chunk-DL6BZKP3.js} +2 -2
  81. package/dist/{chunk-NBQ3KK6X.js → chunk-EA4VDI5D.js} +4 -4
  82. package/dist/chunk-EA4VDI5D.js.map +1 -0
  83. package/dist/{chunk-E2N2T5ZO.js → chunk-ECGXA4LT.js} +2 -2
  84. package/dist/{chunk-PP3K67AJ.js → chunk-EMAWOGVH.js} +3 -3
  85. package/dist/{chunk-WXE4W2U6.js → chunk-EUD3HQM4.js} +4 -4
  86. package/dist/{chunk-MXOQ5JCG.js → chunk-FSQNGPHH.js} +171 -124
  87. package/dist/chunk-FSQNGPHH.js.map +1 -0
  88. package/dist/{chunk-LIOVX5TJ.js → chunk-FZXRLNJO.js} +3 -3
  89. package/dist/{chunk-WPOYWFSE.js → chunk-G46JSSVX.js} +7 -7
  90. package/dist/{chunk-JSMTXZR3.js → chunk-G5EDYVSE.js} +8 -6
  91. package/dist/chunk-G5EDYVSE.js.map +1 -0
  92. package/dist/chunk-G66YXUTY.js +60 -0
  93. package/dist/chunk-G66YXUTY.js.map +1 -0
  94. package/dist/{chunk-FFWI7UH7.js → chunk-GAGT3YZN.js} +1 -1
  95. package/dist/chunk-GAGT3YZN.js.map +1 -0
  96. package/dist/{chunk-AEQGFRU4.js → chunk-GCUMOKTN.js} +3 -3
  97. package/dist/{chunk-244QBK7Z.js → chunk-GETUTTZU.js} +4 -4
  98. package/dist/{chunk-244QBK7Z.js.map → chunk-GETUTTZU.js.map} +1 -1
  99. package/dist/{chunk-V3RWOOSO.js → chunk-GOJQ5DZA.js} +4 -4
  100. package/dist/{chunk-UEFOQH74.js → chunk-GRS2HIV6.js} +2 -2
  101. package/dist/{chunk-3L2NBKDR.js → chunk-H3YM66EI.js} +2 -2
  102. package/dist/{chunk-3A5DUZ56.js → chunk-IVMFIKNA.js} +6 -6
  103. package/dist/{chunk-3A5DUZ56.js.map → chunk-IVMFIKNA.js.map} +1 -1
  104. package/dist/{chunk-747G6CT3.js → chunk-J4KAPKBJ.js} +2 -2
  105. package/dist/{chunk-H23XHRTT.js → chunk-JA25QG5M.js} +211 -6
  106. package/dist/chunk-JA25QG5M.js.map +1 -0
  107. package/dist/{chunk-T7IR4N2S.js → chunk-JBMMWYOH.js} +3 -1
  108. package/dist/{chunk-T7IR4N2S.js.map → chunk-JBMMWYOH.js.map} +1 -1
  109. package/dist/{chunk-MXKI4ABF.js → chunk-JPSL5GIZ.js} +3 -3
  110. package/dist/{chunk-2GHDLTPE.js → chunk-JSWKVZCR.js} +2 -2
  111. package/dist/{chunk-BNWA3WG5.js → chunk-JZ4EDEIP.js} +3 -3
  112. package/dist/{chunk-GUZET4SG.js → chunk-K673OO6B.js} +4 -4
  113. package/dist/chunk-K673OO6B.js.map +1 -0
  114. package/dist/{chunk-5UMK7GRI.js → chunk-K7RW7FI4.js} +5 -5
  115. package/dist/{chunk-N7EVQD5S.js → chunk-L2F3CFCH.js} +4 -4
  116. package/dist/{chunk-2PVXF5CS.js → chunk-L5A3KR7R.js} +3 -3
  117. package/dist/{chunk-O46CHQT7.js → chunk-LGGIFKJP.js} +4 -4
  118. package/dist/{chunk-Y2RKVFKR.js → chunk-MQ7YWBQ5.js} +2 -2
  119. package/dist/{chunk-4CIQDWRB.js → chunk-MRJDLXI3.js} +14 -8
  120. package/dist/{chunk-4CIQDWRB.js.map → chunk-MRJDLXI3.js.map} +1 -1
  121. package/dist/{chunk-YRXFFWG4.js → chunk-NIXRB5BP.js} +2 -2
  122. package/dist/{chunk-RHVMZSUU.js → chunk-NV4OESHC.js} +1 -1
  123. package/dist/chunk-NV4OESHC.js.map +1 -0
  124. package/dist/{chunk-V7ADQF5O.js → chunk-NYJBYVBG.js} +4 -4
  125. package/dist/{chunk-23D6M6VM.js → chunk-NZULV7LK.js} +4 -4
  126. package/dist/{chunk-HW7CMKUG.js → chunk-OFD2HD6F.js} +1 -1
  127. package/dist/{chunk-HW7CMKUG.js.map → chunk-OFD2HD6F.js.map} +1 -1
  128. package/dist/{chunk-BPWYQ25R.js → chunk-OJU67C23.js} +4 -4
  129. package/dist/{chunk-BPWYQ25R.js.map → chunk-OJU67C23.js.map} +1 -1
  130. package/dist/{chunk-AUKKUPVB.js → chunk-OK57EATL.js} +2 -2
  131. package/dist/{chunk-42ALPZ2B.js → chunk-OM3SEDI4.js} +4 -4
  132. package/dist/{chunk-42ALPZ2B.js.map → chunk-OM3SEDI4.js.map} +1 -1
  133. package/dist/{chunk-OYW3I5M4.js → chunk-PCYPXLEX.js} +6 -6
  134. package/dist/{chunk-2MG3SW7Q.js → chunk-PFCTSXHU.js} +2 -2
  135. package/dist/{chunk-FVH5QYY2.js → chunk-PGC35KXE.js} +2 -2
  136. package/dist/{chunk-NCO25JZO.js → chunk-PT2YCQVK.js} +4 -4
  137. package/dist/{chunk-SYNY3VB5.js → chunk-PTJY5R3O.js} +2 -2
  138. package/dist/{chunk-QMWY2FDS.js → chunk-PUBI455O.js} +2 -2
  139. package/dist/{chunk-VMV5SBE4.js → chunk-QDHHHI5Q.js} +5 -5
  140. package/dist/{chunk-JQYKPKG6.js → chunk-QGFEBNHO.js} +4 -4
  141. package/dist/{chunk-52MGURXO.js → chunk-QGSNJD3B.js} +2 -2
  142. package/dist/chunk-QJNAHPVT.js +91 -0
  143. package/dist/chunk-QJNAHPVT.js.map +1 -0
  144. package/dist/{chunk-VVOLDVIR.js → chunk-QSHATAXJ.js} +2 -2
  145. package/dist/{chunk-G2MVBDFP.js → chunk-QXJXG7DN.js} +39 -9
  146. package/dist/chunk-QXJXG7DN.js.map +1 -0
  147. package/dist/{chunk-KZXDLBY6.js → chunk-RDOEOPOI.js} +5 -5
  148. package/dist/{chunk-FLPCETP6.js → chunk-RIZTZJX6.js} +2 -2
  149. package/dist/{chunk-H427H63K.js → chunk-RNACRT5H.js} +2 -2
  150. package/dist/chunk-RWFQVNXR.js +24 -0
  151. package/dist/chunk-RWFQVNXR.js.map +1 -0
  152. package/dist/{chunk-JOSPH3E5.js → chunk-SFCD6OU7.js} +2 -2
  153. package/dist/{chunk-IMQKWR46.js → chunk-SNM7LSYG.js} +4 -5
  154. package/dist/chunk-SNM7LSYG.js.map +1 -0
  155. package/dist/{chunk-Q2XRFWOI.js → chunk-SPPOUJLN.js} +2 -2
  156. package/dist/{chunk-EGVJ7TM4.js → chunk-SWXLZ4HX.js} +8 -9
  157. package/dist/chunk-SWXLZ4HX.js.map +1 -0
  158. package/dist/{chunk-H7JBY4P7.js → chunk-TFWFPZRU.js} +13 -13
  159. package/dist/chunk-TFWFPZRU.js.map +1 -0
  160. package/dist/{chunk-VQDZYB2B.js → chunk-TMIJAR2X.js} +3 -3
  161. package/dist/{chunk-VQDZYB2B.js.map → chunk-TMIJAR2X.js.map} +1 -1
  162. package/dist/{chunk-RB4DOPGZ.js → chunk-TZYTMZZY.js} +10 -10
  163. package/dist/{chunk-Q4UHJ5SN.js → chunk-UAKY6E4N.js} +2 -2
  164. package/dist/chunk-UHFGK6YA.js +40 -0
  165. package/dist/chunk-UHFGK6YA.js.map +1 -0
  166. package/dist/{chunk-DIZLQVAA.js → chunk-UNSQZSZP.js} +2 -2
  167. package/dist/{chunk-4T3SE27M.js → chunk-UOZOWN73.js} +2 -2
  168. package/dist/{chunk-OKSTSITU.js → chunk-V55JASXO.js} +3 -3
  169. package/dist/{chunk-37EPTBBR.js → chunk-VSUQI5Q6.js} +32 -4
  170. package/dist/chunk-VSUQI5Q6.js.map +1 -0
  171. package/dist/{chunk-XQRFSKYM.js → chunk-WFWFXDNS.js} +2 -2
  172. package/dist/{chunk-N7UDP5VU.js → chunk-WHOKGHJ3.js} +7 -7
  173. package/dist/{chunk-7R2Q7CPL.js → chunk-X2RP4TO5.js} +7 -7
  174. package/dist/{chunk-U2FZNEWJ.js → chunk-XA34THLF.js} +8 -6
  175. package/dist/{chunk-U2FZNEWJ.js.map → chunk-XA34THLF.js.map} +1 -1
  176. package/dist/{chunk-UIYESRD6.js → chunk-XITHENBI.js} +9 -9
  177. package/dist/{chunk-UIYESRD6.js.map → chunk-XITHENBI.js.map} +1 -1
  178. package/dist/{chunk-3XJQBBZD.js → chunk-XKBTJGFP.js} +2 -2
  179. package/dist/{chunk-SMV2HRDU.js → chunk-XXNWU5QZ.js} +2 -2
  180. package/dist/{chunk-TZZBXPZK.js → chunk-XXQ5XIYY.js} +2 -2
  181. package/dist/{chunk-3EWS67C7.js → chunk-YFFMPZPY.js} +2 -2
  182. package/dist/{chunk-M5B2W6YY.js → chunk-YKGJ44Z7.js} +3 -3
  183. package/dist/{chunk-5A4345TG.js → chunk-YQFBH5ZJ.js} +3 -3
  184. package/dist/{chunk-DHHGL42E.js → chunk-Z3ZXVB2Y.js} +22 -6
  185. package/dist/chunk-Z3ZXVB2Y.js.map +1 -0
  186. package/dist/{chunk-OIEO4WDL.js → chunk-ZBUAX4EF.js} +2 -2
  187. package/dist/chunk-ZBUAX4EF.js.map +1 -0
  188. package/dist/{chunk-HS554XAF.js → chunk-ZHQJAV6D.js} +2 -2
  189. package/dist/{chunk-IUT3GWP3.js → chunk-ZMVSKYTJ.js} +17 -93
  190. package/dist/chunk-ZMVSKYTJ.js.map +1 -0
  191. package/dist/{chunk-AL6ML4LA.js → chunk-ZVSKSUGI.js} +5 -5
  192. package/dist/{chunk-JDEYF3PJ.js → chunk-ZWF3EWZA.js} +2 -2
  193. package/dist/chunk-ZWF3EWZA.js.map +1 -0
  194. package/dist/classified/index.js +5 -5
  195. package/dist/{classified-marker-SIYKUU5L.js → classified-marker-KHDOYIJB.js} +3 -3
  196. package/dist/collection-facade-LZIF7GWD.js +41 -0
  197. package/dist/{computed-FAD7SED4.js → computed-XMFTHAXV.js} +3 -3
  198. package/dist/consent/index.js +8 -8
  199. package/dist/cover/index.js +8 -8
  200. package/dist/coverage/index.js +1 -1
  201. package/dist/custody/index.js +12 -11
  202. package/dist/{dead-filter-4F3LWYKH.js → dead-filter-CXV5NS67.js} +10 -10
  203. package/dist/debug/index.js +7 -7
  204. package/dist/{delegation-NANZDG4N.js → delegation-ONLM4JFI.js} +49 -25
  205. package/dist/delegation-ONLM4JFI.js.map +1 -0
  206. package/dist/derivations/index.js +24 -23
  207. package/dist/derive-3YSIS36W.js +20 -0
  208. package/dist/directory/index.js +9 -9
  209. package/dist/{dispatch-JDZNGEB3.js → dispatch-2MQFMEGY.js} +20 -20
  210. package/dist/{dispatch-H4HV32AM.js → dispatch-OFDA4WQV.js} +5 -5
  211. package/dist/executor-E6YDJ7YA.js +8 -0
  212. package/dist/executor-NJX3YQQ4.js +35 -0
  213. package/dist/executor-WWM3DD4P.js +8 -0
  214. package/dist/export-accessible-RLHU5G4W.js +22 -0
  215. package/dist/extract-partition-QII2EDCS.js +35 -0
  216. package/dist/{fanout-sidecar-L7NHPIOC.js → fanout-sidecar-BO67PCPO.js} +8 -8
  217. package/dist/find-6M7GYDUZ.js +10 -0
  218. package/dist/forget/index.js +25 -8
  219. package/dist/forget/index.js.map +1 -1
  220. package/dist/guards/index.js +4 -4
  221. package/dist/history/index.js +12 -12
  222. package/dist/i18n/index.js +13 -13
  223. package/dist/index.d.ts +8 -6
  224. package/dist/index.js +122 -110
  225. package/dist/index.js.map +1 -1
  226. package/dist/indexing/index.js +6 -6
  227. package/dist/introspection/index.js +15 -11
  228. package/dist/issue-LPEEEMPP.js +19 -0
  229. package/dist/kernel/cache/index.d.ts +1 -1
  230. package/dist/kernel/collection.d.ts +1 -0
  231. package/dist/kernel/errors.d.ts +33 -4
  232. package/dist/kernel/export-scope.d.ts +40 -0
  233. package/dist/kernel/noydb.d.ts +3 -1
  234. package/dist/kernel/put-many-atomic.d.ts +1 -1
  235. package/dist/kernel/query/live/live.d.ts +2 -1
  236. package/dist/kernel/query/sort-key.d.ts +0 -2
  237. package/dist/kernel/tx-write-gate.d.ts +2 -4
  238. package/dist/kernel/types.d.ts +93 -6
  239. package/dist/kernel/validation.d.ts +0 -10
  240. package/dist/kernel/vault.d.ts +4 -0
  241. package/dist/kernel/via/reconcile.d.ts +1 -42
  242. package/dist/{ledger-5ZMGE44K.js → ledger-MSJGWKGW.js} +10 -10
  243. package/dist/liberate-LEKDYKTC.js +25 -0
  244. package/dist/{link-set-MFXC24VK.js → link-set-QXXSPPHL.js} +10 -10
  245. package/dist/{managed-secret-MFTFT22X.js → managed-secret-VSK7ANQI.js} +9 -9
  246. package/dist/materialized-views/index.js +26 -26
  247. package/dist/{migrate-cek-DZRFFOHW.js → migrate-cek-GEBFYBDC.js} +2 -2
  248. package/dist/money/index.js +5 -5
  249. package/dist/noydb-F2AUF6KL.js +98 -0
  250. package/dist/on/index.js +25 -0
  251. package/dist/overlay-views/index.js +4 -4
  252. package/dist/periods/index.js +11 -11
  253. package/dist/pod/index.js +69 -67
  254. package/dist/{pod-handle-A3LET7NO.js → pod-handle-YE7CT66T.js} +8 -8
  255. package/dist/policy/index.js +9 -9
  256. package/dist/port/as/active.d.ts +4 -0
  257. package/dist/port/as/index.d.ts +1 -0
  258. package/dist/port/by/index.d.ts +14 -5
  259. package/dist/port/on/index.d.ts +26 -0
  260. package/dist/port/to/index.d.ts +1 -1
  261. package/dist/port/with/broker-strategy.d.ts +14 -0
  262. package/dist/port/with/coverage-strategy.d.ts +17 -1
  263. package/dist/port/with/formats-strategy.d.ts +34 -1
  264. package/dist/port/with/lookup-strategy.d.ts +85 -4
  265. package/dist/port/with/service-bus.d.ts +2 -1
  266. package/dist/portability/index.js +8 -8
  267. package/dist/{post-register-7ND27CF2.js → post-register-QC5TEAW3.js} +6 -6
  268. package/dist/query/all/index.js +16 -16
  269. package/dist/query/index.js +8 -8
  270. package/dist/query/live/index.js +7 -7
  271. package/dist/query/reduce/index.js +10 -10
  272. package/dist/query/relate/index.js +10 -10
  273. package/dist/reduce/index.js +8 -8
  274. package/dist/register-SN72QALV.js +30 -0
  275. package/dist/registry-253FF7C6.js +35 -0
  276. package/dist/registry-3AZWQTDT.js +23 -0
  277. package/dist/registry-7UEBTHWG.js +8 -0
  278. package/dist/registry-IVJ67NFQ.js +8 -0
  279. package/dist/request-withdrawal-UKVJZKX2.js +28 -0
  280. package/dist/{reveal-B2TLP4JQ.js → reveal-YQTRNQFH.js} +7 -7
  281. package/dist/revoke-G2KXJQA5.js +24 -0
  282. package/dist/satellites/index.js +1 -1
  283. package/dist/schema-update/index.js +2 -2
  284. package/dist/sealed-record/index.js +11 -11
  285. package/dist/search/index.js +4 -4
  286. package/dist/{seed-XNSE4U3S.js → seed-JMQTRKRE.js} +121 -27
  287. package/dist/seed-JMQTRKRE.js.map +1 -0
  288. package/dist/sequence/index.js +8 -8
  289. package/dist/session/index.js +8 -8
  290. package/dist/shadow/index.js +2 -2
  291. package/dist/signer-IUIYR3CX.js +23 -0
  292. package/dist/snapshots/index.js +9 -9
  293. package/dist/{stale-6GCFMOOR.js → stale-SKV33PBU.js} +9 -9
  294. package/dist/storage-NPBYP2SM.js +21 -0
  295. package/dist/{store-coordination-provider-C4BPT5XF.js → store-coordination-provider-Z6HKPOGM.js} +9 -9
  296. package/dist/sync/index.js +17 -11
  297. package/dist/sync/index.js.map +1 -1
  298. package/dist/team/index.js +17 -15
  299. package/dist/tiers/index.js +10 -10
  300. package/dist/to/index.js +2 -2
  301. package/dist/transactions/index.js +3 -3
  302. package/dist/util/index.js +1 -1
  303. package/dist/vault-head/index.js +8 -8
  304. package/dist/{verify-UKALW7C2.js → verify-KWQIWLGH.js} +7 -7
  305. package/dist/via/classified/presets.d.ts +29 -0
  306. package/dist/via/classified/resolve.d.ts +7 -0
  307. package/dist/via/geo/binding.d.ts +0 -4
  308. package/dist/via/lookup/index.d.ts +32 -0
  309. package/dist/via/money/binding.d.ts +0 -9
  310. package/dist/walk-F4OLXI5H.js +20 -0
  311. package/dist/with-audit/attestation/strategy.d.ts +2 -1
  312. package/dist/with-audit/attestation/vault-facade.d.ts +7 -0
  313. package/dist/with-audit/forget/completeness.d.ts +66 -0
  314. package/dist/with-audit/forget/index.d.ts +2 -0
  315. package/dist/with-audit/forget/strategy.d.ts +65 -0
  316. package/dist/with-audit/periods/periods.d.ts +0 -9
  317. package/dist/with-audit/periods/reserved-collections.d.ts +7 -0
  318. package/dist/with-audit/portability/request-withdrawal.d.ts +0 -1
  319. package/dist/with-audit/portability/withdraw-accessible.d.ts +0 -1
  320. package/dist/with-audit/tiers/index.d.ts +1 -1
  321. package/dist/with-audit/tiers/strategy.d.ts +19 -0
  322. package/dist/with-cargo/extract-partition.d.ts +0 -46
  323. package/dist/with-commit/numbering/index.d.ts +0 -2
  324. package/dist/with-commit/tx/transaction.d.ts +2 -24
  325. package/dist/with-commit/vault-head/strategy.d.ts +7 -0
  326. package/dist/with-fork/snapshots/noydb-facade.d.ts +7 -0
  327. package/dist/with-formula/derivations/trigger-match.d.ts +8 -5
  328. package/dist/with-formula/materialized-views/emit-memo.d.ts +0 -2
  329. package/dist/with-lookup/embeddings/index.d.ts +1 -2
  330. package/dist/with-lookup/indexing/collection-facade.d.ts +1 -15
  331. package/dist/with-lookup/indexing/eager-indexes.d.ts +2 -1
  332. package/dist/with-lookup/search/collection-facade.d.ts +0 -12
  333. package/dist/with-party/broker/index.d.ts +2 -2
  334. package/dist/with-party/broker/seed.d.ts +25 -10
  335. package/dist/with-party/policy/noydb-facade.d.ts +1 -31
  336. package/dist/with-party/team/delegation.d.ts +58 -2
  337. package/dist/with-party/team/echo-secret.d.ts +0 -2
  338. package/dist/with-party/team/keyring.d.ts +1 -21
  339. package/dist/with-party/team/magic-link-grant.d.ts +11 -1
  340. package/dist/with-party/team/noydb-facade.d.ts +5 -0
  341. package/dist/with-party/team/reserved-secret-collections.d.ts +10 -8
  342. package/dist/with-party/team/roster-tag.d.ts +42 -1
  343. package/dist/with-party/team/tiers.d.ts +36 -5
  344. package/dist/with-shape/blobs/blob-set.d.ts +23 -0
  345. package/dist/with-shape/blobs/legacy-sweep.d.ts +16 -0
  346. package/dist/with-shape/introspection/describe.d.ts +1 -2
  347. package/dist/with-shape/introspection/index.d.ts +1 -0
  348. package/dist/with-shape/introspection/types.d.ts +2 -1
  349. package/dist/with-shape/schema-update/fence.d.ts +7 -0
  350. package/dist/with-sync/engine.d.ts +30 -1
  351. package/dist/with-sync/reserved-mirror.d.ts +89 -0
  352. package/dist/with-sync/strategy.d.ts +7 -0
  353. package/dist/with-sync/tab-write-relay.d.ts +0 -10
  354. package/dist/withdraw-accessible-ZKPLZ66E.js +25 -0
  355. package/package.json +3 -3
  356. package/dist/api-OS747DS4.js +0 -18
  357. package/dist/chunk-2AFX33YA.js.map +0 -1
  358. package/dist/chunk-2RH777HH.js +0 -126
  359. package/dist/chunk-2RH777HH.js.map +0 -1
  360. package/dist/chunk-37EPTBBR.js.map +0 -1
  361. package/dist/chunk-7XMHMVTS.js +0 -20
  362. package/dist/chunk-7XMHMVTS.js.map +0 -1
  363. package/dist/chunk-A4XMIZT3.js.map +0 -1
  364. package/dist/chunk-DHHGL42E.js.map +0 -1
  365. package/dist/chunk-DQESF6RP.js.map +0 -1
  366. package/dist/chunk-EGVJ7TM4.js.map +0 -1
  367. package/dist/chunk-EYG2CY2X.js.map +0 -1
  368. package/dist/chunk-FFWI7UH7.js.map +0 -1
  369. package/dist/chunk-G2MVBDFP.js.map +0 -1
  370. package/dist/chunk-GUZET4SG.js.map +0 -1
  371. package/dist/chunk-H23XHRTT.js.map +0 -1
  372. package/dist/chunk-H7JBY4P7.js.map +0 -1
  373. package/dist/chunk-IMQKWR46.js.map +0 -1
  374. package/dist/chunk-IUBMZPHM.js.map +0 -1
  375. package/dist/chunk-IUT3GWP3.js.map +0 -1
  376. package/dist/chunk-JDEYF3PJ.js.map +0 -1
  377. package/dist/chunk-JSMTXZR3.js.map +0 -1
  378. package/dist/chunk-LGNDFRYC.js.map +0 -1
  379. package/dist/chunk-MXOQ5JCG.js.map +0 -1
  380. package/dist/chunk-NBQ3KK6X.js.map +0 -1
  381. package/dist/chunk-OIEO4WDL.js.map +0 -1
  382. package/dist/chunk-PD64727P.js.map +0 -1
  383. package/dist/chunk-RHVMZSUU.js.map +0 -1
  384. package/dist/chunk-SV2PM2OY.js.map +0 -1
  385. package/dist/chunk-UA372JHH.js.map +0 -1
  386. package/dist/chunk-UBSFPGVJ.js +0 -1
  387. package/dist/chunk-VAORSCSU.js.map +0 -1
  388. package/dist/chunk-XSPFDUDG.js.map +0 -1
  389. package/dist/chunk-Y3LPTBG7.js.map +0 -1
  390. package/dist/collection-facade-CS7CA2XO.js +0 -47
  391. package/dist/delegation-NANZDG4N.js.map +0 -1
  392. package/dist/derive-XLOJVXPU.js +0 -20
  393. package/dist/executor-FMPVN6DT.js +0 -35
  394. package/dist/executor-LBBBRTN5.js +0 -8
  395. package/dist/executor-OSRZST2U.js +0 -8
  396. package/dist/export-accessible-RAOJAAU5.js +0 -22
  397. package/dist/extract-partition-JD5CUSTG.js +0 -37
  398. package/dist/find-JRN4RNQ5.js +0 -10
  399. package/dist/issue-YIVBZUTH.js +0 -19
  400. package/dist/liberate-WZSZM2W6.js +0 -24
  401. package/dist/noydb-ITIGNKUF.js +0 -96
  402. package/dist/register-DT5HZ2LZ.js +0 -30
  403. package/dist/registry-BHRZGZHF.js +0 -8
  404. package/dist/registry-ET6ZFFWA.js +0 -34
  405. package/dist/registry-HXFGLGTG.js +0 -8
  406. package/dist/registry-THCPDEOD.js +0 -23
  407. package/dist/request-withdrawal-AV2MJJKY.js +0 -30
  408. package/dist/revoke-6DWIEOCV.js +0 -24
  409. package/dist/seed-XNSE4U3S.js.map +0 -1
  410. package/dist/signer-MHGW3OIL.js +0 -23
  411. package/dist/storage-BYN5LO6Z.js +0 -21
  412. package/dist/walk-4VPK7AS4.js +0 -20
  413. package/dist/withdraw-accessible-HL7GACUE.js +0 -27
  414. /package/dist/{api-OS747DS4.js.map → api-MSJXVYQG.js.map} +0 -0
  415. /package/dist/{backup-YE2VQ26S.js.map → backup-7RKNZMQO.js.map} +0 -0
  416. /package/dist/{capsule-VOLX3QRQ.js.map → capsule-57BDK7LG.js.map} +0 -0
  417. /package/dist/{chunk-LNSVGRHO.js.map → chunk-2A56DSRI.js.map} +0 -0
  418. /package/dist/{chunk-UBSFPGVJ.js.map → chunk-2DX4JCRI.js.map} +0 -0
  419. /package/dist/{chunk-6QVKPHBF.js.map → chunk-2WJKJZSO.js.map} +0 -0
  420. /package/dist/{chunk-TKVUE4JF.js.map → chunk-2ZFD2UJC.js.map} +0 -0
  421. /package/dist/{chunk-4JPMZTJY.js.map → chunk-3Y5JLSXS.js.map} +0 -0
  422. /package/dist/{chunk-O2IMQSNA.js.map → chunk-4UIP3QNW.js.map} +0 -0
  423. /package/dist/{chunk-EJLV62NI.js.map → chunk-55P6OBB7.js.map} +0 -0
  424. /package/dist/{chunk-TEHHROZL.js.map → chunk-5LMCVBMY.js.map} +0 -0
  425. /package/dist/{chunk-4V3Q35WG.js.map → chunk-5UUJE4FP.js.map} +0 -0
  426. /package/dist/{chunk-JWWYRR4Q.js.map → chunk-5XONHAFD.js.map} +0 -0
  427. /package/dist/{chunk-QBLT6POL.js.map → chunk-6WS35E6X.js.map} +0 -0
  428. /package/dist/{chunk-EZOAKKTB.js.map → chunk-ABU6A4Z5.js.map} +0 -0
  429. /package/dist/{chunk-VKI2EB3N.js.map → chunk-AJFPAHMW.js.map} +0 -0
  430. /package/dist/{chunk-2ODVB6LZ.js.map → chunk-B65CC6Z6.js.map} +0 -0
  431. /package/dist/{chunk-MBMTND6D.js.map → chunk-BJH77UY2.js.map} +0 -0
  432. /package/dist/{chunk-FFJFE4T7.js.map → chunk-BNFNQNEP.js.map} +0 -0
  433. /package/dist/{chunk-5WWDGFOS.js.map → chunk-BUE7R3B5.js.map} +0 -0
  434. /package/dist/{chunk-5FE75J4S.js.map → chunk-BVF3SXD7.js.map} +0 -0
  435. /package/dist/{chunk-VFHCKG5M.js.map → chunk-BYHCKX73.js.map} +0 -0
  436. /package/dist/{chunk-BVCUTXE3.js.map → chunk-C53ER7AG.js.map} +0 -0
  437. /package/dist/{chunk-MILI22XQ.js.map → chunk-CAD7N6HQ.js.map} +0 -0
  438. /package/dist/{chunk-5KC7QYEC.js.map → chunk-CB4467G3.js.map} +0 -0
  439. /package/dist/{chunk-JIBUPZHA.js.map → chunk-D4V5JJAK.js.map} +0 -0
  440. /package/dist/{chunk-DLD5LGDS.js.map → chunk-D5A3GCZ4.js.map} +0 -0
  441. /package/dist/{chunk-FOEDQATO.js.map → chunk-DHU2AQ6T.js.map} +0 -0
  442. /package/dist/{chunk-VHBKYN2J.js.map → chunk-DL6BZKP3.js.map} +0 -0
  443. /package/dist/{chunk-E2N2T5ZO.js.map → chunk-ECGXA4LT.js.map} +0 -0
  444. /package/dist/{chunk-PP3K67AJ.js.map → chunk-EMAWOGVH.js.map} +0 -0
  445. /package/dist/{chunk-WXE4W2U6.js.map → chunk-EUD3HQM4.js.map} +0 -0
  446. /package/dist/{chunk-LIOVX5TJ.js.map → chunk-FZXRLNJO.js.map} +0 -0
  447. /package/dist/{chunk-WPOYWFSE.js.map → chunk-G46JSSVX.js.map} +0 -0
  448. /package/dist/{chunk-AEQGFRU4.js.map → chunk-GCUMOKTN.js.map} +0 -0
  449. /package/dist/{chunk-V3RWOOSO.js.map → chunk-GOJQ5DZA.js.map} +0 -0
  450. /package/dist/{chunk-UEFOQH74.js.map → chunk-GRS2HIV6.js.map} +0 -0
  451. /package/dist/{chunk-3L2NBKDR.js.map → chunk-H3YM66EI.js.map} +0 -0
  452. /package/dist/{chunk-747G6CT3.js.map → chunk-J4KAPKBJ.js.map} +0 -0
  453. /package/dist/{chunk-MXKI4ABF.js.map → chunk-JPSL5GIZ.js.map} +0 -0
  454. /package/dist/{chunk-2GHDLTPE.js.map → chunk-JSWKVZCR.js.map} +0 -0
  455. /package/dist/{chunk-BNWA3WG5.js.map → chunk-JZ4EDEIP.js.map} +0 -0
  456. /package/dist/{chunk-5UMK7GRI.js.map → chunk-K7RW7FI4.js.map} +0 -0
  457. /package/dist/{chunk-N7EVQD5S.js.map → chunk-L2F3CFCH.js.map} +0 -0
  458. /package/dist/{chunk-2PVXF5CS.js.map → chunk-L5A3KR7R.js.map} +0 -0
  459. /package/dist/{chunk-O46CHQT7.js.map → chunk-LGGIFKJP.js.map} +0 -0
  460. /package/dist/{chunk-Y2RKVFKR.js.map → chunk-MQ7YWBQ5.js.map} +0 -0
  461. /package/dist/{chunk-YRXFFWG4.js.map → chunk-NIXRB5BP.js.map} +0 -0
  462. /package/dist/{chunk-V7ADQF5O.js.map → chunk-NYJBYVBG.js.map} +0 -0
  463. /package/dist/{chunk-23D6M6VM.js.map → chunk-NZULV7LK.js.map} +0 -0
  464. /package/dist/{chunk-AUKKUPVB.js.map → chunk-OK57EATL.js.map} +0 -0
  465. /package/dist/{chunk-OYW3I5M4.js.map → chunk-PCYPXLEX.js.map} +0 -0
  466. /package/dist/{chunk-2MG3SW7Q.js.map → chunk-PFCTSXHU.js.map} +0 -0
  467. /package/dist/{chunk-FVH5QYY2.js.map → chunk-PGC35KXE.js.map} +0 -0
  468. /package/dist/{chunk-NCO25JZO.js.map → chunk-PT2YCQVK.js.map} +0 -0
  469. /package/dist/{chunk-SYNY3VB5.js.map → chunk-PTJY5R3O.js.map} +0 -0
  470. /package/dist/{chunk-QMWY2FDS.js.map → chunk-PUBI455O.js.map} +0 -0
  471. /package/dist/{chunk-VMV5SBE4.js.map → chunk-QDHHHI5Q.js.map} +0 -0
  472. /package/dist/{chunk-JQYKPKG6.js.map → chunk-QGFEBNHO.js.map} +0 -0
  473. /package/dist/{chunk-52MGURXO.js.map → chunk-QGSNJD3B.js.map} +0 -0
  474. /package/dist/{chunk-VVOLDVIR.js.map → chunk-QSHATAXJ.js.map} +0 -0
  475. /package/dist/{chunk-KZXDLBY6.js.map → chunk-RDOEOPOI.js.map} +0 -0
  476. /package/dist/{chunk-FLPCETP6.js.map → chunk-RIZTZJX6.js.map} +0 -0
  477. /package/dist/{chunk-H427H63K.js.map → chunk-RNACRT5H.js.map} +0 -0
  478. /package/dist/{chunk-JOSPH3E5.js.map → chunk-SFCD6OU7.js.map} +0 -0
  479. /package/dist/{chunk-Q2XRFWOI.js.map → chunk-SPPOUJLN.js.map} +0 -0
  480. /package/dist/{chunk-RB4DOPGZ.js.map → chunk-TZYTMZZY.js.map} +0 -0
  481. /package/dist/{chunk-Q4UHJ5SN.js.map → chunk-UAKY6E4N.js.map} +0 -0
  482. /package/dist/{chunk-DIZLQVAA.js.map → chunk-UNSQZSZP.js.map} +0 -0
  483. /package/dist/{chunk-4T3SE27M.js.map → chunk-UOZOWN73.js.map} +0 -0
  484. /package/dist/{chunk-OKSTSITU.js.map → chunk-V55JASXO.js.map} +0 -0
  485. /package/dist/{chunk-XQRFSKYM.js.map → chunk-WFWFXDNS.js.map} +0 -0
  486. /package/dist/{chunk-N7UDP5VU.js.map → chunk-WHOKGHJ3.js.map} +0 -0
  487. /package/dist/{chunk-7R2Q7CPL.js.map → chunk-X2RP4TO5.js.map} +0 -0
  488. /package/dist/{chunk-3XJQBBZD.js.map → chunk-XKBTJGFP.js.map} +0 -0
  489. /package/dist/{chunk-SMV2HRDU.js.map → chunk-XXNWU5QZ.js.map} +0 -0
  490. /package/dist/{chunk-TZZBXPZK.js.map → chunk-XXQ5XIYY.js.map} +0 -0
  491. /package/dist/{chunk-3EWS67C7.js.map → chunk-YFFMPZPY.js.map} +0 -0
  492. /package/dist/{chunk-M5B2W6YY.js.map → chunk-YKGJ44Z7.js.map} +0 -0
  493. /package/dist/{chunk-5A4345TG.js.map → chunk-YQFBH5ZJ.js.map} +0 -0
  494. /package/dist/{chunk-HS554XAF.js.map → chunk-ZHQJAV6D.js.map} +0 -0
  495. /package/dist/{chunk-AL6ML4LA.js.map → chunk-ZVSKSUGI.js.map} +0 -0
  496. /package/dist/{classified-marker-SIYKUU5L.js.map → classified-marker-KHDOYIJB.js.map} +0 -0
  497. /package/dist/{collection-facade-CS7CA2XO.js.map → collection-facade-LZIF7GWD.js.map} +0 -0
  498. /package/dist/{computed-FAD7SED4.js.map → computed-XMFTHAXV.js.map} +0 -0
  499. /package/dist/{dead-filter-4F3LWYKH.js.map → dead-filter-CXV5NS67.js.map} +0 -0
  500. /package/dist/{derive-XLOJVXPU.js.map → derive-3YSIS36W.js.map} +0 -0
  501. /package/dist/{dispatch-JDZNGEB3.js.map → dispatch-2MQFMEGY.js.map} +0 -0
  502. /package/dist/{dispatch-H4HV32AM.js.map → dispatch-OFDA4WQV.js.map} +0 -0
  503. /package/dist/{executor-FMPVN6DT.js.map → executor-E6YDJ7YA.js.map} +0 -0
  504. /package/dist/{executor-LBBBRTN5.js.map → executor-NJX3YQQ4.js.map} +0 -0
  505. /package/dist/{executor-OSRZST2U.js.map → executor-WWM3DD4P.js.map} +0 -0
  506. /package/dist/{export-accessible-RAOJAAU5.js.map → export-accessible-RLHU5G4W.js.map} +0 -0
  507. /package/dist/{extract-partition-JD5CUSTG.js.map → extract-partition-QII2EDCS.js.map} +0 -0
  508. /package/dist/{fanout-sidecar-L7NHPIOC.js.map → fanout-sidecar-BO67PCPO.js.map} +0 -0
  509. /package/dist/{find-JRN4RNQ5.js.map → find-6M7GYDUZ.js.map} +0 -0
  510. /package/dist/{issue-YIVBZUTH.js.map → issue-LPEEEMPP.js.map} +0 -0
  511. /package/dist/{ledger-5ZMGE44K.js.map → ledger-MSJGWKGW.js.map} +0 -0
  512. /package/dist/{liberate-WZSZM2W6.js.map → liberate-LEKDYKTC.js.map} +0 -0
  513. /package/dist/{link-set-MFXC24VK.js.map → link-set-QXXSPPHL.js.map} +0 -0
  514. /package/dist/{managed-secret-MFTFT22X.js.map → managed-secret-VSK7ANQI.js.map} +0 -0
  515. /package/dist/{migrate-cek-DZRFFOHW.js.map → migrate-cek-GEBFYBDC.js.map} +0 -0
  516. /package/dist/{noydb-ITIGNKUF.js.map → noydb-F2AUF6KL.js.map} +0 -0
  517. /package/dist/{pod-handle-A3LET7NO.js.map → pod-handle-YE7CT66T.js.map} +0 -0
  518. /package/dist/{post-register-7ND27CF2.js.map → post-register-QC5TEAW3.js.map} +0 -0
  519. /package/dist/{register-DT5HZ2LZ.js.map → register-SN72QALV.js.map} +0 -0
  520. /package/dist/{registry-BHRZGZHF.js.map → registry-253FF7C6.js.map} +0 -0
  521. /package/dist/{registry-ET6ZFFWA.js.map → registry-3AZWQTDT.js.map} +0 -0
  522. /package/dist/{registry-HXFGLGTG.js.map → registry-7UEBTHWG.js.map} +0 -0
  523. /package/dist/{registry-THCPDEOD.js.map → registry-IVJ67NFQ.js.map} +0 -0
  524. /package/dist/{request-withdrawal-AV2MJJKY.js.map → request-withdrawal-UKVJZKX2.js.map} +0 -0
  525. /package/dist/{reveal-B2TLP4JQ.js.map → reveal-YQTRNQFH.js.map} +0 -0
  526. /package/dist/{revoke-6DWIEOCV.js.map → revoke-G2KXJQA5.js.map} +0 -0
  527. /package/dist/{signer-MHGW3OIL.js.map → signer-IUIYR3CX.js.map} +0 -0
  528. /package/dist/{stale-6GCFMOOR.js.map → stale-SKV33PBU.js.map} +0 -0
  529. /package/dist/{storage-BYN5LO6Z.js.map → storage-NPBYP2SM.js.map} +0 -0
  530. /package/dist/{store-coordination-provider-C4BPT5XF.js.map → store-coordination-provider-Z6HKPOGM.js.map} +0 -0
  531. /package/dist/{verify-UKALW7C2.js.map → verify-KWQIWLGH.js.map} +0 -0
  532. /package/dist/{walk-4VPK7AS4.js.map → walk-F4OLXI5H.js.map} +0 -0
  533. /package/dist/{withdraw-accessible-HL7GACUE.js.map → withdraw-accessible-ZKPLZ66E.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-formula/materialized-views/window-stage.ts","../src/with-formula/materialized-views/emit-memo.ts","../src/with-formula/materialized-views/executor.ts"],"sourcesContent":["/**\n * #1411 — the declared window stage of a materialized view.\n *\n * `unionSources` → `map` → `groupBy` → `aggregate` → **`window`** → `derive`.\n *\n * ## Why a window is safe here when `derive` is deliberately single-row\n *\n * `derive`'s contract is *pure, single-row, no cross-row access* — a window is\n * the opposite of all three. The difference is not caution, it is that\n * materialization is a FULL RECOMPUTE: the executor holds every row the view\n * will store, in one array, before it writes any of them. So an\n * order-dependent, cross-row pass runs exactly once over exactly the rows that\n * get stored, and its output is then an ordinary column. A per-row recompute\n * could not do this — inserting a row early in a partition moves every later\n * row's running total.\n *\n * ## Why this does not simply call `applyWindow`\n *\n * ⚠️ `applyWindow` does no Via rewriting. On the ad-hoc builder,\n * `Query.window().select()` rewrites reducer slots through the COLLECTION's\n * Via pipeline first, which is what makes `runningMoneySum` exact. A UNION-mode\n * MV has no collection — its rows are MAPPED — so it has the same answer\n * `aggregate` already uses: the MV's own `moneyFields` descriptors, bound\n * through the kernel's Via port. This mirrors `groupAndReduce`'s money block\n * line for line, deliberately: two places that must agree about what a money\n * reducer is, doing it the same way.\n *\n * Without that rewrite the failure is silent and specific — a running total\n * over decimal strings accumulates in float and returns\n * `0.6000000000000001` where the aggregate on the same rows returns `'0.60'`.\n */\nimport { applyWindow } from '../../with-lookup/reduce/window.js'\nimport type { WindowSelectSpec, WindowSpec } from '../../with-lookup/reduce/window.js'\nimport { bindDistinctReducers } from '../../with-lookup/reduce/reducers.js'\nimport type { Reducer } from '../../with-lookup/reduce/reducers.js'\nimport type { ReduceSpec } from '../../with-lookup/reduce/reduction.js'\nimport { viaBinder } from '../../kernel/via/index.js'\nimport type { MaterializedViewWindow, MoneyDescriptorMap } from './types.js'\n\n/** Is this slot a window function rather than a reducer? */\nfunction isWindowFn(v: unknown): boolean {\n return typeof v === 'object' && v !== null && (v as { __window?: unknown }).__window === true\n}\n\n/**\n * Apply a declared window to the finished row set.\n *\n * `moneyFields` is the MV's own descriptor map; when present, every REDUCER\n * slot is rewritten exactly as `aggregate`'s are. Window functions\n * (`rowNumber`, `rank`, `lag`, `lead`) are passed through untouched — they\n * navigate rows rather than accumulate values, so there is nothing to make\n * exact.\n */\nexport function applyDeclaredWindow(\n rows: readonly Record<string, unknown>[],\n window: MaterializedViewWindow,\n moneyFields?: MoneyDescriptorMap,\n): ReadonlyArray<Record<string, unknown>> {\n if (rows.length === 0) return rows\n\n let select: WindowSelectSpec = window.select\n if (moneyFields) {\n const reducersOnly: Record<string, Reducer<unknown, unknown>> = {}\n for (const [k, v] of Object.entries(select)) {\n if (!isWindowFn(v)) reducersOnly[k] = v as Reducer<unknown, unknown>\n }\n if (Object.keys(reducersOnly).length > 0) {\n const binding = viaBinder('money')({ moneyFields })\n let wrapped = binding.wrapReducers!(reducersOnly as ReduceSpec) as Record<\n string,\n Reducer<unknown, unknown>\n >\n wrapped = bindDistinctReducers(wrapped as ReduceSpec, {\n canonicalizeIndexKey: (f, v) => binding.canonicalizeIndexKey?.(f, v),\n }) as Record<string, Reducer<unknown, unknown>>\n select = { ...select, ...wrapped }\n }\n }\n\n // `applyWindow` takes the partition/order spec and the select list\n // separately, so strip `select` off rather than pass it twice. Built by\n // spreading absent keys away rather than assigning `undefined` — the package\n // compiles under `exactOptionalPropertyTypes`, where the two differ.\n const spec: WindowSpec = {\n ...(window.partitionBy !== undefined && { partitionBy: window.partitionBy }),\n ...(window.orderBy !== undefined && { orderBy: window.orderBy }),\n }\n return applyWindow<Record<string, unknown>>(rows, spec, select)\n}\n","/**\n * Skip re-writing materialized-view output rows whose content has not changed\n * (#1418).\n *\n * `MaterializedViewExecutor.refresh()` recomputes the whole view and then\n * writes EVERY output row, on every source write. Measured on one MV with a\n * single union arm, writing rows the MV's own `map` drops:\n *\n * 250 receipts / 250 bills → 23.0 ms per source write\n * 450 receipts / 450 bills → 41.6 ms per source write\n *\n * 1.8x the sources, 1.8x the cost — because the thing that grew was the OUTPUT\n * ROW COUNT, and each row is an encrypt-and-store round trip. The query and the\n * aggregation are not where the time goes.\n *\n * ## Why this, and not \"skip the refresh when the row maps to nothing\"\n *\n * The issue proposed short-circuiting the refresh when the written row's `map`\n * returns null. That cannot be built as stated, and the reason is worth\n * recording so nobody re-attempts it:\n *\n * 1. `materializeUnionResult` feeds `map` rows from `coll.query().toArray()`,\n * which applies `decodeVia` — money arrives as a canonical decimal string,\n * not the stored scaled integer. Probing `arm.map(writtenRecord)` at\n * dispatch time hands `map` a DIFFERENTLY SHAPED row, so any `map` that\n * filters on a money field can answer `null` where the real pipeline would\n * not. The view then silently stops updating, which is far worse than the\n * latency it was meant to fix.\n * 2. Skipping also requires that the row contributed nothing BEFORE, or an\n * update that removes a row from the view is dropped. The prior record is\n * not passed to the dispatcher, and is a stored record, so it hits (1)\n * twice over.\n * 3. An arm with `join` legs has the right side attached before `map` runs, so\n * a probe would have to resolve the legs too.\n *\n * Comparing the row we are ABOUT to write against the row we LAST wrote sides\n * steps all three. It needs no prior record, it is form-agnostic (query, union\n * and projection all benefit), and it degrades to the right thing: a write that\n * changes one group rewrites one row instead of all of them.\n *\n * ## Why the entries are canonical strings and not short hashes\n *\n * A hash collision here means a row that is never rewritten — a silently stale\n * view with no symptom. At the 20k-row cap below, an 8-byte hash carries a\n * couple of percent chance of one collision somewhere, which is not a trade\n * worth making for memory. So entries hold the full canonical string, and\n * memory is bounded by refusing to memoize a view larger than the cap.\n *\n * ## Why a mutation stamp, and what it does NOT cover\n *\n * The memo is only sound while nothing else writes the output collection —\n * tombstoning, `invalidateMVAtRest`, forget/erase and sync cut-over all can. So\n * a refresh records the output collection's mutation stamp AFTER its writes,\n * and the next refresh discards the whole set unless the stamp is still where\n * it left it. That is a \"nobody else touched this\" test rather than an\n * enumeration of writers — the same reasoning that made #1417's keyset memo and\n * #1426's slot guard safe, and it does not rot when a new writer is added.\n *\n * ⚠️ It covers writers that go THROUGH the output `Collection`. A writer that\n * bypasses it and edits the store directly moves neither the stamp nor the\n * collection's own cache — but such a writer already makes `list()` on that\n * collection wrong, so it is a broader defect than this memo.\n *\n * ## ⛔ There is no explicit drop, and that is the design (#59)\n *\n * Invalidation is BY STAMP, in both directions: `readEmitMemo` deletes a memo\n * whose stamp no longer matches, and `writeEmitMemo` deletes rather than store\n * one it cannot trust (`null` stamp, or over the row cap). A refresh that\n * throws midway has already written some rows, so the output collection's\n * stamp has moved and the next read drops the memo itself; a row that failed,\n * was declined or was tombstoned is simply absent from `emitted` and is written\n * again (`executor.ts`, \"Record the stamp AFTER every write and tombstone\").\n *\n * So there is no invalidation path the stamp guard does not already cover. A\n * `dropEmitMemo(key)` hook existed until #59 and was called by nothing for\n * exactly that reason — do not re-add one without first naming the path that\n * leaves a stale memo behind.\n *\n * ## ⛔ The memo stands down when a REDUNDANT write is still observable\n *\n * `Collection._cacheStamp` returns `null` — no memo — whenever writing the same\n * bytes again would have an effect beyond the stored bytes. This is the half\n * that is easy to get wrong, and it was found by a failing test rather than by\n * reasoning, so the cases are recorded:\n *\n * - **A `beforePut` gate handler.** Measured: with `withPeriods()` and a\n * closed period, an unchanged MV row previously produced a\n * `PeriodClosedError` from `put`, which `putDerivedOutput` converts into a\n * `derivation:skipped-frozen` event and an audit record. Skipping the write\n * silences that — `written=0 skipped=2 events=0` where the suite expects one\n * event. A performance change must not quietly narrow a compliance signal.\n * - **Explicit history.** A put records a version, so skipping changes what\n * `history()` returns. (Arguably an improvement — 450 identical versions per\n * source write is not useful — but that is a product call, not this one.)\n * - **Sync (`onDirty`) and the search index.** Both mark state from the fact\n * that a write happened, independently of what was written.\n * - **Lazy mode**, which has no eager cache to stamp.\n *\n * The asymmetry is what makes this the right default: opting out costs the old\n * write path, opting in wrongly changes behaviour with no symptom at all.\n *\n * ⭐ So an MV whose OUTPUT collection carries periods, history, sync or search\n * gets no speedup. That is deliberate, and it is the first thing to check when\n * this fix appears not to help a real workload — the answer is per output\n * collection, not per vault.\n *\n * ⛔ A row is recorded ONLY when the write actually landed. A `putDerivedOutput`\n * that declines (the frozen-period skip) or throws leaves no entry, so the next\n * refresh writes it again rather than believing a row exists that does not.\n *\n * @module\n */\nimport { canonicalizeQueryPlan } from './query-hash.js'\n\n/**\n * Views larger than this are not memoized at all. The memo would otherwise\n * hold a canonical string per row for the process's life, and a view this size\n * is dominated by its write cost in ways one skip cannot rescue.\n */\nconst MAX_MEMOIZED_ROWS = 20_000\n\ninterface EmitMemo {\n /** The output collection's mutation stamp when this set was written. */\n readonly stamp: number\n /** `outputId -> canonical content string` for rows this MV actually wrote. */\n readonly rows: Map<string, string>\n}\n\nconst memos = new Map<string, EmitMemo>()\n\n/**\n * Identity of one MV's output, per vault — MV names are not globally unique.\n *\n * ⚠️ `\\0` written as the ESCAPE, not as a raw byte. A raw NUL in the source\n * makes git classify the whole file as binary, so it stops diffing and stops\n * being reviewable — caught here by a `Bin 0 -> 8811 bytes` line in a diffstat.\n * The separator itself is right: no vault or collection name can contain one.\n */\nexport function emitMemoKey(vault: string, mvName: string, outputCollection: string): string {\n return `${vault}\\0${mvName}\\0${outputCollection}`\n}\n\n/**\n * The rows this MV last wrote, or `null` when the memo cannot be trusted —\n * nothing recorded yet, or the output collection moved under us.\n *\n * `stamp` of `null` means the collection cannot supply one (lazy mode), which\n * is treated as \"no memo\" rather than \"unchanged\".\n */\nexport function readEmitMemo(key: string, stamp: number | null): ReadonlyMap<string, string> | null {\n if (stamp === null) return null\n const hit = memos.get(key)\n if (!hit || hit.stamp !== stamp) {\n // Someone else wrote the output collection. Everything we believed about\n // its contents is now a guess, so drop all of it rather than reconcile.\n if (hit) memos.delete(key)\n return null\n }\n return hit.rows\n}\n\n/** Record what this refresh actually left on disk. A `null` stamp records nothing. */\nexport function writeEmitMemo(key: string, stamp: number | null, rows: Map<string, string>): void {\n if (stamp === null || rows.size > MAX_MEMOIZED_ROWS) {\n memos.delete(key)\n return\n }\n memos.set(key, { stamp, rows })\n}\n\n/**\n * A canonical string for the row a refresh is about to write, or `null` when no\n * safe one exists.\n *\n * The MV's `queryHash` is folded in so a strategy change rewrites every row\n * even where the projected content happens to match — a row carrying a stale\n * `_materializedFrom.queryHash` is stale by definition (`stale.ts`).\n *\n * `_materializedFrom` itself is excluded: its `materializedAt` moves on every\n * refresh, so including it would make every comparison differ and the memo a\n * pure cost.\n *\n * ⛔ Returns `null` rather than throwing on anything `JSON.stringify` refuses\n * (a `BigInt`, a cycle). Declining to memoize costs the old write; guessing\n * costs a stale view.\n */\nexport function rowContentKey(row: Record<string, unknown>, queryHash: string): string | null {\n try {\n // `_materializedFrom` is excluded by rebuilding without it rather than by\n // destructuring into an unused binding — same result, no dead name.\n const content: Record<string, unknown> = {}\n for (const k of Object.keys(row)) {\n if (k !== '_materializedFrom') content[k] = row[k]\n }\n return `${queryHash}\\0${canonicalizeQueryPlan(content)}`\n } catch {\n return null\n }\n}\n\n/** Test seam — the process-wide memo must not leak between test cases. */\nexport function _clearEmitMemos(): void {\n memos.clear()\n}\n","import { groupKeyName, isDateTruncKey, projectDateTruncKeys, type GroupKey } from '../../kernel/query/reduce/date-trunc.js'\nimport 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/relate/join.js'\nimport type { MaterializedFromMeta, MVQueryContext, MaterializedViewSpec, ProjectionJoinLeg } from './types.js'\nimport type { RegisteredMV } from './registry.js'\nimport { wrapDbWithPredicates, ungatedMvContext } from './registry.js'\nimport { groupAndReduce } from '../../with-lookup/reduce/groupby.js'\nimport { applyDeclaredWindow } from './window-stage.js'\nimport { canonicalGroupKey } from '../../with-lookup/reduce/canonical-key.js'\nimport { applyI18nLocale, type I18nTextDescriptor } from '../../via/i18n/core.js'\nimport { canonicalizeMoneyFieldsAsDecimal, decodeMoneyFields } from '../../via/money/normalize.js'\nimport { exactMath } from '../../via/money/exact.js'\nimport { putDerivedOutput, type PutDerivedOutputCtx } from '../../kernel/via/dispatch.js'\nimport { isCollectLeg, resolveLegOwner, type RefLookup } from './projection-legs.js' // #1140\nimport { emitMemoKey, readEmitMemo, writeEmitMemo, rowContentKey } from './emit-memo.js' // #1418\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 /**\n * #1418 — rows whose content was byte-identical to what this MV last wrote,\n * so the encrypt-and-store round trip was skipped. Counted separately from\n * `written` on purpose: `written` means \"a row was persisted\", and reporting\n * a skip as a write would make the two indistinguishable to anyone\n * diagnosing whether a refresh actually did anything.\n */\n skipped: 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: MaterializedViewSpec<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 // #1411 — a declared leg is `Query.joinOn()`; a ref leg is `Query.join()`.\n q = 'on' in leg\n ? q.joinOn(leg.target, { as: leg.as, on: leg.on, mode: leg.mode, maxRows: leg.maxRows })\n : 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/**\n * #1411 — the window stage, applied at every exit from the grouping tail.\n *\n * A no-op without `spec.window`, so the ungrouped and grouped paths can both\n * call it unconditionally rather than each remembering to.\n */\nfunction applyWindowStage<TRow extends Record<string, unknown>>(\n spec: MaterializedViewSpec<TRow>,\n rows: ReadonlyArray<Record<string, unknown>>,\n): ReadonlyArray<Record<string, unknown>> {\n if (!spec.window) return rows\n return applyDeclaredWindow(rows, spec.window, spec.moneyFields)\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: MaterializedViewSpec<TRow>,\n unified: TRow[],\n): ReadonlyArray<Record<string, unknown>> {\n // #1411 — a window with no grouping is a legitimate shape: the pilot's\n // running total is per-row, not per-bucket. Both exits go through the same\n // stage so the two cannot drift on whether a window ran.\n if (!spec.groupBy) return applyWindowStage(spec, unified)\n\n const groupKeys: readonly GroupKey[] = Array.isArray(spec.groupBy)\n ? (spec.groupBy as readonly GroupKey[])\n : [spec.groupBy as GroupKey]\n const groupFields: readonly string[] = groupKeys.map(groupKeyName)\n\n // Derived calendar keys (#1350) are bucketed onto the mapped row first, so\n // every rule below — the i18n resolution, the object-key refusal, the dedup\n // path and `groupAndReduce` — sees an ordinary stored field.\n const derivedKeys = groupKeys.filter(isDateTruncKey)\n if (derivedKeys.length > 0) {\n unified = projectDateTruncKeys(unified, derivedKeys)\n }\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 applyWindowStage(\n spec,\n groupAndReduce<Record<string, unknown>>(unified, groupFields, spec.aggregate, spec.moneyFields),\n )\n}\n\n/**\n * Apply the spec's `derive` to each finished row (#1007).\n *\n * Three rules, all of them about keeping the hook narrow enough that the\n * engine never has to reason about the function:\n *\n * - a `null` / `undefined` return leaves the row untouched;\n * - a returned key that collides with a `groupBy` field is refused — group\n * keys are the row's identity and feed `rowKey`, so letting `derive`\n * rewrite one would silently re-home the row into a different bucket than\n * the one it was aggregated for;\n * - a derived field declared in `moneyFields` is quantised through its\n * descriptor, so the stored value is exact at the declared scale instead of\n * whatever the user's arithmetic produced.\n *\n * @internal\n */\nfunction applyDerive<TRow extends Record<string, unknown>>(\n spec: MaterializedViewSpec<TRow>,\n rows: ReadonlyArray<Record<string, unknown>>,\n): ReadonlyArray<Record<string, unknown>> {\n const groupFields = new Set<string>(\n spec.groupBy === undefined\n ? []\n : (Array.isArray(spec.groupBy) ? spec.groupBy : [spec.groupBy]).map(groupKeyName),\n )\n return rows.map((row) => {\n // `derive` sees the row the way a READER would: money decoded to its\n // canonical decimal form, not the scaled integer the reducer left behind.\n // Handing over `1005` where the schema says `10.05` would make every\n // derived money expression quietly wrong by a factor of the scale.\n // `'raw'` keeps it at the exact decimal rather than a locale-formatted\n // string, which is what `exact.*` consumes.\n const view = spec.moneyFields ? decodeMoneyFields(row, spec.moneyFields, 'raw') : row\n const patch = spec.derive!(view as TRow, exactMath)\n if (patch === null || patch === undefined) return row\n for (const key of Object.keys(patch)) {\n if (groupFields.has(key)) {\n throw new MaterializedViewConfigError(\n `Materialized view \"${spec.name}\": derive() returned the group key \"${key}\". ` +\n 'A group key is the row\\'s identity and feeds rowKey — rewriting it would re-home the ' +\n 'row into a bucket it was not aggregated for. Emit a differently-named field instead.',\n )\n }\n }\n // Canonicalize the PATCH only, into the DECIMAL form the money-aware\n // reducers emit — not the scaled-integer storage form a collection uses.\n // An MV row's money fields are decimal strings, so a derived field\n // quantised into storage form reads back as the scaled integer beside\n // correctly-decoded siblings: `\"1000000\"` next to `\"10000.00\"` (#1018).\n // Precision is still enforced; only the output shape differs.\n const canonical = spec.moneyFields\n ? canonicalizeMoneyFieldsAsDecimal(patch, spec.moneyFields)\n : patch\n return { ...row, ...canonical }\n })\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: MaterializedViewSpec<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 // ROOT forward legs chain through the query builder exactly like UNION arm\n // joins — ref() resolution, dangling-mode semantics, presentation dressing,\n // and ceilings all ride the existing `.join()` path. Cast to `any` for the\n // 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 (isCollectLeg(leg) || leg.from !== undefined) 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 // Remaining legs in DECLARATION order — which is what makes `from` work: a leg\n // may only name an alias declared earlier, so by the time it runs, the rows it\n // attaches to are already on the row. Root collect legs are in this loop too;\n // they were never part of the query chain.\n for (const leg of projection.joins) {\n if (isCollectLeg(leg)) {\n rows = applyCollectLeg(rows, leg, spec.name, projection.source, projection.joins, db)\n } else if (leg.from !== undefined) {\n rows = applyLegRelativeForwardLeg(rows, leg, spec.name, projection.source, projection.joins, db)\n }\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 * A `RefLookup` backed by the live join contexts — the executor's answer to the\n * same question the registry answers from the ref registry. Reads through, so a\n * ref declared after `openVault()` (the only place refs CAN be declared) is\n * visible here.\n *\n * @internal\n */\nfunction legOwnerLookup(db: MVQueryContext): RefLookup {\n return (collection, field) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const q = db.collection<Record<string, unknown>>(collection).query() as any\n return (q._joinContext?.()?.resolveRef(field) as { target: string } | null | undefined) ?? null\n }\n}\n\n/**\n * Attach one FORWARD leg that hangs off another leg's alias (#1140).\n *\n * Root forward legs ride `Query.join()` and are resolved before this runs; a\n * leg-relative one cannot, because the FK it follows lives on an already-attached\n * record rather than on a column of the primary query. It is therefore resolved\n * the same way a collect leg is — one snapshot of the target collection, indexed\n * by id — which keeps it O(N+M) rather than one `get()` per row.\n *\n * Attaches `null` when the `from` alias is null (a dangling ref upstream), when\n * the FK is nullish, or when the target row is missing. That is deliberately\n * outer-by-nature and matches the collect leg's empty array: a projection MV\n * must not drop a primary row because something two hops away is absent.\n *\n * @internal\n */\nfunction applyLegRelativeForwardLeg(\n primaryRows: ReadonlyArray<Record<string, unknown>>,\n leg: Extract<ProjectionJoinLeg, { field: string }>,\n mvName: string,\n source: string,\n joins: ReadonlyArray<ProjectionJoinLeg>,\n db: MVQueryContext,\n): Array<Record<string, unknown>> {\n const lookup = legOwnerLookup(db)\n const owner = resolveLegOwner(leg, joins, source, lookup)\n const refDesc = owner === null ? null : lookup(owner, leg.field)\n if (owner === null || refDesc === null) {\n throw new MaterializedViewConfigError(\n `\"${mvName}\": projection leg \"${leg.as}\" requires a ref() on field \"${leg.field}\" of `\n + `collection \"${owner ?? `(behind from: \"${leg.from}\")`}\" — declare it on that collection, `\n + `then retry`,\n )\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const targetQ = db.collection<Record<string, unknown>>(refDesc.target).query() as any\n const byId = new Map<string, Record<string, unknown>>()\n for (const row of targetQ.toArray() as Array<Record<string, unknown>>) {\n const id = coerceCollectKey(row.id)\n if (id !== null) byId.set(id, row)\n }\n return primaryRows.map((row) => {\n const anchor = leg.from === undefined\n ? row\n : (row[leg.from] as Record<string, unknown> | null | undefined)\n const key = anchor == null ? null : coerceCollectKey(anchor[leg.field])\n return { ...row, [leg.as]: key === null ? null : byId.get(key) ?? null }\n })\n}\n\n/**\n * Attach one reverse \"collect\" leg (#810): every row of `leg.collect`\n * whose `leg.on` field references the ATTACH POINT'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 * The attach point is the primary record, or — with `from` (#1140) — the record\n * already attached under that alias. Matching then keys off `row[from].id`\n * instead of `row.id`, and `leg.on` must ref THAT leg's collection. A row whose\n * `from` alias is null (a dangling forward ref) gets `[]`, which is the same\n * outer-by-nature semantics a root collect leg already has for a primary record\n * with no children.\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 attach point's collection.\n *\n * @internal\n */\nfunction applyCollectLeg(\n primaryRows: ReadonlyArray<Record<string, unknown>>,\n leg: { readonly collect: string; readonly on: string; readonly as: string; readonly from?: string; readonly maxRows?: number },\n mvName: string,\n source: string,\n joins: ReadonlyArray<ProjectionJoinLeg>,\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 // The collection this leg matches AGAINST: the projection source for a root\n // leg, the `from` leg's own target otherwise (#1140).\n const expected = resolveLegOwner(leg, joins, source, legOwnerLookup(db))\n const expectedName = expected ?? source\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 \"${expectedName}\" — declare `\n + `refs: { ${leg.on}: ref('${expectedName}') } on collection \"${leg.collect}\", then retry`,\n )\n }\n if (refDesc.target !== expectedName) {\n throw new MaterializedViewConfigError(\n `\"${mvName}\": projection collect leg \"${leg.as}\" expects field \"${leg.on}\" of collection `\n + `\"${leg.collect}\" to reference ${leg.from === undefined\n ? `the projection source \"${expectedName}\"`\n : `\"${expectedName}\" (the collection behind from: \"${leg.from}\")`}`\n + `, but its ref() targets \"${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 // `from` matches against the attached record's id, not the primary row's.\n const anchor = leg.from === undefined\n ? row\n : (row[leg.from] as Record<string, unknown> | null | undefined)\n const key = anchor == null ? null : coerceCollectKey(anchor.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 // #1414 — `ungatedMvContext` keeps the engine's synchronous source reads\n // exactly as they were before the cold-collection gate existed.\n const baseCtx = ungatedMvContext(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 // #1007 — the post-aggregate projection. Applied here, after every form has\n // produced its finished rows, so union / projection / query all get the\n // same single definition of \"last step before materialisation\".\n if (spec.derive) rows = applyDerive(spec, rows)\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 — skipping any whose content is unchanged (#1418).\n //\n // ⛔ THE OUTPUT ROW COUNT, NOT THE SOURCE SCAN, IS WHAT MADE THIS EXPENSIVE.\n // This loop used to encrypt-and-store EVERY row of the view on EVERY source\n // write, so per-write cost tracked the size of the view: measured 23 ms at\n // 250 output rows and 41.6 ms at 450, for source writes the MV's own `map`\n // dropped entirely. Comparing against what this MV last wrote turns \"one\n // source write rewrites the whole view\" into \"one source write rewrites the\n // groups that moved\". See `emit-memo.ts` for why this, and not a\n // predict-whether-the-refresh-is-needed short circuit.\n const memoKey = emitMemoKey(vaultName, spec.name, reg.outputCollection)\n // Read the stamp BEFORE writing: it has to describe the collection as this\n // refresh found it, so a write by anyone else since last time invalidates.\n const priorEmitted = readEmitMemo(memoKey, outputColl._cacheStamp)\n const emitted = new Map<string, string>()\n\n let written = 0\n let skipped = 0\n let failed = 0\n for (const { id, record } of enrichedRows) {\n const contentKey = rowContentKey(record, reg.queryHash)\n // ⚠️ A txCtx changes what a \"skip\" means: the rollback journal below\n // needs an entry for every row the transaction could revert, and a row we\n // never wrote has nothing to revert TO. Rather than reason about partial\n // journals, the memo stands down inside a transaction entirely.\n // #1439 — and only when no `beforePut` gate can fire FOR THIS ROW. Asking\n // the bus \"is anything registered\" instead disabled the skip for every\n // collection in any vault carrying a guard or a periods strategy —\n // measured by the reporter at 54 redundant writes per source write with\n // guards alone, which is close to every real consumer.\n if (\n contentKey !== null && txCtx === null\n && !outputColl._derivedWriteGated(record)\n && priorEmitted?.get(id) === contentKey\n ) {\n skipped++\n emitted.set(id, contentKey)\n continue\n }\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 let landed = false\n if (accessor.dispatchCtx) {\n if (await putDerivedOutput(outputColl, id, record, accessor.dispatchCtx) === 'written') {\n written++\n landed = true\n }\n } else {\n await outputColl.put(id, record)\n written++\n landed = true\n }\n // ⛔ ONLY a write that actually landed is remembered. `putDerivedOutput`\n // declines inside a frozen period, and recording that row would make\n // every later refresh skip a row that is not there.\n if (landed && contentKey !== null) emitted.set(id, contentKey)\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 // Record the stamp AFTER every write and tombstone, so the next refresh's\n // check means \"nothing has happened to this collection since I finished\".\n // A row that failed, was declined, or was tombstoned is simply absent from\n // `emitted` and will be written again.\n writeEmitMemo(memoKey, outputColl._cacheStamp, emitted)\n\n return { written, skipped, 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":[]}
@@ -6,7 +6,7 @@ import {
6
6
  ConflictError,
7
7
  InvariantError,
8
8
  ValidationError
9
- } from "./chunk-37EPTBBR.js";
9
+ } from "./chunk-VSUQI5Q6.js";
10
10
 
11
11
  // src/with-commit/tx/atomic-eligibility.ts
12
12
  function canCommitAtomically(db, ctx) {
@@ -322,7 +322,7 @@ async function runTransaction(db, fn, options, txInvariants) {
322
322
  db._clearActiveTxContext(ctx);
323
323
  }
324
324
  if (ctx._amendment) {
325
- const { GuardExecutor } = await import("./executor-LBBBRTN5.js");
325
+ const { GuardExecutor } = await import("./executor-WWM3DD4P.js");
326
326
  try {
327
327
  for (const [vaultName, v] of ctx._amendmentVaults) {
328
328
  const registry = v._getGuardRegistry();
@@ -500,4 +500,4 @@ export {
500
500
  TxCollection,
501
501
  runTransaction
502
502
  };
503
- //# sourceMappingURL=chunk-UA372JHH.js.map
503
+ //# sourceMappingURL=chunk-7CT6SX4M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-commit/tx/atomic-eligibility.ts","../src/kernel/best-effort-revert.ts","../src/kernel/tx-write-gate.ts","../src/with-commit/tx/transaction.ts"],"sourcesContent":["/**\n * #893/#906-prep — the atomic-commit eligibility gate.\n *\n * `runTransaction` (Task 5) consults `canCommitAtomically` right after the\n * body returns, to decide whether the whole staged batch can be prepared and\n * submitted as ONE `store.tx(ops)` call instead of the per-op abortable\n * path (Phase 1 pre-flight + Phase 2 Collection-layer execute + Phase 3\n * best-effort revert — see `transaction.ts`'s module doc).\n *\n * Pure decision logic: no side effects, no store reads. Every input is\n * already sitting on `db` / `ctx`.\n *\n * ALL of the following must hold. (Commit-time changeset invariants are NOT a\n * condition: that phase lives after Phase 2 in `runTransaction` and runs\n * unchanged on either path — a failing invariant reverts the atomic batch\n * through the same `ctx._executed` plan.)\n *\n * 1. The store declares `capabilities.txAtomic === true` AND implements\n * `tx()`. Both — mirrors the pairing rule `bestEffortRevert` already\n * enforces (`kernel/best-effort-revert.ts:78`): an undeclared `tx()` is\n * never used, even if present.\n * 2. Not an amendment transaction (`ctx._amendment === false`) — amendments\n * need the guard-registry change-set + invariant machinery the atomic\n * path skips entirely.\n * 3. No `(vault, collection, id)` is touched twice in the batch. The\n * abortable path's Phase 1 snapshots each key once and Phase 2 replays\n * every op against that same snapshot in order; a single `store.tx()`\n * write set can't express \"this key changes twice in sequence.\"\n * 4. Every touched collection reports `_txAtomicSafe(op.type)` — see that\n * method's doc comment on `Collection` for what it excludes and why.\n * #931: of the wrapper-level write signals, only a live `onBeforeWrite`\n * hook still excludes — it may REFUSE a write, which only\n * `Collection.put()`/`.delete()` honors. After-hooks and the\n * `afterPut`/`afterDelete` observe bus are refusal-free observers, so\n * the atomic path fires them itself per leg post-finalize\n * (`Collection._fireAtomicAfterWrite`) instead of forfeiting the batch.\n * Delete gates on the enforcer's `_deleteCascadesPossible(name)` (#922):\n * `Vault.enforceRefsOnDelete` cascades from THREE sources (lookup-ref\n * edges, classic inbound refs, managed-link `onDelete`), and the Vault\n * predicate unions exactly those three — a `getInbound`-only check would\n * be narrower and wrongly admit unsafe atomic deletes, because\n * `_prepareDelete` runs the cascades DURING prepare (see\n * `with-shape/links/vault-facade.ts` `enforceRefsOnDelete`).\n *\n * @internal\n */\n\nimport type { Noydb } from '../../kernel/noydb.js'\nimport type { TxContext } from './transaction.js'\nimport { keyOf } from './transaction.js'\n\nexport function canCommitAtomically(db: Noydb, ctx: TxContext): boolean {\n const store = db._store\n if (store.capabilities?.txAtomic !== true || typeof store.tx !== 'function') return false\n if (ctx._amendment) return false\n\n const seen = new Set<string>()\n for (const op of ctx._ops) {\n const key = keyOf(op)\n if (seen.has(key)) return false\n seen.add(key)\n }\n\n for (const op of ctx._ops) {\n const coll = db.vault(op.vaultName).collection(op.collectionName)\n if (!coll._txAtomicSafe(op.type)) return false\n }\n\n return true\n}\n","/**\n * Best-effort reverse-revert — the shape shared by two independent rollback\n * paths that used to duplicate it: satellite fan-out\n * (`with-shape/satellites/fanout.ts`'s `revertAndCompensate`) and\n * multi-record transactions (`with-commit/tx/transaction.ts`'s\n * `revertExecuted`). Both revert a list of already-executed writes on\n * failure by walking them in REVERSE order and, per leg, restoring the\n * captured prior envelope straight through the raw adapter — `put(prior)`\n * when one existed, `delete` when the leg was a fresh insert — bypassing\n * the Collection layer so the revert itself doesn't re-fire\n * encryption/ledger/change-event machinery. Each leg's raw-adapter revert\n * is best-effort: a throw is swallowed so a revert-path failure never masks\n * the original error that triggered the rollback, and the loop moves on to\n * the next leg.\n *\n * An optional per-leg `compensate` callback runs immediately after a\n * successful raw-adapter revert (still inside the same try, so a throwing\n * callback is swallowed the same way as a throwing raw revert). What the\n * callback does is entirely caller-defined — satellites' fan-out fires\n * `_compensateRevertedWrite` only for legs whose write actually landed\n * (#596); with-commit's transaction executor invalidates the Collection\n * cache. Neither concern belongs here: this helper only knows the generic\n * reverse/best-effort/raw-revert shape.\n *\n * Lives in `kernel/` — not a `with-*` service — so both consumers (one a\n * gated service, `with-commit`; one an always-on schema feature,\n * `with-shape/satellites`) can import it without creating a\n * `with-* → with-*` edge, which would force either family to always bundle\n * the other and defeat the opt-in tree-shaking both are built around.\n *\n * @internal — implementation-sharing only, not part of the public surface.\n */\nimport type { EncryptedEnvelope, StoreCapabilities, TxOp } from './types.js'\n\n/** One already-executed write a revert pass needs to unwind. */\nexport interface BestEffortRevertLeg {\n readonly vaultName: string\n readonly collectionName: string\n readonly id: string\n /** Envelope captured before the write, or `null` if the id didn't exist yet. */\n readonly prior: EncryptedEnvelope | null\n}\n\n/** The subset of `NoydbStore` a raw-adapter revert needs. */\nexport interface BestEffortRevertAdapter {\n put(vaultName: string, collectionName: string, id: string, envelope: EncryptedEnvelope): Promise<void>\n delete(vaultName: string, collectionName: string, id: string): Promise<void>\n /**\n * Optional storage-layer transaction (#886). When the store declares\n * `txAtomic`, the whole revert is submitted as ONE operation instead of a\n * per-leg loop, so a crash mid-revert can no longer leave the vault\n * half-unwound.\n */\n tx?(ops: readonly TxOp[]): Promise<void>\n readonly capabilities?: StoreCapabilities\n}\n\n/**\n * Revert `executed` in reverse order via the raw adapter, best-effort.\n * `compensate`, when supplied, runs once per leg immediately after that\n * leg's own raw revert succeeds.\n */\nexport async function bestEffortRevert<T extends BestEffortRevertLeg>(\n executed: readonly T[],\n adapter: BestEffortRevertAdapter,\n compensate?: (leg: T) => Promise<void> | void,\n): Promise<void> {\n const legs = [...executed].reverse()\n\n // #886 — atomic revert when the store can do it. The legs already carry RAW\n // prior envelopes (captured pre-write), which is exactly the shape `tx()`\n // wants, so this needs none of the Collection-layer machinery that makes\n // delegating the FORWARD write path a much larger job.\n //\n // Failure stays best-effort: if the store rejects the batch we fall through\n // to the per-leg loop rather than surfacing a revert-path error, because a\n // revert failure must never mask the original error that triggered it.\n if (adapter.capabilities?.txAtomic === true && typeof adapter.tx === 'function') {\n const ops: TxOp[] = legs.map(leg =>\n leg.prior !== null\n ? { type: 'put', vault: leg.vaultName, collection: leg.collectionName, id: leg.id, envelope: leg.prior }\n : { type: 'delete', vault: leg.vaultName, collection: leg.collectionName, id: leg.id },\n )\n try {\n await adapter.tx(ops)\n if (compensate) for (const leg of legs) { try { await compensate(leg) } catch { /* best-effort */ } }\n return\n } catch {\n // fall through to the per-leg path below\n }\n }\n\n for (const leg of legs) {\n try {\n if (leg.prior !== null) {\n await adapter.put(leg.vaultName, leg.collectionName, leg.id, leg.prior)\n } else {\n await adapter.delete(leg.vaultName, leg.collectionName, leg.id)\n }\n if (compensate) await compensate(leg)\n } catch {\n // best-effort — a revert-path failure must not mask the original\n // error that triggered the rollback (matches both callers' prior\n // independent implementations).\n }\n }\n}\n","/**\n * #1420 — the in-flight-write gate.\n *\n * ## The defect this closes\n *\n * `runTransaction`'s commit opens with a **pre-flight**: it re-reads every\n * touched envelope and enforces the caller's `expectedVersion`. That check is\n * only as honest as the read, and the read could not see a plain\n * `Collection.put()` that had *started* but not yet reached the store. Such a\n * put is invisible to the pre-flight, so:\n *\n * - it lands after the pre-flight and the transaction overwrites it from a\n * stale snapshot (both writers report success, one write vanishes); or\n * - it lands after the transaction's own write and clobbers it from a stale\n * base (two writes, one version bump).\n *\n * Neither raised an error on either side, and the loss was **store-capability\n * dependent** — `memoryStore({ full: true })` declares `txAtomic` and takes the\n * atomic commit path, `to-browser-idb` does not and takes the per-op replay — so an app\n * tested on a memory store could ship lossy on IndexedDB.\n *\n * ## The remedy: make the pre-flight's read honest\n *\n * Every logical `Collection.put()` / `.delete()` registers itself here for the\n * span of its read-modify-write, keyed by `(vault, collection, id)`. A commit\n * **drains** the writes already in flight on the keys it is about to touch,\n * BEFORE its pre-flight reads. The in-flight case then behaves exactly like\n * the fully-awaited one the pre-flight already handled correctly: the read\n * sees the new version and a mismatched `expectedVersion` refuses with\n * `ConflictError`. No silent loss, and no new refusal for writes that were\n * never in conflict.\n *\n * ## Why this is deadlock-free\n *\n * The wait is strictly one-directional and one-deep. A registered write never\n * waits on anything from this module — only a commit does, and only on writes\n * registered *before* it started draining ({@link drainKeyedWrites} takes a\n * snapshot and does not loop to a fixed point). So there is no cycle to close,\n * and the drain terminates as soon as the pre-existing writes settle,\n * whichever way they settle. A commit's own Phase-2 writes register *after*\n * the drain has returned, so a commit never waits on itself.\n *\n * ## Scope, deliberately\n *\n * Keyed on the STORE object, not the `Noydb` instance — two hub instances over\n * one store are the same race, and this keeps the always-on kernel files\n * (`noydb.ts`) untouched. Same-process only: it is a JS-object registry, and\n * makes no claim about a second tab or a second process. That is the same\n * boundary the reported defect has.\n *\n * ⛔ This does NOT serialize transaction against transaction. Two concurrent\n * commits touching one key can still interleave — a distinct case from the\n * reported one, and one whose fix (a commit barrier) has to solve reentrancy\n * for the commit's own replay writes first. Do not extend this module into\n * that without measuring the reentrancy path.\n *\n * @internal\n */\n\n/** store → key → the settle-promises of the writes currently in flight on it. */\nconst inFlight = new WeakMap<object, Map<string, Set<Promise<void>>>>()\n\n/** The shared `(vault, collection, id)` key shape. @internal */\nfunction writeGateKey(vault: string, collection: string, id: string): string {\n return `${vault}\\x00${collection}\\x00${id}`\n}\n\n/**\n * Run one logical write registered against `(vault, collection, id)` so a\n * concurrent commit can drain it. Returns / throws exactly what `fn` does —\n * registration is invisible to the caller.\n *\n * @internal\n */\nexport async function trackKeyedWrite<R>(\n store: object,\n vault: string,\n collection: string,\n id: string,\n fn: () => Promise<R>,\n): Promise<R> {\n let byKey = inFlight.get(store)\n if (byKey === undefined) {\n byKey = new Map()\n inFlight.set(store, byKey)\n }\n const key = writeGateKey(vault, collection, id)\n let waiters = byKey.get(key)\n if (waiters === undefined) {\n waiters = new Set()\n byKey.set(key, waiters)\n }\n const running = fn()\n // A drainer must never inherit this write's rejection: it is waiting for the\n // write to STOP being in flight, not for it to succeed. The original promise\n // is what the caller gets, unswallowed.\n const settled = running.then(() => undefined, () => undefined)\n waiters.add(settled)\n try {\n return await running\n } finally {\n waiters.delete(settled)\n if (waiters.size === 0) byKey.delete(key)\n }\n}\n\n/**\n * Wait for every write already in flight on `keys` to settle. Snapshot-based\n * and single-pass — see the deadlock note in the module doc. A no-op (and no\n * microtask) when nothing is in flight, which is the overwhelmingly common\n * case for a commit.\n *\n * @internal\n */\nexport async function drainKeyedWrites(store: object, keys: Iterable<string>): Promise<void> {\n const byKey = inFlight.get(store)\n if (byKey === undefined || byKey.size === 0) return\n let waits: Promise<void>[] | undefined\n for (const key of keys) {\n const waiters = byKey.get(key)\n if (waiters === undefined) continue\n for (const w of waiters) (waits ??= []).push(w)\n }\n if (waits !== undefined) await Promise.all(waits)\n}\n","/**\n * Multi-record atomic transactions.\n *\n * Lets an application stage writes across two or more collections (or\n * vaults) and commit them all-or-nothing.\n *\n * ```ts\n * await db.transaction(async (tx) => {\n * const inv = tx.vault('acme').collection<Invoice>('invoices')\n * const pay = tx.vault('acme').collection<Payment>('payments')\n * await inv.put(invoiceId, { ...invoice, status: 'paid' })\n * await pay.put(paymentId, { invoiceId, amount, paidAt })\n * })\n * // If the body throws before returning: nothing persisted.\n * // If the body returns: all puts committed; any CAS mismatch rolls\n * // the batch back and surfaces as ConflictError.\n * ```\n *\n * ## Atomicity semantics\n *\n * Ops are buffered during the body. On body-return the hub:\n *\n * 0. **Drain (#1420)** — waits out any plain `Collection.put()` /\n * `.delete()` already in flight on a key this commit touches, so\n * the pre-flight below reads a version that includes it. Without\n * this the pre-flight cannot see a write that has STARTED but not\n * yet reached the store, and one of the two writes vanishes with\n * both reporting success.\n * 1. **Pre-flight** — re-reads every touched envelope and enforces\n * any caller-supplied `expectedVersion`. A mismatch throws\n * `ConflictError` with *no* writes performed.\n * 2. **Execute** — re-validates each op's `expectedVersion` against\n * the CURRENT stored version (#1420 — the pre-flight's verdict is\n * otherwise unchecked all the way to the write, and this path\n * carries no store-level CAS the way the atomic one does), then\n * calls `Collection.put()` / `.delete()` for each staged op in\n * declaration order. History snapshots, ledger appends, and change\n * events fire as normal per op.\n * 3. **Unwind on failure** — if step 2 throws mid-batch, each\n * already-committed op is reverted via the raw store (restoring\n * the captured prior envelope, or deleting if none existed). The\n * ledger is NOT rewritten — audit history preserves the partial\n * commit and the revert.\n *\n * **Atomic delegation (#906).** Steps 1–3 above describe the OCC\n * fallback. When the store declares `StoreCapabilities.txAtomic` AND\n * implements `tx()`, AND the staged batch is statically safe\n * (`canCommitAtomically` — see `atomic-eligibility.ts`), the commit\n * instead: prepares every op through `Collection._preparePut` /\n * `_prepareDelete` (encrypt, resolve the prior version, mint the #589\n * marker — no observable side effect), submits the whole write set as\n * ONE `store.tx(ops)` call with a per-leg `expectedVersion`, then\n * finalizes each op in staged order. The visible difference: history\n * snapshots, ledger entries and change events all fire AFTER the bytes\n * are durable, instead of interleaving per op.\n *\n * **Crash window.** On the OCC fallback, steps 2–3 are not a\n * storage-layer transaction — if the process dies between two executed\n * ops, the on-disk state is partial. The atomic path above closes that\n * window for the write set itself (`memoryStore({ full: true })` and the SQL\n * stores in `noy-db-to` implement `tx()`); a crash between the batch landing and\n * the finalize loop finishing still leaves per-op side effects (history,\n * ledger, cache) incomplete. Stores that cannot commit a batch\n * atomically (file, S3) omit `tx()` and keep the fallback.\n *\n * ## Not covered\n *\n * - Cross-sync-peer atomicity. Transactions commit against the\n * primary store only; the sync engine pushes on its normal\n * schedule. For cross-peer two-phase commit use `SyncTransaction`\n * via `db.transaction(vaultName)`.\n * - Read-your-writes within the body. `tx.collection().get(id)`\n * returns the most-recently-staged value for that id when one\n * exists; if no staged op has touched the id, it reads the current\n * committed state. Version numbers returned by `get` reflect the\n * pre-transaction state (staged puts have no version yet).\n *\n * @module\n */\n\nimport type { Noydb } from '../../kernel/noydb.js'\nimport type { Vault } from '../../kernel/vault.js'\nimport type { Collection } from '../../kernel/collection.js'\nimport type { EncryptedEnvelope, TxOp } from '../../kernel/types.js'\nimport type { PreparedPut, PreparedDelete } from '../../kernel/prepared-write.js'\nimport { canCommitAtomically } from './atomic-eligibility.js'\nimport {\n AmendmentForbiddenError,\n ConflictError,\n InvariantError,\n ValidationError,\n} from '../../kernel/errors.js'\nimport { generateULID } from '../../with-pod/ulid.js'\nimport type { GuardExecutor as GuardExecutorModule } from '../../with-audit/guards/executor.js'\nimport type { LedgerEntry } from '../history/ledger/entry.js'\nimport type { TransactionInvariant } from './invariants.js'\nimport type { GuardChange, GuardContext, ReadOnlyVaultFacade } from '../../with-audit/guards/types.js'\nimport { bestEffortRevert } from '../../kernel/best-effort-revert.js'\nimport { drainKeyedWrites } from '../../kernel/tx-write-gate.js'\n\n/** One op buffered inside a running `TxContext`. @internal */\nexport interface StagedOp {\n type: 'put' | 'delete'\n vaultName: string\n collectionName: string\n id: string\n record?: unknown\n expectedVersion?: number\n /**\n * Optional human-readable tag forwarded to the resulting ledger\n * entry's `reason` field. Set by callers via\n * `tx.vault(v).collection(c).put(id, record, { reason })`.\n */\n reason?: string\n}\n\n/**\n * One executed op (main staged op or recursive side-effect like a\n * derivation output) paired with the envelope captured before the write.\n * `revertExecuted` walks this array in reverse on rollback.\n * @internal\n */\nexport interface ExecutedOp {\n op: StagedOp\n priorEnvelope: EncryptedEnvelope | null\n}\n\n/**\n * Options accepted by `db.transaction({ amendment, reason }, fn)`.\n * Only the amendment variant uses these — a plain `db.transaction(fn)`\n * never sees this shape.\n */\nexport interface AmendmentTxOptions {\n /** Opt into amendment mode. Required to be `true`. */\n readonly amendment: true\n /** Human-readable rationale recorded in the ledger entry. Required. */\n readonly reason: string\n}\n\n/**\n * Transaction handle passed to the user's body. Use\n * `tx.vault(name).collection<T>(name)` to get a per-collection\n * facade; its `put`/`delete`/`get` calls stage ops against the tx.\n */\nexport class TxContext {\n /** Stable id for this transaction; shared by all writes it performs. */\n readonly txId: string = generateULID()\n /** @internal */\n readonly _ops: StagedOp[] = []\n /**\n * @internal — write log built up in Phase 2. Each entry records the\n * envelope captured BEFORE the write so a mid-batch failure can\n * restore prior state via `revertExecuted`. Side-effect writes (e.g.\n * recursive derivation outputs fired inside `Collection.put`) are\n * appended here in execution order so they roll back alongside the\n * main staged ops.\n */\n readonly _executed: ExecutedOp[] = []\n /** @internal */\n readonly _db: Noydb\n /**\n * @internal — true when this TxContext was opened in amendment\n * mode. Toggles the lazy-`beginAmendment` + role-check path on first\n * `tx.vault(name)` and unlocks the post-Phase-2 invariant + audit run.\n */\n readonly _amendment: boolean\n /** @internal — vaults that have already had `beginAmendment` called. */\n readonly _amendmentVaults = new Map<string, Vault>()\n\n /** @internal */\n constructor(db: Noydb, amendment = false) {\n this._db = db\n this._amendment = amendment\n }\n\n /** Scope subsequent `collection()` calls to the named vault. */\n vault(name: string): TxVault {\n const v = this._db.vault(name)\n if (this._amendment && !this._amendmentVaults.has(name)) {\n // Role check is per-vault. The task spec (\"only admin or owner\n // can open an amendment\") is implemented lazy-on-first-touch\n // because the role lives on the vault's keyring, and `tx.vault()`\n // is the first place we know which vault we're addressing. The\n // observable effect is identical to an eager check in the single-\n // vault case the tests exercise; multi-vault amendments check\n // each touched vault as they first appear.\n const role = v.role\n // FR-6: custodian is admin-rank for operational mutations, and an\n // amendment is an operational (data-correcting) act — not an ownership\n // meta-capability — so custodian is allowed alongside owner/admin.\n if (role !== 'admin' && role !== 'owner' && role !== 'custodian') {\n throw new AmendmentForbiddenError(v.userId, role)\n }\n // Amendments require an initialised guard registry — they\n // produce a structured invariant + change-set audit. A vault\n // opened without `guardStrategies` (or via the sync fallback\n // path) has a null registry and cannot run an amendment.\n const reg = v._getGuardRegistry()\n if (reg === null) {\n throw new ValidationError(\n `Vault \"${name}\": amendment mode requires at least one ` +\n `guardStrategy registered via createNoydb({ guardStrategies }). ` +\n `Open the vault with guardStrategies before calling ` +\n `db.transaction({ amendment: true }).`,\n )\n }\n reg.beginAmendment()\n this._amendmentVaults.set(name, v)\n }\n return new TxVault(this, v)\n }\n}\n\n/** Per-vault facade inside a running transaction. */\nexport class TxVault {\n /** @internal */\n readonly _ctx: TxContext\n /** @internal */\n readonly _vault: Vault\n\n /** @internal */\n constructor(ctx: TxContext, vault: Vault) {\n this._ctx = ctx\n this._vault = vault\n }\n\n /** Scope subsequent op calls to the named collection. */\n collection<T>(name: string): TxCollection<T> {\n const c = this._vault.collection<T>(name)\n return new TxCollection<T>(this._ctx, this._vault, c, name)\n }\n}\n\n/** Per-collection facade inside a running transaction. */\nexport class TxCollection<T> {\n /** @internal */\n readonly _ctx: TxContext\n /** @internal */\n readonly _vault: Vault\n /** @internal */\n readonly _coll: Collection<T>\n /** @internal */\n readonly _name: string\n\n /** @internal */\n constructor(ctx: TxContext, vault: Vault, coll: Collection<T>, name: string) {\n this._ctx = ctx\n this._vault = vault\n this._coll = coll\n this._name = name\n }\n\n /**\n * Read the current committed value, or the most-recently-staged\n * value from the same transaction if one exists.\n */\n async get(id: string): Promise<T | null> {\n for (let i = this._ctx._ops.length - 1; i >= 0; i--) {\n const op = this._ctx._ops[i]!\n if (\n op.vaultName === this._vault.name &&\n op.collectionName === this._name &&\n op.id === id\n ) {\n if (op.type === 'delete') return null\n return op.record as T\n }\n }\n return this._coll.get(id)\n }\n\n /**\n * Stage a put. Does not write until the transaction body returns.\n * Supply `{ expectedVersion }` to enforce optimistic concurrency\n * during the commit pre-flight.\n */\n put(id: string, record: T, options?: { expectedVersion?: number; reason?: string }): void {\n const op: StagedOp = {\n type: 'put',\n vaultName: this._vault.name,\n collectionName: this._name,\n id,\n record,\n }\n if (options?.expectedVersion !== undefined) op.expectedVersion = options.expectedVersion\n if (options?.reason !== undefined) op.reason = options.reason\n this._ctx._ops.push(op)\n }\n\n /**\n * Stage a delete. Does not write until the transaction body returns.\n * Supply `{ expectedVersion }` to enforce optimistic concurrency\n * during the commit pre-flight.\n */\n delete(id: string, options?: { expectedVersion?: number }): void {\n const op: StagedOp = {\n type: 'delete',\n vaultName: this._vault.name,\n collectionName: this._name,\n id,\n }\n if (options?.expectedVersion !== undefined) op.expectedVersion = options.expectedVersion\n this._ctx._ops.push(op)\n }\n}\n\n/**\n * Commit plan: pre-flight check + execution + revert plan.\n *\n * @internal — driven by `withTransactions()` (via `tx/active.ts`) for\n * user-facing `db.transaction(...)` calls and by the `amendment` path\n * in `noydb.ts`. `Collection.putManyAtomic` runs its own Phase 2 loop\n * but shares the `_activeTxContext` mechanism (and the `revertExecuted`\n * helper) so nested side-effect derivation writes get registered for\n * revert alongside the bulk-put source ops.\n */\nexport async function runTransaction<T>(\n db: Noydb,\n fn: (tx: TxContext) => Promise<T> | T,\n options?: AmendmentTxOptions,\n txInvariants?: ReadonlyArray<TransactionInvariant>,\n): Promise<T> {\n // ─── Amendment-mode pre-flight ───────────────────────────────\n // `reason` is the only thing we can validate before the body runs;\n // the per-vault role check happens lazily on first `tx.vault(name)`\n // because we don't know which vaults the body will touch ahead of\n // time. Throwing here keeps the failure mode close to the call site\n // so the developer doesn't have to walk an async stack to find the\n // missing-reason mistake.\n if (options?.amendment) {\n if (typeof options.reason !== 'string' || options.reason.trim().length === 0) {\n throw new ValidationError(\n 'db.transaction({ amendment: true }) requires a non-empty `reason` string.',\n )\n }\n }\n\n const ctx = new TxContext(db, options?.amendment === true)\n const bodyResult = await fn(ctx)\n\n if (ctx._ops.length === 0) {\n // Body produced no ops. If amendment mode was active we still\n // need to close any opened windows so a subsequent (unrelated)\n // write doesn't surprise-collect into a stale change-set. Each\n // `beginAmendment` is matched by exactly one `consumeChanges`.\n if (ctx._amendment) {\n for (const v of ctx._amendmentVaults.values()) {\n // Registry is guaranteed non-null here — `tx.vault(name)`\n // threw above if it was null before adding to\n // `_amendmentVaults`.\n const reg = v._getGuardRegistry()\n if (reg !== null) {\n reg.consumeChanges()\n reg.consumeMeta()\n }\n }\n }\n return bodyResult\n }\n\n // Phase 1 — pre-flight: snapshot every touched envelope and enforce\n // any caller-supplied expectedVersion. Same (vault, coll, id) touched\n // more than once in one tx snapshots only the *initial* committed\n // state; the in-order replay in Phase 2 takes care of successor ops.\n const priorEnvelopes = new Map<string, EncryptedEnvelope | null>()\n const store = db._store\n\n // #1420 — before the first pre-flight read, wait out any plain\n // `Collection.put()`/`.delete()` already in flight on a key this commit is\n // about to touch. Without it the pre-flight's re-read cannot see a write\n // that has started but not yet reached the store, so the check passes\n // against a stale snapshot and one of the two writes vanishes with both\n // reporting success. Draining makes the in-flight case behave exactly like\n // the fully-awaited one, which the pre-flight below already handled\n // correctly. Deadlock-free by construction — see `kernel/tx-write-gate.ts`.\n await drainKeyedWrites(store, ctx._ops.map(keyOf))\n\n // Commit-time changeset invariants need PLAINTEXT prior records\n // for `before`, but `priorEnvelopes` holds ENCRYPTED envelopes. So for\n // ops in a watched scope we additionally decrypt the prior record here,\n // in Phase 1, BEFORE Phase 2 overwrites it. Snapshots only the initial\n // committed state per (vault, coll, id), matching the envelope snapshot.\n const invariants = txInvariants ?? []\n const watchedScopes = new Set(invariants.map(i => i.scope))\n const plainBefore = new Map<string, unknown>()\n\n for (const op of ctx._ops) {\n const key = keyOf(op)\n if (!priorEnvelopes.has(key)) {\n const env = await store.get(op.vaultName, op.collectionName, op.id)\n priorEnvelopes.set(key, env)\n }\n if (watchedScopes.has(op.collectionName) && !plainBefore.has(key)) {\n const prior = await db\n .vault(op.vaultName)\n .collection(op.collectionName)\n .get(op.id)\n plainBefore.set(key, prior ?? null)\n }\n if (op.expectedVersion !== undefined) {\n const env = priorEnvelopes.get(key) ?? null\n const actual = env?._v ?? 0\n if (actual !== op.expectedVersion) {\n throw new ConflictError(\n actual,\n `Transaction pre-flight: ${op.vaultName}/${op.collectionName}/${op.id} ` +\n `expected v${op.expectedVersion}, found v${actual}`,\n )\n }\n }\n }\n\n // Phase 2 — execute via the Collection layer so history snapshots,\n // ledger entries, and change events fire normally. We capture each\n // successful op so a mid-batch throw can revert in Phase 3.\n //\n // `_activeTxContext` is published on the Noydb instance for the\n // duration of Phase 2 so recursive writes triggered inside\n // `Collection.put` (today: eager derivation outputs) can register\n // their own envelopes onto `ctx._executed` and roll back alongside\n // the main staged ops. The `finally` clears it before the\n // amendment commit phase runs.\n db._setActiveTxContext(ctx)\n try {\n if (canCommitAtomically(db, ctx)) {\n // #906 — the whole batch goes to the store as ONE `tx()` write set.\n // Tracked here because the atomic path bypasses `Collection.put()`,\n // which is where an ordinary write enters the queue: without this,\n // `hub.writeQueue.pending` would read false for the entire commit.\n // One tracked unit, not one per op — the batch IS one logical write.\n await db._writeQueueTracker.track(() => commitAtomicBatch(db, ctx, priorEnvelopes))\n } else {\n const writtenKeys = new Set<string>()\n try {\n for (const op of ctx._ops) {\n const coll = db.vault(op.vaultName).collection(op.collectionName)\n const key = keyOf(op)\n const prior = priorEnvelopes.get(key) ?? null\n // #1420 — the per-op path replays through `Collection.put()`, which\n // carries no CAS: whatever the pre-flight decided stands unchecked\n // until the write lands. The atomic path re-validates by handing\n // every leg an `expectedVersion` to `store.tx()`; this is that check\n // for the path that has no store-level batch. Once THIS transaction\n // has written the key its version has legitimately moved, so a\n // second op on the same key is exempt — matching Phase 1, which\n // snapshots (and checks) only the first occurrence per key.\n if (op.expectedVersion !== undefined && !writtenKeys.has(key)) {\n const current = await store.get(op.vaultName, op.collectionName, op.id)\n const actual = current?._v ?? 0\n if (actual !== op.expectedVersion) {\n throw new ConflictError(\n actual,\n `Transaction execute: ${op.vaultName}/${op.collectionName}/${op.id} ` +\n `expected v${op.expectedVersion}, found v${actual}`,\n )\n }\n }\n // Record the revert plan BEFORE the call so a mid-`coll.put` throw\n // (e.g. strict-mode derivation failure firing after `store.put`\n // has already committed the envelope) still has its source write\n // reverted. `revertExecuted` is best-effort: putting prior back is\n // idempotent when the failing op never actually wrote, and\n // `_invalidateCacheEntry` is a no-op when the collection isn't\n // hydrated.\n ctx._executed.push({ op, priorEnvelope: prior })\n if (op.type === 'put') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await coll.put(op.id, op.record as any, op.reason !== undefined ? { reason: op.reason } : undefined)\n } else {\n await coll.delete(op.id)\n }\n writtenKeys.add(key)\n }\n } catch (err) {\n // Phase 3 — best-effort revert. See helper docstring.\n await revertExecuted(ctx._executed, store, db)\n // Drain amendment windows so the next transaction starts clean.\n if (ctx._amendment) {\n for (const v of ctx._amendmentVaults.values()) {\n const reg = v._getGuardRegistry()\n if (reg !== null) {\n reg.consumeChanges()\n reg.consumeMeta()\n }\n }\n }\n throw err\n }\n }\n } finally {\n db._clearActiveTxContext(ctx)\n }\n\n // ─── Amendment commit phase (only if amendment === true) ────\n // Body succeeded — now run each touched vault's invariants over the\n // collected change-set, then append a structured ledger entry. If\n // any invariant throws, treat it exactly like a mid-Phase-2 failure:\n // revert every executed op and re-throw the InvariantError.\n if (ctx._amendment) {\n // Lazy-load GuardExecutor at the dispatch site — keeps the floor\n // bundle free of the guards service when amendments aren't used.\n // Mirrors the deferred-load pattern from elsewhere in this module.\n const { GuardExecutor } = (await import('../../with-audit/guards/executor.js')) as {\n GuardExecutor: typeof GuardExecutorModule\n }\n try {\n for (const [vaultName, v] of ctx._amendmentVaults) {\n const registry = v._getGuardRegistry()\n // Registry is guaranteed non-null at this point — the\n // `tx.vault(name)` path that populates `_amendmentVaults`\n // throws if the registry is null. The defensive check here\n // is for TypeScript's narrowing.\n if (registry === null) continue\n const changesByCollection = registry.consumeChanges()\n const meta = registry.consumeMeta()\n if (changesByCollection.size === 0) continue\n\n const readOnlyVault = v._getReadOnlyFacade()\n if (readOnlyVault === null) continue\n\n // Build the invariant ctx once per vault — it's the same shape\n // every guard sees on the normal `check` path, just with a\n // synthetic `existing: null` (invariants get the full change\n // set in their first parameter; `existing` is a per-record\n // concept that doesn't apply here).\n const invariantsPassed: string[] = []\n for (const [collection, changes] of changesByCollection) {\n const guards = registry.guardsFor(collection).filter(g => g.amendment !== undefined)\n for (const guard of guards) {\n await GuardExecutor.runInvariant(guard, changes, {\n existing: null,\n vault: readOnlyVault,\n userId: v.userId,\n role: v.role,\n })\n }\n if (guards.length > 0) invariantsPassed.push(collection)\n }\n\n // Append the audit ledger entry. Silent no-op when the\n // history strategy isn't configured — the records still\n // committed, only the multi-record summary is unavailable.\n const ledger = v._getLedgerOrNull()\n if (ledger) {\n const role = v.role as 'admin' | 'owner'\n const amendment: NonNullable<LedgerEntry['amendment']> = {\n reason: options!.reason,\n role,\n changes: meta,\n invariantsPassed,\n }\n await ledger.append({\n op: 'amendment',\n collection: '',\n id: '',\n version: 0,\n actor: v.userId,\n // No payload to hash — the per-record entries already\n // captured `payloadHash` at their own append time. We use\n // a sha256 of the canonical reason string so the field is\n // populated with something deterministic and non-empty.\n payloadHash: '',\n amendment,\n })\n }\n void vaultName\n }\n } catch (err) {\n await revertExecuted(ctx._executed, store, db)\n throw err instanceof InvariantError ? err : new InvariantError(\n err instanceof Error ? err.message : `invariant violated: ${String(err)}`,\n )\n }\n }\n\n // ─── Commit-time changeset invariant phase ───────────\n // Runs for BOTH ordinary and amendment transactions (placed after the\n // amendment phase so an amendment commit is still subject to these\n // set-level constraints). Assemble the changeset from the executed\n // staged ops, deduped to the LAST write per (vault, coll, id) while\n // preserving write order, then group `GuardChange` by collection\n // (scope) and run each matching invariant. A throw mirrors the\n // amendment-phase failure mode exactly: revert every executed op and\n // re-throw as `InvariantError`.\n if (invariants.length > 0) {\n // Dedup ctx._ops to the last write per key, preserving first-seen\n // (write) order so the changeset is stable and order-meaningful.\n const lastOp = new Map<string, StagedOp>()\n const order: string[] = []\n for (const op of ctx._ops) {\n const key = keyOf(op)\n if (!lastOp.has(key)) order.push(key)\n lastOp.set(key, op)\n }\n\n // Group {before, after} pairs by collection name (the invariant\n // scope). `before` is the plaintext prior captured in Phase 1 (null\n // for inserts / unwatched — only watched scopes were captured, and\n // every grouped key belongs to a watched scope). `after` is the\n // written record, null for a delete.\n const changesByScope = new Map<string, GuardChange<unknown>[]>()\n // Parallel map: scope → the vault name of its (last-seen) op, used to\n // build the per-invariant read-only ctx (facade + userId + role).\n const scopeVault = new Map<string, string>()\n for (const key of order) {\n const op = lastOp.get(key)!\n if (!watchedScopes.has(op.collectionName)) continue\n const before = plainBefore.get(key) ?? null\n const after = op.type === 'delete' ? null : (op.record ?? null)\n const change = { before, after } as GuardChange<unknown>\n const arr = changesByScope.get(op.collectionName)\n if (arr) arr.push(change)\n else changesByScope.set(op.collectionName, [change])\n\n // Stash the vault name alongside so we can build a per-vault ctx.\n // (All ops in a scope group could span vaults; we resolve the\n // vault per change below via a parallel map keyed the same way.)\n scopeVault.set(op.collectionName, op.vaultName)\n }\n\n try {\n for (const inv of invariants) {\n const changes = changesByScope.get(inv.scope)\n if (changes === undefined || changes.length === 0) continue\n const vaultName = scopeVault.get(inv.scope)!\n const v = db.vault(vaultName)\n // Prefer the real read-only facade so the invariant can read\n // sibling collections; fall back to a minimal read-only stub.\n const facade: ReadOnlyVaultFacade =\n v._getReadOnlyFacade() ?? {\n collection<R = unknown>(name: string) {\n const c = v.collection<R>(name)\n return {\n get: (id: string) => c.get(id),\n list: () => c.list(),\n query: () => c.query(),\n }\n },\n }\n const ctxForInv: GuardContext<unknown> = {\n existing: null,\n vault: facade,\n userId: v.userId,\n role: v.role,\n }\n await inv.check(changes, ctxForInv)\n }\n } catch (err) {\n await revertExecuted(ctx._executed, store, db)\n throw err instanceof InvariantError ? err : new InvariantError(\n err instanceof Error ? err.message : `invariant violated: ${String(err)}`,\n )\n }\n }\n\n return bodyResult\n}\n\n/**\n * One prepared leg of an atomic batch: the `store.tx()` op to submit plus the\n * carrier its finalize half needs.\n * @internal\n */\ninterface AtomicLeg {\n readonly op: StagedOp\n readonly coll: Collection<unknown>\n readonly txOp: TxOp\n readonly prepared: PreparedPut<unknown> | PreparedDelete<unknown>\n}\n\n/**\n * #906 — the atomic commit path: prepare every staged op, submit the whole\n * write set as ONE `store.tx()` call, then finalize each op in staged order.\n *\n * Only ever reached through `canCommitAtomically` (`atomic-eligibility.ts`),\n * whose exclusions are what make this safe — no CRDT, no refs, no\n * derivation/MV source, no unique constraints, no amendment, no id touched\n * twice. Do not call it without that blessing.\n *\n * @internal\n */\nasync function commitAtomicBatch(\n db: Noydb,\n ctx: TxContext,\n priorEnvelopes: ReadonlyMap<string, EncryptedEnvelope | null>,\n): Promise<void> {\n const store = db._store\n const legs: AtomicLeg[] = []\n\n // ─── Prepare ───────────────────────────────────────────────────\n // Encrypt, resolve the prior version, mint the #589 marker — with zero\n // observable side effects on the collections the gate admits. A throw here\n // therefore needs no unwind: nothing has been written yet, and the caller\n // sees the refusal exactly as it would from `Collection.put()`. The revert\n // plan is recorded all the same, because a FINALIZE failure below does need\n // it (same record-before-the-call convention as the OCC loop).\n for (const op of ctx._ops) {\n const coll = db.vault(op.vaultName).collection(op.collectionName)\n // The two refusals `Collection.put()` / `.delete()` assert before anything\n // else — schema-update gate + schema fence. They live in those wrappers,\n // not in the prepare halves this path calls, so assert them here, per op.\n await coll._assertWriteGates()\n const prior = priorEnvelopes.get(keyOf(op)) ?? null\n // Every leg carries CAS against the Phase-1 snapshot, so a writer landing\n // between the body returning and the batch reaching the store loses.\n const base = { vault: op.vaultName, collection: op.collectionName, id: op.id, expectedVersion: prior?._v ?? 0 }\n ctx._executed.push({ op, priorEnvelope: prior })\n if (op.type === 'put') {\n const prepared = await coll._preparePut(op.id, op.record, op.reason !== undefined ? { reason: op.reason } : undefined)\n legs.push({ op, coll, prepared, txOp: { type: 'put', ...base, envelope: prepared.envelope } })\n } else {\n const prepared = await coll._prepareDelete(op.id, false)\n if (prepared === null) {\n // Nothing to delete (no live record / already a marker / shredded) —\n // the case `_doDelete` answers with `false`. Drop the op and its\n // revert entry rather than sending a leg for it.\n ctx._executed.pop()\n continue\n }\n legs.push({\n op, coll, prepared,\n // Under sync the delete is a marker PUT at `live._v + 1` (#589);\n // without sync it is a physical removal.\n txOp: prepared.marker ? { type: 'put', ...base, envelope: prepared.marker } : { type: 'delete', ...base },\n })\n }\n }\n\n // Every op turned out to be a no-op delete — same as the OCC loop, which\n // would have written nothing either. Don't hand the store an empty batch.\n if (legs.length === 0) return\n\n // ─── The batch ─────────────────────────────────────────────────\n // Deliberately NOT inside a revert-guarded try: a rejection means the store\n // applied nothing (all-or-nothing is the capability we gated on), so there\n // is nothing to unwind and a revert pass would write over records this\n // transaction never touched. No ledger entry, history snapshot or change\n // event has fired either — every one of those lives in finalize below. The\n // error (a `ConflictError` when a leg lost its CAS) surfaces unwrapped.\n await store.tx!(legs.map(l => l.txOp))\n\n // ─── Finalize ──────────────────────────────────────────────────\n // History snapshot, ledger entry, cache/index update, change event — per op,\n // in staged order, all AFTER the bytes are durable (where the OCC loop\n // interleaves them per op). #931: then the after-write observers (user\n // `onAfterWrite` hooks + the `afterPut`/`afterDelete` observe bus), which\n // no longer gate eligibility — they cannot refuse a completed write.\n try {\n for (const leg of legs) {\n if (leg.op.type === 'put') await leg.coll._finalizePut(leg.prepared as PreparedPut<unknown>)\n else await leg.coll._finalizeDelete(leg.prepared as PreparedDelete<unknown>)\n await leg.coll._fireAtomicAfterWrite(leg.op.type, leg.prepared)\n }\n } catch (err) {\n // The bytes ARE durable now, so this is today's best-effort unwind over\n // the plan recorded above. No amendment window to drain — the gate\n // excludes amendment transactions.\n await revertExecuted(ctx._executed, store, db)\n throw err\n }\n}\n\n/**\n * Phase 3 helper — restore captured prior envelopes via the raw store\n * to avoid re-firing Collection-level side effects (we don't want a\n * cascade of change events undoing themselves). The ledger is left\n * as-is: each committed op appended an entry; the revert is\n * deliberately NOT recorded as a compensating entry because the\n * caller-facing contract is \"atomic or not at all,\" not \"every write\n * visible in the audit trail.\" Auditors who need the intermediate\n * state can still reconstruct it by walking the ledger through the\n * failed-tx timestamp.\n *\n * Delegates the reverse/best-effort/raw-revert shape to the shared\n * `bestEffortRevert` helper (`kernel/best-effort-revert.ts`); the cache\n * invalidation below rides along as that helper's per-leg `compensate`\n * callback, gated on `db` exactly as before.\n *\n * @internal — shared between `runTransaction` and\n * `Collection.putManyAtomic`. Both register source ops + nested\n * derivation side-effect ops onto `_executed`; this helper unwinds the\n * combined list in reverse on rollback.\n */\nasync function revertExecuted(\n executed: ReadonlyArray<ExecutedOp>,\n store: Noydb['_store'],\n db?: Noydb,\n): Promise<void> {\n const legs = executed.map(({ op, priorEnvelope }) => ({\n vaultName: op.vaultName,\n collectionName: op.collectionName,\n id: op.id,\n prior: priorEnvelope,\n }))\n await bestEffortRevert(\n legs,\n store,\n db\n ? async (leg) => {\n // Sync the Collection-layer cache with what we just wrote at\n // the raw store. Without this, eager-mode `get` would still\n // return the rolled-back record from its in-memory map. The\n // Collection's `_invalidateCacheEntry` is a no-op when the\n // collection hasn't yet been hydrated.\n const coll = db.vault(leg.vaultName).collection(leg.collectionName)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await (coll as any)._invalidateCacheEntry(leg.id)\n }\n : undefined,\n )\n}\n\n/** @internal — shared (vault, collection, id) key shape; also used by `atomic-eligibility.ts`'s duplicate-key scan. */\nexport function keyOf(op: StagedOp): string {\n return `${op.vaultName}\\x00${op.collectionName}\\x00${op.id}`\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  bufferToBase64
3
- } from "./chunk-QMWY2FDS.js";
3
+ } from "./chunk-PUBI455O.js";
4
4
 
5
5
  // src/capsule/enclave-aes/classify/digest.ts
6
6
  var subtle = globalThis.crypto.subtle;
@@ -75,4 +75,4 @@ export {
75
75
  mintAt,
76
76
  mintBidxTag
77
77
  };
78
- //# sourceMappingURL=chunk-EZOAKKTB.js.map
78
+ //# sourceMappingURL=chunk-ABU6A4Z5.js.map
@@ -3,10 +3,10 @@ import {
3
3
  } from "./chunk-5D2ALSM5.js";
4
4
  import {
5
5
  RecordCodec
6
- } from "./chunk-EZGV6F47.js";
6
+ } from "./chunk-4J3MNVVX.js";
7
7
 
8
8
  // src/with-formula/materialized-views/stale.ts
9
- var loadMVExecutor = lazy(() => import("./executor-FMPVN6DT.js"));
9
+ var loadMVExecutor = lazy(() => import("./executor-NJX3YQQ4.js"));
10
10
  var _staleByRegistry = /* @__PURE__ */ new WeakMap();
11
11
  function markMVStale(registry, mvName) {
12
12
  let set = _staleByRegistry.get(registry);
@@ -134,4 +134,4 @@ export {
134
134
  clearMVStale,
135
135
  clearMVStaleFully
136
136
  };
137
- //# sourceMappingURL=chunk-VKI2EB3N.js.map
137
+ //# sourceMappingURL=chunk-AJFPAHMW.js.map
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  loadVaultPolicy
3
- } from "./chunk-VHBKYN2J.js";
3
+ } from "./chunk-DL6BZKP3.js";
4
4
  import {
5
+ BROKER_MEMBER_COLLECTION,
5
6
  assertRosterAuthenticated,
6
7
  assertRosterTagValid,
7
8
  assertStrongEchoSecret,
@@ -10,15 +11,15 @@ import {
10
11
  deriveKekForKeyring,
11
12
  mintKeyringCanary,
12
13
  mintRosterTag,
13
- nextRosterEpoch,
14
14
  persistKeyring,
15
15
  readKeyringFile,
16
16
  requireRosterKey,
17
- rotateKeys
18
- } from "./chunk-XSPFDUDG.js";
17
+ rotateKeys,
18
+ stampAuthority
19
+ } from "./chunk-45VHWE4C.js";
19
20
  import {
20
21
  dekKey
21
- } from "./chunk-FLPCETP6.js";
22
+ } from "./chunk-RIZTZJX6.js";
22
23
  import {
23
24
  base64ToBuffer,
24
25
  bufferToBase64,
@@ -31,6 +32,7 @@ import {
31
32
  encrypt,
32
33
  encryptBytes,
33
34
  exportDekSet,
35
+ generateDEK,
34
36
  generateRecoverySecret,
35
37
  generateSalt,
36
38
  hkdfAesGcmKey,
@@ -39,10 +41,10 @@ import {
39
41
  sha256Bytes,
40
42
  unwrapKey,
41
43
  wrapKey
42
- } from "./chunk-EZGV6F47.js";
44
+ } from "./chunk-4J3MNVVX.js";
43
45
  import {
44
46
  NOYDB_KEYRING_VERSION
45
- } from "./chunk-SV2PM2OY.js";
47
+ } from "./chunk-2ELOCEXE.js";
46
48
  import {
47
49
  BLOB_ADDRESS_KEY_ID,
48
50
  DelegationTargetMissingError,
@@ -55,7 +57,7 @@ import {
55
57
  TamperedError,
56
58
  TeamNotEnabledError,
57
59
  ValidationError
58
- } from "./chunk-37EPTBBR.js";
60
+ } from "./chunk-VSUQI5Q6.js";
59
61
 
60
62
  // src/port/with/team-strategy.ts
61
63
  var NO_TEAM = {
@@ -222,11 +224,17 @@ async function deriveMagicLinkContentKey(serverSecret, token, vault) {
222
224
  }
223
225
  async function writeMagicLinkGrant(store, vault, grantor, contentKey, grantKek, recordId, opts) {
224
226
  const collectionName = opts.collection ?? null;
225
- const sourceKey = collectionName ? dekKey(collectionName, opts.tier) : `__any#${opts.tier}`;
226
- const sourceDek = grantor.deks.get(sourceKey);
227
+ if (!collectionName) {
228
+ throw new DelegationTargetMissingError(
229
+ opts.toUser,
230
+ `writeMagicLinkGrant({ collection: undefined }) \u2014 a magic-link grant carries a single wrapped DEK and cannot express "every collection", because each collection has its own tier-${opts.tier} DEK. Pass an explicit \`collection\`, or use a collection-wide delegation token (core#56).`
231
+ );
232
+ }
233
+ const sourceDek = grantor.deks.get(dekKey(collectionName, opts.tier));
227
234
  if (!sourceDek) {
228
235
  throw new DelegationTargetMissingError(
229
- `grantor cannot find tier ${opts.tier} DEK for ${collectionName ?? "(any)"}`
236
+ opts.toUser,
237
+ `grantor holds no tier-${opts.tier} DEK for collection "${collectionName}", so there is nothing to grant. Obtain the tier grant first.`
230
238
  );
231
239
  }
232
240
  const wrappedDek = await wrapKey(sourceDek, grantKek);
@@ -395,7 +403,7 @@ async function rotateSecret(store, vault, userId, input) {
395
403
  canary,
396
404
  ...await echoFieldForNewSecret(input.newSecret, input.echoOptions)
397
405
  };
398
- const withEpoch = { ...rebuilt, roster_epoch: nextRosterEpoch(found?.file.roster_epoch) };
406
+ const withEpoch = stampAuthority(rebuilt, found?.file.roster_epoch);
399
407
  const next = {
400
408
  ...withEpoch,
401
409
  roster_tag: await mintRosterTag(withEpoch, requireRecoveredRosterKey(deks))
@@ -479,7 +487,7 @@ async function recoverViaPaperCode(store, vault, userId, input) {
479
487
  canary,
480
488
  ...await echoFieldForNewSecret(input.newSecret)
481
489
  };
482
- const withEpoch = { ...rebuilt, roster_epoch: nextRosterEpoch(found?.file.roster_epoch) };
490
+ const withEpoch = stampAuthority(rebuilt, found?.file.roster_epoch);
483
491
  const next = {
484
492
  ...withEpoch,
485
493
  roster_tag: await mintRosterTag(withEpoch, requireRecoveredRosterKey(deks))
@@ -579,7 +587,7 @@ async function recoverViaShamir(provider, store, vault, userId, input) {
579
587
  canary,
580
588
  ...await echoFieldForNewSecret(input.newSecret)
581
589
  };
582
- const withEpoch = { ...rebuilt, roster_epoch: nextRosterEpoch(file.roster_epoch) };
590
+ const withEpoch = stampAuthority(rebuilt, file.roster_epoch);
583
591
  const next = {
584
592
  ...withEpoch,
585
593
  roster_tag: await mintRosterTag(withEpoch, requireRecoveredRosterKey(recoveredDeks))
@@ -649,6 +657,7 @@ async function recoverUser(store, vault, callerKeyring, options) {
649
657
  );
650
658
  }
651
659
  for (const coll of Object.keys(target.deks)) {
660
+ if (coll === BROKER_MEMBER_COLLECTION) continue;
652
661
  if (!callerKeyring.deks.has(coll)) {
653
662
  throw new PrivilegeEscalationError(coll);
654
663
  }
@@ -659,7 +668,11 @@ async function recoverUser(store, vault, callerKeyring, options) {
659
668
  const newSalt = generateSalt();
660
669
  const newKek = await deriveKey(options.secret, newSalt);
661
670
  const wrappedDeks = {};
671
+ if (targetRole !== "owner" && targetRole !== "admin") {
672
+ wrappedDeks[BROKER_MEMBER_COLLECTION] = await wrapKey(await generateDEK(), newKek);
673
+ }
662
674
  for (const coll of Object.keys(target.deks)) {
675
+ if (coll === BROKER_MEMBER_COLLECTION) continue;
663
676
  const callerDek = callerKeyring.deks.get(coll);
664
677
  if (!callerDek) {
665
678
  throw new PrivilegeEscalationError(coll);
@@ -679,7 +692,7 @@ async function recoverUser(store, vault, callerKeyring, options) {
679
692
  authenticators: [],
680
693
  canary
681
694
  };
682
- const withEpoch = { ...edited, roster_epoch: nextRosterEpoch(target.roster_epoch) };
695
+ const withEpoch = stampAuthority(edited, target.roster_epoch);
683
696
  const next = {
684
697
  ...withEpoch,
685
698
  roster_tag: await mintRosterTag(withEpoch, rosterKey)
@@ -955,4 +968,4 @@ export {
955
968
  findAuthenticator,
956
969
  revokeAuthenticator
957
970
  };
958
- //# sourceMappingURL=chunk-DQESF6RP.js.map
971
+ //# sourceMappingURL=chunk-APFFJN5T.js.map