@noy-db/hub 0.7.1-pre.0 → 0.8.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 (812) hide show
  1. package/CHANGELOG.md +147 -14
  2. package/LICENSE +202 -21
  3. package/NOTICE +1 -0
  4. package/README.md +5 -5
  5. package/codemods/0.8.0-pre.json +61 -0
  6. package/dist/api-OS747DS4.js +18 -0
  7. package/dist/as/index.js +11 -12
  8. package/dist/as/index.js.map +1 -1
  9. package/dist/at/index.js +9 -10
  10. package/dist/attestation/index.js +37 -26
  11. package/dist/attestation/index.js.map +1 -1
  12. package/dist/{backup-XKCXVKV3.js → backup-YE2VQ26S.js} +15 -16
  13. package/dist/backup-YE2VQ26S.js.map +1 -0
  14. package/dist/blobs/index.js +13 -14
  15. package/dist/blobs/index.js.map +1 -1
  16. package/dist/broker/index.js +12 -13
  17. package/dist/broker/index.js.map +1 -1
  18. package/dist/by/index.js +2 -2
  19. package/dist/capsule/contract.d.ts +159 -0
  20. package/dist/capsule/contract.js +95 -0
  21. package/dist/capsule/enclave-aes/bound.d.ts +52 -0
  22. package/dist/capsule/enclave-aes/capabilities.d.ts +2 -0
  23. package/dist/capsule/enclave-aes/classify/compare.d.ts +20 -0
  24. package/dist/{kernel/enclave → capsule/enclave-aes}/classify/find.d.ts +1 -1
  25. package/dist/{kernel/enclave → capsule/enclave-aes}/classify/reveal.d.ts +1 -1
  26. package/dist/{kernel/enclave → capsule/enclave-aes}/classify/verify.d.ts +2 -2
  27. package/dist/{kernel/enclave → capsule/enclave-aes}/classify/write.d.ts +1 -1
  28. package/dist/{kernel/enclave → capsule/enclave-aes}/crypto.d.ts +33 -129
  29. package/dist/capsule/enclave-aes/index.d.ts +113 -0
  30. package/dist/capsule/enclave-aes/index.js +335 -0
  31. package/dist/capsule/enclave-aes/index.js.map +1 -0
  32. package/dist/capsule/enclave-aes/primitives.d.ts +29 -0
  33. package/dist/capsule/index.d.ts +27 -0
  34. package/dist/capsule/plumbing/ct-equal.d.ts +11 -0
  35. package/dist/{kernel/enclave/record-keys → capsule/plumbing}/deterministic.d.ts +8 -21
  36. package/dist/capsule/plumbing/digest.d.ts +122 -0
  37. package/dist/{kernel/enclave/record-keys → capsule/plumbing}/envelope-body.d.ts +44 -48
  38. package/dist/capsule/plumbing/index.d.ts +100 -0
  39. package/dist/capsule/plumbing/lifecycle.d.ts +50 -0
  40. package/dist/{kernel/enclave/record-keys → capsule/plumbing}/record-codec.d.ts +80 -20
  41. package/dist/{kernel/enclave → capsule/plumbing}/record-envelope.d.ts +1 -1
  42. package/dist/capsule/plumbing/rekey-blob.d.ts +33 -0
  43. package/dist/capsule/plumbing/rekey.d.ts +44 -0
  44. package/dist/capsule/plumbing/sealed-slot.d.ts +22 -0
  45. package/dist/capsule/plumbing/sealed-slots.d.ts +37 -0
  46. package/dist/capsule/plumbing/sealing.d.ts +29 -0
  47. package/dist/capsule/plumbing/sign.d.ts +9 -0
  48. package/dist/{kernel/enclave/record-keys → capsule/plumbing}/tombstone.d.ts +2 -2
  49. package/dist/capsule-VOLX3QRQ.js +209 -0
  50. package/dist/cargo/index.js +39 -36
  51. package/dist/{chunk-Q2MPFCQ7.js → chunk-23D6M6VM.js} +5 -5
  52. package/dist/chunk-23D6M6VM.js.map +1 -0
  53. package/dist/{chunk-R7BX2NB3.js → chunk-244QBK7Z.js} +4 -4
  54. package/dist/chunk-244QBK7Z.js.map +1 -0
  55. package/dist/chunk-2AFX33YA.js +936 -0
  56. package/dist/chunk-2AFX33YA.js.map +1 -0
  57. package/dist/{chunk-MVMXZYXT.js → chunk-2GHDLTPE.js} +2 -2
  58. package/dist/{chunk-GYGLAVCX.js → chunk-2MG3SW7Q.js} +6 -2
  59. package/dist/chunk-2MG3SW7Q.js.map +1 -0
  60. package/dist/{chunk-XLMEZIAJ.js → chunk-2ODVB6LZ.js} +2 -2
  61. package/dist/{chunk-HJUWN7JN.js → chunk-2PVXF5CS.js} +33 -8
  62. package/dist/chunk-2PVXF5CS.js.map +1 -0
  63. package/dist/{chunk-YJRT5UQM.js → chunk-2RH777HH.js} +21 -20
  64. package/dist/{chunk-YJRT5UQM.js.map → chunk-2RH777HH.js.map} +1 -1
  65. package/dist/{chunk-7O3Y4PPD.js → chunk-37EPTBBR.js} +153 -16
  66. package/dist/chunk-37EPTBBR.js.map +1 -0
  67. package/dist/{chunk-2ENE6445.js → chunk-3A5DUZ56.js} +102 -16
  68. package/dist/chunk-3A5DUZ56.js.map +1 -0
  69. package/dist/chunk-3EWS67C7.js +461 -0
  70. package/dist/chunk-3EWS67C7.js.map +1 -0
  71. package/dist/{chunk-SGZAIJCV.js → chunk-3L2NBKDR.js} +4 -8
  72. package/dist/chunk-3L2NBKDR.js.map +1 -0
  73. package/dist/{chunk-YMUFFJCO.js → chunk-3TDUWVWB.js} +5 -2
  74. package/dist/chunk-3TDUWVWB.js.map +1 -0
  75. package/dist/{chunk-4GVM6QZA.js → chunk-3XJQBBZD.js} +26 -28
  76. package/dist/chunk-3XJQBBZD.js.map +1 -0
  77. package/dist/{chunk-4ZS56W5S.js → chunk-42ALPZ2B.js} +672 -664
  78. package/dist/chunk-42ALPZ2B.js.map +1 -0
  79. package/dist/chunk-4CIQDWRB.js +524 -0
  80. package/dist/chunk-4CIQDWRB.js.map +1 -0
  81. package/dist/{chunk-RMS3NEA3.js → chunk-4JPMZTJY.js} +2 -2
  82. package/dist/{chunk-P3MG6QCN.js → chunk-4T3SE27M.js} +5 -9
  83. package/dist/chunk-4T3SE27M.js.map +1 -0
  84. package/dist/chunk-4V3Q35WG.js +204 -0
  85. package/dist/chunk-4V3Q35WG.js.map +1 -0
  86. package/dist/{chunk-NQKIUNW5.js → chunk-52MGURXO.js} +2 -2
  87. package/dist/{chunk-EQEYOJBM.js → chunk-5A4345TG.js} +4 -4
  88. package/dist/chunk-5A4345TG.js.map +1 -0
  89. package/dist/{chunk-334WSVOW.js → chunk-5FE75J4S.js} +6 -6
  90. package/dist/chunk-5FE75J4S.js.map +1 -0
  91. package/dist/chunk-5KC7QYEC.js +565 -0
  92. package/dist/chunk-5KC7QYEC.js.map +1 -0
  93. package/dist/{chunk-RSGLUIO6.js → chunk-5UMK7GRI.js} +13 -12
  94. package/dist/chunk-5UMK7GRI.js.map +1 -0
  95. package/dist/chunk-5WWDGFOS.js +275 -0
  96. package/dist/chunk-5WWDGFOS.js.map +1 -0
  97. package/dist/{chunk-QPQUVOZ2.js → chunk-6QVKPHBF.js} +3 -5
  98. package/dist/chunk-6QVKPHBF.js.map +1 -0
  99. package/dist/{chunk-ACAQ2DSG.js → chunk-747G6CT3.js} +2 -2
  100. package/dist/chunk-747G6CT3.js.map +1 -0
  101. package/dist/{chunk-QTQUH4DS.js → chunk-7R2Q7CPL.js} +16 -16
  102. package/dist/chunk-7R2Q7CPL.js.map +1 -0
  103. package/dist/{chunk-UGTBXF5U.js → chunk-7XMHMVTS.js} +3 -3
  104. package/dist/{chunk-YJX7EOJD.js → chunk-A4XMIZT3.js} +6 -6
  105. package/dist/{chunk-YJX7EOJD.js.map → chunk-A4XMIZT3.js.map} +1 -1
  106. package/dist/{chunk-A66I4JOA.js → chunk-AEQGFRU4.js} +4 -4
  107. package/dist/chunk-AEQGFRU4.js.map +1 -0
  108. package/dist/chunk-AL6ML4LA.js +1558 -0
  109. package/dist/chunk-AL6ML4LA.js.map +1 -0
  110. package/dist/{chunk-BZ3534YM.js → chunk-AUKKUPVB.js} +2 -2
  111. package/dist/{chunk-CUZLNGD5.js → chunk-B2YY6WDD.js} +1 -1
  112. package/dist/chunk-B2YY6WDD.js.map +1 -0
  113. package/dist/chunk-BKT776R5.js +1 -0
  114. package/dist/chunk-BNWA3WG5.js +22 -0
  115. package/dist/chunk-BNWA3WG5.js.map +1 -0
  116. package/dist/{chunk-VXANTWBJ.js → chunk-BPWYQ25R.js} +92 -6
  117. package/dist/{chunk-VXANTWBJ.js.map → chunk-BPWYQ25R.js.map} +1 -1
  118. package/dist/{chunk-6LKOJBV6.js → chunk-BVCUTXE3.js} +2 -2
  119. package/dist/chunk-CY2CYVWZ.js +41 -0
  120. package/dist/chunk-CY2CYVWZ.js.map +1 -0
  121. package/dist/{chunk-M4YPHYEH.js → chunk-DHHGL42E.js} +70 -25
  122. package/dist/chunk-DHHGL42E.js.map +1 -0
  123. package/dist/{chunk-VTFVLCUH.js → chunk-DIZLQVAA.js} +2 -2
  124. package/dist/{chunk-G73UVHCA.js → chunk-DLD5LGDS.js} +11 -12
  125. package/dist/chunk-DLD5LGDS.js.map +1 -0
  126. package/dist/{chunk-WQBG4SZS.js → chunk-DQESF6RP.js} +60 -49
  127. package/dist/chunk-DQESF6RP.js.map +1 -0
  128. package/dist/{chunk-LWBCUYZW.js → chunk-E2N2T5ZO.js} +2 -2
  129. package/dist/{chunk-3PGS7TYR.js → chunk-EGVJ7TM4.js} +29 -32
  130. package/dist/chunk-EGVJ7TM4.js.map +1 -0
  131. package/dist/{chunk-JVIBCBC7.js → chunk-EJLV62NI.js} +2 -2
  132. package/dist/{chunk-KKEESNPE.js → chunk-EYG2CY2X.js} +126 -19
  133. package/dist/chunk-EYG2CY2X.js.map +1 -0
  134. package/dist/{enclave-55PAM4YO.js → chunk-EZGV6F47.js} +83 -56
  135. package/dist/chunk-EZGV6F47.js.map +1 -0
  136. package/dist/{chunk-CHQCZZWC.js → chunk-EZOAKKTB.js} +36 -27
  137. package/dist/chunk-EZOAKKTB.js.map +1 -0
  138. package/dist/chunk-F6NCB7KT.js +13 -0
  139. package/dist/chunk-F6NCB7KT.js.map +1 -0
  140. package/dist/chunk-FFJFE4T7.js +100 -0
  141. package/dist/chunk-FFJFE4T7.js.map +1 -0
  142. package/dist/{chunk-JMGDHKQF.js → chunk-FLPCETP6.js} +2 -2
  143. package/dist/chunk-FOEDQATO.js +53 -0
  144. package/dist/chunk-FOEDQATO.js.map +1 -0
  145. package/dist/{chunk-DGOZ4UZD.js → chunk-FVH5QYY2.js} +2 -2
  146. package/dist/{chunk-HIWCKBEY.js → chunk-G2MVBDFP.js} +54 -28
  147. package/dist/chunk-G2MVBDFP.js.map +1 -0
  148. package/dist/chunk-GMKGGY7V.js +234 -0
  149. package/dist/chunk-GMKGGY7V.js.map +1 -0
  150. package/dist/{chunk-EIPVYUEP.js → chunk-GQ4MF3CM.js} +3 -3
  151. package/dist/chunk-GQ4MF3CM.js.map +1 -0
  152. package/dist/{chunk-PEOZ34EM.js → chunk-GSAK56VF.js} +1 -1
  153. package/dist/chunk-GSAK56VF.js.map +1 -0
  154. package/dist/{chunk-5VCRVKOZ.js → chunk-GUZET4SG.js} +12 -4
  155. package/dist/chunk-GUZET4SG.js.map +1 -0
  156. package/dist/{chunk-JBDFMYKQ.js → chunk-GZT3NQRA.js} +2 -2
  157. package/dist/{chunk-K23VKTN4.js → chunk-H23XHRTT.js} +19 -34
  158. package/dist/chunk-H23XHRTT.js.map +1 -0
  159. package/dist/{chunk-TFR7DSOV.js → chunk-H427H63K.js} +2 -2
  160. package/dist/{chunk-DFMWUOU5.js → chunk-H7JBY4P7.js} +23 -32
  161. package/dist/chunk-H7JBY4P7.js.map +1 -0
  162. package/dist/{chunk-SKGMN35F.js → chunk-HS554XAF.js} +3 -3
  163. package/dist/chunk-HS554XAF.js.map +1 -0
  164. package/dist/{chunk-HK67PX4J.js → chunk-HW7CMKUG.js} +1 -1
  165. package/dist/chunk-HW7CMKUG.js.map +1 -0
  166. package/dist/{chunk-3BVH633C.js → chunk-IMQKWR46.js} +5 -7
  167. package/dist/chunk-IMQKWR46.js.map +1 -0
  168. package/dist/{chunk-R42NSZI6.js → chunk-IUBMZPHM.js} +7 -7
  169. package/dist/chunk-IUBMZPHM.js.map +1 -0
  170. package/dist/{chunk-CUQPWYRX.js → chunk-IUT3GWP3.js} +75 -386
  171. package/dist/chunk-IUT3GWP3.js.map +1 -0
  172. package/dist/{chunk-RF6D3Y5E.js → chunk-JDEYF3PJ.js} +4 -8
  173. package/dist/{chunk-RF6D3Y5E.js.map → chunk-JDEYF3PJ.js.map} +1 -1
  174. package/dist/{chunk-PPTHY5QO.js → chunk-JIBUPZHA.js} +99 -8
  175. package/dist/chunk-JIBUPZHA.js.map +1 -0
  176. package/dist/{chunk-SMH6SRX7.js → chunk-JOSPH3E5.js} +2 -2
  177. package/dist/chunk-JQYKPKG6.js +193 -0
  178. package/dist/chunk-JQYKPKG6.js.map +1 -0
  179. package/dist/{chunk-7APJ6CO6.js → chunk-JSMTXZR3.js} +45 -13
  180. package/dist/chunk-JSMTXZR3.js.map +1 -0
  181. package/dist/chunk-JWWYRR4Q.js +12 -0
  182. package/dist/chunk-JWWYRR4Q.js.map +1 -0
  183. package/dist/{chunk-BVN6KXL2.js → chunk-KZXDLBY6.js} +14 -9
  184. package/dist/chunk-KZXDLBY6.js.map +1 -0
  185. package/dist/chunk-LGNDFRYC.js +23 -0
  186. package/dist/chunk-LGNDFRYC.js.map +1 -0
  187. package/dist/{chunk-XKWGNJ26.js → chunk-LIOVX5TJ.js} +7 -11
  188. package/dist/chunk-LIOVX5TJ.js.map +1 -0
  189. package/dist/{chunk-AYX7AINO.js → chunk-LNSVGRHO.js} +5 -7
  190. package/dist/chunk-LNSVGRHO.js.map +1 -0
  191. package/dist/chunk-M5B2W6YY.js +293 -0
  192. package/dist/chunk-M5B2W6YY.js.map +1 -0
  193. package/dist/chunk-MBMTND6D.js +456 -0
  194. package/dist/chunk-MBMTND6D.js.map +1 -0
  195. package/dist/{chunk-3BZZJJMQ.js → chunk-MILI22XQ.js} +3 -3
  196. package/dist/{chunk-A2HKRLPV.js → chunk-MXKI4ABF.js} +18 -59
  197. package/dist/chunk-MXKI4ABF.js.map +1 -0
  198. package/dist/{chunk-ZYIYHJ5R.js → chunk-MXOQ5JCG.js} +869 -238
  199. package/dist/chunk-MXOQ5JCG.js.map +1 -0
  200. package/dist/{chunk-V7ZRRCRJ.js → chunk-N7EVQD5S.js} +9 -13
  201. package/dist/chunk-N7EVQD5S.js.map +1 -0
  202. package/dist/chunk-N7UDP5VU.js +757 -0
  203. package/dist/chunk-N7UDP5VU.js.map +1 -0
  204. package/dist/chunk-NBQ3KK6X.js +270 -0
  205. package/dist/chunk-NBQ3KK6X.js.map +1 -0
  206. package/dist/{chunk-ZORTV6NH.js → chunk-NCO25JZO.js} +88 -4
  207. package/dist/chunk-NCO25JZO.js.map +1 -0
  208. package/dist/chunk-NH2UOV3B.js +18 -0
  209. package/dist/chunk-NH2UOV3B.js.map +1 -0
  210. package/dist/chunk-NYMLINRP.js +28 -0
  211. package/dist/chunk-NYMLINRP.js.map +1 -0
  212. package/dist/{chunk-YYP7WSEB.js → chunk-O2IMQSNA.js} +2 -2
  213. package/dist/chunk-O46CHQT7.js +215 -0
  214. package/dist/chunk-O46CHQT7.js.map +1 -0
  215. package/dist/chunk-OIEO4WDL.js +27 -0
  216. package/dist/chunk-OIEO4WDL.js.map +1 -0
  217. package/dist/{chunk-TRGTKX5E.js → chunk-OKSTSITU.js} +27 -4
  218. package/dist/chunk-OKSTSITU.js.map +1 -0
  219. package/dist/chunk-OYW3I5M4.js +31 -0
  220. package/dist/chunk-OYW3I5M4.js.map +1 -0
  221. package/dist/{chunk-Q7HZX3IF.js → chunk-PD64727P.js} +2 -2
  222. package/dist/chunk-PD64727P.js.map +1 -0
  223. package/dist/{chunk-FET5XCAT.js → chunk-PP3K67AJ.js} +34 -6
  224. package/dist/chunk-PP3K67AJ.js.map +1 -0
  225. package/dist/chunk-Q2XRFWOI.js +40 -0
  226. package/dist/chunk-Q2XRFWOI.js.map +1 -0
  227. package/dist/{chunk-QIZPZMUI.js → chunk-Q4UHJ5SN.js} +2 -2
  228. package/dist/{chunk-FAHMLERK.js → chunk-QBLT6POL.js} +2 -2
  229. package/dist/chunk-QMWY2FDS.js +157 -0
  230. package/dist/chunk-QMWY2FDS.js.map +1 -0
  231. package/dist/{chunk-LH5A3ZPG.js → chunk-RB4DOPGZ.js} +150 -22
  232. package/dist/chunk-RB4DOPGZ.js.map +1 -0
  233. package/dist/chunk-RHVMZSUU.js +7 -0
  234. package/dist/chunk-RHVMZSUU.js.map +1 -0
  235. package/dist/{chunk-BUE2D7PX.js → chunk-SMV2HRDU.js} +2 -2
  236. package/dist/chunk-SUZKW6UR.js +25 -0
  237. package/dist/chunk-SUZKW6UR.js.map +1 -0
  238. package/dist/{chunk-7MG7SJT7.js → chunk-SV2PM2OY.js} +1 -1
  239. package/dist/chunk-SV2PM2OY.js.map +1 -0
  240. package/dist/{chunk-UXVWEX5L.js → chunk-SYNY3VB5.js} +6 -2
  241. package/dist/chunk-SYNY3VB5.js.map +1 -0
  242. package/dist/{chunk-4GFX6MPA.js → chunk-TEHHROZL.js} +6 -8
  243. package/dist/chunk-TEHHROZL.js.map +1 -0
  244. package/dist/chunk-TKVUE4JF.js +1289 -0
  245. package/dist/chunk-TKVUE4JF.js.map +1 -0
  246. package/dist/{chunk-SFAWCTEM.js → chunk-TZZBXPZK.js} +2 -2
  247. package/dist/{chunk-F3W6YMDC.js → chunk-U2FZNEWJ.js} +4 -4
  248. package/dist/chunk-U2FZNEWJ.js.map +1 -0
  249. package/dist/{chunk-BLN54W3L.js → chunk-UA372JHH.js} +56 -3
  250. package/dist/chunk-UA372JHH.js.map +1 -0
  251. package/dist/{chunk-6YXCPL4T.js → chunk-UEFOQH74.js} +2 -2
  252. package/dist/chunk-UEFOQH74.js.map +1 -0
  253. package/dist/{chunk-2N5ML6HT.js → chunk-UIYESRD6.js} +9 -11
  254. package/dist/chunk-UIYESRD6.js.map +1 -0
  255. package/dist/{chunk-UHHPLO3I.js → chunk-V3RWOOSO.js} +4 -4
  256. package/dist/{chunk-KTFRCC5C.js → chunk-V7ADQF5O.js} +82 -8
  257. package/dist/chunk-V7ADQF5O.js.map +1 -0
  258. package/dist/{chunk-453F654R.js → chunk-VAORSCSU.js} +3 -3
  259. package/dist/chunk-VAORSCSU.js.map +1 -0
  260. package/dist/{chunk-GPNTB4Y7.js → chunk-VFHCKG5M.js} +6 -10
  261. package/dist/chunk-VFHCKG5M.js.map +1 -0
  262. package/dist/{chunk-2577DKXB.js → chunk-VHBKYN2J.js} +3 -3
  263. package/dist/chunk-VHBKYN2J.js.map +1 -0
  264. package/dist/chunk-VHM7HCKB.js +220 -0
  265. package/dist/chunk-VHM7HCKB.js.map +1 -0
  266. package/dist/{chunk-ZHKOPKE3.js → chunk-VKI2EB3N.js} +3 -3
  267. package/dist/chunk-VKI2EB3N.js.map +1 -0
  268. package/dist/{chunk-UDHWDSRL.js → chunk-VMV5SBE4.js} +16 -17
  269. package/dist/chunk-VMV5SBE4.js.map +1 -0
  270. package/dist/{chunk-SPYWXKJN.js → chunk-VQDZYB2B.js} +3 -3
  271. package/dist/chunk-VQDZYB2B.js.map +1 -0
  272. package/dist/{chunk-Q2PU57HC.js → chunk-VVOLDVIR.js} +2 -2
  273. package/dist/{chunk-3VF3WQ4F.js → chunk-WPOYWFSE.js} +7 -7
  274. package/dist/{chunk-3VF3WQ4F.js.map → chunk-WPOYWFSE.js.map} +1 -1
  275. package/dist/{chunk-OTQZ7ZWU.js → chunk-WXE4W2U6.js} +7 -11
  276. package/dist/chunk-WXE4W2U6.js.map +1 -0
  277. package/dist/chunk-XBKH4FOC.js +195 -0
  278. package/dist/chunk-XBKH4FOC.js.map +1 -0
  279. package/dist/{chunk-TUFM4UZP.js → chunk-XQRFSKYM.js} +2 -2
  280. package/dist/{chunk-3V4KWFX7.js → chunk-XSPFDUDG.js} +58 -53
  281. package/dist/chunk-XSPFDUDG.js.map +1 -0
  282. package/dist/{chunk-GY4WYNNG.js → chunk-Y2RKVFKR.js} +2 -2
  283. package/dist/{chunk-UP4BECPY.js → chunk-Y3LPTBG7.js} +89 -27
  284. package/dist/chunk-Y3LPTBG7.js.map +1 -0
  285. package/dist/{chunk-4OZNXTO4.js → chunk-YRXFFWG4.js} +2 -2
  286. package/dist/classified/index.js +5 -5
  287. package/dist/{classified-marker-BWOFVYAC.js → classified-marker-SIYKUU5L.js} +3 -3
  288. package/dist/classified-marker-SIYKUU5L.js.map +1 -0
  289. package/dist/collection-facade-CS7CA2XO.js +47 -0
  290. package/dist/{computed-VPOKQK4N.js → computed-FAD7SED4.js} +3 -3
  291. package/dist/consent/index.js +10 -11
  292. package/dist/consent/index.js.map +1 -1
  293. package/dist/cover/index.js +10 -11
  294. package/dist/coverage/index.js +306 -0
  295. package/dist/coverage/index.js.map +1 -0
  296. package/dist/custody/index.js +12 -13
  297. package/dist/{dead-filter-PKQDLOT4.js → dead-filter-4F3LWYKH.js} +11 -3
  298. package/dist/dead-filter-4F3LWYKH.js.map +1 -0
  299. package/dist/debug/index.js +11 -2
  300. package/dist/debug/index.js.map +1 -1
  301. package/dist/{delegation-DS5NRILW.js → delegation-NANZDG4N.js} +13 -16
  302. package/dist/delegation-NANZDG4N.js.map +1 -0
  303. package/dist/derivations/index.js +25 -23
  304. package/dist/derive-XLOJVXPU.js +20 -0
  305. package/dist/directory/index.js +10 -11
  306. package/dist/{dispatch-IEPAVQUM.js → dispatch-H4HV32AM.js} +5 -5
  307. package/dist/{dispatch-Q6MWLOJY.js → dispatch-JDZNGEB3.js} +20 -21
  308. package/dist/dispatch-JDZNGEB3.js.map +1 -0
  309. package/dist/executor-FMPVN6DT.js +35 -0
  310. package/dist/executor-LBBBRTN5.js +8 -0
  311. package/dist/executor-OSRZST2U.js +8 -0
  312. package/dist/export-accessible-RAOJAAU5.js +22 -0
  313. package/dist/extract-partition-JD5CUSTG.js +37 -0
  314. package/dist/{fanout-sidecar-S3QL53YX.js → fanout-sidecar-L7NHPIOC.js} +13 -15
  315. package/dist/fanout-sidecar-L7NHPIOC.js.map +1 -0
  316. package/dist/find-JRN4RNQ5.js +10 -0
  317. package/dist/forget/index.js +9 -10
  318. package/dist/forget/index.js.map +1 -1
  319. package/dist/guards/index.js +4 -4
  320. package/dist/history/index.js +13 -14
  321. package/dist/history/index.js.map +1 -1
  322. package/dist/i18n/index.js +14 -15
  323. package/dist/i18n/index.js.map +1 -1
  324. package/dist/index.d.ts +36 -14
  325. package/dist/index.js +970 -163
  326. package/dist/index.js.map +1 -1
  327. package/dist/indexing/index.js +13 -5
  328. package/dist/indexing/index.js.map +1 -1
  329. package/dist/introspection/index.js +11 -12
  330. package/dist/issue-YIVBZUTH.js +19 -0
  331. package/dist/ivf-flat-UZ6DQDLS.js +314 -0
  332. package/dist/ivf-flat-UZ6DQDLS.js.map +1 -0
  333. package/dist/{json-schema-V3M5MUCM.js → json-schema-3SHX72CC.js} +2 -1
  334. package/dist/json-schema-3SHX72CC.js.map +1 -0
  335. package/dist/kernel/attestation-types.d.ts +62 -0
  336. package/dist/kernel/collection-config.d.ts +5 -68
  337. package/dist/kernel/collection.d.ts +30 -9
  338. package/dist/kernel/cutover-transform.d.ts +1 -1
  339. package/dist/kernel/errors.d.ts +257 -38
  340. package/dist/kernel/generation-map.d.ts +48 -0
  341. package/dist/kernel/merge-authority.d.ts +1 -1
  342. package/dist/kernel/noydb.d.ts +6 -1
  343. package/dist/kernel/paths.d.ts +29 -5
  344. package/dist/kernel/prepared-write.d.ts +1 -1
  345. package/dist/kernel/present-cache.d.ts +58 -0
  346. package/dist/kernel/query/all.d.ts +7 -0
  347. package/dist/kernel/query/builder.d.ts +601 -270
  348. package/dist/kernel/query/civil-date.d.ts +64 -0
  349. package/dist/kernel/query/cursor.d.ts +40 -0
  350. package/dist/kernel/query/distinct-key.d.ts +98 -0
  351. package/dist/kernel/query/hydration.d.ts +76 -0
  352. package/dist/kernel/query/index.d.ts +31 -15
  353. package/dist/kernel/query/internal/core.d.ts +30 -0
  354. package/dist/kernel/query/internal/hooks.d.ts +22 -0
  355. package/dist/kernel/query/internal/maintenance.d.ts +43 -0
  356. package/dist/kernel/query/live/incremental.d.ts +314 -0
  357. package/dist/kernel/query/live/index.d.ts +22 -0
  358. package/dist/kernel/query/live/install.d.ts +2 -0
  359. package/dist/kernel/query/{live.d.ts → live/live.d.ts} +39 -9
  360. package/dist/kernel/query/live/methods.d.ts +107 -0
  361. package/dist/kernel/query/predicate.d.ts +119 -1
  362. package/dist/kernel/query/reduce/date-trunc.d.ts +75 -0
  363. package/dist/kernel/query/reduce/index.d.ts +36 -0
  364. package/dist/kernel/query/reduce/install.d.ts +2 -0
  365. package/dist/kernel/query/reduce/methods.d.ts +259 -0
  366. package/dist/kernel/query/reduce/scan-methods.d.ts +121 -0
  367. package/dist/kernel/query/relate/explain.d.ts +199 -0
  368. package/dist/kernel/query/relate/index.d.ts +48 -0
  369. package/dist/kernel/query/relate/install.d.ts +2 -0
  370. package/dist/kernel/query/relate/join-on.d.ts +126 -0
  371. package/dist/kernel/query/relate/join-reduce.d.ts +16 -0
  372. package/dist/kernel/query/relate/join.d.ts +452 -0
  373. package/dist/kernel/query/relate/methods.d.ts +426 -0
  374. package/dist/kernel/query/relate/partition.d.ts +87 -0
  375. package/dist/kernel/query/relate/scan-methods.d.ts +163 -0
  376. package/dist/kernel/query/relate/traverse.d.ts +109 -0
  377. package/dist/kernel/query/scan-builder.d.ts +79 -176
  378. package/dist/kernel/query/sort-key.d.ts +52 -0
  379. package/dist/kernel/secret-mode.d.ts +1 -1
  380. package/dist/kernel/tx-write-gate.d.ts +77 -0
  381. package/dist/kernel/types.d.ts +113 -8
  382. package/dist/kernel/validation.d.ts +27 -10
  383. package/dist/kernel/vault.d.ts +11 -6
  384. package/dist/kernel/via/compose.d.ts +3 -0
  385. package/dist/kernel/via/index.d.ts +56 -0
  386. package/dist/kernel/via/pipeline.d.ts +48 -0
  387. package/dist/kernel/write-queue.d.ts +17 -0
  388. package/dist/{ledger-EDXFFZQL.js → ledger-5ZMGE44K.js} +11 -12
  389. package/dist/liberate-WZSZM2W6.js +24 -0
  390. package/dist/link-set-MFXC24VK.js +29 -0
  391. package/dist/{managed-secret-NCWEMPUQ.js → managed-secret-MFTFT22X.js} +10 -11
  392. package/dist/materialized-views/index.js +30 -24
  393. package/dist/{migrate-cek-5ENH64AA.js → migrate-cek-DZRFFOHW.js} +2 -2
  394. package/dist/money/index.js +5 -5
  395. package/dist/noydb-ITIGNKUF.js +96 -0
  396. package/dist/overlay-views/index.js +4 -4
  397. package/dist/periods/index.js +12 -13
  398. package/dist/pod/index.js +74 -67
  399. package/dist/{pod-handle-ECVCDIXW.js → pod-handle-A3LET7NO.js} +10 -11
  400. package/dist/pod-handle-A3LET7NO.js.map +1 -0
  401. package/dist/policy/index.js +10 -11
  402. package/dist/port/on/index.d.ts +1 -1
  403. package/dist/port/to/index.d.ts +1 -1
  404. package/dist/port/with/blob-strategy.d.ts +10 -1
  405. package/dist/port/with/classified-strategy.d.ts +1 -1
  406. package/dist/port/with/collection-options.d.ts +6 -1
  407. package/dist/port/with/collection-registries.d.ts +1 -1
  408. package/dist/port/with/coverage-strategy.d.ts +83 -0
  409. package/dist/port/with/lookup-strategy.d.ts +2 -2
  410. package/dist/port/with/service-bus.d.ts +46 -0
  411. package/dist/port/with/strategies.d.ts +2 -0
  412. package/dist/portability/index.js +8 -8
  413. package/dist/{post-register-3IPCSG6Q.js → post-register-7ND27CF2.js} +6 -6
  414. package/dist/post-register-7ND27CF2.js.map +1 -0
  415. package/dist/query/all/index.js +31 -0
  416. package/dist/query/index.js +20 -32
  417. package/dist/query/live/index.js +21 -0
  418. package/dist/query/live/index.js.map +1 -0
  419. package/dist/query/reduce/index.js +33 -0
  420. package/dist/query/reduce/index.js.map +1 -0
  421. package/dist/query/relate/index.js +56 -0
  422. package/dist/query/relate/index.js.map +1 -0
  423. package/dist/reduce/index.js +72 -18
  424. package/dist/reduce/index.js.map +1 -1
  425. package/dist/register-DT5HZ2LZ.js +30 -0
  426. package/dist/registry-BHRZGZHF.js +8 -0
  427. package/dist/registry-ET6ZFFWA.js +34 -0
  428. package/dist/registry-HXFGLGTG.js +8 -0
  429. package/dist/registry-THCPDEOD.js +23 -0
  430. package/dist/request-withdrawal-AV2MJJKY.js +30 -0
  431. package/dist/{reveal-QZDHSGD4.js → reveal-B2TLP4JQ.js} +10 -9
  432. package/dist/reveal-B2TLP4JQ.js.map +1 -0
  433. package/dist/revoke-6DWIEOCV.js +24 -0
  434. package/dist/satellites/index.js +1 -1
  435. package/dist/schema-update/index.js +2 -2
  436. package/dist/sealed-record/index.js +16 -18
  437. package/dist/sealed-record/index.js.map +1 -1
  438. package/dist/search/index.js +11 -5
  439. package/dist/{seed-X5CC22CQ.js → seed-XNSE4U3S.js} +15 -18
  440. package/dist/seed-XNSE4U3S.js.map +1 -0
  441. package/dist/sequence/index.js +9 -10
  442. package/dist/session/index.js +9 -10
  443. package/dist/session/index.js.map +1 -1
  444. package/dist/shadow/index.js +2 -2
  445. package/dist/signer-MHGW3OIL.js +23 -0
  446. package/dist/snapshots/index.js +11 -11
  447. package/dist/stale-6GCFMOOR.js +28 -0
  448. package/dist/storage-BYN5LO6Z.js +21 -0
  449. package/dist/storage-BYN5LO6Z.js.map +1 -0
  450. package/dist/store/index.js +1 -1
  451. package/dist/{store-coordination-provider-4WZAIRHC.js → store-coordination-provider-C4BPT5XF.js} +11 -12
  452. package/dist/store-coordination-provider-C4BPT5XF.js.map +1 -0
  453. package/dist/sync/index.js +10 -11
  454. package/dist/sync/index.js.map +1 -1
  455. package/dist/team/index.js +17 -16
  456. package/dist/tiers/index.js +13 -12
  457. package/dist/to/index.js +2 -2
  458. package/dist/transactions/index.js +3 -3
  459. package/dist/util/index.js +1 -1
  460. package/dist/vault-head/index.js +11 -14
  461. package/dist/vault-head/index.js.map +1 -1
  462. package/dist/{verify-6MDTIUEV.js → verify-UKALW7C2.js} +14 -12
  463. package/dist/verify-UKALW7C2.js.map +1 -0
  464. package/dist/via/blob/index.d.ts +1 -0
  465. package/dist/via/classified/binding.d.ts +2 -2
  466. package/dist/via/classified/config-drift.d.ts +2 -2
  467. package/dist/via/classified/errors.d.ts +1 -1
  468. package/dist/via/geo/binding.d.ts +31 -0
  469. package/dist/via/geo/descriptor.d.ts +54 -0
  470. package/dist/via/geo/geohash.d.ts +95 -0
  471. package/dist/via/geo/index.d.ts +13 -0
  472. package/dist/via/geo/where.d.ts +50 -0
  473. package/dist/via/i18n/core.d.ts +1 -1
  474. package/dist/via/lookup/handle.d.ts +4 -4
  475. package/dist/via/lookup/registry.d.ts +1 -1
  476. package/dist/via/lookup/snapshot.d.ts +3 -3
  477. package/dist/walk-4VPK7AS4.js +20 -0
  478. package/dist/walk-4VPK7AS4.js.map +1 -0
  479. package/dist/with-audit/attestation/index.d.ts +2 -1
  480. package/dist/with-audit/attestation/issue.d.ts +2 -2
  481. package/dist/with-audit/attestation/revoke.d.ts +2 -2
  482. package/dist/with-audit/attestation/scheme.d.ts +7 -0
  483. package/dist/with-audit/attestation/signer.d.ts +1 -1
  484. package/dist/with-audit/attestation/strategy.d.ts +2 -2
  485. package/dist/with-audit/attestation/types.d.ts +10 -0
  486. package/dist/with-audit/attestation/vault-facade.d.ts +2 -2
  487. package/dist/with-audit/attestation/verifier.d.ts +6 -0
  488. package/dist/with-audit/consent/consent.d.ts +1 -1
  489. package/dist/with-audit/consent/strategy.d.ts +1 -1
  490. package/dist/with-audit/coverage/accounting.d.ts +112 -0
  491. package/dist/with-audit/coverage/active.d.ts +29 -0
  492. package/dist/with-audit/coverage/index.d.ts +61 -0
  493. package/dist/with-audit/coverage/sketch.d.ts +75 -0
  494. package/dist/with-audit/forget/subject-index.d.ts +1 -1
  495. package/dist/with-audit/periods/periods.d.ts +55 -7
  496. package/dist/with-audit/periods/reserved-collections.d.ts +3 -0
  497. package/dist/with-audit/periods/vault-facade.d.ts +18 -1
  498. package/dist/with-audit/sealed-record/index.d.ts +2 -2
  499. package/dist/with-audit/sealed-record/strategy.d.ts +1 -1
  500. package/dist/with-audit/tiers/index.d.ts +53 -2
  501. package/dist/with-audit/tiers/strategy.d.ts +8 -0
  502. package/dist/with-cargo/adopt-partition.d.ts +1 -1
  503. package/dist/with-cargo/extract-partition.d.ts +1 -1
  504. package/dist/with-cargo/floor.d.ts +3 -3
  505. package/dist/with-commit/history/history.d.ts +2 -2
  506. package/dist/with-commit/history/index.d.ts +1 -1
  507. package/dist/with-commit/history/ledger/store.d.ts +1 -1
  508. package/dist/with-commit/history/strategy.d.ts +1 -1
  509. package/dist/with-commit/history/time-machine.d.ts +1 -1
  510. package/dist/with-commit/numbering/index.d.ts +1 -1
  511. package/dist/with-commit/sequence/index.d.ts +1 -1
  512. package/dist/with-commit/tx/invariants.d.ts +1 -1
  513. package/dist/with-commit/tx/transaction.d.ts +13 -3
  514. package/dist/with-commit/vault-head/head.d.ts +1 -1
  515. package/dist/with-commit/vault-head/index.d.ts +1 -1
  516. package/dist/with-commit/vault-head/strategy.d.ts +1 -1
  517. package/dist/with-commit/vault-head/verify.d.ts +1 -1
  518. package/dist/with-formula/derivations/dispatch.d.ts +1 -1
  519. package/dist/with-formula/derivations/fanout-sidecar.d.ts +1 -1
  520. package/dist/with-formula/materialized-views/dependency-analyzer.d.ts +4 -3
  521. package/dist/with-formula/materialized-views/emit-memo.d.ts +40 -0
  522. package/dist/with-formula/materialized-views/executor.d.ts +8 -0
  523. package/dist/with-formula/materialized-views/index.d.ts +1 -1
  524. package/dist/with-formula/materialized-views/registry.d.ts +15 -0
  525. package/dist/with-formula/materialized-views/types.d.ts +106 -14
  526. package/dist/with-formula/materialized-views/window-stage.d.ts +11 -0
  527. package/dist/with-formula/overlay-views/types.d.ts +1 -1
  528. package/dist/with-formula/overlay-views/virtual-collection.d.ts +13 -4
  529. package/dist/with-lookup/embeddings/chunks.d.ts +79 -0
  530. package/dist/with-lookup/embeddings/descriptor.d.ts +21 -0
  531. package/dist/with-lookup/embeddings/index.d.ts +3 -0
  532. package/dist/with-lookup/embeddings/ivf-flat.d.ts +93 -0
  533. package/dist/with-lookup/embeddings/vector-index.d.ts +73 -0
  534. package/dist/with-lookup/embeddings/vector-set.d.ts +94 -1
  535. package/dist/with-lookup/embeddings/with-vector-index.d.ts +67 -0
  536. package/dist/with-lookup/indexing/collection-facade.d.ts +86 -3
  537. package/dist/with-lookup/indexing/compound-indexes.d.ts +129 -0
  538. package/dist/with-lookup/indexing/eager-indexes.d.ts +170 -1
  539. package/dist/with-lookup/indexing/index-snapshot.d.ts +62 -0
  540. package/dist/with-lookup/indexing/lazy-builder.d.ts +33 -0
  541. package/dist/with-lookup/indexing/persisted-field-indexes.d.ts +104 -0
  542. package/dist/with-lookup/indexing/persisted-indexes.d.ts +12 -0
  543. package/dist/with-lookup/indexing/sorted-indexes.d.ts +117 -0
  544. package/dist/with-lookup/indexing/unique-constraints.d.ts +106 -23
  545. package/dist/with-lookup/reduce/active.d.ts +2 -24
  546. package/dist/with-lookup/reduce/group-core.d.ts +43 -0
  547. package/dist/with-lookup/reduce/groupby.d.ts +195 -36
  548. package/dist/with-lookup/reduce/incremental-group.d.ts +153 -0
  549. package/dist/with-lookup/reduce/index.d.ts +26 -5
  550. package/dist/with-lookup/reduce/reducers.d.ts +255 -1
  551. package/dist/with-lookup/reduce/reduction.d.ts +44 -13
  552. package/dist/with-lookup/reduce/strategy.d.ts +43 -3
  553. package/dist/with-lookup/reduce/window.d.ts +262 -0
  554. package/dist/with-lookup/search/collection-facade.d.ts +45 -9
  555. package/dist/with-lookup/search/index-store.d.ts +5 -3
  556. package/dist/with-lookup/search/index.d.ts +4 -2
  557. package/dist/with-lookup/search/inverted-index.d.ts +38 -2
  558. package/dist/with-lookup/search/persisted-index-store.d.ts +5 -2
  559. package/dist/with-lookup/search/phrase.d.ts +28 -0
  560. package/dist/with-lookup/search/retrieve-types.d.ts +57 -1
  561. package/dist/with-lookup/search/serialize.d.ts +29 -3
  562. package/dist/with-lookup/search/strategy.d.ts +2 -6
  563. package/dist/with-party/broker/index.d.ts +3 -3
  564. package/dist/with-party/directory/cover/index.d.ts +1 -1
  565. package/dist/with-party/directory/cover/storage.d.ts +1 -1
  566. package/dist/with-party/directory/cover/types.d.ts +1 -1
  567. package/dist/with-party/directory/index.d.ts +1 -1
  568. package/dist/with-party/directory/types.d.ts +1 -1
  569. package/dist/with-party/directory/user-envelope/api.d.ts +1 -1
  570. package/dist/with-party/directory/user-envelope/storage.d.ts +1 -1
  571. package/dist/with-party/policy/engine.d.ts +1 -1
  572. package/dist/with-party/policy/index.d.ts +1 -1
  573. package/dist/with-party/policy/presets.d.ts +1 -1
  574. package/dist/with-party/team/authenticators.d.ts +91 -1
  575. package/dist/with-party/team/delegation.d.ts +1 -1
  576. package/dist/with-party/team/echo-secret.d.ts +2 -2
  577. package/dist/with-party/team/index.d.ts +4 -3
  578. package/dist/with-party/team/keyring.d.ts +2 -2
  579. package/dist/with-party/team/magic-link-grant.d.ts +1 -1
  580. package/dist/with-party/team/managed-secret.d.ts +1 -1
  581. package/dist/with-party/team/noydb-facade.d.ts +12 -3
  582. package/dist/with-party/team/recovery.d.ts +1 -1
  583. package/dist/with-party/team/roster-tag.d.ts +1 -1
  584. package/dist/with-party/team/rotate-recover.d.ts +1 -1
  585. package/dist/with-party/team/wrapped-deks.d.ts +1 -1
  586. package/dist/with-pod/format.d.ts +1 -1
  587. package/dist/with-pod/index.d.ts +1 -1
  588. package/dist/with-pod/pod.d.ts +1 -1
  589. package/dist/with-shape/blobs/blob-compaction.d.ts +17 -1
  590. package/dist/with-shape/blobs/blob-intent.d.ts +1 -1
  591. package/dist/with-shape/blobs/blob-set.d.ts +23 -4
  592. package/dist/with-shape/blobs/legacy-sweep.d.ts +35 -0
  593. package/dist/with-shape/introspection/describe.d.ts +7 -1
  594. package/dist/with-shape/introspection/field-meta.d.ts +18 -0
  595. package/dist/with-shape/introspection/types.d.ts +57 -1
  596. package/dist/with-shape/introspection/walk.d.ts +1 -1
  597. package/dist/with-shape/links/lazy-handle.d.ts +1 -1
  598. package/dist/with-shape/links/link-set.d.ts +1 -1
  599. package/dist/with-shape/links/vault-facade.d.ts +1 -1
  600. package/dist/with-shape/manifest/derive.d.ts +1 -1
  601. package/dist/with-shape/manifest/storage.d.ts +1 -1
  602. package/dist/with-shape/persisted-schemas/register.d.ts +1 -1
  603. package/dist/with-shape/persisted-schemas/storage.d.ts +1 -1
  604. package/dist/with-shape/satellites/dead-filter.d.ts +1 -1
  605. package/dist/with-shape/satellites/declare.d.ts +1 -1
  606. package/dist/with-shape/satellites/marker.d.ts +1 -1
  607. package/dist/with-shape/satellites/post-register.d.ts +1 -1
  608. package/dist/with-store/partitioned/index.d.ts +337 -0
  609. package/dist/with-sync/change-broadcast.d.ts +153 -0
  610. package/dist/with-sync/presence.d.ts +5 -10
  611. package/dist/withdraw-accessible-HL7GACUE.js +27 -0
  612. package/dist/withdraw-accessible-HL7GACUE.js.map +1 -0
  613. package/package.json +48 -12
  614. package/dist/api-WYW4YEQG.js +0 -19
  615. package/dist/backup-XKCXVKV3.js.map +0 -1
  616. package/dist/chunk-2577DKXB.js.map +0 -1
  617. package/dist/chunk-2ENE6445.js.map +0 -1
  618. package/dist/chunk-2N5ML6HT.js.map +0 -1
  619. package/dist/chunk-334WSVOW.js.map +0 -1
  620. package/dist/chunk-3BVH633C.js.map +0 -1
  621. package/dist/chunk-3PGS7TYR.js.map +0 -1
  622. package/dist/chunk-3V4KWFX7.js.map +0 -1
  623. package/dist/chunk-453F654R.js.map +0 -1
  624. package/dist/chunk-4GFX6MPA.js.map +0 -1
  625. package/dist/chunk-4GVM6QZA.js.map +0 -1
  626. package/dist/chunk-4ZS56W5S.js.map +0 -1
  627. package/dist/chunk-5VCRVKOZ.js.map +0 -1
  628. package/dist/chunk-6YXCPL4T.js.map +0 -1
  629. package/dist/chunk-7APJ6CO6.js.map +0 -1
  630. package/dist/chunk-7MG2LHO5.js +0 -1616
  631. package/dist/chunk-7MG2LHO5.js.map +0 -1
  632. package/dist/chunk-7MG7SJT7.js.map +0 -1
  633. package/dist/chunk-7O3Y4PPD.js.map +0 -1
  634. package/dist/chunk-A2HKRLPV.js.map +0 -1
  635. package/dist/chunk-A66I4JOA.js.map +0 -1
  636. package/dist/chunk-ACAQ2DSG.js.map +0 -1
  637. package/dist/chunk-ATL3ZVXT.js +0 -151
  638. package/dist/chunk-ATL3ZVXT.js.map +0 -1
  639. package/dist/chunk-AYX7AINO.js.map +0 -1
  640. package/dist/chunk-BLN54W3L.js.map +0 -1
  641. package/dist/chunk-BRLKZUBT.js +0 -95
  642. package/dist/chunk-BRLKZUBT.js.map +0 -1
  643. package/dist/chunk-BTDR2PXY.js +0 -29
  644. package/dist/chunk-BTDR2PXY.js.map +0 -1
  645. package/dist/chunk-BVN6KXL2.js.map +0 -1
  646. package/dist/chunk-CHQCZZWC.js.map +0 -1
  647. package/dist/chunk-CUQPWYRX.js.map +0 -1
  648. package/dist/chunk-CUZLNGD5.js.map +0 -1
  649. package/dist/chunk-DFMWUOU5.js.map +0 -1
  650. package/dist/chunk-EIPVYUEP.js.map +0 -1
  651. package/dist/chunk-EQEYOJBM.js.map +0 -1
  652. package/dist/chunk-F3W6YMDC.js.map +0 -1
  653. package/dist/chunk-FET5XCAT.js.map +0 -1
  654. package/dist/chunk-G73UVHCA.js.map +0 -1
  655. package/dist/chunk-GPNTB4Y7.js.map +0 -1
  656. package/dist/chunk-GYGLAVCX.js.map +0 -1
  657. package/dist/chunk-HIWCKBEY.js.map +0 -1
  658. package/dist/chunk-HJUWN7JN.js.map +0 -1
  659. package/dist/chunk-HK67PX4J.js.map +0 -1
  660. package/dist/chunk-HPVZCW43.js +0 -479
  661. package/dist/chunk-HPVZCW43.js.map +0 -1
  662. package/dist/chunk-I3ISCYT7.js +0 -159
  663. package/dist/chunk-I3ISCYT7.js.map +0 -1
  664. package/dist/chunk-K23VKTN4.js.map +0 -1
  665. package/dist/chunk-KKEESNPE.js.map +0 -1
  666. package/dist/chunk-KTFRCC5C.js.map +0 -1
  667. package/dist/chunk-LH5A3ZPG.js.map +0 -1
  668. package/dist/chunk-LP7BEXCT.js +0 -32
  669. package/dist/chunk-LP7BEXCT.js.map +0 -1
  670. package/dist/chunk-M4YPHYEH.js.map +0 -1
  671. package/dist/chunk-NSITFOCJ.js +0 -99
  672. package/dist/chunk-NSITFOCJ.js.map +0 -1
  673. package/dist/chunk-OTQZ7ZWU.js.map +0 -1
  674. package/dist/chunk-P3MG6QCN.js.map +0 -1
  675. package/dist/chunk-PEOZ34EM.js.map +0 -1
  676. package/dist/chunk-PPTHY5QO.js.map +0 -1
  677. package/dist/chunk-Q2MPFCQ7.js.map +0 -1
  678. package/dist/chunk-Q7HZX3IF.js.map +0 -1
  679. package/dist/chunk-QPQUVOZ2.js.map +0 -1
  680. package/dist/chunk-QTQUH4DS.js.map +0 -1
  681. package/dist/chunk-R42NSZI6.js.map +0 -1
  682. package/dist/chunk-R7BX2NB3.js.map +0 -1
  683. package/dist/chunk-RSGLUIO6.js.map +0 -1
  684. package/dist/chunk-RTBJ5IOO.js +0 -87
  685. package/dist/chunk-RTBJ5IOO.js.map +0 -1
  686. package/dist/chunk-SGZAIJCV.js.map +0 -1
  687. package/dist/chunk-SKGMN35F.js.map +0 -1
  688. package/dist/chunk-SPYWXKJN.js.map +0 -1
  689. package/dist/chunk-SZJ3DLZA.js +0 -66
  690. package/dist/chunk-SZJ3DLZA.js.map +0 -1
  691. package/dist/chunk-TRGTKX5E.js.map +0 -1
  692. package/dist/chunk-UDHWDSRL.js.map +0 -1
  693. package/dist/chunk-UP4BECPY.js.map +0 -1
  694. package/dist/chunk-UXVWEX5L.js.map +0 -1
  695. package/dist/chunk-V7ZRRCRJ.js.map +0 -1
  696. package/dist/chunk-WQBG4SZS.js.map +0 -1
  697. package/dist/chunk-XKWGNJ26.js.map +0 -1
  698. package/dist/chunk-YMUFFJCO.js.map +0 -1
  699. package/dist/chunk-ZHKOPKE3.js.map +0 -1
  700. package/dist/chunk-ZN4FD4PE.js +0 -364
  701. package/dist/chunk-ZN4FD4PE.js.map +0 -1
  702. package/dist/chunk-ZORTV6NH.js.map +0 -1
  703. package/dist/chunk-ZYIYHJ5R.js.map +0 -1
  704. package/dist/classified-marker-BWOFVYAC.js.map +0 -1
  705. package/dist/collection-facade-JSJYIKS4.js +0 -45
  706. package/dist/dead-filter-PKQDLOT4.js.map +0 -1
  707. package/dist/delegation-DS5NRILW.js.map +0 -1
  708. package/dist/derive-E642AOUB.js +0 -21
  709. package/dist/dispatch-Q6MWLOJY.js.map +0 -1
  710. package/dist/executor-5NIMLSKZ.js +0 -8
  711. package/dist/executor-7UQ3BZ4F.js +0 -29
  712. package/dist/executor-AQVXV5GZ.js +0 -8
  713. package/dist/export-accessible-ORMKLA3E.js +0 -22
  714. package/dist/extract-partition-NKYO3WNG.js +0 -37
  715. package/dist/fanout-sidecar-S3QL53YX.js.map +0 -1
  716. package/dist/find-NOGJ25VX.js +0 -10
  717. package/dist/issue-3DTQ7VJJ.js +0 -18
  718. package/dist/json-schema-V3M5MUCM.js.map +0 -1
  719. package/dist/kernel/enclave/classify/compare.d.ts +0 -10
  720. package/dist/kernel/enclave/index.d.ts +0 -87
  721. package/dist/kernel/enclave/record-keys/lifecycle.d.ts +0 -124
  722. package/dist/kernel/enclave/record-keys/rekey-blob.d.ts +0 -88
  723. package/dist/kernel/enclave/record-keys/rekey.d.ts +0 -91
  724. package/dist/kernel/enclave/record-keys/sealed-slot.d.ts +0 -14
  725. package/dist/kernel/enclave/record-keys/sealed-slots.d.ts +0 -123
  726. package/dist/kernel/enclave/record-keys/sealing.d.ts +0 -70
  727. package/dist/kernel/query/join.d.ts +0 -232
  728. package/dist/liberate-V35QUHJP.js +0 -24
  729. package/dist/link-set-2TTM3IZC.js +0 -30
  730. package/dist/noydb-62MX4QUG.js +0 -90
  731. package/dist/pod-handle-ECVCDIXW.js.map +0 -1
  732. package/dist/post-register-3IPCSG6Q.js.map +0 -1
  733. package/dist/register-HHLXEQDN.js +0 -31
  734. package/dist/registry-23WF3TGH.js +0 -8
  735. package/dist/registry-4AYVUNXK.js +0 -8
  736. package/dist/registry-JS3YFQQM.js +0 -18
  737. package/dist/registry-XX2Z7B46.js +0 -32
  738. package/dist/request-withdrawal-CHPATE4G.js +0 -30
  739. package/dist/reveal-QZDHSGD4.js.map +0 -1
  740. package/dist/revoke-7M2VW4ON.js +0 -23
  741. package/dist/seed-X5CC22CQ.js.map +0 -1
  742. package/dist/signer-SJQJVSM6.js +0 -24
  743. package/dist/stale-BZS6H2RY.js +0 -29
  744. package/dist/storage-RW4QBS23.js +0 -22
  745. package/dist/store-coordination-provider-4WZAIRHC.js.map +0 -1
  746. package/dist/verify-6MDTIUEV.js.map +0 -1
  747. package/dist/walk-ZURCH6RZ.js +0 -21
  748. package/dist/withdraw-accessible-PXR4IXDX.js +0 -27
  749. /package/dist/{api-WYW4YEQG.js.map → api-OS747DS4.js.map} +0 -0
  750. /package/dist/{computed-VPOKQK4N.js.map → capsule/contract.js.map} +0 -0
  751. /package/dist/{kernel/enclave → capsule/enclave-aes}/broker/proof.d.ts +0 -0
  752. /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/bidx.d.ts +0 -0
  753. /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/digest.d.ts +0 -0
  754. /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/vdig.d.ts +0 -0
  755. /package/dist/{kernel/enclave/classify → capsule/plumbing}/kofn.d.ts +0 -0
  756. /package/dist/{kernel/enclave/classify → capsule/plumbing}/normalize.d.ts +0 -0
  757. /package/dist/{kernel/enclave → capsule/plumbing}/record-aad.d.ts +0 -0
  758. /package/dist/{collection-facade-JSJYIKS4.js.map → capsule-VOLX3QRQ.js.map} +0 -0
  759. /package/dist/{chunk-MVMXZYXT.js.map → chunk-2GHDLTPE.js.map} +0 -0
  760. /package/dist/{chunk-XLMEZIAJ.js.map → chunk-2ODVB6LZ.js.map} +0 -0
  761. /package/dist/{chunk-RMS3NEA3.js.map → chunk-4JPMZTJY.js.map} +0 -0
  762. /package/dist/{chunk-NQKIUNW5.js.map → chunk-52MGURXO.js.map} +0 -0
  763. /package/dist/{chunk-UGTBXF5U.js.map → chunk-7XMHMVTS.js.map} +0 -0
  764. /package/dist/{chunk-BZ3534YM.js.map → chunk-AUKKUPVB.js.map} +0 -0
  765. /package/dist/{derive-E642AOUB.js.map → chunk-BKT776R5.js.map} +0 -0
  766. /package/dist/{chunk-6LKOJBV6.js.map → chunk-BVCUTXE3.js.map} +0 -0
  767. /package/dist/{chunk-VTFVLCUH.js.map → chunk-DIZLQVAA.js.map} +0 -0
  768. /package/dist/{chunk-LWBCUYZW.js.map → chunk-E2N2T5ZO.js.map} +0 -0
  769. /package/dist/{chunk-JVIBCBC7.js.map → chunk-EJLV62NI.js.map} +0 -0
  770. /package/dist/{chunk-JMGDHKQF.js.map → chunk-FLPCETP6.js.map} +0 -0
  771. /package/dist/{chunk-DGOZ4UZD.js.map → chunk-FVH5QYY2.js.map} +0 -0
  772. /package/dist/{chunk-JBDFMYKQ.js.map → chunk-GZT3NQRA.js.map} +0 -0
  773. /package/dist/{chunk-TFR7DSOV.js.map → chunk-H427H63K.js.map} +0 -0
  774. /package/dist/{chunk-SMH6SRX7.js.map → chunk-JOSPH3E5.js.map} +0 -0
  775. /package/dist/{chunk-3BZZJJMQ.js.map → chunk-MILI22XQ.js.map} +0 -0
  776. /package/dist/{chunk-YYP7WSEB.js.map → chunk-O2IMQSNA.js.map} +0 -0
  777. /package/dist/{chunk-QIZPZMUI.js.map → chunk-Q4UHJ5SN.js.map} +0 -0
  778. /package/dist/{chunk-FAHMLERK.js.map → chunk-QBLT6POL.js.map} +0 -0
  779. /package/dist/{chunk-BUE2D7PX.js.map → chunk-SMV2HRDU.js.map} +0 -0
  780. /package/dist/{chunk-SFAWCTEM.js.map → chunk-TZZBXPZK.js.map} +0 -0
  781. /package/dist/{chunk-UHHPLO3I.js.map → chunk-V3RWOOSO.js.map} +0 -0
  782. /package/dist/{chunk-Q2PU57HC.js.map → chunk-VVOLDVIR.js.map} +0 -0
  783. /package/dist/{chunk-TUFM4UZP.js.map → chunk-XQRFSKYM.js.map} +0 -0
  784. /package/dist/{chunk-GY4WYNNG.js.map → chunk-Y2RKVFKR.js.map} +0 -0
  785. /package/dist/{chunk-4OZNXTO4.js.map → chunk-YRXFFWG4.js.map} +0 -0
  786. /package/dist/{enclave-55PAM4YO.js.map → collection-facade-CS7CA2XO.js.map} +0 -0
  787. /package/dist/{executor-5NIMLSKZ.js.map → computed-FAD7SED4.js.map} +0 -0
  788. /package/dist/{executor-7UQ3BZ4F.js.map → derive-XLOJVXPU.js.map} +0 -0
  789. /package/dist/{dispatch-IEPAVQUM.js.map → dispatch-H4HV32AM.js.map} +0 -0
  790. /package/dist/{executor-AQVXV5GZ.js.map → executor-FMPVN6DT.js.map} +0 -0
  791. /package/dist/{export-accessible-ORMKLA3E.js.map → executor-LBBBRTN5.js.map} +0 -0
  792. /package/dist/{extract-partition-NKYO3WNG.js.map → executor-OSRZST2U.js.map} +0 -0
  793. /package/dist/{find-NOGJ25VX.js.map → export-accessible-RAOJAAU5.js.map} +0 -0
  794. /package/dist/{issue-3DTQ7VJJ.js.map → extract-partition-JD5CUSTG.js.map} +0 -0
  795. /package/dist/{ledger-EDXFFZQL.js.map → find-JRN4RNQ5.js.map} +0 -0
  796. /package/dist/{liberate-V35QUHJP.js.map → issue-YIVBZUTH.js.map} +0 -0
  797. /package/dist/{link-set-2TTM3IZC.js.map → ledger-5ZMGE44K.js.map} +0 -0
  798. /package/dist/{managed-secret-NCWEMPUQ.js.map → liberate-WZSZM2W6.js.map} +0 -0
  799. /package/dist/{noydb-62MX4QUG.js.map → link-set-MFXC24VK.js.map} +0 -0
  800. /package/dist/{register-HHLXEQDN.js.map → managed-secret-MFTFT22X.js.map} +0 -0
  801. /package/dist/{migrate-cek-5ENH64AA.js.map → migrate-cek-DZRFFOHW.js.map} +0 -0
  802. /package/dist/{registry-23WF3TGH.js.map → noydb-ITIGNKUF.js.map} +0 -0
  803. /package/dist/{registry-4AYVUNXK.js.map → query/all/index.js.map} +0 -0
  804. /package/dist/{registry-JS3YFQQM.js.map → register-DT5HZ2LZ.js.map} +0 -0
  805. /package/dist/{registry-XX2Z7B46.js.map → registry-BHRZGZHF.js.map} +0 -0
  806. /package/dist/{request-withdrawal-CHPATE4G.js.map → registry-ET6ZFFWA.js.map} +0 -0
  807. /package/dist/{revoke-7M2VW4ON.js.map → registry-HXFGLGTG.js.map} +0 -0
  808. /package/dist/{signer-SJQJVSM6.js.map → registry-THCPDEOD.js.map} +0 -0
  809. /package/dist/{stale-BZS6H2RY.js.map → request-withdrawal-AV2MJJKY.js.map} +0 -0
  810. /package/dist/{storage-RW4QBS23.js.map → revoke-6DWIEOCV.js.map} +0 -0
  811. /package/dist/{walk-ZURCH6RZ.js.map → signer-MHGW3OIL.js.map} +0 -0
  812. /package/dist/{withdraw-accessible-PXR4IXDX.js.map → stale-6GCFMOOR.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-lookup/indexing/index-snapshot.ts","../src/with-lookup/indexing/sorted-indexes.ts","../src/with-lookup/indexing/compound-indexes.ts","../src/with-lookup/indexing/eager-indexes.ts"],"sourcesContent":["/**\n * The on-disk shape of a persisted field index (#1359) — the format both\n * `SortedIndex` (#1344) and `CompoundIndex` (#1345) round-trip through, plus\n * the structural validator every load must pass.\n *\n * ⭐ **Nothing is flattened into a delimited string.** A compound entry keeps\n * its tuple as an ARRAY of per-component keys, each carrying its runtime KIND\n * alongside its value — which is the whole point of #1345's in-memory shape\n * and would be destroyed by a `join()`. Two properties depend on it:\n *\n * - **Kind survives.** Entries rank by runtime kind FIRST (mirroring\n * `predicate.ts`'s `isComparable`), so a `string` probe must not reach\n * `number` entries. An encoding that wrote only the value would collapse\n * `1` and `'1'` into one key space on the way back in.\n * - **Per-component ordering survives.** A string component may contain any\n * byte, including whatever a separator would have been.\n *\n * The validator is deliberately paranoid and its failure mode is a REBUILD,\n * never a partial load: a blob that is truncated, from a future format, or\n * internally out of order is rejected whole. See\n * {@link parseFieldIndexSnapshot}.\n */\n\n/** Bump on ANY incompatible change to the shapes below. An older stamp is rejected, not migrated. */\nexport const FIELD_INDEX_SNAPSHOT_VERSION = 1\n\n/** One `SortKey`, wire form: `[kind, key]`. `kind` IS the sort rank. */\nexport type WireKey = readonly [kind: number, key: number | string]\n\n/** One `SortedIndex` entry: `[kind, key, seq, id]`. */\nexport type WireSortedEntry = readonly [kind: number, key: number | string, seq: number, id: string]\n\n/** One `CompoundIndex` entry: `[tupleKeys, seq, id]` — the tuple stays an ARRAY. */\nexport type WireCompoundEntry = readonly [keys: readonly WireKey[], seq: number, id: string]\n\nexport interface SortedIndexSnapshot {\n readonly v: number\n readonly t: 'sorted'\n readonly field: string\n readonly nextSeq: number\n readonly entries: readonly WireSortedEntry[]\n}\n\nexport interface CompoundIndexSnapshot {\n readonly v: number\n readonly t: 'compound'\n readonly fields: readonly string[]\n readonly nextSeq: number\n readonly entries: readonly WireCompoundEntry[]\n}\n\nexport type FieldIndexSnapshot = SortedIndexSnapshot | CompoundIndexSnapshot\n\n/**\n * Sidecar key for a single-field sorted index. Field paths are\n * percent-encoded so no field name can collide with the `,` the compound\n * form joins on, nor with the `s:` / `c:` discriminator.\n */\nexport function sortedIndexKey(field: string): string {\n return `s:${encodeURIComponent(field)}`\n}\n\n/** Sidecar key for a compound index over an ordered field tuple. */\nexport function compoundIndexKey(fields: readonly string[]): string {\n return `c:${fields.map(encodeURIComponent).join(',')}`\n}\n\n/** A key is well-formed only if its declared kind matches its value's runtime type. */\nfunction isWireKey(x: unknown): x is WireKey {\n if (!Array.isArray(x) || x.length !== 2) return false\n const [kind, key] = x as [unknown, unknown]\n // 0 = number, 1 = string, 2 = Date-as-epoch-millis. See `sorted-indexes.ts`.\n if (kind === 0 || kind === 2) return typeof key === 'number' && Number.isFinite(key)\n if (kind === 1) return typeof key === 'string'\n return false\n}\n\nfunction isSeq(x: unknown): x is number {\n return typeof x === 'number' && Number.isInteger(x) && x >= 0\n}\n\n/**\n * Decode + validate a persisted snapshot. Returns `null` — meaning \"rebuild\"\n * — for anything that is not exactly the current format: bad JSON (a torn\n * write), a version stamp from another release, a shape mismatch, a\n * malformed key, or entries out of the order the index's binary searches\n * require. A caller must never repair a snapshot; the source of truth is the\n * cache, and rebuilding from it is always available.\n */\nexport function parseFieldIndexSnapshot(json: string): FieldIndexSnapshot | null {\n let raw: unknown\n try {\n raw = JSON.parse(json)\n } catch {\n return null\n }\n if (typeof raw !== 'object' || raw === null) return null\n const o = raw as Record<string, unknown>\n if (o['v'] !== FIELD_INDEX_SNAPSHOT_VERSION) return null\n if (!isSeq(o['nextSeq']) || !Array.isArray(o['entries'])) return null\n const nextSeq = o['nextSeq']\n const entries = o['entries'] as unknown[]\n\n if (o['t'] === 'sorted') {\n if (typeof o['field'] !== 'string') return null\n const out: WireSortedEntry[] = []\n for (const e of entries) {\n if (!Array.isArray(e) || e.length !== 4) return null\n const [kind, key, seq, id] = e as [unknown, unknown, unknown, unknown]\n if (!isWireKey([kind, key])) return null\n if (!isSeq(seq) || seq >= nextSeq || typeof id !== 'string') return null\n out.push([kind as number, key as number | string, seq, id])\n }\n if (!isAscending(out.map(e => [[e[0], e[1]] as WireKey]), out.map(e => e[2]))) return null\n return { v: FIELD_INDEX_SNAPSHOT_VERSION, t: 'sorted', field: o['field'], nextSeq, entries: out }\n }\n\n if (o['t'] === 'compound') {\n const fields = o['fields']\n if (!Array.isArray(fields) || fields.length === 0 || !fields.every(f => typeof f === 'string')) return null\n const out: WireCompoundEntry[] = []\n for (const e of entries) {\n if (!Array.isArray(e) || e.length !== 3) return null\n const [keys, seq, id] = e as [unknown, unknown, unknown]\n if (!Array.isArray(keys) || keys.length !== fields.length || !keys.every(isWireKey)) return null\n if (!isSeq(seq) || seq >= nextSeq || typeof id !== 'string') return null\n out.push([keys as readonly WireKey[], seq, id])\n }\n if (!isAscending(out.map(e => e[0]), out.map(e => e[1]))) return null\n return { v: FIELD_INDEX_SNAPSHOT_VERSION, t: 'compound', fields, nextSeq, entries: out }\n }\n\n return null\n}\n\n/**\n * Every binary search in both index classes assumes `(keys…, seq)` ascending.\n * A blob that is not sorted would not merely be slow — it would answer\n * WRONGLY, so it is rejected rather than re-sorted (re-sorting would launder\n * a corrupt blob into a plausible-looking answer).\n */\nfunction isAscending(keys: ReadonlyArray<readonly WireKey[]>, seqs: readonly number[]): boolean {\n for (let i = 1; i < keys.length; i++) {\n const c = compareWireTuples(keys[i - 1]!, keys[i]!)\n if (c > 0) return false\n if (c === 0 && seqs[i - 1]! >= seqs[i]!) return false\n }\n return true\n}\n\nfunction compareWireTuples(a: readonly WireKey[], b: readonly WireKey[]): number {\n for (let i = 0; i < a.length; i++) {\n const x = a[i]!\n const y = b[i]!\n if (x[0] !== y[0]) return x[0] - y[0]\n if (typeof x[1] === 'number' && typeof y[1] === 'number') {\n if (x[1] !== y[1]) return x[1] - y[1]\n } else if (x[1] !== y[1]) {\n return x[1] < y[1] ? -1 : 1\n }\n }\n return 0\n}\n","/**\n * Sorted (range) secondary indexes — the ordered sibling of the hash\n * index in `eager-indexes.ts` (#1344).\n *\n * A sorted index is an array of `{ kind, key, seq, id }` entries kept in\n * ascending `(kindRank, key, seq)` order. Binary search then answers\n * `<`, `<=`, `>`, `>=`, `between` and `startsWith` as a contiguous slice,\n * and `orderedIds()` walks the array for `orderBy(field).limit(n)`.\n *\n * Three properties are load-bearing, each mirroring the linear scan this\n * replaces (`kernel/query/predicate.ts`):\n *\n * - **Kind-partitioned.** `evaluateFieldClause`'s `isComparable` refuses\n * to order two values of different runtime types, so entries are ranked\n * by kind FIRST. A `string` probe therefore cannot reach `number`\n * entries, exactly as the scan cannot. Values with no order-defined\n * type (booleans, objects, arrays) are not indexed at all.\n * - **Nullish is not indexed**, same as the hash index.\n * - **Ties keep insertion order** (`seq`), which after a `build()` is\n * snapshot order — so an index-served `orderBy(...).limit(n)` returns\n * the same rows the stable scan-and-sort would. An in-place UPDATE\n * reinstates the rank it held rather than appending (#1369): the record\n * cache does not move a re-`put` record, so neither may the index.\n *\n * Keys canonicalise through the SAME per-field closure the hash index\n * uses (`ViaPipeline.canonicalizeIndexKey`), so a Via-covered field's\n * entries live in one key space here too. Range DISPATCH for a\n * Via-covered clause is nevertheless declined by the query builder (a\n * money operand has no ordered stored-form probe) — see\n * `kernel/query/builder.ts`'s `candidateRecords`.\n *\n * PERSISTENCE (#1359) is OPT-IN, via `{ persist: true }` on the declaration.\n * {@link SortedIndex.toSnapshot} / {@link SortedIndex.loadSnapshot} are the\n * whole of this class's part in it — the encrypted sidecar, the freshness\n * stamp and the debounce live in `persisted-field-indexes.ts`. Without the\n * opt-in the index is in memory only and rebuilt on hydrate, as before.\n */\n\nimport { readPath } from '../../kernel/query/predicate.js'\nimport { KIND_STRING, compareKeys, toSortKey, type KeyKind, type SortKey } from '../../kernel/query/sort-key.js'\nimport {\n FIELD_INDEX_SNAPSHOT_VERSION,\n type FieldIndexSnapshot,\n type SortedIndexSnapshot,\n type WireSortedEntry,\n} from './index-snapshot.js'\n\n/** Range operators a sorted index can answer. */\nexport type RangeOperator = '<' | '<=' | '>' | '>=' | 'between' | 'startsWith'\n\n// The ordered-key encoding itself moved to `kernel/query/sort-key.ts` (#1339):\n// #1339's declared joins key on it too, and the kernel spine may not\n// statically import a `with-*` service (`check-architecture.mjs`'s\n// port-layering ratchet). Re-exported here so every existing importer of this\n// module is unchanged, and so there is still exactly ONE definition of what\n// makes two stored values comparable.\nexport { KIND_STRING, compareKeys, toSortKey, type KeyKind, type SortKey } from '../../kernel/query/sort-key.js'\n\ninterface Entry extends SortKey {\n readonly seq: number\n readonly id: string\n}\n\n/** A single field's sorted index. */\nexport class SortedIndex {\n private readonly entries: Entry[] = []\n private nextSeq = 0\n\n constructor(readonly field: string) {}\n\n get size(): number {\n return this.entries.length\n }\n\n clear(): void {\n this.entries.length = 0\n this.nextSeq = 0\n }\n\n /**\n * Insert one record. No-op when the value has no order-defined kind.\n *\n * `seq` REINSTATES a rank a previous entry for this id held — see\n * {@link remove}'s return value and `CollectionIndexes.upsert`. Omit it\n * for a fresh insert, which appends after every existing tie.\n */\n add(id: string, value: unknown, canonicalKey: string | undefined, seq?: number): void {\n const sk = toSortKey(value, canonicalKey)\n if (!sk) return\n const entry: Entry = { ...sk, seq: seq ?? this.nextSeq++, id }\n this.entries.splice(this.insertionPoint(entry), 0, entry)\n }\n\n /**\n * Remove one record, addressed by the value it was indexed under.\n * Returns the rank it held, so an UPDATE can reinstate it (#1369):\n * `sortRecords()` sorts a snapshot whose order does not change when a\n * record is written in place, so a tie-breaking rank that drifted to the\n * back on every `put` would make an index-served page disagree with the\n * scan it must match. Same contract as `CompoundIndex.remove`.\n */\n remove(id: string, value: unknown, canonicalKey: string | undefined): number | undefined {\n const sk = toSortKey(value, canonicalKey)\n if (!sk) return undefined\n // Every entry sharing this key is contiguous; walk that run for the id.\n for (let i = this.lowerBound(sk); i < this.entries.length; i++) {\n const e = this.entries[i]!\n if (compareKeys(e, sk) !== 0) break\n if (e.id === id) {\n this.entries.splice(i, 1)\n return e.seq\n }\n }\n return undefined\n }\n\n /**\n * Ids in ascending (or descending) key order. Ties keep INSERTION order\n * in both directions — `sortRecords()` negates its comparator over a\n * stable sort, which reverses the key order but not the order of equal\n * keys. A plain `.reverse()` here would disagree on ties.\n */\n orderedIds(direction: 'asc' | 'desc'): string[] {\n if (direction === 'asc') return this.entries.map(e => e.id)\n const out: string[] = []\n let end = this.entries.length\n while (end > 0) {\n let start = end - 1\n while (start > 0 && compareKeys(this.entries[start - 1]!, this.entries[end - 1]!) === 0) start--\n for (let i = start; i < end; i++) out.push(this.entries[i]!.id)\n end = start\n }\n return out\n }\n\n /**\n * Ids matching a range clause. Returns an empty set when the probe has\n * no comparable kind — which is what the linear scan would produce too.\n */\n lookup(op: RangeOperator, value: unknown): Set<string> {\n if (op === 'startsWith') return this.prefix(value)\n if (op === 'between') {\n if (!Array.isArray(value) || value.length !== 2) return new Set()\n const lo = toSortKey(value[0], undefined)\n const hi = toSortKey(value[1], undefined)\n if (!lo || !hi || lo.kind !== hi.kind) return new Set()\n return this.slice(this.lowerBound(lo), this.upperBound(hi))\n }\n const probe = toSortKey(value, undefined)\n if (!probe) return new Set()\n const lo = this.lowerBound(probe)\n const hi = this.upperBound(probe)\n // Kind-partitioned: `<`/`>` must stay inside the probe's own kind run.\n const [kindStart, kindEnd] = this.kindBounds(probe.kind)\n switch (op) {\n case '<':\n return this.slice(kindStart, lo)\n case '<=':\n return this.slice(kindStart, hi)\n case '>':\n return this.slice(hi, kindEnd)\n case '>=':\n return this.slice(lo, kindEnd)\n default: {\n const _exhaustive: never = op\n void _exhaustive\n return new Set()\n }\n }\n }\n\n private prefix(value: unknown): Set<string> {\n if (typeof value !== 'string') return new Set()\n const out = new Set<string>()\n const from = this.lowerBound({ kind: KIND_STRING, key: value })\n for (let i = from; i < this.entries.length; i++) {\n const e = this.entries[i]!\n if (e.kind !== KIND_STRING) break\n if (!(e.key as string).startsWith(value)) break\n out.add(e.id)\n }\n return out\n }\n\n private slice(from: number, to: number): Set<string> {\n const out = new Set<string>()\n for (let i = from; i < to; i++) out.add(this.entries[i]!.id)\n return out\n }\n\n /** [start, end) of the run of entries with the given kind — binary, not linear. */\n private kindBounds(kind: KeyKind): [number, number] {\n return [this.kindBoundary(k => k < kind), this.kindBoundary(k => k <= kind)]\n }\n\n private kindBoundary(before: (k: KeyKind) => boolean): number {\n let lo = 0\n let hi = this.entries.length\n while (lo < hi) {\n const mid = (lo + hi) >>> 1\n if (before(this.entries[mid]!.kind)) lo = mid + 1\n else hi = mid\n }\n return lo\n }\n\n /** First index whose key is >= `probe`. */\n private lowerBound(probe: SortKey): number {\n let lo = 0\n let hi = this.entries.length\n while (lo < hi) {\n const mid = (lo + hi) >>> 1\n if (compareKeys(this.entries[mid]!, probe) < 0) lo = mid + 1\n else hi = mid\n }\n return lo\n }\n\n /** First index whose key is > `probe`. */\n private upperBound(probe: SortKey): number {\n let lo = 0\n let hi = this.entries.length\n while (lo < hi) {\n const mid = (lo + hi) >>> 1\n if (compareKeys(this.entries[mid]!, probe) <= 0) lo = mid + 1\n else hi = mid\n }\n return lo\n }\n\n /**\n * The persistable form of this index (#1359). `kind` travels with every\n * key: entries rank by runtime kind first, so an encoding that dropped it\n * would let a `string` probe reach `number` entries on the way back in.\n */\n toSnapshot(): SortedIndexSnapshot {\n return {\n v: FIELD_INDEX_SNAPSHOT_VERSION,\n t: 'sorted',\n field: this.field,\n nextSeq: this.nextSeq,\n entries: this.entries.map(e => [e.kind, e.key, e.seq, e.id] as WireSortedEntry),\n }\n }\n\n /**\n * Adopt a validated snapshot, or refuse it. Refusal (`false`) means the\n * caller rebuilds — it NEVER means a partial index: the entries are staged\n * and only swapped in once every one of them is accepted.\n *\n * `isLive` is the caller's liveness predicate over the record cache. An\n * entry naming a record the cache does not hold means the blob and the\n * collection have diverged (a crash between the two writes, say), so the\n * whole blob is discarded. Crash residue must be a rebuild, never a wrong\n * answer.\n */\n loadSnapshot(snap: FieldIndexSnapshot, isLive: (id: string) => boolean): boolean {\n if (snap.t !== 'sorted' || snap.field !== this.field) return false\n const staged: Entry[] = []\n for (const [kind, key, seq, id] of snap.entries) {\n if (!isLive(id)) return false\n staged.push({ kind: kind as KeyKind, key, seq, id })\n }\n this.entries.length = 0\n for (const e of staged) this.entries.push(e)\n this.nextSeq = snap.nextSeq\n return true\n }\n\n /**\n * Insertion point that keeps ties in `seq` order. A fresh entry lands at\n * the end of its tie run; a REINSTATED one (see {@link add}) lands back at\n * its own rank inside it.\n */\n private insertionPoint(entry: Entry): number {\n let i = this.upperBound(entry)\n while (i > 0 && compareKeys(this.entries[i - 1]!, entry) === 0 && this.entries[i - 1]!.seq > entry.seq) {\n i--\n }\n return i\n }\n}\n\n/** Build the whole index from a snapshot. Entry seqs follow snapshot order. */\nexport function buildSortedIndex<T>(\n idx: SortedIndex,\n records: ReadonlyArray<{ id: string; record: T }>,\n canonicalize?: (field: string, value: unknown) => string | undefined,\n): void {\n idx.clear()\n for (const { id, record } of records) {\n const value = readPath(record, idx.field)\n if (value === null || value === undefined) continue\n idx.add(id, value, canonicalize?.(idx.field, value))\n }\n}\n\n","/**\n * Compound (multi-field) sorted indexes — the tuple-keyed sibling of\n * `sorted-indexes.ts` (#1345).\n *\n * A compound index is an array of `{ keys, seq, id }` entries kept in\n * ascending `(keys[0], keys[1], …, seq)` order, where each `keys[i]` is\n * the SAME `SortKey` the single-field sorted index builds — so the tuple\n * encoding is order-preserving per component BY CONSTRUCTION rather than\n * by a second, hand-rolled serialization. Nothing is flattened into a\n * delimited string: a string component can therefore contain any byte\n * without colliding with a separator, and a money field canonicalized to\n * a scaled-integer string (`ViaPipeline.canonicalizeIndexKey`) or a date\n * stored as ISO text sorts inside its own component exactly as it does in\n * the single-field index.\n *\n * The two load-bearing properties of #1344 hold PER COMPONENT:\n *\n * - **Kind-partitioned.** `compareKeys` ranks by runtime kind first, so\n * within any equality-prefix run a `string` probe on the next\n * component cannot reach `number` entries — mirroring `predicate.ts`'s\n * `isComparable`, exactly as the linear scan behaves.\n * - **Ties keep insertion order** in both directions. `orderedIds()`\n * walks equal-key runs forward even when emitting descending, because\n * `sortRecords()` negates its comparator over a STABLE sort.\n *\n * **A record is indexed only when EVERY component has an order-defined\n * value.** One nullish or non-orderable component and the record is\n * absent — which is why the query builder compares {@link\n * CompoundIndex.size} against the snapshot size before dispatching, and\n * falls back to the scan when the index does not cover the collection.\n *\n * PERSISTENCE (#1359) is OPT-IN, same as its single-field sibling. The wire\n * form keeps the tuple as an ARRAY of per-component keys — see\n * `index-snapshot.ts`: flattening it to a delimited string would destroy\n * exactly the per-component ordering and kind partition this class is built\n * to preserve.\n */\n\nimport { readPath } from '../../kernel/query/predicate.js'\nimport { KIND_STRING, compareKeys, toSortKey, type RangeOperator, type SortKey } from './sorted-indexes.js'\nimport {\n FIELD_INDEX_SNAPSHOT_VERSION,\n type CompoundIndexSnapshot,\n type FieldIndexSnapshot,\n type WireCompoundEntry,\n type WireKey,\n} from './index-snapshot.js'\n\n/** A range constraint on the component just past the equality prefix. */\nexport interface CompoundRangeProbe {\n readonly op: RangeOperator\n readonly value: unknown\n}\n\ninterface CompoundEntry {\n readonly keys: readonly SortKey[]\n readonly seq: number\n readonly id: string\n}\n\n/** One collection's index over an ordered field tuple. */\nexport class CompoundIndex {\n private readonly entries: CompoundEntry[] = []\n private nextSeq = 0\n\n constructor(readonly fields: readonly string[]) {}\n\n get size(): number {\n return this.entries.length\n }\n\n clear(): void {\n this.entries.length = 0\n this.nextSeq = 0\n }\n\n /**\n * Insert one record. No-op unless every component has an ordered key.\n *\n * `seq` REINSTATES a rank a previous entry for this id held — see\n * {@link remove}'s return value and `CollectionIndexes.upsert`. Omit it\n * for a fresh insert, which appends after every existing tie.\n */\n add(id: string, keys: readonly SortKey[] | undefined, seq?: number): void {\n if (!keys) return\n const entry: CompoundEntry = { keys, seq: seq ?? this.nextSeq++, id }\n this.entries.splice(this.insertionPoint(entry), 0, entry)\n }\n\n /**\n * Remove one record, addressed by the tuple it was indexed under.\n * Returns the rank it held, so an UPDATE can reinstate it: `sortRecords()`\n * sorts a snapshot whose order does not change when a record is written in\n * place, so a tie-breaking rank that drifted to the back on every `put`\n * would make an index-served page disagree with the scan it must match.\n */\n remove(id: string, keys: readonly SortKey[] | undefined): number | undefined {\n if (!keys) return undefined\n const [from, to] = this.run(keys, keys.length)\n for (let i = from; i < to; i++) {\n if (this.entries[i]!.id === id) {\n const [gone] = this.entries.splice(i, 1)\n return gone!.seq\n }\n }\n return undefined\n }\n\n /**\n * Ids matching an equality prefix, optionally narrowed by a range on\n * the next component. An empty set is authoritative: the index covers\n * these fields and nothing matches.\n */\n lookup(prefix: readonly SortKey[], range?: CompoundRangeProbe): Set<string> {\n const [from, to] = this.run(prefix, prefix.length)\n if (!range) return this.slice(from, to)\n const k = prefix.length\n if (k >= this.fields.length) return new Set()\n\n if (range.op === 'startsWith') {\n if (typeof range.value !== 'string') return new Set()\n const out = new Set<string>()\n const start = this.lowerBound([...prefix, { kind: KIND_STRING, key: range.value }], k + 1, from, to)\n for (let i = start; i < to; i++) {\n const key = this.entries[i]!.keys[k]!\n if (key.kind !== KIND_STRING) break\n if (!(key.key as string).startsWith(range.value)) break\n out.add(this.entries[i]!.id)\n }\n return out\n }\n\n if (range.op === 'between') {\n if (!Array.isArray(range.value) || range.value.length !== 2) return new Set()\n const lo = toSortKey(range.value[0], undefined)\n const hi = toSortKey(range.value[1], undefined)\n if (!lo || !hi || lo.kind !== hi.kind) return new Set()\n return this.slice(\n this.lowerBound([...prefix, lo], k + 1, from, to),\n this.upperBound([...prefix, hi], k + 1, from, to),\n )\n }\n\n const probe = toSortKey(range.value, undefined)\n if (!probe) return new Set()\n // Kind-partitioned per component: an open-ended bound stays inside the\n // probe's own kind run, so `< '5'` never sweeps up numeric entries.\n const [kindStart, kindEnd] = this.kindRun(from, to, k, probe.kind)\n const lo = this.lowerBound([...prefix, probe], k + 1, from, to)\n const hi = this.upperBound([...prefix, probe], k + 1, from, to)\n switch (range.op) {\n case '<':\n return this.slice(kindStart, lo)\n case '<=':\n return this.slice(kindStart, hi)\n case '>':\n return this.slice(hi, kindEnd)\n case '>=':\n return this.slice(lo, kindEnd)\n default: {\n const _exhaustive: never = range.op\n void _exhaustive\n return new Set()\n }\n }\n }\n\n /**\n * Ids matching an equality prefix, in the order of the remaining\n * components. Ties keep INSERTION order in both directions — a plain\n * `.reverse()` would disagree with `sortRecords()` on equal keys.\n */\n orderedIds(prefix: readonly SortKey[], direction: 'asc' | 'desc'): string[] {\n const [from, to] = this.run(prefix, prefix.length)\n const out: string[] = []\n if (direction === 'asc') {\n for (let i = from; i < to; i++) out.push(this.entries[i]!.id)\n return out\n }\n let end = to\n while (end > from) {\n let start = end - 1\n while (start > from && this.compare(this.entries[start - 1]!, this.entries[end - 1]!.keys, this.fields.length) === 0) {\n start--\n }\n for (let i = start; i < end; i++) out.push(this.entries[i]!.id)\n end = start\n }\n return out\n }\n\n private slice(from: number, to: number): Set<string> {\n const out = new Set<string>()\n for (let i = from; i < to; i++) out.add(this.entries[i]!.id)\n return out\n }\n\n /** [start, end) of the entries whose first `upto` components equal `probe`. */\n private run(probe: readonly SortKey[], upto: number): [number, number] {\n return [\n this.lowerBound(probe, upto, 0, this.entries.length),\n this.upperBound(probe, upto, 0, this.entries.length),\n ]\n }\n\n /** [start, end) of the entries in [from,to) whose component `k` has this kind. */\n private kindRun(from: number, to: number, k: number, kind: number): [number, number] {\n return [\n this.kindBoundary(from, to, k, x => x < kind),\n this.kindBoundary(from, to, k, x => x <= kind),\n ]\n }\n\n private kindBoundary(from: number, to: number, k: number, before: (kind: number) => boolean): number {\n let lo = from\n let hi = to\n while (lo < hi) {\n const mid = (lo + hi) >>> 1\n if (before(this.entries[mid]!.keys[k]!.kind)) lo = mid + 1\n else hi = mid\n }\n return lo\n }\n\n /** First index in [from,to) whose first `upto` components are >= `probe`. */\n private lowerBound(probe: readonly SortKey[], upto: number, from: number, to: number): number {\n let lo = from\n let hi = to\n while (lo < hi) {\n const mid = (lo + hi) >>> 1\n if (this.compare(this.entries[mid]!, probe, upto) < 0) lo = mid + 1\n else hi = mid\n }\n return lo\n }\n\n /** First index in [from,to) whose first `upto` components are > `probe`. */\n private upperBound(probe: readonly SortKey[], upto: number, from: number, to: number): number {\n let lo = from\n let hi = to\n while (lo < hi) {\n const mid = (lo + hi) >>> 1\n if (this.compare(this.entries[mid]!, probe, upto) <= 0) lo = mid + 1\n else hi = mid\n }\n return lo\n }\n\n /**\n * The persistable form of this index (#1359). Each entry's tuple stays an\n * ARRAY of `[kind, key]` pairs: nothing is joined into a string, so a\n * string component may hold any byte and the per-component kind partition\n * survives the round trip intact.\n */\n toSnapshot(): CompoundIndexSnapshot {\n return {\n v: FIELD_INDEX_SNAPSHOT_VERSION,\n t: 'compound',\n fields: [...this.fields],\n nextSeq: this.nextSeq,\n entries: this.entries.map(\n e => [e.keys.map(k => [k.kind, k.key] as WireKey), e.seq, e.id] as WireCompoundEntry,\n ),\n }\n }\n\n /**\n * Adopt a validated snapshot, or refuse it. Same contract as\n * `SortedIndex.loadSnapshot`: all-or-nothing, and an entry naming a record\n * the cache does not hold rejects the whole blob so crash residue becomes a\n * rebuild rather than a wrong answer. A snapshot whose field tuple is not\n * exactly this index's is refused — the declaration changed under it.\n */\n loadSnapshot(snap: FieldIndexSnapshot, isLive: (id: string) => boolean): boolean {\n if (snap.t !== 'compound') return false\n if (snap.fields.length !== this.fields.length) return false\n for (let i = 0; i < snap.fields.length; i++) if (snap.fields[i] !== this.fields[i]) return false\n const staged: CompoundEntry[] = []\n for (const [keys, seq, id] of snap.entries) {\n if (!isLive(id)) return false\n staged.push({ keys: keys.map(k => ({ kind: k[0] as SortKey['kind'], key: k[1] })), seq, id })\n }\n this.entries.length = 0\n for (const e of staged) this.entries.push(e)\n this.nextSeq = snap.nextSeq\n return true\n }\n\n /**\n * Insertion point that keeps ties in `seq` order. A fresh entry lands at\n * the end of its tie run; a REINSTATED one (see {@link add}) lands back at\n * its own rank inside it.\n */\n private insertionPoint(entry: CompoundEntry): number {\n const to = this.upperBound(entry.keys, this.fields.length, 0, this.entries.length)\n let i = to\n while (i > 0 && this.compare(this.entries[i - 1]!, entry.keys, this.fields.length) === 0\n && this.entries[i - 1]!.seq > entry.seq) {\n i--\n }\n return i\n }\n\n private compare(entry: CompoundEntry, probe: readonly SortKey[], upto: number): number {\n for (let i = 0; i < upto; i++) {\n const c = compareKeys(entry.keys[i]!, probe[i]!)\n if (c !== 0) return c\n }\n return 0\n }\n}\n\n/**\n * The tuple key for one record, or `undefined` when any component is\n * nullish or has no order-defined runtime type. Canonicalizes through the\n * same per-field closure the hash and sorted indexes use, so a Via-covered\n * component lives in one key space across all three.\n */\nexport function tupleKeyOf<T>(\n fields: readonly string[],\n record: T,\n canonicalize?: (field: string, value: unknown) => string | undefined,\n): SortKey[] | undefined {\n const keys: SortKey[] = []\n for (const field of fields) {\n const value = readPath(record, field)\n if (value === null || value === undefined) return undefined\n const key = toSortKey(value, canonicalize?.(field, value))\n if (!key) return undefined\n keys.push(key)\n }\n return keys\n}\n\n/** Probe keys for an equality prefix, or `undefined` if any operand is unorderable. */\nexport function probeKeysOf(values: readonly unknown[]): SortKey[] | undefined {\n const keys: SortKey[] = []\n for (const value of values) {\n const key = toSortKey(value, undefined)\n if (!key) return undefined\n keys.push(key)\n }\n return keys\n}\n\n/** Build the whole index from a snapshot. Entry seqs follow snapshot order. */\nexport function buildCompoundIndex<T>(\n idx: CompoundIndex,\n records: ReadonlyArray<{ id: string; record: T }>,\n canonicalize?: (field: string, value: unknown) => string | undefined,\n): void {\n idx.clear()\n for (const { id, record } of records) {\n idx.add(id, tupleKeyOf(idx.fields, record, canonicalize))\n }\n}\n\n/** Stable map key for a field tuple. `\\0` cannot appear in a field path. */\nexport function compoundKey(fields: readonly string[]): string {\n return fields.join('\\u0000')\n}\n","/**\n * Secondary indexes for the query DSL.\n *\n * ships **in-memory hash indexes**:\n * - Built during `Collection.ensureHydrated()` from the decrypted cache\n * - Maintained incrementally on `put` and `delete`\n * - Consulted by the query executor for `==` and `in` operators on\n * indexed fields, falling back to a linear scan otherwise\n * - Live entirely in memory — no adapter writes for the index itself\n *\n * Persistent encrypted index blobs (the spec's \"store as a separate\n * AES-256-GCM blob\" note) are deferred to a follow-up issue. The reasons\n * are documented in the PR body — short version: at the target\n * scale of 1K–50K records, building the index during hydrate is free,\n * so persistence buys nothing measurable.\n */\n\nimport { readPath } from '../../kernel/query/predicate.js'\nimport { stringifyBucketKey, isProbeableBucketKey } from '../../kernel/query/distinct-key.js'\nimport { SortedIndex, buildSortedIndex, type RangeOperator } from './sorted-indexes.js'\nimport {\n CompoundIndex,\n buildCompoundIndex,\n compoundKey,\n probeKeysOf,\n tupleKeyOf,\n type CompoundRangeProbe,\n} from './compound-indexes.js'\nimport {\n compoundIndexKey,\n sortedIndexKey,\n type FieldIndexSnapshot,\n} from './index-snapshot.js'\n\n/**\n * Index declaration accepted by `Collection`'s constructor.\n *\n * Accepts:\n * - `string` — a single-field hash index (`'clientId'`)\n * - `{ fields: [...] }` or `readonly string[]` — a composite index\n * over an ordered field tuple. Only lazy-mode\n * collections consume composite declarations today; eager mode\n * silently treats a composite as equivalent to declaring each\n * component field as its own single-field index.\n *\n * Additive variants (unique constraints, partial indexes) will land as\n * further union members without breaking existing declarations.\n */\nexport type IndexDef =\n | string\n | {\n readonly fields: readonly string[]\n /**\n * Enforce that no two records share this field tuple. A MULTI-field\n * tuple is a COMPOUND unique — uniqueness over the tuple, never over\n * each component on its own (`['workerId','employerId']` allows one\n * worker at many employers). Null-distinct: a record with `null` or\n * `undefined` in any constrained field is exempt.\n *\n * ⚠️ **What \"unique\" means depends on the collection's mode (#1358),\n * and one of the four cannot promise prevention at all:**\n *\n * - eager (default) — prevented, from the in-memory map.\n * - lazy (`prefetch: false`) — prevented, by a point lookup through the\n * persisted `_idx/` mirror. Requires `withIndexing()`.\n * - tiered (`tiers: [...]`) — prevented across every tier whose DEK the\n * writer holds. **A tier the writer cannot read is outside the\n * guarantee** — those records are unreadable, so no local check can\n * see them, and a duplicate against one is accepted.\n * - CRDT (`crdt: '...'`) — **NOT prevented.** Uniqueness cannot be\n * enforced across concurrent replicas: two replicas that are offline\n * from each other can both accept the same value, and no local check\n * can prevent that. The write always succeeds and both records are\n * kept; the collision is reported on the `unique:violation` event as\n * a `UniqueConstraintError`, both when it happens and when a later\n * session first sees the two records together. What you get is\n * uniqueness within what this writer could see at write time, plus\n * detection when the replicas meet.\n */\n readonly unique?: boolean\n readonly kind?: IndexKind\n /**\n * Persist this index as an encrypted sidecar so a restart reuses it\n * instead of rebuilding (#1359). Only meaningful with `kind: 'sorted'`\n * — the hash index is not persisted. OPT-IN until measured: at the\n * 1K–50K target scale rebuild-on-open is free, and a sidecar is a\n * write on every debounce window plus a blob at rest.\n */\n readonly persist?: boolean\n }\n | readonly string[]\n\n/**\n * The access structure an index declaration asks for (#1344).\n *\n * `'hash'` (the default, and what every pre-#1344 declaration means) is\n * the equality/`in` bucket map. `'sorted'` additionally maintains an\n * ordered array over the same canonicalized keys, which lights up\n * index-driven `<`, `<=`, `>`, `>=`, `between`, `startsWith` and\n * `orderBy(field).limit(n)`. A `'sorted'` declaration keeps the hash\n * index too — `==`/`in` stay O(1).\n */\nexport type IndexKind = 'hash' | 'sorted'\n\n/**\n * Normalize a declared `IndexDef[]` into a uniform `{ fields, unique? }`\n * shape: `string` → `{fields:[s]}`, `string[]` → `{fields}`, object →\n * passthrough. Pure — used by `Collection`'s sensitive-field leak check\n * and by `getDeclaredIndexes()` (introspection).\n */\nexport function normalizeIndexDefs(\n defs: readonly IndexDef[],\n): ReadonlyArray<{ readonly fields: readonly string[]; readonly unique?: boolean }> {\n return defs.map((def) => {\n if (typeof def === 'string') return { fields: [def] }\n if (Array.isArray(def)) return { fields: def }\n return def as { readonly fields: readonly string[]; readonly unique?: boolean }\n })\n}\n\n/**\n * Internal representation of a built hash index.\n *\n * Maps stringified field values to the set of record ids whose value\n * for that field matches. Stringification keeps the index simple and\n * works uniformly for primitives (`'open'`, `'42'`, `'true'`).\n *\n * Records whose indexed field is `undefined` or `null` are NOT inserted\n * — `query().where('field', '==', undefined)` falls back to a linear\n * scan, which is the conservative behavior.\n */\nexport interface HashIndex {\n readonly field: string\n readonly buckets: Map<string, Set<string>>\n}\n\n/**\n * Container for all indexes on a single collection.\n *\n * Methods are pure with respect to the in-memory `buckets` Map — they\n * never touch the adapter or the keyring. The Collection class owns\n * lifecycle (build on hydrate, maintain on put/delete).\n */\nexport class CollectionIndexes {\n private readonly indexes = new Map<string, HashIndex>()\n\n /**\n * Sorted (range) indexes, keyed by field — the #1344 half. Parallel to\n * `indexes` above and maintained at the SAME mutation sites, through the\n * SAME `canonicalize` closure, so the two can never disagree about which\n * key space a field lives in.\n */\n private readonly sorted = new Map<string, SortedIndex>()\n\n /**\n * Compound (tuple-keyed) sorted indexes, keyed by the joined field\n * tuple — the #1345 half. Third parallel map, maintained at the SAME\n * mutation sites through the SAME `canonicalize` closure as the other\n * two, so no field can end up in disagreeing key spaces.\n */\n private readonly compound = new Map<string, CompoundIndex>()\n\n /**\n * The indexes declared `persist: true` (#1359), keyed by their SIDECAR key\n * (`s:<field>` / `c:<f1>,<f2>`). A separate map rather than a flag on the\n * index classes: persistence is a property of the DECLARATION, and the\n * index classes stay unaware of storage.\n */\n private readonly persistable = new Map<string, SortedIndex | CompoundIndex>()\n\n /**\n * Per-field bucket-key canonicalizer (#672 review C1), registered ONCE\n * via {@link setCanonicalizer} when the collection wires indexing up\n * (money-aware via `ViaPipeline.canonicalizeIndexKey`). Consulted by\n * EVERY bucket-mutation site — `build`/`upsert`/`remove` — so bucket\n * membership is symmetric by construction: a value can never be added\n * under a canonical key and later removed under the raw one (or vice\n * versa), which is what stranded ids on `put`/`delete` before this fix.\n */\n private canonicalize?: (field: string, value: unknown) => string | undefined\n\n /**\n * Register the bucket-key canonicalizer. Called once, where the\n * collection constructs its indexing state — safe to call again (the\n * closure is simply replaced) but there is normally only one caller.\n */\n setCanonicalizer(fn: (field: string, value: unknown) => string | undefined): void {\n this.canonicalize = fn\n }\n\n /**\n * Declare an index. Subsequent record additions are tracked under it.\n * Calling this twice for the same field is a no-op (idempotent).\n */\n declare(field: string): void {\n if (this.indexes.has(field)) return\n this.indexes.set(field, { field, buckets: new Map() })\n }\n\n /**\n * Declare a sorted (range) index on a field. Independent of\n * {@link declare} — callers that want both `==` speed and range speed\n * declare both (which is what `withIndexing()` does for a\n * `kind: 'sorted'` declaration). Idempotent.\n */\n declareSorted(field: string, opts?: { readonly persist?: boolean }): void {\n let idx = this.sorted.get(field)\n if (!idx) {\n idx = new SortedIndex(field)\n this.sorted.set(field, idx)\n }\n if (opts?.persist) this.persistable.set(sortedIndexKey(field), idx)\n }\n\n /** True if the given field has a declared SORTED index. */\n hasSorted(field: string): boolean {\n return this.sorted.has(field)\n }\n\n /** All sorted-index field names, in declaration order. */\n sortedFields(): string[] {\n return [...this.sorted.keys()]\n }\n\n /** Number of entries in a field's sorted index (0 when undeclared). */\n sortedSize(field: string): number {\n return this.sorted.get(field)?.size ?? 0\n }\n\n /**\n * Range lookup: ids whose `field` satisfies the operator. Returns\n * `null` when no SORTED index covers the field — the caller falls back\n * to a linear scan. An empty set means \"the index covers this field and\n * nothing matches\", which is authoritative.\n */\n lookupRange(field: string, op: RangeOperator, value: unknown): ReadonlySet<string> | null {\n return this.sorted.get(field)?.lookup(op, value) ?? null\n }\n\n /**\n * Ids of every indexed record in `field` order. `null` when no sorted\n * index covers the field. Records whose value is nullish or has no\n * order-defined type are absent — compare against {@link sortedSize}\n * before treating the result as the full collection.\n */\n orderedIds(field: string, direction: 'asc' | 'desc'): readonly string[] | null {\n return this.sorted.get(field)?.orderedIds(direction) ?? null\n }\n\n /**\n * Declare a compound (multi-field) sorted index over an ordered field\n * tuple. A tuple shorter than two fields is a single-field sorted index\n * and is ignored here. Idempotent.\n */\n declareCompound(fields: readonly string[], opts?: { readonly persist?: boolean }): void {\n if (fields.length < 2) return\n const key = compoundKey(fields)\n let idx = this.compound.get(key)\n if (!idx) {\n idx = new CompoundIndex([...fields])\n this.compound.set(key, idx)\n }\n if (opts?.persist) this.persistable.set(compoundIndexKey(fields), idx)\n }\n\n /** Every declared field tuple, in declaration order. */\n compoundTuples(): ReadonlyArray<readonly string[]> {\n return [...this.compound.values()].map(idx => idx.fields)\n }\n\n /**\n * Number of records the tuple's index holds (0 when undeclared). A\n * record with a nullish or non-orderable component is absent, so a\n * caller that removes clauses from the plan MUST compare this against\n * the snapshot size before trusting the result.\n */\n compoundSize(fields: readonly string[]): number {\n return this.compound.get(compoundKey(fields))?.size ?? 0\n }\n\n /**\n * Compound lookup: ids whose leading components equal `prefixValues`,\n * optionally narrowed by a range on the component just past them.\n * `null` when no compound index covers the tuple, or when an operand\n * has no order-defined type — the caller falls back to a linear scan.\n */\n lookupCompound(\n fields: readonly string[],\n prefixValues: readonly unknown[],\n range?: CompoundRangeProbe,\n ): ReadonlySet<string> | null {\n const idx = this.compound.get(compoundKey(fields))\n if (!idx) return null\n const prefix = probeKeysOf(prefixValues)\n if (!prefix) return null\n return idx.lookup(prefix, range)\n }\n\n /**\n * Ids matching an equality prefix, ordered by the remaining components.\n * `null` when no compound index covers the tuple or an operand has no\n * order-defined type. See {@link compoundSize} for the coverage caveat.\n */\n compoundOrderedIds(\n fields: readonly string[],\n prefixValues: readonly unknown[],\n direction: 'asc' | 'desc',\n ): readonly string[] | null {\n const idx = this.compound.get(compoundKey(fields))\n if (!idx) return null\n const prefix = probeKeysOf(prefixValues)\n if (!prefix) return null\n return idx.orderedIds(prefix, direction)\n }\n\n /** True if the given field has a declared index. */\n has(field: string): boolean {\n return this.indexes.has(field)\n }\n\n /** All declared field names, in declaration order. */\n fields(): string[] {\n return [...this.indexes.keys()]\n }\n\n /**\n * Build all declared indexes from a snapshot of records.\n * Called once per hydration. O(N × indexes.size). Buckets through the\n * registered {@link setCanonicalizer} closure, same as `upsert`/`remove`.\n */\n build<T>(records: ReadonlyArray<{ id: string; record: T }>, skip: ReadonlySet<string> = EMPTY_KEYS): void {\n for (const idx of this.indexes.values()) {\n idx.buckets.clear()\n for (const { id, record } of records) {\n addToIndex(idx, id, record, this.canonicalize)\n }\n }\n // `skip` names the sidecar keys a persisted snapshot already restored\n // (#1359) — rebuilding them would throw that work away AND renumber every\n // `seq`, which is what the whole ordered fast path rests on.\n for (const [field, idx] of this.sorted) {\n if (skip.has(sortedIndexKey(field))) continue\n buildSortedIndex(idx, records, this.canonicalize)\n }\n for (const idx of this.compound.values()) {\n if (skip.has(compoundIndexKey(idx.fields))) continue\n buildCompoundIndex(idx, records, this.canonicalize)\n }\n }\n\n /** Sidecar keys of every index declared `persist: true`, in declaration order. */\n persistableKeys(): readonly string[] {\n return [...this.persistable.keys()]\n }\n\n /** The persistable snapshot behind one sidecar key, or `undefined` if it is not declared. */\n snapshotIndex(key: string): FieldIndexSnapshot | undefined {\n return this.persistable.get(key)?.toSnapshot()\n }\n\n /**\n * Adopt a validated snapshot into the index behind `key`. `false` means the\n * caller must rebuild that index from the cache — the index is left\n * untouched, never half-loaded.\n */\n restoreIndex(key: string, snap: FieldIndexSnapshot, isLive: (id: string) => boolean): boolean {\n return this.persistable.get(key)?.loadSnapshot(snap, isLive) ?? false\n }\n\n /**\n * Insert or update a single record across all indexes.\n * Called by `Collection.put()` after the encrypted write succeeds.\n *\n * If `previousRecord` is provided, the record is removed from any old\n * buckets first — this is the update path. Pass `null` for fresh adds.\n */\n upsert<T>(id: string, newRecord: T, previousRecord: T | null): void {\n if (this.indexes.size === 0 && this.sorted.size === 0 && this.compound.size === 0) return\n // Detach the compound and sorted entries FIRST, holding the rank each one had. An\n // in-place `put` does not move a record within `snapshot()`, so it must\n // not move it within a tie run either — otherwise an index-served\n // `orderBy(...).limit(n)` page disagrees with the stable scan-and-sort\n // it is required to reproduce exactly (#1345, #1369). The `this.remove()`\n // below re-runs both removals, which are then no-ops.\n const ranks = new Map<string, number | undefined>()\n const sortedRanks = new Map<string, number | undefined>()\n if (previousRecord !== null) {\n for (const [key, idx] of this.compound) {\n ranks.set(key, idx.remove(id, tupleKeyOf(idx.fields, previousRecord, this.canonicalize)))\n }\n // Same for the single-field sorted indexes (#1369) — the defect and the\n // remedy are identical, and the two implementations must agree.\n for (const [key, idx] of this.sorted) {\n const value = readPath(previousRecord, idx.field)\n if (value === null || value === undefined) continue\n sortedRanks.set(key, idx.remove(id, value, this.canonicalize?.(idx.field, value)))\n }\n this.remove(id, previousRecord)\n }\n for (const idx of this.indexes.values()) {\n addToIndex(idx, id, newRecord, this.canonicalize)\n }\n for (const [key, idx] of this.sorted) {\n const value = readPath(newRecord, idx.field)\n if (value === null || value === undefined) continue\n idx.add(id, value, this.canonicalize?.(idx.field, value), sortedRanks.get(key))\n }\n for (const [key, idx] of this.compound) {\n idx.add(id, tupleKeyOf(idx.fields, newRecord, this.canonicalize), ranks.get(key))\n }\n }\n\n /**\n * Remove a record from all indexes. Called by `Collection.delete()`\n * (and as the first half of `upsert` for the update path).\n */\n remove<T>(id: string, record: T): void {\n if (this.indexes.size === 0 && this.sorted.size === 0 && this.compound.size === 0) return\n for (const idx of this.indexes.values()) {\n removeFromIndex(idx, id, record, this.canonicalize)\n }\n for (const idx of this.sorted.values()) {\n const value = readPath(record, idx.field)\n if (value === null || value === undefined) continue\n idx.remove(id, value, this.canonicalize?.(idx.field, value))\n }\n for (const idx of this.compound.values()) {\n idx.remove(id, tupleKeyOf(idx.fields, record, this.canonicalize))\n }\n }\n\n /** Drop all index data. Called when the collection is invalidated. */\n clear(): void {\n for (const idx of this.indexes.values()) {\n idx.buckets.clear()\n }\n for (const idx of this.sorted.values()) {\n idx.clear()\n }\n for (const idx of this.compound.values()) {\n idx.clear()\n }\n }\n\n /**\n * Equality lookup: return the set of record ids whose `field` matches\n * the given value. Returns `null` if no index covers the field — the\n * caller should fall back to a linear scan.\n *\n * ⛔ ALSO `null` when the OPERAND has no bucket ADDRESS (#1402) — a\n * nullish operand, or an object one, which every object-valued record in\n * the collection shares. Answering those from the buckets returns rows\n * the scan does not, silently, and only on the collections that happen to\n * have an index. See `isProbeableBucketKey` for the two measurements.\n *\n * The returned Set is a reference to the index's internal storage —\n * callers must NOT mutate it.\n */\n lookupEqual(field: string, value: unknown): ReadonlySet<string> | null {\n const idx = this.indexes.get(field)\n if (!idx) return null\n if (!isProbeableBucketKey(value)) return null\n const key = stringifyKey(value)\n return idx.buckets.get(key) ?? EMPTY_SET\n }\n\n /**\n * Set lookup: return the union of record ids whose `field` matches any\n * of the given values. Returns `null` if no index covers the field.\n *\n * ⛔ ALSO `null` when ANY member of `values` has no bucket address\n * (#1402) — one unaddressable member poisons the whole union, since the\n * result is a union and there is no partial answer to hand back. Same\n * measurement as {@link lookupEqual}.\n */\n lookupIn(field: string, values: readonly unknown[]): ReadonlySet<string> | null {\n const idx = this.indexes.get(field)\n if (!idx) return null\n if (!values.every(isProbeableBucketKey)) return null\n const out = new Set<string>()\n for (const value of values) {\n const key = stringifyKey(value)\n const bucket = idx.buckets.get(key)\n if (bucket) {\n for (const id of bucket) out.add(id)\n }\n }\n return out\n }\n\n /**\n * One record id per NON-EMPTY bucket of `field`'s hash index, in bucket\n * order — the index-backed spine of `Query.distinct()` (#1347). `null` when\n * no hash index covers the field, so the caller scans instead.\n *\n * The bucket set IS the distinct key set, so this costs O(buckets) rather\n * than O(records). It returns REPRESENTATIVE IDS rather than the keys\n * themselves on purpose: a bucket key is a canonical string (money's\n * BigInt-normalized scaled int, say), and `distinct()` owes its caller the\n * field's real value, which only the record carries.\n *\n * Bucket insertion order is first-seen record order — `build()` walks the\n * snapshot in order and `upsert()` appends — which is why an index-backed\n * `distinct()` and a scanned one agree on ORDER too, not merely on the set.\n * Empty buckets are skipped defensively; `removeFromIndex` already deletes\n * them, so this is belt-and-braces against a future partial removal path.\n */\n bucketRepresentatives(field: string): readonly string[] | null {\n const idx = this.indexes.get(field)\n if (!idx) return null\n const out: string[] = []\n for (const bucket of idx.buckets.values()) {\n for (const id of bucket) {\n out.push(id)\n break\n }\n }\n return out\n }\n}\n\nconst EMPTY_SET: ReadonlySet<string> = new Set()\nconst EMPTY_KEYS: ReadonlySet<string> = new Set()\n\n/**\n * Stringify a value into a stable bucket key.\n *\n * ⚠️ The DEFINITION moved to `kernel/query/distinct-key.ts` (#1347) and is\n * only aliased here. `distinct()` / `countDistinct()` recompute this key on\n * the scan path, and an index-backed `distinct()` reads the buckets it made —\n * one definition is what stops those two answers from drifting apart. Change\n * the shared function, not a copy.\n */\nconst stringifyKey = stringifyBucketKey\n\nfunction addToIndex<T>(\n idx: HashIndex,\n id: string,\n record: T,\n canonicalize?: (field: string, value: unknown) => string | undefined,\n): void {\n const value = readPath(record, idx.field)\n if (value === null || value === undefined) return\n const key = canonicalize?.(idx.field, value) ?? stringifyKey(value)\n let bucket = idx.buckets.get(key)\n if (!bucket) {\n bucket = new Set()\n idx.buckets.set(key, bucket)\n }\n bucket.add(id)\n}\n\nfunction removeFromIndex<T>(\n idx: HashIndex,\n id: string,\n record: T,\n canonicalize?: (field: string, value: unknown) => string | undefined,\n): void {\n const value = readPath(record, idx.field)\n if (value === null || value === undefined) return\n const key = canonicalize?.(idx.field, value) ?? stringifyKey(value)\n const bucket = idx.buckets.get(key)\n if (!bucket) return\n bucket.delete(id)\n // Clean up empty buckets so the Map doesn't accumulate dead keys.\n if (bucket.size === 0) idx.buckets.delete(key)\n}\n"],"mappings":"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","names":["lo","hi","lo","hi"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  linkI18nVia
3
- } from "./chunk-TRGTKX5E.js";
3
+ } from "./chunk-OKSTSITU.js";
4
4
 
5
5
  // src/via/i18n/dictionary.ts
6
6
  function dictKey(name, keysOrMap, opts) {
@@ -71,4 +71,4 @@ export {
71
71
  dictKey,
72
72
  staticDict
73
73
  };
74
- //# sourceMappingURL=chunk-MVMXZYXT.js.map
74
+ //# sourceMappingURL=chunk-2GHDLTPE.js.map
@@ -1,6 +1,10 @@
1
+ import {
2
+ hasSealedBody
3
+ } from "./chunk-EZGV6F47.js";
4
+
1
5
  // src/with-shape/satellites/existence.ts
2
6
  function isEnvelopeLive(env) {
3
- return env !== null && !(env._iv === "" && env._data === "");
7
+ return env !== null && (hasSealedBody(env) || (env._data ?? "") !== "");
4
8
  }
5
9
  async function isBaseLive(adapter, vault, base, id) {
6
10
  return isEnvelopeLive(await adapter.get(vault, base, id));
@@ -16,4 +20,4 @@ export {
16
20
  isBaseLive,
17
21
  liveBaseIdSet
18
22
  };
19
- //# sourceMappingURL=chunk-GYGLAVCX.js.map
23
+ //# sourceMappingURL=chunk-2MG3SW7Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-shape/satellites/existence.ts"],"sourcesContent":["import type { NoydbStore, EncryptedEnvelope } from '../../kernel/types.js'\nimport { hasSealedBody } from '../../capsule/index.js'\n\n/**\n * Existence authority (spec § Convergence & existence authority, rule 1): the\n * base row is the sole authority on record existence. `null` (absent) and the\n * tombstone shape (`_iv === '' && _data === ''`, per `buildTombstone()`) both\n * read as \"not live\" — undecrypted, envelope-level checks only.\n */\nfunction isEnvelopeLive(env: EncryptedEnvelope | null): boolean {\n // #15: absence is the same statement as `''`, so both spellings of a\n // bodyless envelope must read as NOT existing. `hasSealedBody` carries\n // that equivalence; the raw `=== ''` comparison silently lost it for an\n // omitted field — and, being a comparison rather than a read, it stayed\n // perfectly well-typed while doing so.\n return env !== null && (hasSealedBody(env) || (env._data ?? '') !== '')\n}\n\n/** One undecrypted adapter `get` on the base — the store-shape the spec pins (zero extra crypto). */\nexport async function isBaseLive(adapter: NoydbStore, vault: string, base: string, id: string): Promise<boolean> {\n return isEnvelopeLive(await adapter.get(vault, base, id))\n}\n\n/** The set of base ids that are currently live — used to id-filter satellite `list()` results. */\nexport async function liveBaseIdSet(adapter: NoydbStore, vault: string, base: string): Promise<Set<string>> {\n const ids = await adapter.list(vault, base)\n const out = new Set<string>()\n for (const id of ids) if (await isBaseLive(adapter, vault, base, id)) out.add(id)\n return out\n}\n"],"mappings":";;;;;AASA,SAAS,eAAe,KAAwC;AAM9D,SAAO,QAAQ,SAAS,cAAc,GAAG,MAAM,IAAI,SAAS,QAAQ;AACtE;AAGA,eAAsB,WAAW,SAAqB,OAAe,MAAc,IAA8B;AAC/G,SAAO,eAAe,MAAM,QAAQ,IAAI,OAAO,MAAM,EAAE,CAAC;AAC1D;AAGA,eAAsB,cAAc,SAAqB,OAAe,MAAoC;AAC1G,QAAM,MAAM,MAAM,QAAQ,KAAK,OAAO,IAAI;AAC1C,QAAM,MAAM,oBAAI,IAAY;AAC5B,aAAW,MAAM,IAAK,KAAI,MAAM,WAAW,SAAS,OAAO,MAAM,EAAE,EAAG,KAAI,IAAI,EAAE;AAChF,SAAO;AACT;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ReadOnlyFrameError
3
- } from "./chunk-7O3Y4PPD.js";
3
+ } from "./chunk-37EPTBBR.js";
4
4
 
5
5
  // src/with-fork/shadow/vault-frame.ts
6
6
  var VaultFrame = class {
@@ -71,4 +71,4 @@ export {
71
71
  VaultFrame,
72
72
  CollectionFrame
73
73
  };
74
- //# sourceMappingURL=chunk-XLMEZIAJ.js.map
74
+ //# sourceMappingURL=chunk-2ODVB6LZ.js.map
@@ -1,10 +1,13 @@
1
1
  import {
2
2
  validateProjectionLegs
3
- } from "./chunk-PPTHY5QO.js";
3
+ } from "./chunk-JIBUPZHA.js";
4
+ import {
5
+ describeGroupKey
6
+ } from "./chunk-XBKH4FOC.js";
4
7
  import {
5
8
  MaterializedViewConfigError,
6
9
  ValidationError
7
- } from "./chunk-7O3Y4PPD.js";
10
+ } from "./chunk-37EPTBBR.js";
8
11
 
9
12
  // src/with-formula/materialized-views/with-materialized-view.ts
10
13
  function withMaterializedView(spec) {
@@ -60,12 +63,12 @@ function withMaterializedView(spec) {
60
63
  `withMaterializedView "${spec.name}": UNION strategy with aggregate requires groupBy \u2014 use groupBy to declare the bucketing keys, or remove aggregate for a pure dedup MV`
61
64
  );
62
65
  }
63
- if (spec.moneyFields && !spec.aggregate) {
66
+ if (spec.moneyFields && !spec.aggregate && !spec.window) {
64
67
  throw new MaterializedViewConfigError(
65
- `withMaterializedView "${spec.name}": moneyFields requires aggregate \u2014 moneyFields rewrites sum/min/max reducers over money output fields, so it is meaningless without an aggregate spec`
68
+ `withMaterializedView "${spec.name}": moneyFields requires aggregate or window \u2014 moneyFields rewrites sum/min/max reducers over money output fields, so it is meaningless without one`
66
69
  );
67
70
  }
68
- if (spec.unionSources.some((s) => s.join && s.join.length > 0) && (!spec.sources || spec.sources.length === 0)) {
71
+ if (spec.unionSources.some((s) => s.join?.some((leg) => !("on" in leg))) && (!spec.sources || spec.sources.length === 0)) {
69
72
  throw new MaterializedViewConfigError(
70
73
  `withMaterializedView "${spec.name}": a unionSources arm declares join(s) but no \`sources\` are listed \u2014 declare sources: [...] with the right-side (join-target) collection names so writes to them trigger MV refresh`
71
74
  );
@@ -76,6 +79,28 @@ function withMaterializedView(spec) {
76
79
  );
77
80
  }
78
81
  }
82
+ if (spec.window) {
83
+ if (spec.query) {
84
+ throw new MaterializedViewConfigError(
85
+ `withMaterializedView "${spec.name}": window is not supported on the query() form \u2014 the rows come from a Query, which has its own .window(...).select(...). window is for the unionSources / projection forms, whose rows are mapped`
86
+ );
87
+ }
88
+ if (typeof spec.window.select !== "object" || spec.window.select === null || Object.keys(spec.window.select).length === 0) {
89
+ throw new MaterializedViewConfigError(
90
+ `withMaterializedView "${spec.name}": window.select must declare at least one output \u2014 a window that selects nothing computes nothing, so declaring one is more likely a mistake than an intention`
91
+ );
92
+ }
93
+ const groupFields = new Set(
94
+ spec.groupBy === void 0 ? [] : (Array.isArray(spec.groupBy) ? spec.groupBy : [spec.groupBy]).map(describeGroupKey)
95
+ );
96
+ for (const key of Object.keys(spec.window.select)) {
97
+ if (groupFields.has(key)) {
98
+ throw new MaterializedViewConfigError(
99
+ `withMaterializedView "${spec.name}": window.select["${key}"] collides with a groupBy key \u2014 a group key is the row's identity and feeds rowKey, so a window output may not overwrite it. Pick another name for the window column`
100
+ );
101
+ }
102
+ }
103
+ }
79
104
  if (spec.projection) {
80
105
  const projection = spec.projection;
81
106
  if (typeof projection.source !== "string" || projection.source.length === 0) {
@@ -148,9 +173,9 @@ function withMaterializedView(spec) {
148
173
  `withMaterializedView "${spec.name}": projection strategy with aggregate requires groupBy \u2014 use groupBy to declare the bucketing keys, or remove aggregate for a row-per-primary-record MV`
149
174
  );
150
175
  }
151
- if (spec.moneyFields && !spec.aggregate) {
176
+ if (spec.moneyFields && !spec.aggregate && !spec.window) {
152
177
  throw new MaterializedViewConfigError(
153
- `withMaterializedView "${spec.name}": moneyFields requires aggregate \u2014 moneyFields rewrites sum/min/max reducers over money output fields, so it is meaningless without an aggregate spec`
178
+ `withMaterializedView "${spec.name}": moneyFields requires aggregate or window \u2014 moneyFields rewrites sum/min/max reducers over money output fields, so it is meaningless without one`
154
179
  );
155
180
  }
156
181
  if (spec.predicates) {
@@ -183,4 +208,4 @@ function withMaterializedView(spec) {
183
208
  export {
184
209
  withMaterializedView
185
210
  };
186
- //# sourceMappingURL=chunk-HJUWN7JN.js.map
211
+ //# sourceMappingURL=chunk-2PVXF5CS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-formula/materialized-views/with-materialized-view.ts"],"sourcesContent":["import { MaterializedViewConfigError, ValidationError } from '../../kernel/errors.js'\nimport type { MaterializedViewSpec, MaterializedViewStrategy } from './types.js'\nimport { validateProjectionLegs } from './projection-legs.js' // #1140\nimport { describeGroupKey } from '../../kernel/query/reduce/date-trunc.js'\n\n/**\n * Register a materialized view: a declared query whose result is\n * persisted as a queryable collection and kept fresh as sources\n * change. Writes go through the standard `Collection.put` pipeline;\n * refresh-driven deletes route through `Collection._internalDelete` so\n * user `onDelete` guards on the output collection aren't tripped by\n * housekeeping.\n *\n * Three registration modes:\n * - **single-source** — declare `query: (db) => Query<TRow>`; the\n * dependency analyzer derives source collections from the plan.\n * - **UNION** — declare `unionSources: [{ collection, map }, ...]`\n * plus optional `groupBy` + `aggregate`; the executor reads each\n * arm, maps to the unified row shape, concatenates, then groups\n * and aggregates.\n * - **projection** (#810) — declare `projection: { source, joins,\n * map }`; one output row per primary record, enriched with\n * forward FK legs and reverse \"collect\" legs before `map` runs.\n *\n * The three modes are mutually exclusive — exactly one of `query` /\n * `unionSources` / `projection` must be set at registration time.\n *\n * See design-history/2026-05-20-dim14-mv-v2-design.md (single-source v2),\n * design-history/2026-05-21-dim14-mv-multikey-and-union.md (UNION),\n * and design-history/2026-07-25-join-projection-mv-design.md (projection).\n */\nexport function withMaterializedView<TRow extends Record<string, unknown>>(\n spec: MaterializedViewSpec<TRow>,\n): MaterializedViewStrategy {\n if (!spec.name || spec.name.length === 0) {\n throw new ValidationError('withMaterializedView: name is required')\n }\n // Mutual exclusion: exactly one of the three forms must be declared.\n const declaredForms = [spec.query, spec.unionSources, spec.projection]\n .filter((f) => f !== undefined).length\n if (declaredForms > 1) {\n throw new MaterializedViewConfigError(\n 'query, unionSources, and projection are mutually exclusive — pick one',\n )\n }\n if (declaredForms === 0) {\n throw new MaterializedViewConfigError(\n 'strategy must declare exactly one of query, unionSources, or projection',\n )\n }\n if (spec.query !== undefined && typeof spec.query !== 'function') {\n throw new ValidationError('withMaterializedView: query must be a function returning a Query<T>')\n }\n // UNION-form invariants.\n if (spec.unionSources) {\n // A single arm is a deliberate shape: map→group→aggregate over\n // ONE collection with a COMPUTED bucket key (e.g. month sliced from a\n // date field) — something the query form's stored-field groupBy cannot\n // express. The executor and dependency analyzer are arm-count-agnostic.\n if (spec.unionSources.length < 1) {\n throw new MaterializedViewConfigError(\n 'unionSources requires at least 1 source collection',\n )\n }\n const seen = new Set<string>()\n for (const s of spec.unionSources) {\n if (typeof s?.collection !== 'string' || s.collection.length === 0) {\n throw new MaterializedViewConfigError(\n 'each unionSources entry must declare a non-empty `collection` string',\n )\n }\n if (typeof s.map !== 'function') {\n throw new MaterializedViewConfigError(\n `unionSources entry for \"${s.collection}\" is missing a \\`map\\` function`,\n )\n }\n if (seen.has(s.collection)) {\n throw new MaterializedViewConfigError(\n `unionSources must reference distinct collections (duplicate: \"${s.collection}\")`,\n )\n }\n seen.add(s.collection)\n }\n if (Array.isArray(spec.groupBy) && spec.groupBy.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": groupBy must not be an empty array — omit it or provide at least one field name`,\n )\n }\n if (spec.aggregate && !spec.groupBy) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": UNION strategy with aggregate requires groupBy — `\n + `use groupBy to declare the bucketing keys, or remove aggregate for a pure dedup MV`,\n )\n }\n // `moneyFields` only has meaning when there's a reducer to money-rewrite —\n // it keys reducer outputs, so declaring it with neither is a no-op config\n // mistake.\n //\n // ⚠️ #1411 widened this: a WINDOW's reducer slots are money-rewritten by\n // the same binding, so `moneyFields` is meaningful for a view that\n // declares a window and no aggregate — which is exactly the pilot's\n // per-row running total. Before the widening this guard refused that view\n // with a message about aggregates it was not trying to use.\n if (spec.moneyFields && !spec.aggregate && !spec.window) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": moneyFields requires aggregate or window — `\n + `moneyFields rewrites sum/min/max reducers over money output fields, `\n + `so it is meaningless without one`,\n )\n }\n // Per-arm joins resolve right-side collections that the union\n // dependency set (built from arm `collection`s alone) does NOT\n // include. The consumer must list those right-side collections in\n // `sources` so writes to them trigger MV refresh.\n // #1411 — declared (`on`) legs name their target literally and fold it in\n // themselves; only ref legs need the consumer to list the right side.\n if (spec.unionSources.some(s => s.join?.some(leg => !('on' in leg))) && (!spec.sources || spec.sources.length === 0)) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a unionSources arm declares join(s) but `\n + `no \\`sources\\` are listed — declare sources: [...] with the right-side `\n + `(join-target) collection names so writes to them trigger MV refresh`,\n )\n }\n if (spec.predicates) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": predicates are not supported on UNION strategies — `\n + `UNION mode does not use a Query<T> chain, so .wherePredicate() cannot fire. `\n + `Use the query() form, or open an issue if per-arm predicates are needed`,\n )\n }\n }\n // #1411 — window-form invariants. Shared by UNION and projection, since the\n // stage runs at both exits from the grouping tail.\n if (spec.window) {\n if (spec.query) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": window is not supported on the query() form — `\n + `the rows come from a Query, which has its own .window(...).select(...). `\n + `window is for the unionSources / projection forms, whose rows are mapped`,\n )\n }\n if (typeof spec.window.select !== 'object' || spec.window.select === null\n || Object.keys(spec.window.select).length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": window.select must declare at least one output — `\n + `a window that selects nothing computes nothing, so declaring one is `\n + `more likely a mistake than an intention`,\n )\n }\n // Same rule `derive` has, and the same reason: a group key is the row's\n // identity and feeds rowKey, so writing one from a later stage would\n // silently re-home the row.\n const groupFields = new Set<string>(\n spec.groupBy === undefined\n ? []\n : (Array.isArray(spec.groupBy) ? spec.groupBy : [spec.groupBy]).map(describeGroupKey),\n )\n for (const key of Object.keys(spec.window.select)) {\n if (groupFields.has(key)) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": window.select[\"${key}\"] collides with a groupBy key — `\n + `a group key is the row's identity and feeds rowKey, so a window output `\n + `may not overwrite it. Pick another name for the window column`,\n )\n }\n }\n }\n\n // Projection-form invariants (#810). Shape checks only — the\n // semantic ref() check on collect legs (the `on` field must carry a\n // ref() targeting the projection source) runs at first\n // materialization, parity with join-time ref errors.\n if (spec.projection) {\n const projection = spec.projection\n if (typeof projection.source !== 'string' || projection.source.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection.source must be a non-empty collection name`,\n )\n }\n if (typeof projection.map !== 'function') {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection is missing a \\`map\\` function`,\n )\n }\n if (!Array.isArray(projection.joins) || projection.joins.length < 1) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection.joins must declare at least 1 leg — `\n + `a leg-less single-source MV is the query() form's job`,\n )\n }\n const seenAs = new Set<string>()\n for (const leg of projection.joins) {\n const l = leg as { field?: unknown; collect?: unknown; on?: unknown; as?: unknown }\n const isForward = l.field !== undefined\n const isCollect = l.collect !== undefined\n if (isForward && isCollect) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a projection leg cannot declare both \\`field\\` `\n + `(forward) and \\`collect\\` (reverse) — split it into two legs`,\n )\n }\n if (!isForward && !isCollect) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": each projection leg must declare either \\`field\\` `\n + `(forward FK) or \\`collect\\` (reverse one-to-many)`,\n )\n }\n if (isForward && (typeof l.field !== 'string' || l.field.length === 0)) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a forward projection leg must declare a non-empty \\`field\\``,\n )\n }\n if (isCollect) {\n if (typeof l.collect !== 'string' || l.collect.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": a collect projection leg must declare a non-empty \\`collect\\` collection name`,\n )\n }\n if (typeof l.on !== 'string' || l.on.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": collect leg for \"${l.collect}\" must declare a non-empty \\`on\\` FK field`,\n )\n }\n }\n if (typeof l.as !== 'string' || l.as.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": each projection leg must declare a non-empty \\`as\\` alias`,\n )\n }\n if (seenAs.has(l.as)) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection legs must attach under distinct \\`as\\` aliases (duplicate: \"${l.as}\")`,\n )\n }\n seenAs.add(l.as)\n }\n // #1140 — `from` wiring, checked here with the rest of the leg shape rather\n // than at vault open: it is pure configuration, so the earliest failure is\n // the best one. Owned by `projection-legs.ts` because the executor and the\n // registry both walk the same graph.\n validateProjectionLegs(spec.name, spec.projection)\n // Post-map grouping invariants — same rules as UNION (the mapped\n // stream feeds the same shared groupAndReduce tail).\n if (Array.isArray(spec.groupBy) && spec.groupBy.length === 0) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": groupBy must not be an empty array — omit it or provide at least one field name`,\n )\n }\n if (spec.aggregate && !spec.groupBy) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": projection strategy with aggregate requires groupBy — `\n + `use groupBy to declare the bucketing keys, or remove aggregate for a row-per-primary-record MV`,\n )\n }\n if (spec.moneyFields && !spec.aggregate && !spec.window) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": moneyFields requires aggregate or window — `\n + `moneyFields rewrites sum/min/max reducers over money output fields, `\n + `so it is meaningless without one`,\n )\n }\n if (spec.predicates) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": predicates are not supported on projection strategies — `\n + `projection mode does not use a Query<T> chain, so .wherePredicate() cannot fire. `\n + `Filter inside projection.map (return null to omit) instead`,\n )\n }\n }\n // i18nLocale + i18nFields drive compute-time i18n resolution of group-key\n // i18nText fields before bucketing — UNION mode (resolved on the unified rows)\n // AND query mode (resolved in GroupedReduction.run before groupAndReduce).\n // i18nLocale without i18nFields cannot resolve anything, so reject it early.\n if (spec.i18nLocale !== undefined && spec.i18nFields === undefined) {\n throw new MaterializedViewConfigError(\n `withMaterializedView \"${spec.name}\": i18nLocale requires i18nFields — `\n + `declare the i18nText descriptors of the group-key fields so they can be `\n + `resolved at the mv layer before bucketing.`,\n )\n }\n if (typeof spec.rowKey !== 'function') {\n // Two states, two messages. The original text said \"required\" for BOTH,\n // so passing a field NAME — the shape every other option here takes —\n // reported the key as ABSENT. That collapse cost this author three\n // attempts and produced a probe that measured nothing.\n throw new ValidationError(\n spec.rowKey === undefined\n ? 'withMaterializedView: rowKey is required (no default; see spec § Type surface)'\n : `withMaterializedView: rowKey must be a FUNCTION (row) => string, not a ${typeof spec.rowKey}`\n + ` — it computes each output row's id from the grouped row, so a field NAME is not enough.`\n + ` Pass \\`rowKey: (r) => String(r.${typeof spec.rowKey === 'string' ? String(spec.rowKey) : 'someField'})\\`.`)\n }\n if (spec.refresh !== 'eager' && spec.refresh !== 'lazy' && spec.refresh !== 'manual') {\n throw new ValidationError(\n `withMaterializedView: refresh must be 'eager' | 'lazy' | 'manual', got \"${String(spec.refresh)}\"`,\n )\n }\n return {\n __noydb_strategy: 'materialized-view',\n spec,\n }\n}\n"],"mappings":"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","names":[]}
@@ -10,14 +10,21 @@ import {
10
10
  verifyPrompt,
11
11
  verifyRoster,
12
12
  verifyTypedEcho
13
- } from "./chunk-3V4KWFX7.js";
13
+ } from "./chunk-XSPFDUDG.js";
14
+ import {
15
+ base64ToBuffer,
16
+ bufferToBase64,
17
+ decryptBytes,
18
+ encryptBytes,
19
+ generateEphemeralKey
20
+ } from "./chunk-EZGV6F47.js";
14
21
  import {
15
22
  NoAccessError,
16
23
  NoydbError,
17
24
  ValidationError,
18
25
  WrongEchoError,
19
26
  WrongPromptError
20
- } from "./chunk-7O3Y4PPD.js";
27
+ } from "./chunk-37EPTBBR.js";
21
28
 
22
29
  // src/with-party/team/echo-ceremony.ts
23
30
  async function beginEchoUnlock(store, vault, opts) {
@@ -66,29 +73,23 @@ var MemoryDeviceSeal = class {
66
73
  keyPromise;
67
74
  constructor(opts) {
68
75
  this.id = opts.id;
69
- this.keyPromise = globalThis.crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, false, [
70
- "encrypt",
71
- "decrypt"
72
- ]);
76
+ this.keyPromise = generateEphemeralKey();
73
77
  }
74
78
  async seal(plain) {
75
- const iv = globalThis.crypto.getRandomValues(new Uint8Array(12));
76
- const ct = new Uint8Array(
77
- await globalThis.crypto.subtle.encrypt({ name: "AES-GCM", iv }, await this.keyPromise, plain)
78
- );
79
- const out = new Uint8Array(12 + ct.length);
80
- out.set(iv, 0);
81
- out.set(ct, 12);
79
+ const { iv, data } = await encryptBytes(plain, await this.keyPromise);
80
+ const ivB = base64ToBuffer(iv);
81
+ const ct = base64ToBuffer(data);
82
+ const out = new Uint8Array(ivB.byteLength + ct.byteLength);
83
+ out.set(ivB, 0);
84
+ out.set(ct, ivB.byteLength);
82
85
  return out;
83
86
  }
84
87
  async unseal(sealed) {
85
88
  try {
86
- return new Uint8Array(
87
- await globalThis.crypto.subtle.decrypt(
88
- { name: "AES-GCM", iv: sealed.slice(0, 12) },
89
- await this.keyPromise,
90
- sealed.slice(12)
91
- )
89
+ return await decryptBytes(
90
+ bufferToBase64(sealed.slice(0, 12)),
91
+ bufferToBase64(sealed.slice(12)),
92
+ await this.keyPromise
92
93
  );
93
94
  } catch {
94
95
  throw new NoydbError("DEVICE_SEAL_UNSEAL_FAILED", "Device seal: unseal failed (tamper or wrong device).");
@@ -122,4 +123,4 @@ export {
122
123
  MemoryDeviceSeal,
123
124
  withTeam
124
125
  };
125
- //# sourceMappingURL=chunk-YJRT5UQM.js.map
126
+ //# sourceMappingURL=chunk-2RH777HH.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/with-party/team/echo-ceremony.ts","../src/with-party/team/device-seal.ts","../src/with-party/team/active.ts"],"sourcesContent":["/**\n * `beginEchoUnlock` — the interactive ceremony API (spec\n * design-history/2026-08-02-echo-secret-design.md, #940, Task 6).\n *\n * Split out of `echo-secret.ts` (which owns only the block builders +\n * verifiers) because this module orchestrates BOTH `echo-secret.ts`\n * (`verifyPrompt`/`resolveEchoReveal`/`verifyTypedEcho`) AND `keyring.ts`\n * (`loadKeyring`) — and `keyring.ts` itself imports `buildEchoBlock` from\n * `echo-secret.ts`. Keeping the ceremony here instead of inside\n * `echo-secret.ts` yields a clean DAG (`echo-ceremony.ts` → {`echo-secret.ts`,\n * `keyring.ts`}; `keyring.ts` → `echo-secret.ts`) instead of a two-file\n * cycle, and restores `echo-secret.ts`'s documented charter (builders +\n * verifiers only).\n *\n * @module\n */\n\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { NoydbDeviceSeal } from './device-seal.js'\nimport { WrongPromptError, WrongEchoError, ValidationError, NoAccessError } from '../../kernel/errors.js'\nimport { verifyPrompt, resolveEchoReveal, verifyTypedEcho } from './echo-secret.js'\nimport { loadKeyring, readKeyringFile, assertKeyringNotExpired, type UnlockedKeyring } from './keyring.js'\n\n/** Options for {@link beginEchoUnlock}. */\nexport interface BeginEchoUnlockOptions {\n readonly userId: string\n readonly prompt: string\n readonly deviceSeal?: NoydbDeviceSeal\n}\n\n/**\n * A prompt-verified, in-progress echo unlock. Stateless w.r.t. attempts —\n * `complete()` may be called more than once (e.g. retry after a wrong key).\n */\nexport interface EchoCeremony {\n /**\n * Echo to display for owner recognition; null ⇒ degraded: ask the owner to\n * TYPE it.\n *\n * Conforming-player contract (spec\n * design-history/2026-08-02-echo-secret-design.md, \"Ceremony\"):\n * when the owner does NOT recognize the revealed echo, the player MUST show\n * a hard phishing warning — do not continue, open the official app, rotate\n * the secret immediately — MUST NOT offer any skip or\n * \"verification unavailable\" fallback, and MUST simply abandon the ceremony\n * by never calling {@link EchoCeremony.complete}. The kernel cannot enforce\n * this terminal state; it is the player's obligation.\n */\n readonly reveal: string | null\n readonly maskHint: string | undefined\n /** Complete the ceremony. `echo` is REQUIRED when `reveal` is null. */\n complete(input: { readonly echo?: string; readonly key: string }): Promise<UnlockedKeyring>\n}\n\n/**\n * Begin the interactive anti-phishing unlock ceremony (spec decision 4):\n * prompt → echo reveal → key. Fetches and parses the `_keyring/{userId}`\n * row (same store path as `loadKeyring`), verifies the prompt, and resolves\n * the echo for display (or degrades to the typed-echo path when the reveal\n * cannot be resolved — sealed reveal under a foreign device).\n *\n * Conforming-player contract (spec\n * design-history/2026-08-02-echo-secret-design.md): an owner who does\n * not recognize `ceremony.reveal` is looking at a phish. The player MUST then\n * show a hard warning (stop, open the official app, rotate the secret now),\n * MUST NOT offer a skip / \"verification unavailable\" fallback or any\n * single-field secret entry, and MUST abandon the ceremony without calling\n * `complete()`.\n *\n * @throws NoAccessError when no keyring exists for `userId` (mirrors\n * `loadKeyring`'s missing-row error).\n * @throws KeyringExpiredError when the slot is past its `expires_at` —\n * checked before the prompt is verified, so an expired slot never reveals.\n * @throws ValidationError when the keyring is not an echo keyring.\n * @throws WrongPromptError when the prompt fails its verifier.\n */\nexport async function beginEchoUnlock(\n store: NoydbStore,\n vault: string,\n opts: BeginEchoUnlockOptions,\n): Promise<EchoCeremony> {\n const { userId, prompt, deviceSeal } = opts\n\n // Same store path + missing-row error as loadKeyring, now shared via\n // `readKeyringFile` (#951).\n const found = await readKeyringFile(store, vault, userId)\n if (!found) {\n throw new NoAccessError(`No keyring found for user \"${userId}\" in vault \"${vault}\"`)\n }\n const { file: keyringFile } = found\n\n // Same expiry gate as loadKeyring, applied BEFORE the prompt is verified so\n // an expired slot never reveals its echo (and leaks no timing on the\n // prompt). Now shared via `assertKeyringNotExpired` (#951).\n assertKeyringNotExpired(keyringFile)\n\n const block = keyringFile.echo\n if (block === undefined) {\n throw new ValidationError('not an echo keyring')\n }\n\n if (!(await verifyPrompt(block, prompt))) {\n throw new WrongPromptError()\n }\n\n const reveal = await resolveEchoReveal(block, prompt, deviceSeal)\n\n return {\n reveal,\n maskHint: block.mask_hint,\n async complete(input: { readonly echo?: string; readonly key: string }): Promise<UnlockedKeyring> {\n let echo: string\n if (reveal !== null) {\n // A supplied input.echo must agree with the revealed echo — defensive:\n // a player that collects a typed echo despite a reveal must not\n // silently unlock with a mismatched pair.\n if (input.echo !== undefined && input.echo !== reveal) {\n throw new WrongEchoError()\n }\n echo = reveal\n } else {\n if (input.echo === undefined) {\n throw new ValidationError('beginEchoUnlock: echo is required to complete a degraded (typed-echo) ceremony.')\n }\n if (!(await verifyTypedEcho(block, input.echo))) {\n throw new WrongEchoError()\n }\n echo = input.echo\n }\n return loadKeyring(store, vault, { userId, secret: { prompt, echo, key: input.key } })\n },\n }\n}\n","import { NoydbError } from '../../kernel/errors.js'\nimport type { NoydbDeviceSeal } from '../../port/with/device-seal-strategy.js'\n\n/**\n * Device-local sealer for the echo reveal-blob (spec decision 5).\n * DISTINCT from `NoydbSealer` (managed-secret mode, which seals\n * the WHOLE secret): this seals only the echo part, and only so an\n * enrolled device can display it during the unlock ceremony. The\n * sealed bytes may sit in the (untrusted) keyring file — attacker-B\n * resistance comes from `unseal` requiring this device's key store.\n *\n * The interface itself is declared on the `/with` port\n * ({@link NoydbDeviceSeal} from `port/with/device-seal-strategy.js`)\n * so the kernel spine can reference it without a static spine→service\n * import; re-exported here as the canonical consumer-facing home.\n */\nexport type { NoydbDeviceSeal }\n\n/** In-memory test provider — AES-GCM under a per-instance random key. */\nexport class MemoryDeviceSeal implements NoydbDeviceSeal {\n readonly id: string\n private readonly keyPromise: Promise<CryptoKey>\n constructor(opts: { id: string }) {\n this.id = opts.id\n this.keyPromise = globalThis.crypto.subtle.generateKey({ name: 'AES-GCM', length: 256 }, false, [\n 'encrypt',\n 'decrypt',\n ])\n }\n async seal(plain: Uint8Array): Promise<Uint8Array> {\n const iv = globalThis.crypto.getRandomValues(new Uint8Array(12))\n const ct = new Uint8Array(\n await globalThis.crypto.subtle.encrypt({ name: 'AES-GCM', iv }, await this.keyPromise, plain as BufferSource),\n )\n const out = new Uint8Array(12 + ct.length)\n out.set(iv, 0)\n out.set(ct, 12)\n return out\n }\n async unseal(sealed: Uint8Array): Promise<Uint8Array> {\n try {\n return new Uint8Array(\n await globalThis.crypto.subtle.decrypt(\n { name: 'AES-GCM', iv: sealed.slice(0, 12) },\n await this.keyPromise,\n sealed.slice(12) as BufferSource,\n ),\n )\n } catch {\n throw new NoydbError('DEVICE_SEAL_UNSEAL_FAILED', 'Device seal: unseal failed (tamper or wrong device).')\n }\n }\n}\n","/**\n * Enable the multi-user team capability (#267 Track A tail).\n *\n * Pass to `createNoydb({ teamStrategy: withTeam() })` to make `db.grant` /\n * `db.revoke` / `db.rotate` live. The keyring grant/revoke/rotate engines\n * are statically imported HERE — this module is reachable only through the\n * `@noy-db/hub/team` subpath (and the root barrel's tree-shakeable\n * re-export), so a single-user floor bundle never carries them. The facade\n * (`TeamFacade.runGrant` / `runRevoke` / `runRotate`) owns the policy-gate +\n * keyring plumbing and receives the engine as an argument.\n */\nimport type { TeamStrategy } from './strategy.js'\nimport { grant as grantEngine, revoke as revokeEngine, rotateKeys as rotateEngine, verifyRoster as verifyRosterEngine, quarantineKeyring as quarantineEngine } from './keyring.js'\n\nexport function withTeam(): TeamStrategy {\n return {\n async grant(team, vault, options, factors) {\n return team.runGrant(grantEngine, vault, options, factors)\n },\n async revoke(team, vault, options, factors) {\n return team.runRevoke(revokeEngine, vault, options, factors)\n },\n async rotate(team, vault, collections) {\n return team.runRotate(rotateEngine, vault, collections)\n },\n async verifyRoster(team, vault) {\n return team.runVerifyRoster(verifyRosterEngine, vault)\n },\n async quarantineKeyring(team, vault, userId, factors) {\n return team.runQuarantine(quarantineEngine, vault, userId, factors)\n },\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/with-party/team/echo-ceremony.ts","../src/with-party/team/device-seal.ts","../src/with-party/team/active.ts"],"sourcesContent":["/**\n * `beginEchoUnlock` — the interactive ceremony API (spec\n * design-history/2026-08-02-echo-secret-design.md, #940, Task 6).\n *\n * Split out of `echo-secret.ts` (which owns only the block builders +\n * verifiers) because this module orchestrates BOTH `echo-secret.ts`\n * (`verifyPrompt`/`resolveEchoReveal`/`verifyTypedEcho`) AND `keyring.ts`\n * (`loadKeyring`) — and `keyring.ts` itself imports `buildEchoBlock` from\n * `echo-secret.ts`. Keeping the ceremony here instead of inside\n * `echo-secret.ts` yields a clean DAG (`echo-ceremony.ts` → {`echo-secret.ts`,\n * `keyring.ts`}; `keyring.ts` → `echo-secret.ts`) instead of a two-file\n * cycle, and restores `echo-secret.ts`'s documented charter (builders +\n * verifiers only).\n *\n * @module\n */\n\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { NoydbDeviceSeal } from './device-seal.js'\nimport { WrongPromptError, WrongEchoError, ValidationError, NoAccessError } from '../../kernel/errors.js'\nimport { verifyPrompt, resolveEchoReveal, verifyTypedEcho } from './echo-secret.js'\nimport { loadKeyring, readKeyringFile, assertKeyringNotExpired, type UnlockedKeyring } from './keyring.js'\n\n/** Options for {@link beginEchoUnlock}. */\nexport interface BeginEchoUnlockOptions {\n readonly userId: string\n readonly prompt: string\n readonly deviceSeal?: NoydbDeviceSeal\n}\n\n/**\n * A prompt-verified, in-progress echo unlock. Stateless w.r.t. attempts —\n * `complete()` may be called more than once (e.g. retry after a wrong key).\n */\nexport interface EchoCeremony {\n /**\n * Echo to display for owner recognition; null ⇒ degraded: ask the owner to\n * TYPE it.\n *\n * Conforming-player contract (spec\n * design-history/2026-08-02-echo-secret-design.md, \"Ceremony\"):\n * when the owner does NOT recognize the revealed echo, the player MUST show\n * a hard phishing warning — do not continue, open the official app, rotate\n * the secret immediately — MUST NOT offer any skip or\n * \"verification unavailable\" fallback, and MUST simply abandon the ceremony\n * by never calling {@link EchoCeremony.complete}. The kernel cannot enforce\n * this terminal state; it is the player's obligation.\n */\n readonly reveal: string | null\n readonly maskHint: string | undefined\n /** Complete the ceremony. `echo` is REQUIRED when `reveal` is null. */\n complete(input: { readonly echo?: string; readonly key: string }): Promise<UnlockedKeyring>\n}\n\n/**\n * Begin the interactive anti-phishing unlock ceremony (spec decision 4):\n * prompt → echo reveal → key. Fetches and parses the `_keyring/{userId}`\n * row (same store path as `loadKeyring`), verifies the prompt, and resolves\n * the echo for display (or degrades to the typed-echo path when the reveal\n * cannot be resolved — sealed reveal under a foreign device).\n *\n * Conforming-player contract (spec\n * design-history/2026-08-02-echo-secret-design.md): an owner who does\n * not recognize `ceremony.reveal` is looking at a phish. The player MUST then\n * show a hard warning (stop, open the official app, rotate the secret now),\n * MUST NOT offer a skip / \"verification unavailable\" fallback or any\n * single-field secret entry, and MUST abandon the ceremony without calling\n * `complete()`.\n *\n * @throws NoAccessError when no keyring exists for `userId` (mirrors\n * `loadKeyring`'s missing-row error).\n * @throws KeyringExpiredError when the slot is past its `expires_at` —\n * checked before the prompt is verified, so an expired slot never reveals.\n * @throws ValidationError when the keyring is not an echo keyring.\n * @throws WrongPromptError when the prompt fails its verifier.\n */\nexport async function beginEchoUnlock(\n store: NoydbStore,\n vault: string,\n opts: BeginEchoUnlockOptions,\n): Promise<EchoCeremony> {\n const { userId, prompt, deviceSeal } = opts\n\n // Same store path + missing-row error as loadKeyring, now shared via\n // `readKeyringFile` (#951).\n const found = await readKeyringFile(store, vault, userId)\n if (!found) {\n throw new NoAccessError(`No keyring found for user \"${userId}\" in vault \"${vault}\"`)\n }\n const { file: keyringFile } = found\n\n // Same expiry gate as loadKeyring, applied BEFORE the prompt is verified so\n // an expired slot never reveals its echo (and leaks no timing on the\n // prompt). Now shared via `assertKeyringNotExpired` (#951).\n assertKeyringNotExpired(keyringFile)\n\n const block = keyringFile.echo\n if (block === undefined) {\n throw new ValidationError('not an echo keyring')\n }\n\n if (!(await verifyPrompt(block, prompt))) {\n throw new WrongPromptError()\n }\n\n const reveal = await resolveEchoReveal(block, prompt, deviceSeal)\n\n return {\n reveal,\n maskHint: block.mask_hint,\n async complete(input: { readonly echo?: string; readonly key: string }): Promise<UnlockedKeyring> {\n let echo: string\n if (reveal !== null) {\n // A supplied input.echo must agree with the revealed echo — defensive:\n // a player that collects a typed echo despite a reveal must not\n // silently unlock with a mismatched pair.\n if (input.echo !== undefined && input.echo !== reveal) {\n throw new WrongEchoError()\n }\n echo = reveal\n } else {\n if (input.echo === undefined) {\n throw new ValidationError('beginEchoUnlock: echo is required to complete a degraded (typed-echo) ceremony.')\n }\n if (!(await verifyTypedEcho(block, input.echo))) {\n throw new WrongEchoError()\n }\n echo = input.echo\n }\n return loadKeyring(store, vault, { userId, secret: { prompt, echo, key: input.key } })\n },\n }\n}\n","import { NoydbError } from '../../kernel/errors.js'\nimport {\n generateEphemeralKey, encryptBytes, decryptBytes, bufferToBase64, base64ToBuffer, type EnclaveKey,\n} from '../../capsule/index.js'\nimport type { NoydbDeviceSeal } from '../../port/with/device-seal-strategy.js'\n\n/**\n * Device-local sealer for the echo reveal-blob (spec decision 5).\n * DISTINCT from `NoydbSealer` (managed-secret mode, which seals\n * the WHOLE secret): this seals only the echo part, and only so an\n * enrolled device can display it during the unlock ceremony. The\n * sealed bytes may sit in the (untrusted) keyring file — attacker-B\n * resistance comes from `unseal` requiring this device's key store.\n *\n * The interface itself is declared on the `/with` port\n * ({@link NoydbDeviceSeal} from `port/with/device-seal-strategy.js`)\n * so the kernel spine can reference it without a static spine→service\n * import; re-exported here as the canonical consumer-facing home.\n */\nexport type { NoydbDeviceSeal }\n\n/** In-memory test provider — AES-GCM under a per-instance random key. */\nexport class MemoryDeviceSeal implements NoydbDeviceSeal {\n readonly id: string\n private readonly keyPromise: Promise<EnclaveKey>\n constructor(opts: { id: string }) {\n this.id = opts.id\n this.keyPromise = generateEphemeralKey()\n }\n async seal(plain: Uint8Array): Promise<Uint8Array> {\n const { iv, data } = await encryptBytes(plain, await this.keyPromise)\n const ivB = base64ToBuffer(iv)\n const ct = base64ToBuffer(data)\n const out = new Uint8Array(ivB.byteLength + ct.byteLength)\n out.set(ivB, 0)\n out.set(ct, ivB.byteLength)\n return out\n }\n async unseal(sealed: Uint8Array): Promise<Uint8Array> {\n try {\n return await decryptBytes(\n bufferToBase64(sealed.slice(0, 12)),\n bufferToBase64(sealed.slice(12)),\n await this.keyPromise,\n )\n } catch {\n throw new NoydbError('DEVICE_SEAL_UNSEAL_FAILED', 'Device seal: unseal failed (tamper or wrong device).')\n }\n }\n}\n","/**\n * Enable the multi-user team capability (#267 Track A tail).\n *\n * Pass to `createNoydb({ teamStrategy: withTeam() })` to make `db.grant` /\n * `db.revoke` / `db.rotate` live. The keyring grant/revoke/rotate engines\n * are statically imported HERE — this module is reachable only through the\n * `@noy-db/hub/team` subpath (and the root barrel's tree-shakeable\n * re-export), so a single-user floor bundle never carries them. The facade\n * (`TeamFacade.runGrant` / `runRevoke` / `runRotate`) owns the policy-gate +\n * keyring plumbing and receives the engine as an argument.\n */\nimport type { TeamStrategy } from './strategy.js'\nimport { grant as grantEngine, revoke as revokeEngine, rotateKeys as rotateEngine, verifyRoster as verifyRosterEngine, quarantineKeyring as quarantineEngine } from './keyring.js'\n\nexport function withTeam(): TeamStrategy {\n return {\n async grant(team, vault, options, factors) {\n return team.runGrant(grantEngine, vault, options, factors)\n },\n async revoke(team, vault, options, factors) {\n return team.runRevoke(revokeEngine, vault, options, factors)\n },\n async rotate(team, vault, collections) {\n return team.runRotate(rotateEngine, vault, collections)\n },\n async verifyRoster(team, vault) {\n return team.runVerifyRoster(verifyRosterEngine, vault)\n },\n async quarantineKeyring(team, vault, userId, factors) {\n return team.runQuarantine(quarantineEngine, vault, userId, factors)\n },\n }\n}\n"],"mappings":"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","names":[]}