@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
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/with-commit/numbering/descriptor.ts","../src/via/computed/binding.ts","../src/via/computed/descriptor.ts","../src/via/lookup/binding.ts","../src/via/lookup/descriptor.ts","../src/with-sync/credentials.ts"],"sourcesContent":["/**\n * @category capability\n * Deferred-numbering config descriptor. See\n * design-history/2026-06-08-sealed-numbering-and-store-clock-design.md.\n */\n\n/** A registered deferred-numbering series. */\nexport interface DeferredNumberingConfig {\n /** Series name — the key passed to `vault.sequence(series)`. */\n readonly series: string\n /** Collection holding the records to number. */\n readonly collection: string\n /** Field on each record where the assigned serial is written. */\n readonly field: string\n /**\n * Minimum wall-clock age (ms) before an entry is eligible at a pass, in\n * addition to the interval commit-wait. Default 0 — the store-clock\n * interval (`storeLatest ≤ now.earliest`) is the correctness mechanism.\n */\n readonly settleWindowMs: number\n}\n\n/**\n * Options for {@link withDeferredNumbering} (#844b — was an inline literal, so\n * unnameable). Same shape as {@link DeferredNumberingConfig} except\n * `settleWindowMs` is optional; the factory defaults it to 0.\n */\nexport interface WithDeferredNumberingOptions {\n /** Series name — the key passed to `vault.sequence(series)`. */\n readonly series: string\n /** Collection holding the records to number. */\n readonly collection: string\n /** Field on each record where the assigned serial is written. */\n readonly field: string\n /** See {@link DeferredNumberingConfig.settleWindowMs}. Default 0. */\n readonly settleWindowMs?: number\n}\n\n/** Declare a deferred-numbering series. Pass the result in `createNoydb({ numbering: [...] })`. */\nexport function withDeferredNumbering(opts: WithDeferredNumberingOptions): DeferredNumberingConfig {\n return {\n series: opts.series,\n collection: opts.collection,\n field: opts.field,\n settleWindowMs: opts.settleWindowMs ?? 0,\n }\n}\n","/**\n * The `computed` via-binding (#638 Task 7) — covers ONLY `mode: 'virtual'`\n * fields. Materialized entries never reach here: they compile into\n * `mergedComputed` (`kernel/collection-config.ts`) and run through the\n * EXISTING stage-5 `evalComputedFields` write path, byte-for-byte unchanged\n * (the behavior lock).\n *\n * A virtual field is computed on READ, inside `present()` — the money-\n * `Formatted`/i18n-`Label` precedent (seam map Part 4) generalized to a\n * user-declared function. It is NEVER stored (no `encodeAtRest`/\n * `decodeAtRest` — the field never appears in `_data` or any `_sealed`\n * slot), and its posture is fixed `queryable: 'none'` — there is no stored/\n * indexed form to query against, regardless of what its sources would\n * otherwise permit (`ViaGraph`'s grain-'virtual' clamp, `kernel/via/graph.ts`,\n * is the belt; this binding's own static posture is the suspenders for a\n * depsless virtual field, which registers no graph edge at all).\n *\n * Export/read redaction for a TAINTED virtual field (sourced from a\n * classified/sealed field) is NOT this binding's job — it stays ignorant of\n * taint, exactly like `evalComputedFields` stays ignorant of it for\n * materialized fields. `kernel/via/taint-binding.ts#taintBinding` (appended\n * to the pipeline by `via/graph-wiring.ts#applyTaintOverlay`, AFTER this\n * binding) overwrites a tainted virtual field's value with the same\n * `EXPORT_REDACTION_MARKER` on every present() — the one enforcement seam\n * every via feature's taint already routes through.\n */\nimport type { NoydbVia, ViaPosture } from '../../kernel/via/index.js'\nimport { installViaBinder } from '../../kernel/via/index.js'\nimport type { ComputedDescriptor } from './descriptor.js'\n\nexport interface ComputedViaConfig {\n /** field name -> its virtual-mode descriptor. Materialized entries are never present here. */\n readonly virtualFields: ReadonlyMap<string, ComputedDescriptor>\n}\n\nconst VIRTUAL_POSTURE: ViaPosture = { encryptedAtRest: 'envelope', queryable: 'none', exportable: true, forgettable: false }\n\nexport function computedVia(cfg: ComputedViaConfig): NoydbVia {\n const fields = cfg.virtualFields\n return {\n brand: 'computed',\n posture: VIRTUAL_POSTURE,\n covers: (field) => fields.has(field),\n present: (record) => {\n let r = record\n for (const [field, desc] of fields) {\n if (r === record) r = { ...record }\n r[field] = desc.fn(r)\n }\n return r\n },\n }\n}\n\nexport function linkComputedVia(): void {\n installViaBinder('computed', (cfg) => computedVia(cfg as ComputedViaConfig))\n}\n","/**\n * computed() — the declaration factory for a field whose value is DERIVED\n * from other fields on the same record (#638 Task 7, spec §6). Composes\n * with `via()` (the locked grammar since phase A: `via(computed(fn, { deps,\n * mode }), money('EUR'))`), grouped by `_viaBrand` like every other via\n * feature (`kernel/via/compose.ts#mergeViaFields`).\n *\n * `mode` picks where the function runs:\n * - `'materialized'` (default) — TODAY's stage-5 write-time eager compute\n * (`with-formula/computed/index.ts#evalComputedFields`), stored like any\n * other field. Byte-for-byte the existing `computed: { field: fn }` sugar.\n * - `'virtual'` — rides the `present` read phase (the money-`Formatted`/\n * i18n-`Label` precedent, seam map Part 4): computed fresh on every\n * read, NEVER stored, `queryable: 'none'`, excluded from export unless\n * its declared `deps` permit (identical taint rule to materialized —\n * see `via/computed/binding.ts`).\n *\n * `deps` names the OTHER fields `fn` reads — feeds `ViaGraph` (Task 1/2) so\n * a source's taint (e.g. a classified field) propagates to this derived\n * field. A depsless entry is fine UNLESS the collection also declares\n * classified fields (`kernel/collection-config.ts#resolveComputedEdges`\n * refuses it — closes the #636 opaque-function leak).\n */\nimport type { ViaDescriptor } from '../../kernel/via/index.js'\nimport { linkComputedVia } from './binding.js'\n\nexport interface ComputedDescriptor extends ViaDescriptor {\n readonly _viaBrand: 'computed'\n readonly fn: (record: Record<string, unknown>) => unknown\n readonly deps?: readonly string[]\n readonly mode: 'materialized' | 'virtual'\n}\n\nexport function computed(\n fn: (record: Record<string, unknown>) => unknown,\n opts?: { readonly deps?: readonly string[]; readonly mode?: 'materialized' | 'virtual' },\n): ComputedDescriptor {\n // Self-link, exactly as `money()` and `lookup()` do (#813). Until this call\n // existed, `computed` was the only via feature whose binder was installed by a\n // DIFFERENT module — `port/with/computed-strategy.ts` — rather than by its own\n // declaration factory. That works whenever the kernel spine and the consumer's\n // `computed` import resolve to one module instance, and fails when they do not:\n // under vitest's `server.deps.inline`, a consumer got the descriptor from one\n // transformed instance while the binder registry consulted at bind time lived in\n // another, producing `VIA_NOT_LINKED` for a descriptor `isComputedDescriptor()`\n // accepted. money/i18n/lookup were immune precisely because they self-link.\n //\n // Constructing a descriptor is the binding's opt-in unit, so linking here makes\n // the guarantee local: whatever instance produced the descriptor also has the\n // binder. `installViaBinder` is idempotent + first-wins, so the eager call in\n // `port/with/computed-strategy.ts` stays harmless.\n linkComputedVia()\n return {\n _viaBrand: 'computed',\n fn,\n ...(opts?.deps !== undefined ? { deps: opts.deps } : {}),\n mode: opts?.mode ?? 'materialized',\n }\n}\n\nexport function isComputedDescriptor(x: unknown): x is ComputedDescriptor {\n return typeof x === 'object' && x !== null && (x as { _viaBrand?: unknown })._viaBrand === 'computed'\n}\n","/**\n * The `'lookup'` `NoydbVia` — wires the lookup engine (present-time label\n * dressing across all three backing tiers) into the kernel's generic Via\n * port. Mirrors `via/i18n/binding.ts`'s #553 static-link pattern; the\n * present-time label-dressing algorithm below is adapted from\n * `via-i18n/binding.ts:253-337` (the same wildcard/array/scalar handling,\n * the same `onMissing`/`substitute` policy engine), generalized to branch on\n * `backing` instead of a static-vs-dynamic descriptor-shape check. For the\n * `'static'` and `'reserved'` tiers this delegates to `cfg.lookupLabelResolver`\n * — the SAME vault-built closure the i18n binding's `dictLabelResolver` uses\n * (static table first, else the `vault.dictionary()` handle) — so a native\n * `dict()`/`lookup(static)` field resolves through the identical label data\n * as its `dictKey()`/`staticDict()` alias (the byte-equivalence lock).\n *\n * `lookup()`/`enumOf()`/`dict()` each call {@link linkLookupVia} first — the\n * same #553 pattern `money()`/`dictKey()` use.\n *\n * `buildClause` (label-predicate queries) is still undeclared — out of scope\n * for #650. `compareForOrder` (#650 Task 6, spec §5; matrix tier added Task\n * 7) resolves a `sortBy`-declared field's ordering via `cfg.snapshotFor`'s\n * sync snapshot; the hook signature is UNCHANGED (`via/index.ts:128-129` — no\n * locale param), so it closes over each descriptor's own `displayLocale`\n * (the same locale-less-hinge default `runLookupPresent`'s\n * `hasStaticDisplay` branch already uses). `resolveOrderLabel` (#650 Task\n * 7) is the PER-CALL-locale sibling `orderBy(..., {by:'label'})` needs —\n * see its own doc comment below. `describeFragment` (#650 Task 7) is the\n * first-ever consumed `NoydbVia.describeFragment` implementation — see\n * `with-shape/introspection/describe.ts`'s `buildDescription`.\n */\nimport type { NoydbVia, ViaReadCtx } from '../../kernel/via/index.js'\nimport { installViaBinder } from '../../kernel/via/index.js'\nimport type { LookupDescriptor, LookupBacking, Vocabulary, OnDelete } from './descriptor.js'\nimport { resolvePolicy, type Layer } from '../i18n/policy.js'\nimport { LocaleNotSpecifiedError, UnknownLookupKeyError, ValidationError } from '../../kernel/errors.js'\nimport { getAtPath, setAtPathInPlace } from '../../kernel/paths.js'\nimport type { MaterializedBacking } from './registry.js'\nimport { buildLookupSnapshot } from './snapshot.js'\n\n/**\n * Config a collection's lookup declarations resolve to — the binding's\n * construction input. `lookupLabelResolver`/`getLookupBacking`/`membership`/\n * `snapshotFor` are vault-built closures (never a `Collection` handle,\n * keyring, or DEK/CEK — the zero-knowledge boundary).\n */\nexport interface LookupViaConfig {\n readonly lookupFields: Record<string, LookupDescriptor>\n readonly lookupLabelResolver?: (dimension: string, key: string, locale: string, fallback?: unknown) => Promise<string | undefined>\n /**\n * The matrix (collection) tier's present-time backing-row source, keyed by the full\n * descriptor (not a bare dimension name) so the closure can resolve by `descriptor.key`,\n * not the backing row's PUT-id (#651 Task 3 — the same descriptor-gaining dispatch Task 7\n * already applied to `snapshotFor`).\n */\n readonly getLookupBacking?: (descriptor: LookupDescriptor) => (key: string) => Promise<Record<string, unknown> | undefined>\n /** Closed-vocabulary write-time membership test (#650 Task 3) — `(field, key) => known?`. */\n readonly membership?: (field: string, key: string) => boolean | Promise<boolean>\n /** Sync per-descriptor altKey index — `ingest`'s normalization source (#650 Task 3). */\n readonly getAltIndex?: (desc: LookupDescriptor) => MaterializedBacking | undefined\n /**\n * Sync materialized `key -> row` rows for a lookup descriptor (#650 Task\n * 6, spec §5; matrix-tier routing added #650 Task 7) — `compareForOrder`\n * and `resolveOrderLabel` below, and `snapshot.ts`'s `presentForJoin`\n * builder, all read this same vault-built closure. Reserved AND\n * collection (matrix) tier route here (the vault wires\n * `dimension -> LookupHandle.snapshotEntries()` / `dimension ->\n * collection.querySourceForJoin().snapshot()` respectively, keyed by\n * `descriptor.key` for the matrix case — see `registry.ts`'s\n * `buildLookupSnapshotRows`); static tier is resolved locally from\n * `descriptor.table` without calling this.\n */\n readonly snapshotFor?: (descriptor: LookupDescriptor) => ReadonlyMap<string, Record<string, unknown>> | undefined\n readonly collectionName: string\n}\n\n/** Enum tier (`backing:'static'`, no `table`) has no label source at all — never dressed. */\nfunction hasLabelSource(desc: LookupDescriptor): boolean {\n return !(desc.backing === 'static' && desc.table === undefined)\n}\n\n/**\n * Resolve one key's label. `'static'`/`'reserved'` both go through\n * `cfg.lookupLabelResolver` (mirrors `dictLabelResolver`'s own static-table-\n * first-else-reserved-handle branching — the SAME closure is reused, see\n * `kernel/vault.ts`). `'collection'` (matrix tier) reads the declared\n * `present.label` off the backing row via `cfg.getLookupBacking`; when\n * `present.by` is set, that field's value is a `{ locale -> label }` map\n * indexed by the effective locale.\n */\nasync function fetchLookupLabel(\n desc: LookupDescriptor,\n key: string,\n effLocale: string,\n fieldFallback: string | readonly string[] | undefined,\n cfg: LookupViaConfig,\n): Promise<string | undefined> {\n if (desc.backing === 'collection') {\n const getRow = cfg.getLookupBacking?.(desc)\n const row = getRow ? await getRow(key) : undefined\n const labelField = desc.present?.label\n if (!row || labelField === undefined) return undefined\n const raw = row[labelField]\n if (desc.present?.by !== undefined) {\n return raw && typeof raw === 'object' ? (raw as Record<string, unknown>)[effLocale] as string | undefined : undefined\n }\n return typeof raw === 'string' ? raw : undefined\n }\n return cfg.lookupLabelResolver?.(desc.dimension, key, effLocale, fieldFallback)\n}\n\n/** `present` — resolve `<field>Label` for every declared lookup field. Adapted from `via-i18n/binding.ts:253-337`. */\nasync function runLookupPresent(\n record: Record<string, unknown>,\n ctx: ViaReadCtx,\n cfg: LookupViaConfig,\n): Promise<Record<string, unknown>> {\n const fields = Object.entries(cfg.lookupFields).filter(([, d]) => hasLabelSource(d))\n if (fields.length === 0) return record\n\n const locale = typeof ctx.locale === 'string' ? ctx.locale : undefined\n const fallback = ctx.fallback as string | readonly string[] | undefined\n const layer = ctx.layer as Layer\n\n // `{ locale: 'raw' }` wants the untouched record — mirrors\n // `via-i18n/binding.ts`'s `locale !== 'raw'` dict-label gate exactly (no\n // synthetic `<field>Label` derivative on a raw read).\n if (locale === 'raw') return record\n\n // Static-display hybrid hinge: a `backing:'static'` field with a declared\n // `displayLocale` resolves its `<field>Label` even under a locale-less\n // read (mirrors staticDict's `hasStaticDisplay` gate).\n const hasStaticDisplay = fields.some(([, d]) => d.backing === 'static' && d.displayLocale !== undefined)\n if (!locale && !hasStaticDisplay) return record\n\n let result = record\n const withLabels = { ...result }\n\n for (const [field, desc] of fields) {\n const policy = desc.onMissing ? resolvePolicy(desc.onMissing, layer) : 'null'\n const fieldFallback = policy === 'substitute' ? (fallback ?? desc.substitute) : fallback\n const effLocale = locale ?? (desc.backing === 'static' ? desc.displayLocale : undefined)\n\n const resolveKey = async (key: string): Promise<string | null> => {\n if (!effLocale) {\n if (policy === 'throw') {\n throw new LocaleNotSpecifiedError(field, `lookup \"${field}\": no locale active to resolve key \"${key}\".`)\n }\n return null\n }\n const label = await fetchLookupLabel(desc, key, effLocale, fieldFallback, cfg)\n if (label === undefined) {\n if (policy === 'throw') {\n throw new LocaleNotSpecifiedError(field, `lookup \"${field}\": no label for key \"${key}\" in locale \"${effLocale}\".`)\n }\n return null\n }\n return label\n }\n\n if (field.includes('[].')) {\n const parts = field.split('[].')\n const arrayKey = parts[0]!\n const leaf = parts[1]\n if (!leaf || leaf.includes('.')) continue\n const arr = (withLabels as Record<string, unknown>)[arrayKey]\n if (!Array.isArray(arr)) continue\n const labelKey = `${leaf}Label`\n ;(withLabels as Record<string, unknown>)[arrayKey] = await Promise.all(\n arr.map(async (el) => {\n if (!el || typeof el !== 'object' || Array.isArray(el)) return el\n const k = (el as Record<string, unknown>)[leaf]\n if (typeof k !== 'string') return el\n return { ...(el as Record<string, unknown>), [labelKey]: await resolveKey(k) }\n }),\n )\n continue\n }\n\n const val = result[field]\n if (Array.isArray(val)) {\n withLabels[`${field}Label`] = await Promise.all(\n val.map(async (k) => ({ key: k, label: typeof k === 'string' ? await resolveKey(k) : null })),\n )\n } else if (typeof val === 'string') {\n const label = await resolveKey(val)\n if (label !== null) withLabels[`${field}Label`] = label\n }\n }\n\n result = withLabels\n return result\n}\n\n/**\n * One field's `lookup` descriptor as it appears on a `NoydbVia.\n * describeFragment()` payload (#650 Task 7 — the first real consumer,\n * `with-shape/introspection/describe.ts`'s `buildDescription`, imports this\n * type directly; `describe.ts` is NOT under `kernel/**`, so it's free to\n * import concrete via/ types the way it already does for\n * `LookupDescriptor`/`MoneyDescriptor`/etc.). `dimension` is OMITTED (not\n * emitted as `''`) for a bare `enumOf()` descriptor — the #650 Task 2\n * `dimension:''` sentinel resolved: no dimension name means no `dimension`\n * key, not a meaningless empty string (T2 carry, #650 Task 7).\n */\nexport interface LookupDescribeFragmentEntry {\n readonly dimension?: string\n readonly backing: LookupBacking\n readonly vocabulary: Vocabulary\n readonly key: string\n readonly altKeys?: readonly string[]\n readonly present?: { readonly label: string; readonly by?: string }\n readonly sortBy?: string\n readonly onDelete: OnDelete\n /** Statically-known closed-vocabulary key set (declared `keys`, or a static table's own keys). Omitted when membership lives only in the backing collection/dictionary (open vocabulary, or closed with no declared `keys`). */\n readonly keys?: readonly string[]\n}\n\n/** The `'lookup'` binding's `describeFragment()` payload shape. */\nexport interface LookupDescribeFragment {\n readonly lookupFields: Record<string, LookupDescribeFragmentEntry>\n}\n\nfunction buildLookupDescribeFragment(cfg: LookupViaConfig): Record<string, unknown> {\n const lookupFields: Record<string, LookupDescribeFragmentEntry> = {}\n for (const [field, desc] of Object.entries(cfg.lookupFields)) {\n lookupFields[field] = {\n ...(desc.dimension !== '' ? { dimension: desc.dimension } : {}),\n backing: desc.backing,\n vocabulary: desc.vocabulary,\n key: desc.key,\n onDelete: desc.onDelete,\n ...(desc.altKeys !== undefined ? { altKeys: desc.altKeys } : {}),\n ...(desc.present !== undefined ? { present: desc.present } : {}),\n ...(desc.sortBy !== undefined ? { sortBy: desc.sortBy } : {}),\n // #657 — static tier: when no `keys` was explicitly declared but a\n // `table` was (the staticDict()-equivalent `lookup(dim, {backing:\n // 'static', table})` shape), the table's own key set IS the\n // statically-known closed-vocabulary set the DescribedField.lookup\n // docblock promises (\"declared `keys`, OR a static table's own\n // keys\"). Reserved/matrix tiers never carry `table`, so this branch\n // never fires for them — their `keys` emission is unchanged.\n ...(desc.keys !== undefined\n ? { keys: desc.keys }\n : desc.backing === 'static' && desc.table !== undefined ? { keys: Object.keys(desc.table) } : {}),\n }\n }\n return { lookupFields }\n}\n\n/**\n * `cfg.getAltIndex(desc)` (matrix tier) reads the backing collection's cache\n * via `querySourceForJoin()` (`buildLookupAltIndex`, registry.ts) — which\n * throws a `.join()`-branded message when that collection was opened\n * `{prefetch:false}` (lazy mode is unsupported for altKey normalization).\n * Normalization must never silently not happen (the banned silent-no-op\n * class, #650 Task 3 review, Important 2) — detect that specific failure\n * and surface a CLEAR, lookup-branded `ValidationError` at the point of\n * failure instead of letting the confusing join-branded one leak onto an\n * unrelated `put()`. Any OTHER error (e.g. `materializeBackingTable`'s own\n * altKey-collision `ValidationError`) propagates unchanged.\n */\nfunction getAltIndexOrThrow(field: string, desc: LookupDescriptor, cfg: LookupViaConfig): MaterializedBacking | undefined {\n try {\n return cfg.getAltIndex?.(desc)\n } catch (err) {\n if (err instanceof Error && err.message.includes('lazy-mode')) {\n throw new ValidationError(\n `lookup: altKeys on \"${field}\" require the backing collection \"${desc.dimension}\" to be ` +\n `prefetch-enabled (lazy mode unsupported); open it without {prefetch:false} or drop altKeys.`,\n )\n }\n throw err\n }\n}\n\n/**\n * `ingest` — altKey candidate values normalize to the canonical key (#650\n * Task 3, spec §3). Pure, sync, idempotent (a canonical key maps to\n * itself); no store read — consults the pre-materialized\n * `cfg.getAltIndex(desc)`. The money `canonicalizeIncomingMoney` precedent\n * (`via/index.ts:108`).\n *\n * A `[].`-wildcard multi-value path (`getAtPath` resolves >1 entries — an\n * array of nested objects, e.g. `'lines[].country'`, the same wildcard\n * convention `runLookupPresent` above already handles) normalizes EVERY\n * element's leaf value, not just a lone scalar (#652 fix — this used to bail\n * out entirely here while `runLookupEnforceWrite` below validated every\n * value unnormalized, so a legitimate altKey in an array position was\n * wrongly refused by closed-vocabulary enforcement). `setAtPathInPlace`\n * can't write into a `[].`-wildcard path, so the array is reconstructed\n * immutably instead, mirroring `runLookupPresent`'s own `field.includes\n * ('[].')` branch. A plain field whose OWN value is a bare top-level array\n * (not a `[].`-wildcard path) gets the SAME element-wise normalization\n * against `backing.altIndex` (#661 fix — `getAtPath` resolves it to one\n * opaque value, so the array itself is `values[0]`; a non-string element is\n * left untouched, mirroring the scalar branch's own `typeof !== 'string'`\n * skip — no parallel coercion invented for this shape).\n */\nfunction runLookupIngest(record: Record<string, unknown>, cfg: LookupViaConfig): Record<string, unknown> {\n const withAltKeys = Object.entries(cfg.lookupFields).filter(([, d]) => (d.altKeys?.length ?? 0) > 0)\n if (withAltKeys.length === 0) return record\n\n let result = record\n for (const [field, desc] of withAltKeys) {\n const backing = getAltIndexOrThrow(field, desc, cfg)\n if (!backing || backing.altIndex.size === 0) continue\n\n if (field.includes('[].')) {\n const [arrayKey, leaf] = field.split('[].')\n if (!leaf || leaf.includes('.')) continue\n const arr = record[arrayKey!]\n if (!Array.isArray(arr)) continue\n let changed = false\n const normalized = arr.map((item) => {\n if (!item || typeof item !== 'object' || Array.isArray(item)) return item\n const value = (item as Record<string, unknown>)[leaf]\n if (typeof value !== 'string') return item\n const canonical = backing.altIndex.get(value)\n if (canonical === undefined || canonical === value) return item\n changed = true\n return { ...(item as Record<string, unknown>), [leaf]: canonical }\n })\n if (!changed) continue\n if (result === record) result = { ...record }\n result[arrayKey!] = normalized\n continue\n }\n\n const values = getAtPath(record, field)\n if (values.length !== 1) continue\n const value = values[0]\n\n // `getAtPath`/`setAtPathInPlace` resolve `field` generically, dotted\n // paths included (e.g. 'meta.tags') — do not rewrite this branch to a\n // direct `record[field]` bracket access, which would silently stop\n // normalizing/enforcing a dotted-non-wildcard bare-array field (#661).\n if (Array.isArray(value)) {\n if (value.length === 0) continue\n let changed = false\n const normalized = value.map((el) => {\n if (typeof el !== 'string') return el\n const canonical = backing.altIndex.get(el)\n if (canonical === undefined || canonical === el) return el\n changed = true\n return canonical\n })\n if (!changed) continue\n if (result === record) result = { ...record }\n setAtPathInPlace(result, field, normalized)\n continue\n }\n\n if (typeof value !== 'string') continue\n const canonical = backing.altIndex.get(value)\n if (canonical === undefined || canonical === value) continue\n if (result === record) result = { ...record }\n setAtPathInPlace(result, field, canonical)\n }\n return result\n}\n\n/**\n * `enforceWrite` — closed-vocabulary write refusal (#650 Task 3, spec §3).\n * Runs only for `vocabulary:'closed'` fields; `'open'` (the dictKey/dict\n * default) skips the check entirely, so #649's fix is additive — existing\n * dictKey/staticDict collections are unaffected. `ctx` carries no\n * cross-collection door (`id`/`vault`/`prior`/`emit` only, unchanged) —\n * membership is a vault-built closure on `cfg`, per spec.\n */\nasync function runLookupEnforceWrite(record: Record<string, unknown>, cfg: LookupViaConfig): Promise<void> {\n for (const [field, desc] of Object.entries(cfg.lookupFields)) {\n if (desc.vocabulary !== 'closed') continue\n // Checks every value `getAtPath` returns — for a `[].`-wildcard\n // multi-value path, that's every element's leaf value.\n // `runLookupIngest` above now normalizes each of those elements first\n // (#652), so what lands here for a `[].`-wildcard field is already\n // canonical; this loop's job stays membership, not normalization.\n for (const value of getAtPath(record, field)) {\n // A plain field whose OWN value is a bare top-level array (#661) —\n // `runLookupIngest` above has already normalized its elements'\n // altKeys, so membership-check each element through the SAME\n // `cfg.membership` closure the scalar branch below uses, refusing on\n // the first unknown one. A non-string element is skipped, mirroring\n // the scalar branch's own skip.\n if (Array.isArray(value)) {\n for (const el of value) {\n if (typeof el !== 'string') continue\n const known = cfg.membership ? await cfg.membership(field, el) : true\n if (!known) throw new UnknownLookupKeyError(desc.dimension, field, el)\n }\n continue\n }\n if (typeof value !== 'string') continue\n const known = cfg.membership ? await cfg.membership(field, value) : true\n if (!known) throw new UnknownLookupKeyError(desc.dimension, field, value)\n }\n }\n}\n\n/**\n * `compareForOrder` — exact ordering for a `sortBy`-declared lookup field\n * against the sync snapshot (#650 Task 6, spec §5, conflict resolution 4;\n * matrix-tier coverage added #650 Task 7). Opt-in: undeclared `sortBy`\n * (every dictKey/staticDict alias and every lookup field declared before\n * Task 6) returns `undefined` — falls through to the generic stored-value\n * comparator, byte-identical to today. Static tier reads `descriptor.table`\n * directly; reserved AND matrix (collection) tier both read `cfg.snapshotFor`\n * (the SAME live cache `presentForJoin`'s lookup half reads — see\n * `snapshot.ts`'s file header). The hook has no locale parameter\n * (`via/index.ts:128-129`, unchanged) — closes over the descriptor's own\n * `displayLocale` (the same locale-less-hinge default `runLookupPresent`\n * already uses); a `sortBy` field whose value isn't locale-keyed\n * (`present.by` undefined) never needs one. A `by`-keyed `sortBy` field\n * with NO declared `displayLocale` degrades to comparing the raw canonical\n * keys (silent — `LookupSnapshot.compareKeys` never throws; declare-time\n * warning at `descriptor.ts`'s `lookup()` factory; use\n * `orderBy(field, dir, {by:'label'})` — `resolveOrderLabel` below — for a\n * PER-CALL locale instead).\n */\nfunction compareLookupOrder(field: string, a: unknown, b: unknown, cfg: LookupViaConfig): number | undefined {\n if (typeof a !== 'string' || typeof b !== 'string') return undefined\n const desc = cfg.lookupFields[field]\n if (!desc || desc.sortBy === undefined) return undefined\n const rows = desc.backing === 'static'\n ? (desc.table ? new Map(Object.entries(desc.table)) : undefined)\n : cfg.snapshotFor?.(desc)\n if (!rows) return undefined\n return buildLookupSnapshot(desc.dimension, rows, desc).compareKeys(a, b, desc.displayLocale ?? '')\n}\n\n/**\n * `resolveOrderLabel` — per-key, PER-CALL-locale label resolution for\n * `orderBy(field, dir, { by: 'label' })` (#650 Task 7, spec §6 / seam map\n * Part 10 surprise 6's option (b)) — the channel `compareForOrder` above\n * structurally cannot serve, since `NoydbVia.compareForOrder` carries no\n * locale parameter. Consumed by `kernel/query/builder.ts`'s\n * `buildOrderLabelMaps` as the fallback for lookup fields the legacy dict\n * registries don't bridge (matrix tier; reserved/static tier already\n * resolves via that bridge — `JoinContext.resolveDictSource` — tried\n * FIRST by the caller, see `registry.ts`'s `collectLookupDictCompat` doc\n * comment). Reuses the exact same `cfg.snapshotFor`/`buildLookupSnapshot`\n * machinery as `compareLookupOrder` above, just with the per-call `locale`\n * in place of the descriptor's own `displayLocale` — falling back to\n * `displayLocale` only when the call itself is locale-less, the same\n * hinge order `runLookupPresent` already uses.\n */\nfunction resolveLookupOrderLabel(field: string, key: string, locale: string | undefined, cfg: LookupViaConfig): string | undefined {\n const desc = cfg.lookupFields[field]\n if (!desc) return undefined\n const rows = desc.backing === 'static'\n ? (desc.table ? new Map(Object.entries(desc.table)) : undefined)\n : cfg.snapshotFor?.(desc)\n if (!rows) return undefined\n return buildLookupSnapshot(desc.dimension, rows, desc).label(key, locale ?? desc.displayLocale ?? '')\n}\n\nexport function lookupVia(cfg: LookupViaConfig): NoydbVia {\n return {\n brand: 'lookup',\n posture: { encryptedAtRest: 'envelope', queryable: 'full', exportable: true, forgettable: false },\n reservedPrefixes: ['_dict_', '_lookup_'],\n covers: (field) => field in cfg.lookupFields,\n ingest: (record) => runLookupIngest(record, cfg),\n enforceWrite: (record) => runLookupEnforceWrite(record, cfg),\n present: async (record, ctx) => runLookupPresent(record, ctx, cfg),\n compareForOrder: (field, a, b) => compareLookupOrder(field, a, b, cfg),\n resolveOrderLabel: (field, key, locale) => resolveLookupOrderLabel(field, key, locale, cfg),\n describeFragment: () => buildLookupDescribeFragment(cfg),\n }\n}\n\nexport function linkLookupVia(): void {\n installViaBinder('lookup', (c) => lookupVia(c as LookupViaConfig))\n}\n","/**\n * `lookup()` / `enumOf()` / `dict()` descriptors — the three declaration\n * surfaces for the `'lookup'` via binding (#650 Task 2, phase D of the Via\n * port). One `LookupDescriptor` shape; the tiers are `backing` details:\n *\n * - `lookup(dimension, opts?)` — matrix tier: first-class collection backing\n * (default `backing:'collection'`) — a reference-collection dimension\n * (e.g. `countries`), open vocabulary by default.\n * - `enumOf(keys)` — enum tier: static in-config table, CLOSED\n * vocabulary, no backing store at all (no dimension name — pure inline\n * keys). Exported as `enumOf`; the barrel (`index.ts`) re-exports it as\n * `enum` (`enum` is a reserved word, so it can't be the function's own\n * name).\n * - `dict(dimension, opts?)` — dict tier: reserved `_dict_<dimension>`\n * micro-collection backing (the `vault.dictionary(name)` engine), open\n * vocabulary by default.\n *\n * Each factory calls {@link linkLookupVia} first — the declaration IS the\n * via binding's opt-in unit (#553), same pattern as `money()`/`i18nText()`/\n * `dictKey()`.\n */\n\nimport type { OnMissingPolicy } from '../i18n/policy.js'\nimport { linkLookupVia } from './binding.js'\n\n/** `'closed'` = enum semantics (membership enforced, Task 3); `'open'` permits unknown keys. */\nexport type Vocabulary = 'open' | 'closed'\n\n/** Where a dimension's rows live: static in-config table / reserved micro-collection / first-class collection. */\nexport type LookupBacking = 'static' | 'reserved' | 'collection'\n\n/** Delete-time referential policy for the backing dimension (default `'restrict'`, enforced in Task 5). */\nexport type OnDelete = 'restrict' | 'cascade' | 'nullify'\n\n/** The one descriptor shape every tier compiles to — tiers differ only by `backing`. */\nexport interface LookupDescriptor<Keys extends string = string> {\n readonly _viaBrand: 'lookup'\n /** Dimension/dictionary/target name. Empty for a bare `enumOf()` (no backing store, no name). */\n readonly dimension: string\n /** Canonical key field on the row (default `'id'`). */\n readonly key: string\n /** Candidate keys normalized to `key` on ingest (Task 3). */\n readonly altKeys?: readonly string[]\n readonly vocabulary: Vocabulary\n /** Dressing dimension: which backing-row field supplies `<field>Label`, optionally keyed `by` a sub-field (e.g. locale). */\n readonly present?: { readonly label: string; readonly by?: string }\n /** Field to sort by against the snapshot (Task 6). */\n readonly sortBy?: string\n readonly backing: LookupBacking\n readonly onDelete: OnDelete\n /** Static/enum inline key set. */\n readonly keys?: readonly Keys[]\n /** Static tier only: in-code `key -> { locale -> label }` table. */\n readonly table?: Readonly<Record<string, Readonly<Record<string, string>>>>\n /** Static hybrid hinge (the `staticDict` alias) — locale-less `<field>Label`. */\n readonly displayLocale?: string\n readonly onMissing?: OnMissingPolicy\n readonly substitute?: readonly string[]\n /** Inline display labels (value -> label), the dict-tier sync fallback (mirrors `dictKey`'s `labels`). */\n readonly labels?: Record<string, string>\n}\n\n/**\n * `sortBy`/`present.by` coupling warning (#650 Task 7, T6 minor — task-6-\n * report.md Concern #4). A `by`-keyed `present` (locale-map) field used as\n * `sortBy` needs a declared `displayLocale` for the locale-less\n * `compareForOrder` sort hook (a plain `orderBy(field)`, no `{by:'label'}`)\n * to resolve anything — without one it silently degrades to comparing the\n * raw canonical keys (never throws — `LookupSnapshot.compareKeys`'s\n * contract). `orderBy(field, dir, {by:'label'})` doesn't need this (it\n * carries its own per-call locale via `NoydbVia.resolveOrderLabel`,\n * #650 Task 7) — only a sortBy-driven PLAIN orderBy does. Warn once at\n * declare time rather than degrade silently at query time.\n */\nfunction warnIfSortByNeedsDisplayLocale(\n dimension: string,\n opts?: { sortBy?: string; present?: { by?: string }; displayLocale?: string },\n): void {\n if (opts?.sortBy !== undefined && opts.present?.by !== undefined && opts.displayLocale === undefined) {\n console.warn(\n `[noy-db] lookup(\"${dimension}\"): sortBy \"${opts.sortBy}\" is locale-keyed (present.by is set) but no ` +\n `displayLocale is declared — a locale-less orderBy() will silently sort by the raw stored key instead ` +\n `of the resolved label. Declare displayLocale, or sort via orderBy(field, dir, { by: 'label' }), which ` +\n `resolves at the query's own per-call locale.`,\n )\n }\n}\n\n/**\n * Matrix tier — first-class collection backing (default `backing:'collection'`).\n * `dimension` names the backing collection (e.g. `'countries'`).\n *\n * `backing` may be overridden to construct any tier through this one\n * factory — e.g. `lookup(name, { backing:'static', table, displayLocale })`\n * is the table-bearing static tier `staticDict()` compiles onto. The\n * `table`/`displayLocale`/`keys`/`onMissing`/`substitute`/`labels` options\n * are a superset of the brief's literal opts list: `LookupDescriptor`\n * already carries these fields for exactly this purpose, and without them\n * `backing:'static'` would be unreachable stand-alone through `lookup()`\n * (see task-2-report.md's \"Design decisions\").\n *\n * **`altKeys` caveat (matrix tier only)**: normalizing an altKey candidate\n * to its canonical `key` requires the backing `dimension` collection to be\n * open in EAGER mode (the default; `{ prefetch: false }` — lazy mode — is\n * unsupported). A `put()` on a field with `altKeys` whose backing collection\n * is lazy throws a `ValidationError` naming the field and dimension; open\n * the backing collection without `{ prefetch: false }`, or drop `altKeys`.\n */\nexport function lookup<Keys extends string>(\n dimension: string,\n opts?: {\n key?: string\n altKeys?: readonly string[]\n vocabulary?: Vocabulary\n present?: { label: string; by?: string }\n sortBy?: string\n backing?: LookupBacking\n onDelete?: OnDelete\n keys?: readonly Keys[]\n table?: Readonly<Record<string, Readonly<Record<string, string>>>>\n displayLocale?: string\n onMissing?: OnMissingPolicy\n substitute?: readonly string[]\n labels?: Record<string, string>\n },\n): LookupDescriptor<Keys> {\n linkLookupVia()\n warnIfSortByNeedsDisplayLocale(dimension, opts)\n return {\n _viaBrand: 'lookup',\n dimension,\n key: opts?.key ?? 'id',\n vocabulary: opts?.vocabulary ?? 'open',\n backing: opts?.backing ?? 'collection',\n onDelete: opts?.onDelete ?? 'restrict',\n ...(opts?.altKeys !== undefined ? { altKeys: opts.altKeys } : {}),\n ...(opts?.present !== undefined ? { present: opts.present } : {}),\n ...(opts?.sortBy !== undefined ? { sortBy: opts.sortBy } : {}),\n ...(opts?.keys !== undefined ? { keys: opts.keys } : {}),\n ...(opts?.table !== undefined ? { table: opts.table } : {}),\n ...(opts?.displayLocale !== undefined ? { displayLocale: opts.displayLocale } : {}),\n ...(opts?.onMissing !== undefined ? { onMissing: opts.onMissing } : {}),\n ...(opts?.substitute !== undefined ? { substitute: opts.substitute } : {}),\n ...(opts?.labels !== undefined ? { labels: opts.labels } : {}),\n }\n}\n\n/**\n * Enum tier — static in-config table, CLOSED vocabulary, no backing store.\n * No dimension name (pure inline keys) — `dimension` is `''`.\n */\nexport function enumOf<const Keys extends readonly string[]>(keys: Keys): LookupDescriptor<Keys[number]> {\n linkLookupVia()\n return {\n _viaBrand: 'lookup',\n dimension: '',\n key: 'id',\n vocabulary: 'closed',\n backing: 'static',\n onDelete: 'restrict',\n keys,\n }\n}\n\n/**\n * Dict tier — reserved `_dict_<dimension>` micro-collection backing (the\n * `vault.dictionary(dimension)` engine), open vocabulary by default. The\n * native equivalent of `dictKey()`.\n *\n * Unlike `lookup()`'s matrix tier, `dict()` has no `altKeys` option — its\n * `_dict_<dimension>` backing is the always-synchronous `LookupHandle`\n * write-through cache, never a `vault.collection()` that can be opened\n * `{ prefetch: false }`, so the matrix tier's lazy-mode altKeys restriction\n * does not apply here.\n */\nexport function dict<Keys extends string>(\n dimension: string,\n opts?: {\n keys?: readonly Keys[]\n vocabulary?: Vocabulary\n present?: { label: string; by?: string }\n onDelete?: OnDelete\n onMissing?: OnMissingPolicy\n substitute?: readonly string[]\n },\n): LookupDescriptor<Keys> {\n linkLookupVia()\n return {\n _viaBrand: 'lookup',\n dimension,\n key: 'id',\n vocabulary: opts?.vocabulary ?? 'open',\n backing: 'reserved',\n onDelete: opts?.onDelete ?? 'restrict',\n ...(opts?.keys !== undefined ? { keys: opts.keys } : {}),\n ...(opts?.present !== undefined ? { present: opts.present } : {}),\n ...(opts?.onMissing !== undefined ? { onMissing: opts.onMissing } : {}),\n ...(opts?.substitute !== undefined ? { substitute: opts.substitute } : {}),\n }\n}\n","/**\n * _sync_credentials reserved collection —\n *\n * Stores per-adapter OAuth tokens (and any other long-lived sync secrets) as\n * encrypted records inside the vault itself. Tokens are wrapped with the\n * compartment's own DEK, live on disk as ciphertext like any other record, and\n * are accessed only through the dedicated API in this module — never via\n * `vault.collection('_sync_credentials')`.\n *\n * Design decisions\n * ────────────────\n *\n * **Why a reserved collection, not a separate store?**\n * The compartment's existing encryption stack (AES-256-GCM + collection DEK)\n * is exactly the right primitive for protecting OAuth tokens at rest. Using a\n * separate store would require a new encryption surface, new adapter calls,\n * and a new backup/restore path — all of which already exist for collections.\n *\n * **Why not exposed as a regular collection?**\n * The same reason `_keyring` and `_ledger` aren't: they have invariants that\n * must be enforced (naming scheme, no cross-user leakage, no schema\n * validation, no history/ledger writes for privacy). Routing through a\n * dedicated API enforces those invariants.\n *\n * **Token lifecycle:**\n * - `putCredential(vault, adapterId, token)` — store or overwrite\n * - `getCredential(vault, adapterId)` — load and decrypt\n * - `deleteCredential(vault, adapterId)` — remove\n * - `listCredentials(vault)` — enumerate adapter IDs (not tokens)\n *\n * The `adapterId` is the record ID within the `_sync_credentials` collection.\n * It should be a stable, human-readable identifier for the adapter instance\n * (e.g. `'google-drive'`, `'dropbox'`, `'s3-prod'`).\n *\n * **ACL:** only `owner` and `admin` roles can read/write sync credentials.\n * Operators, viewers, and clients cannot call this API. The check is made\n * against the caller's keyring role at call time.\n */\n\nimport { buildRecordAad, buildRecordEnvelope } from '../kernel/enclave/index.js'\nimport type { NoydbStore, EncryptedEnvelope } from '../kernel/types.js'\nimport type { UnlockedKeyring } from '../with-party/team/keyring.js'\nimport { encrypt, openEnvelopeJson } from '../kernel/enclave/index.js'\nimport { ensureCollectionDEK } from '../with-party/team/keyring.js'\nimport { PermissionDeniedError } from '../kernel/errors.js'\n\n/**\n * The reserved collection name. Never collides with user collections.\n * Canonical definition lives in `reserved-secret-collections.ts` (shared with\n * the `vault.collection()` guard and grant DEK-propagation); re-exported here\n * for existing consumers.\n */\nexport { SYNC_CREDENTIALS_COLLECTION } from '../with-party/team/reserved-secret-collections.js'\nimport { SYNC_CREDENTIALS_COLLECTION } from '../with-party/team/reserved-secret-collections.js'\n\n// ─── Token types ──────────────────────────────────────────────────────\n\n/**\n * An OAuth/auth token stored in `_sync_credentials`.\n *\n * Fields mirror the OAuth2 token response shape. `customData` is an escape\n * hatch for adapter-specific secrets (API keys, connection strings, etc.)\n * that don't fit the OAuth2 shape.\n */\nexport interface SyncCredential {\n /** Stable identifier for the adapter instance (e.g. 'google-drive'). */\n readonly adapterId: string\n /** OAuth token type, usually 'Bearer'. */\n readonly tokenType: string\n /** The access token. Expires at `expiresAt` if set. */\n readonly accessToken: string\n /** Long-lived refresh token for renewing the access token. */\n readonly refreshToken?: string\n /** ISO timestamp when `accessToken` expires. Absent means \"no expiry\". */\n readonly expiresAt?: string\n /** Space-separated OAuth scopes. */\n readonly scopes?: string\n /** Adapter-specific opaque data (API keys, endpoints, etc.). */\n readonly customData?: Record<string, string>\n}\n\n// ─── Access check ─────────────────────────────────────────────────────\n\nfunction requireAdminAccess(keyring: UnlockedKeyring): void {\n // FR-6: custodian is INTENTIONALLY excluded. Sync credentials are the\n // firm's hosting/infrastructure secrets (OAuth tokens, connection strings) —\n // not the custodian's operational scope. A custodian operates the DATA but\n // must never mint or read transport credentials that could be used to\n // re-home or impersonate the firm's vault. Do NOT add 'custodian' here.\n if (keyring.role !== 'owner' && keyring.role !== 'admin') {\n throw new PermissionDeniedError(\n `Sync credentials require owner or admin role. Current role: \"${keyring.role}\"`,\n )\n }\n}\n\n// ─── Public API ────────────────────────────────────────────────────────\n\n/**\n * Store or overwrite a sync credential for the given adapter.\n *\n * The credential is encrypted with the `_sync_credentials` collection DEK\n * (auto-generated on first use). The record ID is the `adapterId`.\n *\n * Requires owner or admin role.\n */\nexport async function putCredential(\n adapter: NoydbStore,\n vault: string,\n keyring: UnlockedKeyring,\n credential: SyncCredential,\n): Promise<void> {\n requireAdminAccess(keyring)\n\n const getDek = await ensureCollectionDEK(adapter, vault, keyring)\n const dek = await getDek(SYNC_CREDENTIALS_COLLECTION)\n\n // The version is resolved BEFORE the identity, because it is now part of it:\n // sealing under one version and stamping another produces a record no reader\n // can open (#1093).\n const existing = await adapter.get(vault, SYNC_CREDENTIALS_COLLECTION, credential.adapterId)\n const version = existing ? existing._v + 1 : 1\n\n const identity = { collection: SYNC_CREDENTIALS_COLLECTION, id: credential.adapterId, version }\n const { iv, data } = await encrypt(JSON.stringify(credential), dek, buildRecordAad(identity))\n\n const envelope: EncryptedEnvelope = buildRecordEnvelope(identity, { iv, data })\n\n await adapter.put(\n vault,\n SYNC_CREDENTIALS_COLLECTION,\n credential.adapterId,\n envelope,\n existing ? existing._v : undefined,\n )\n}\n\n/**\n * Load and decrypt a sync credential for the given adapter ID.\n *\n * Returns `null` if no credential exists for this adapter.\n * Requires owner or admin role.\n */\nexport async function getCredential(\n adapter: NoydbStore,\n vault: string,\n keyring: UnlockedKeyring,\n adapterId: string,\n): Promise<SyncCredential | null> {\n requireAdminAccess(keyring)\n\n const getDek = await ensureCollectionDEK(adapter, vault, keyring)\n const dek = await getDek(SYNC_CREDENTIALS_COLLECTION)\n\n const envelope = await adapter.get(vault, SYNC_CREDENTIALS_COLLECTION, adapterId)\n if (!envelope) return null\n\n const plaintext = await openEnvelopeJson({ collection: SYNC_CREDENTIALS_COLLECTION, id: adapterId }, envelope, dek)\n return JSON.parse(plaintext) as SyncCredential\n}\n\n/**\n * Delete a sync credential by adapter ID.\n *\n * No-op if the credential doesn't exist. Requires owner or admin role.\n */\nexport async function deleteCredential(\n adapter: NoydbStore,\n vault: string,\n keyring: UnlockedKeyring,\n adapterId: string,\n): Promise<void> {\n requireAdminAccess(keyring)\n await adapter.delete(vault, SYNC_CREDENTIALS_COLLECTION, adapterId)\n}\n\n/**\n * List all adapter IDs that have stored credentials.\n *\n * Returns only the IDs, never the credential payloads. Useful for\n * displaying \"connected adapters\" in UI without decrypting tokens.\n * Requires owner or admin role.\n */\nexport async function listCredentials(\n adapter: NoydbStore,\n vault: string,\n keyring: UnlockedKeyring,\n): Promise<string[]> {\n requireAdminAccess(keyring)\n return adapter.list(vault, SYNC_CREDENTIALS_COLLECTION)\n}\n\n/**\n * Check whether a credential exists and whether its access token has expired.\n *\n * Returns `{ exists: false }` if no credential is stored, or\n * `{ exists: true, expired: boolean }` based on the `expiresAt` field.\n * Requires owner or admin role.\n */\nexport async function credentialStatus(\n adapter: NoydbStore,\n vault: string,\n keyring: UnlockedKeyring,\n adapterId: string,\n): Promise<{ exists: false } | { exists: true; expired: boolean }> {\n const credential = await getCredential(adapter, vault, keyring, adapterId)\n if (!credential) return { exists: false }\n\n const expired = credential.expiresAt\n ? Date.now() > new Date(credential.expiresAt).getTime()\n : false\n\n return { exists: true, expired }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCO,SAAS,sBAAsB,MAA6D;AACjG,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,YAAY,KAAK;AAAA,IACjB,OAAO,KAAK;AAAA,IACZ,gBAAgB,KAAK,kBAAkB;AAAA,EACzC;AACF;;;ACXA,IAAM,kBAA8B,EAAE,iBAAiB,YAAY,WAAW,QAAQ,YAAY,MAAM,aAAa,MAAM;AAEpH,SAAS,YAAY,KAAkC;AAC5D,QAAM,SAAS,IAAI;AACnB,SAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ,CAAC,UAAU,OAAO,IAAI,KAAK;AAAA,IACnC,SAAS,CAAC,WAAW;AACnB,UAAI,IAAI;AACR,iBAAW,CAAC,OAAO,IAAI,KAAK,QAAQ;AAClC,YAAI,MAAM,OAAQ,KAAI,EAAE,GAAG,OAAO;AAClC,UAAE,KAAK,IAAI,KAAK,GAAG,CAAC;AAAA,MACtB;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEO,SAAS,kBAAwB;AACtC,mBAAiB,YAAY,CAAC,QAAQ,YAAY,GAAwB,CAAC;AAC7E;;;ACvBO,SAAS,SACd,IACA,MACoB;AAepB,kBAAgB;AAChB,SAAO;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,IACtD,MAAM,MAAM,QAAQ;AAAA,EACtB;AACF;AAEO,SAAS,qBAAqB,GAAqC;AACxE,SAAO,OAAO,MAAM,YAAY,MAAM,QAAS,EAA8B,cAAc;AAC7F;;;ACaA,SAAS,eAAe,MAAiC;AACvD,SAAO,EAAE,KAAK,YAAY,YAAY,KAAK,UAAU;AACvD;AAWA,eAAe,iBACb,MACA,KACA,WACA,eACA,KAC6B;AAC7B,MAAI,KAAK,YAAY,cAAc;AACjC,UAAM,SAAS,IAAI,mBAAmB,IAAI;AAC1C,UAAM,MAAM,SAAS,MAAM,OAAO,GAAG,IAAI;AACzC,UAAM,aAAa,KAAK,SAAS;AACjC,QAAI,CAAC,OAAO,eAAe,OAAW,QAAO;AAC7C,UAAM,MAAM,IAAI,UAAU;AAC1B,QAAI,KAAK,SAAS,OAAO,QAAW;AAClC,aAAO,OAAO,OAAO,QAAQ,WAAY,IAAgC,SAAS,IAA0B;AAAA,IAC9G;AACA,WAAO,OAAO,QAAQ,WAAW,MAAM;AAAA,EACzC;AACA,SAAO,IAAI,sBAAsB,KAAK,WAAW,KAAK,WAAW,aAAa;AAChF;AAGA,eAAe,iBACb,QACA,KACA,KACkC;AAClC,QAAM,SAAS,OAAO,QAAQ,IAAI,YAAY,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,eAAe,CAAC,CAAC;AACnF,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QAAM,SAAS,OAAO,IAAI,WAAW,WAAW,IAAI,SAAS;AAC7D,QAAM,WAAW,IAAI;AACrB,QAAM,QAAQ,IAAI;AAKlB,MAAI,WAAW,MAAO,QAAO;AAK7B,QAAM,mBAAmB,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,YAAY,EAAE,kBAAkB,MAAS;AACvG,MAAI,CAAC,UAAU,CAAC,iBAAkB,QAAO;AAEzC,MAAI,SAAS;AACb,QAAM,aAAa,EAAE,GAAG,OAAO;AAE/B,aAAW,CAAC,OAAO,IAAI,KAAK,QAAQ;AAClC,UAAM,SAAS,KAAK,YAAY,cAAc,KAAK,WAAW,KAAK,IAAI;AACvE,UAAM,gBAAgB,WAAW,eAAgB,YAAY,KAAK,aAAc;AAChF,UAAM,YAAY,WAAW,KAAK,YAAY,WAAW,KAAK,gBAAgB;AAE9E,UAAM,aAAa,OAAO,QAAwC;AAChE,UAAI,CAAC,WAAW;AACd,YAAI,WAAW,SAAS;AACtB,gBAAM,IAAI,wBAAwB,OAAO,WAAW,KAAK,uCAAuC,GAAG,IAAI;AAAA,QACzG;AACA,eAAO;AAAA,MACT;AACA,YAAM,QAAQ,MAAM,iBAAiB,MAAM,KAAK,WAAW,eAAe,GAAG;AAC7E,UAAI,UAAU,QAAW;AACvB,YAAI,WAAW,SAAS;AACtB,gBAAM,IAAI,wBAAwB,OAAO,WAAW,KAAK,wBAAwB,GAAG,gBAAgB,SAAS,IAAI;AAAA,QACnH;AACA,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAEA,QAAI,MAAM,SAAS,KAAK,GAAG;AACzB,YAAM,QAAQ,MAAM,MAAM,KAAK;AAC/B,YAAM,WAAW,MAAM,CAAC;AACxB,YAAM,OAAO,MAAM,CAAC;AACpB,UAAI,CAAC,QAAQ,KAAK,SAAS,GAAG,EAAG;AACjC,YAAM,MAAO,WAAuC,QAAQ;AAC5D,UAAI,CAAC,MAAM,QAAQ,GAAG,EAAG;AACzB,YAAM,WAAW,GAAG,IAAI;AACvB,MAAC,WAAuC,QAAQ,IAAI,MAAM,QAAQ;AAAA,QACjE,IAAI,IAAI,OAAO,OAAO;AACpB,cAAI,CAAC,MAAM,OAAO,OAAO,YAAY,MAAM,QAAQ,EAAE,EAAG,QAAO;AAC/D,gBAAM,IAAK,GAA+B,IAAI;AAC9C,cAAI,OAAO,MAAM,SAAU,QAAO;AAClC,iBAAO,EAAE,GAAI,IAAgC,CAAC,QAAQ,GAAG,MAAM,WAAW,CAAC,EAAE;AAAA,QAC/E,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAEA,UAAM,MAAM,OAAO,KAAK;AACxB,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,iBAAW,GAAG,KAAK,OAAO,IAAI,MAAM,QAAQ;AAAA,QAC1C,IAAI,IAAI,OAAO,OAAO,EAAE,KAAK,GAAG,OAAO,OAAO,MAAM,WAAW,MAAM,WAAW,CAAC,IAAI,KAAK,EAAE;AAAA,MAC9F;AAAA,IACF,WAAW,OAAO,QAAQ,UAAU;AAClC,YAAM,QAAQ,MAAM,WAAW,GAAG;AAClC,UAAI,UAAU,KAAM,YAAW,GAAG,KAAK,OAAO,IAAI;AAAA,IACpD;AAAA,EACF;AAEA,WAAS;AACT,SAAO;AACT;AA+BA,SAAS,4BAA4B,KAA+C;AAClF,QAAM,eAA4D,CAAC;AACnE,aAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,IAAI,YAAY,GAAG;AAC5D,iBAAa,KAAK,IAAI;AAAA,MACpB,GAAI,KAAK,cAAc,KAAK,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,MAC7D,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,KAAK,KAAK;AAAA,MACV,UAAU,KAAK;AAAA,MACf,GAAI,KAAK,YAAY,SAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,MAC9D,GAAI,KAAK,YAAY,SAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,MAC9D,GAAI,KAAK,WAAW,SAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQ3D,GAAI,KAAK,SAAS,SACd,EAAE,MAAM,KAAK,KAAK,IAClB,KAAK,YAAY,YAAY,KAAK,UAAU,SAAY,EAAE,MAAM,OAAO,KAAK,KAAK,KAAK,EAAE,IAAI,CAAC;AAAA,IACnG;AAAA,EACF;AACA,SAAO,EAAE,aAAa;AACxB;AAcA,SAAS,mBAAmB,OAAe,MAAwB,KAAuD;AACxH,MAAI;AACF,WAAO,IAAI,cAAc,IAAI;AAAA,EAC/B,SAAS,KAAK;AACZ,QAAI,eAAe,SAAS,IAAI,QAAQ,SAAS,WAAW,GAAG;AAC7D,YAAM,IAAI;AAAA,QACR,uBAAuB,KAAK,qCAAqC,KAAK,SAAS;AAAA,MAEjF;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;AAyBA,SAAS,gBAAgB,QAAiC,KAA+C;AACvG,QAAM,cAAc,OAAO,QAAQ,IAAI,YAAY,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,UAAU,KAAK,CAAC;AACnG,MAAI,YAAY,WAAW,EAAG,QAAO;AAErC,MAAI,SAAS;AACb,aAAW,CAAC,OAAO,IAAI,KAAK,aAAa;AACvC,UAAM,UAAU,mBAAmB,OAAO,MAAM,GAAG;AACnD,QAAI,CAAC,WAAW,QAAQ,SAAS,SAAS,EAAG;AAE7C,QAAI,MAAM,SAAS,KAAK,GAAG;AACzB,YAAM,CAAC,UAAU,IAAI,IAAI,MAAM,MAAM,KAAK;AAC1C,UAAI,CAAC,QAAQ,KAAK,SAAS,GAAG,EAAG;AACjC,YAAM,MAAM,OAAO,QAAS;AAC5B,UAAI,CAAC,MAAM,QAAQ,GAAG,EAAG;AACzB,UAAI,UAAU;AACd,YAAM,aAAa,IAAI,IAAI,CAAC,SAAS;AACnC,YAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,EAAG,QAAO;AACrE,cAAMA,SAAS,KAAiC,IAAI;AACpD,YAAI,OAAOA,WAAU,SAAU,QAAO;AACtC,cAAMC,aAAY,QAAQ,SAAS,IAAID,MAAK;AAC5C,YAAIC,eAAc,UAAaA,eAAcD,OAAO,QAAO;AAC3D,kBAAU;AACV,eAAO,EAAE,GAAI,MAAkC,CAAC,IAAI,GAAGC,WAAU;AAAA,MACnE,CAAC;AACD,UAAI,CAAC,QAAS;AACd,UAAI,WAAW,OAAQ,UAAS,EAAE,GAAG,OAAO;AAC5C,aAAO,QAAS,IAAI;AACpB;AAAA,IACF;AAEA,UAAM,SAAS,UAAU,QAAQ,KAAK;AACtC,QAAI,OAAO,WAAW,EAAG;AACzB,UAAM,QAAQ,OAAO,CAAC;AAMtB,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,UAAI,MAAM,WAAW,EAAG;AACxB,UAAI,UAAU;AACd,YAAM,aAAa,MAAM,IAAI,CAAC,OAAO;AACnC,YAAI,OAAO,OAAO,SAAU,QAAO;AACnC,cAAMA,aAAY,QAAQ,SAAS,IAAI,EAAE;AACzC,YAAIA,eAAc,UAAaA,eAAc,GAAI,QAAO;AACxD,kBAAU;AACV,eAAOA;AAAA,MACT,CAAC;AACD,UAAI,CAAC,QAAS;AACd,UAAI,WAAW,OAAQ,UAAS,EAAE,GAAG,OAAO;AAC5C,uBAAiB,QAAQ,OAAO,UAAU;AAC1C;AAAA,IACF;AAEA,QAAI,OAAO,UAAU,SAAU;AAC/B,UAAM,YAAY,QAAQ,SAAS,IAAI,KAAK;AAC5C,QAAI,cAAc,UAAa,cAAc,MAAO;AACpD,QAAI,WAAW,OAAQ,UAAS,EAAE,GAAG,OAAO;AAC5C,qBAAiB,QAAQ,OAAO,SAAS;AAAA,EAC3C;AACA,SAAO;AACT;AAUA,eAAe,sBAAsB,QAAiC,KAAqC;AACzG,aAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,IAAI,YAAY,GAAG;AAC5D,QAAI,KAAK,eAAe,SAAU;AAMlC,eAAW,SAAS,UAAU,QAAQ,KAAK,GAAG;AAO5C,UAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,mBAAW,MAAM,OAAO;AACtB,cAAI,OAAO,OAAO,SAAU;AAC5B,gBAAMC,SAAQ,IAAI,aAAa,MAAM,IAAI,WAAW,OAAO,EAAE,IAAI;AACjE,cAAI,CAACA,OAAO,OAAM,IAAI,sBAAsB,KAAK,WAAW,OAAO,EAAE;AAAA,QACvE;AACA;AAAA,MACF;AACA,UAAI,OAAO,UAAU,SAAU;AAC/B,YAAM,QAAQ,IAAI,aAAa,MAAM,IAAI,WAAW,OAAO,KAAK,IAAI;AACpE,UAAI,CAAC,MAAO,OAAM,IAAI,sBAAsB,KAAK,WAAW,OAAO,KAAK;AAAA,IAC1E;AAAA,EACF;AACF;AAsBA,SAAS,mBAAmB,OAAe,GAAY,GAAY,KAA0C;AAC3G,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,SAAU,QAAO;AAC3D,QAAM,OAAO,IAAI,aAAa,KAAK;AACnC,MAAI,CAAC,QAAQ,KAAK,WAAW,OAAW,QAAO;AAC/C,QAAM,OAAO,KAAK,YAAY,WACzB,KAAK,QAAQ,IAAI,IAAI,OAAO,QAAQ,KAAK,KAAK,CAAC,IAAI,SACpD,IAAI,cAAc,IAAI;AAC1B,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,oBAAoB,KAAK,WAAW,MAAM,IAAI,EAAE,YAAY,GAAG,GAAG,KAAK,iBAAiB,EAAE;AACnG;AAkBA,SAAS,wBAAwB,OAAe,KAAa,QAA4B,KAA0C;AACjI,QAAM,OAAO,IAAI,aAAa,KAAK;AACnC,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,OAAO,KAAK,YAAY,WACzB,KAAK,QAAQ,IAAI,IAAI,OAAO,QAAQ,KAAK,KAAK,CAAC,IAAI,SACpD,IAAI,cAAc,IAAI;AAC1B,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,oBAAoB,KAAK,WAAW,MAAM,IAAI,EAAE,MAAM,KAAK,UAAU,KAAK,iBAAiB,EAAE;AACtG;AAEO,SAAS,UAAU,KAAgC;AACxD,SAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS,EAAE,iBAAiB,YAAY,WAAW,QAAQ,YAAY,MAAM,aAAa,MAAM;AAAA,IAChG,kBAAkB,CAAC,UAAU,UAAU;AAAA,IACvC,QAAQ,CAAC,UAAU,SAAS,IAAI;AAAA,IAChC,QAAQ,CAAC,WAAW,gBAAgB,QAAQ,GAAG;AAAA,IAC/C,cAAc,CAAC,WAAW,sBAAsB,QAAQ,GAAG;AAAA,IAC3D,SAAS,OAAO,QAAQ,QAAQ,iBAAiB,QAAQ,KAAK,GAAG;AAAA,IACjE,iBAAiB,CAAC,OAAO,GAAG,MAAM,mBAAmB,OAAO,GAAG,GAAG,GAAG;AAAA,IACrE,mBAAmB,CAAC,OAAO,KAAK,WAAW,wBAAwB,OAAO,KAAK,QAAQ,GAAG;AAAA,IAC1F,kBAAkB,MAAM,4BAA4B,GAAG;AAAA,EACzD;AACF;AAEO,SAAS,gBAAsB;AACpC,mBAAiB,UAAU,CAAC,MAAM,UAAU,CAAoB,CAAC;AACnE;;;AC9YA,SAAS,+BACP,WACA,MACM;AACN,MAAI,MAAM,WAAW,UAAa,KAAK,SAAS,OAAO,UAAa,KAAK,kBAAkB,QAAW;AACpG,YAAQ;AAAA,MACN,oBAAoB,SAAS,eAAe,KAAK,MAAM;AAAA,IAIzD;AAAA,EACF;AACF;AAsBO,SAAS,OACd,WACA,MAewB;AACxB,gBAAc;AACd,iCAA+B,WAAW,IAAI;AAC9C,SAAO;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA,KAAK,MAAM,OAAO;AAAA,IAClB,YAAY,MAAM,cAAc;AAAA,IAChC,SAAS,MAAM,WAAW;AAAA,IAC1B,UAAU,MAAM,YAAY;AAAA,IAC5B,GAAI,MAAM,YAAY,SAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,IAC/D,GAAI,MAAM,YAAY,SAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,IAC/D,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,IAC5D,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,IACtD,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,IACzD,GAAI,MAAM,kBAAkB,SAAY,EAAE,eAAe,KAAK,cAAc,IAAI,CAAC;AAAA,IACjF,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,IACrE,GAAI,MAAM,eAAe,SAAY,EAAE,YAAY,KAAK,WAAW,IAAI,CAAC;AAAA,IACxE,GAAI,MAAM,WAAW,SAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,EAC9D;AACF;AAMO,SAAS,OAA6C,MAA4C;AACvG,gBAAc;AACd,SAAO;AAAA,IACL,WAAW;AAAA,IACX,WAAW;AAAA,IACX,KAAK;AAAA,IACL,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,UAAU;AAAA,IACV;AAAA,EACF;AACF;AAaO,SAAS,KACd,WACA,MAQwB;AACxB,gBAAc;AACd,SAAO;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA,KAAK;AAAA,IACL,YAAY,MAAM,cAAc;AAAA,IAChC,SAAS;AAAA,IACT,UAAU,MAAM,YAAY;AAAA,IAC5B,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,IACtD,GAAI,MAAM,YAAY,SAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,IAC/D,GAAI,MAAM,cAAc,SAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,IACrE,GAAI,MAAM,eAAe,SAAY,EAAE,YAAY,KAAK,WAAW,IAAI,CAAC;AAAA,EAC1E;AACF;;;ACpHA,SAAS,mBAAmB,SAAgC;AAM1D,MAAI,QAAQ,SAAS,WAAW,QAAQ,SAAS,SAAS;AACxD,UAAM,IAAI;AAAA,MACR,gEAAgE,QAAQ,IAAI;AAAA,IAC9E;AAAA,EACF;AACF;AAYA,eAAsB,cACpB,SACA,OACA,SACA,YACe;AACf,qBAAmB,OAAO;AAE1B,QAAM,SAAS,MAAM,oBAAoB,SAAS,OAAO,OAAO;AAChE,QAAM,MAAM,MAAM,OAAO,2BAA2B;AAKpD,QAAM,WAAW,MAAM,QAAQ,IAAI,OAAO,6BAA6B,WAAW,SAAS;AAC3F,QAAM,UAAU,WAAW,SAAS,KAAK,IAAI;AAE7C,QAAM,WAAW,EAAE,YAAY,6BAA6B,IAAI,WAAW,WAAW,QAAQ;AAC9F,QAAM,EAAE,IAAI,KAAK,IAAI,MAAM,QAAQ,KAAK,UAAU,UAAU,GAAG,KAAK,eAAe,QAAQ,CAAC;AAE5F,QAAM,WAA8B,oBAAoB,UAAU,EAAE,IAAI,KAAK,CAAC;AAE9E,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,WAAW,SAAS,KAAK;AAAA,EAC3B;AACF;AAQA,eAAsB,cACpB,SACA,OACA,SACA,WACgC;AAChC,qBAAmB,OAAO;AAE1B,QAAM,SAAS,MAAM,oBAAoB,SAAS,OAAO,OAAO;AAChE,QAAM,MAAM,MAAM,OAAO,2BAA2B;AAEpD,QAAM,WAAW,MAAM,QAAQ,IAAI,OAAO,6BAA6B,SAAS;AAChF,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,YAAY,MAAM,iBAAiB,EAAE,YAAY,6BAA6B,IAAI,UAAU,GAAG,UAAU,GAAG;AAClH,SAAO,KAAK,MAAM,SAAS;AAC7B;AAOA,eAAsB,iBACpB,SACA,OACA,SACA,WACe;AACf,qBAAmB,OAAO;AAC1B,QAAM,QAAQ,OAAO,OAAO,6BAA6B,SAAS;AACpE;AASA,eAAsB,gBACpB,SACA,OACA,SACmB;AACnB,qBAAmB,OAAO;AAC1B,SAAO,QAAQ,KAAK,OAAO,2BAA2B;AACxD;AASA,eAAsB,iBACpB,SACA,OACA,SACA,WACiE;AACjE,QAAM,aAAa,MAAM,cAAc,SAAS,OAAO,SAAS,SAAS;AACzE,MAAI,CAAC,WAAY,QAAO,EAAE,QAAQ,MAAM;AAExC,QAAM,UAAU,WAAW,YACvB,KAAK,IAAI,IAAI,IAAI,KAAK,WAAW,SAAS,EAAE,QAAQ,IACpD;AAEJ,SAAO,EAAE,QAAQ,MAAM,QAAQ;AACjC;","names":["value","canonical","known"]}
1
+ {"version":3,"sources":["../src/with-sync/change-broadcast.ts","../src/with-commit/numbering/descriptor.ts","../src/via/computed/binding.ts","../src/via/geo/geohash.ts","../src/via/geo/where.ts","../src/via/geo/binding.ts","../src/via/geo/descriptor.ts","../src/via/computed/descriptor.ts","../src/via/lookup/binding.ts","../src/via/lookup/descriptor.ts","../src/with-sync/credentials.ts","../src/with-store/partitioned/index.ts"],"sourcesContent":["/**\n * Cross-tab / cross-process change signals for `.live()` — #1362.\n *\n * A live query is in-process only: a write in tab A leaves tab B's `.live()`\n * showing the old rows until B happens to read again. This module closes that\n * without an external coordinator: every locally-committed change posts a\n * compact ADDRESS on a channel named per store, and every listening instance\n * re-reads that address **through its own keyring** and re-fires the live\n * queries that touch it.\n *\n * ## The zero-knowledge constraint is the feature\n *\n * The frame is `{ vault, collection, id, ts }` and nothing else. No record, no\n * field, no ciphertext, no key, not even the VERB — see below. Encryption\n * happens in hub before any store, and a broadcast channel is **not a store**:\n * it is a side channel with no authentication and no access control, so it is\n * treated as untrusted in BOTH directions.\n *\n * - **Untrusted egress** — only the address leaves. A peer that should not\n * be able to read a record learns, at most, that a record at that address\n * changed. `change-broadcast.test.ts` asserts on the exact bytes posted and\n * fails if anything resembling record content ever appears in them; that\n * test is the thing that catches a future change which starts sending\n * payloads.\n * - **Untrusted ingress** — the frame carries no `action`. A peer's claim\n * \"this was a delete\" is not evidence, and it is free not to need it: the\n * receiver re-reads the address and decides the verb from what IT can\n * decrypt. So a hostile or buggy peer on the channel can cost a wasted\n * re-read, and cannot make a receiver report a state its own store does\n * not hold.\n *\n * ## Why the receiver re-reads rather than patches\n *\n * #1341's `LiveMaintainer` patches a result set from a delta it TRUSTS —\n * trustworthy because it was derived from a local write the same process\n * observed, with the record in hand. A remote signal is a different animal: it\n * says only \"id X in collection Y changed\", and the receiving instance has not\n * decrypted the new record and knows neither the before nor the after state.\n * Feeding it to the maintainer as if it were a local delta would patch a set\n * from an address. So a remote-origin change re-reads and re-runs: the\n * `ChangeEvent` it produces is tagged `remote: true`, and `Collection`'s query\n * source hands the live query NO delta for such an event — which the maintainer\n * already understands as \"rebuild from scratch\", the pre-#1341 behaviour.\n *\n * ## Transport\n *\n * `BroadcastChannel` when the host has one (browsers, Node >= 18,\n * Deno, Bun) — feature-detected at enable time, never assumed. With no channel\n * the whole feature is an inert no-op and behaviour is exactly what it is\n * today. Any other host transport (Electron IPC, a worker `MessagePort`, a\n * test bus) is supported by passing a `channel` that satisfies `TabChannel`.\n */\nimport type { TabChannel, Unsubscribe } from './tab-coordination.js'\nimport type { ChangeEvent } from '../kernel/types.js'\n\n/**\n * The frame on the wire. `kind` discriminates it from any other traffic\n * sharing the channel; `origin` identifies the sender so a channel that echoes\n * to itself cannot feed an instance its own signal.\n *\n * ⛔ **Do not add a field carrying record state to this interface.** Not the\n * record, not a field of it, not a hash of it, not the verb. Everything here\n * is an ADDRESS plus routing. The test asserting on the posted bytes is what\n * holds the line; it will fail loudly, which is the point.\n */\nexport interface ChangeSignal {\n readonly kind: 'noydb:change'\n /** Sending instance's id — an incoming frame with our own id is ignored. */\n readonly origin: string\n readonly vault: string\n readonly collection: string\n readonly id: string\n /** Sender's wall clock at post time. Diagnostic only; never compared for ordering. */\n readonly ts: number\n}\n\nexport interface ChangeBroadcastOptions {\n /**\n * Host-provided transport. Supply this for a host with no\n * `BroadcastChannel` (Electron IPC, a worker `MessagePort`, a test bus) or to\n * take ownership of the channel's lifetime. Default: an inline\n * `BroadcastChannel` if the host has one, else nothing at all.\n */\n readonly channel?: TabChannel\n /**\n * Discriminator for the default channel name — `noydb:change:<storeId>`.\n *\n * ⚠️ Defaults to `store.name`, which is the backend KIND ('memory', 'file',\n * 'idb'), not a per-dataset identity: two different IndexedDB databases both\n * reporting `'idb'` would share one channel and re-read each other's\n * addresses (harmless — a miss costs one read that finds nothing — but\n * wasteful). Pass a `storeId` that names the DATASET whenever a host can\n * open more than one.\n */\n readonly storeId?: string\n /** This instance's id. Default: a random one. */\n readonly originId?: string\n /** Clock for the frame's `ts`. Default: `Date.now`. */\n readonly now?: () => number\n}\n\n/** The slice of `Noydb` this needs. Structural, so there is no import cycle. */\nexport interface ChangeBroadcastHost {\n on(event: 'change', handler: (e: ChangeEvent) => void): void\n off(event: 'change', handler: (e: ChangeEvent) => void): void\n /** @internal Store backend name, for the default channel name. */\n readonly _storeName: string | undefined\n /** @internal Re-read one address through this instance's own keyring. */\n _applyRemoteSignal(vault: string, collection: string, id: string): Promise<void>\n}\n\n/**\n * An inline `BroadcastChannel` wrapper, or `undefined` when the host has none.\n *\n * ⚠️ Deliberately does NOT gate on `window`, and that asymmetry with\n * `defaultChannel()` is the cross-process half of this feature, not an\n * oversight. That gate exists because a presence HEARTBEAT and a Web-Locks role\n * ELECTION are browser-tab concepts that should not start running in Node; a\n * change signal is the opposite — Node workers and Electron processes sharing a\n * store are exactly the case #1362 names, and gating on `window` would silently\n * exclude them.\n */\nexport function defaultChangeChannel(name: string): TabChannel | undefined {\n const Bc = (globalThis as { BroadcastChannel?: typeof BroadcastChannel }).BroadcastChannel\n if (typeof Bc !== 'function') return undefined\n const bc = new Bc(name)\n // Node's BroadcastChannel is an active handle and would keep a process alive\n // for a listener nobody is waiting on. Browsers have no such method.\n const maybeUnref = bc as unknown as { unref?: () => void }\n if (typeof maybeUnref.unref === 'function') maybeUnref.unref()\n const listeners = new Set<(p: string) => void>()\n bc.onmessage = (e: MessageEvent) => { for (const l of listeners) l(String(e.data)) }\n return {\n isOpen: true,\n send(payload) { bc.postMessage(payload) },\n on(event, listener) {\n if (event === 'message') { const l = listener as (p: string) => void; listeners.add(l); return () => listeners.delete(l) }\n return () => {}\n },\n close() { listeners.clear(); bc.close() },\n }\n}\n\n/** Channel name for a store. One namespace per store so unrelated datasets never cross-signal. */\nexport function changeChannelName(storeId: string): string {\n return `noydb:change:${storeId}`\n}\n\n/**\n * The relay itself: local change out as an address, remote address in as a\n * re-read. Started by {@link enableChangeBroadcast}.\n */\nexport class ChangeBroadcast {\n readonly #host: ChangeBroadcastHost\n readonly #channel: TabChannel\n readonly #originId: string\n readonly #now: () => number\n readonly #ownsChannel: boolean\n #unsubMsg: Unsubscribe | undefined\n #started = false\n #disposed = false\n\n constructor(host: ChangeBroadcastHost, channel: TabChannel, opts: { originId: string; now: () => number; ownsChannel: boolean }) {\n this.#host = host\n this.#channel = channel\n this.#originId = opts.originId\n this.#now = opts.now\n this.#ownsChannel = opts.ownsChannel\n }\n\n get originId(): string { return this.#originId }\n\n start(): void {\n if (this.#started || this.#disposed) return\n this.#started = true\n this.#unsubMsg = this.#channel.on('message', (p) => this.#onMessage(p))\n this.#host.on('change', this.#onLocalChange)\n }\n\n dispose(): void {\n if (this.#disposed) return\n this.#disposed = true\n this.#host.off('change', this.#onLocalChange)\n this.#unsubMsg?.()\n if (this.#ownsChannel) this.#channel.close()\n }\n\n /**\n * Echo suppression, first and primary layer: a change this instance produced\n * BY APPLYING a peer's signal is tagged `remote` and is never re-posted. Two\n * instances would otherwise volley one address forever.\n */\n readonly #onLocalChange = (e: ChangeEvent): void => {\n if (this.#disposed || e.remote === true) return\n if (!this.#channel.isOpen) return\n const signal: ChangeSignal = {\n kind: 'noydb:change',\n origin: this.#originId,\n vault: e.vault,\n collection: e.collection,\n id: e.id,\n ts: this.#now(),\n }\n this.#channel.send(JSON.stringify(signal))\n }\n\n #onMessage(payload: string): void {\n if (this.#disposed) return\n let msg: unknown\n try { msg = JSON.parse(payload) } catch { return }\n // Echo suppression, second layer: `BroadcastChannel` does not deliver to the\n // poster, but a host transport (or a same-process test bus) may, and the\n // origin check makes the relay correct on either.\n if (!isChangeSignal(msg) || msg.origin === this.#originId) return\n void Promise.resolve(this.#host._applyRemoteSignal(msg.vault, msg.collection, msg.id)).catch((err) => {\n console.warn(`[noy-db] change-signal apply failed for ${msg.collection}/${msg.id}: ` + (err instanceof Error ? err.message : String(err)))\n })\n }\n}\n\n/**\n * Opt in to cross-tab / cross-process live-query reactivity.\n *\n * ```ts\n * const stop = enableChangeBroadcast(db, { storeId: 'invoices-2026' })\n * // …a put in another tab now re-fires this tab's `.live()` queries…\n * stop.dispose()\n * ```\n *\n * Opt-in on purpose: it is a side channel, and a host that does not want one\n * gets exactly today's behaviour by not calling this. **With no channel\n * available it is also a no-op** — it returns a disposable that does nothing,\n * never throws, and leaves in-process reactivity untouched.\n */\nexport function enableChangeBroadcast(host: ChangeBroadcastHost, opts: ChangeBroadcastOptions = {}): { dispose: () => void } {\n const storeId = opts.storeId ?? host._storeName ?? 'default'\n const channel = opts.channel ?? defaultChangeChannel(changeChannelName(storeId))\n if (!channel) return { dispose: () => {} }\n const relay = new ChangeBroadcast(host, channel, {\n originId: opts.originId ?? `noydb-${cheapRand()}`,\n now: opts.now ?? (() => Date.now()),\n // Own the channel only when we created it; never close a caller-injected one.\n ownsChannel: opts.channel === undefined,\n })\n relay.start()\n return { dispose: () => relay.dispose() }\n}\n\nfunction isChangeSignal(x: unknown): x is ChangeSignal {\n if (x === null || typeof x !== 'object') return false\n const o = x as Record<string, unknown>\n return o['kind'] === 'noydb:change'\n && typeof o['origin'] === 'string'\n && typeof o['vault'] === 'string'\n && typeof o['collection'] === 'string'\n && typeof o['id'] === 'string'\n && typeof o['ts'] === 'number'\n}\n\nfunction cheapRand(): string {\n const g = globalThis as { crypto?: { randomUUID?: () => string } }\n return g.crypto?.randomUUID ? g.crypto.randomUUID() : `anon-${Math.random().toString(36).slice(2)}`\n}\n","/**\n * @category capability\n * Deferred-numbering config descriptor. See\n * design-history/2026-06-08-sealed-numbering-and-store-clock-design.md.\n */\n\n/** A registered deferred-numbering series. */\nexport interface DeferredNumberingConfig {\n /** Series name — the key passed to `vault.sequence(series)`. */\n readonly series: string\n /** Collection holding the records to number. */\n readonly collection: string\n /** Field on each record where the assigned serial is written. */\n readonly field: string\n /**\n * Minimum wall-clock age (ms) before an entry is eligible at a pass, in\n * addition to the interval commit-wait. Default 0 — the store-clock\n * interval (`storeLatest ≤ now.earliest`) is the correctness mechanism.\n */\n readonly settleWindowMs: number\n}\n\n/**\n * Options for {@link withDeferredNumbering} (#844b — was an inline literal, so\n * unnameable). Same shape as {@link DeferredNumberingConfig} except\n * `settleWindowMs` is optional; the factory defaults it to 0.\n */\nexport interface WithDeferredNumberingOptions {\n /** Series name — the key passed to `vault.sequence(series)`. */\n readonly series: string\n /** Collection holding the records to number. */\n readonly collection: string\n /** Field on each record where the assigned serial is written. */\n readonly field: string\n /** See {@link DeferredNumberingConfig.settleWindowMs}. Default 0. */\n readonly settleWindowMs?: number\n}\n\n/** Declare a deferred-numbering series. Pass the result in `createNoydb({ numbering: [...] })`. */\nexport function withDeferredNumbering(opts: WithDeferredNumberingOptions): DeferredNumberingConfig {\n return {\n series: opts.series,\n collection: opts.collection,\n field: opts.field,\n settleWindowMs: opts.settleWindowMs ?? 0,\n }\n}\n","/**\n * The `computed` via-binding (#638 Task 7) — covers ONLY `mode: 'virtual'`\n * fields. Materialized entries never reach here: they compile into\n * `mergedComputed` (`kernel/collection-config.ts`) and run through the\n * EXISTING stage-5 `evalComputedFields` write path, byte-for-byte unchanged\n * (the behavior lock).\n *\n * A virtual field is computed on READ, inside `present()` — the money-\n * `Formatted`/i18n-`Label` precedent (seam map Part 4) generalized to a\n * user-declared function. It is NEVER stored (no `encodeAtRest`/\n * `decodeAtRest` — the field never appears in `_data` or any `_sealed`\n * slot), and its posture is fixed `queryable: 'none'` — there is no stored/\n * indexed form to query against, regardless of what its sources would\n * otherwise permit (`ViaGraph`'s grain-'virtual' clamp, `kernel/via/graph.ts`,\n * is the belt; this binding's own static posture is the suspenders for a\n * depsless virtual field, which registers no graph edge at all).\n *\n * Export/read redaction for a TAINTED virtual field (sourced from a\n * classified/sealed field) is NOT this binding's job — it stays ignorant of\n * taint, exactly like `evalComputedFields` stays ignorant of it for\n * materialized fields. `kernel/via/taint-binding.ts#taintBinding` (appended\n * to the pipeline by `via/graph-wiring.ts#applyTaintOverlay`, AFTER this\n * binding) overwrites a tainted virtual field's value with the same\n * `EXPORT_REDACTION_MARKER` on every present() — the one enforcement seam\n * every via feature's taint already routes through.\n */\nimport type { NoydbVia, ViaPosture } from '../../kernel/via/index.js'\nimport { installViaBinder } from '../../kernel/via/index.js'\nimport type { ComputedDescriptor } from './descriptor.js'\n\nexport interface ComputedViaConfig {\n /** field name -> its virtual-mode descriptor. Materialized entries are never present here. */\n readonly virtualFields: ReadonlyMap<string, ComputedDescriptor>\n}\n\nconst VIRTUAL_POSTURE: ViaPosture = { encryptedAtRest: 'envelope', queryable: 'none', exportable: true, forgettable: false }\n\nexport function computedVia(cfg: ComputedViaConfig): NoydbVia {\n const fields = cfg.virtualFields\n return {\n brand: 'computed',\n presentIsSync: true, // #1416 — `desc.fn(r)` is declared sync by the computed contract\n posture: VIRTUAL_POSTURE,\n covers: (field) => fields.has(field),\n coveredFields: [...fields.keys()], // #1447 — virtual fields live ONLY here, which is why a predicate cannot report them\n present: (record) => {\n let r = record\n for (const [field, desc] of fields) {\n if (r === record) r = { ...record }\n r[field] = desc.fn(r)\n }\n return r\n },\n }\n}\n\nexport function linkComputedVia(): void {\n installViaBinder('computed', (cfg) => computedVia(cfg as ComputedViaConfig))\n}\n","/**\n * The geospatial primitives (#1355) — geohash encoding, great-circle\n * distance, and the bounding-box → prefix-set cover that lets a `near()`\n * query take the existing sorted index.\n *\n * ⭐ WHY A GEOHASH PREFIX AND NOT A COORDINATE. The store holds ciphertext\n * and never runs a query, but a secondary index key is a value the hub\n * itself keeps in a structure a persisted sidecar can carry (#1359). A raw\n * `lat`/`lng` in that key space is a coordinate at full precision; a\n * geohash PREFIX is a cell — deliberately lossy, and the coarser the query\n * the less it says. That is the whole reason this module exists rather\n * than a pair of numeric range indexes on `lat` and `lng`.\n *\n * ⛔ THE SUPERSET LAW. {@link coverPrefixes} must return a cover whose\n * union CONTAINS every point of the box, and {@link boundingBox} a box\n * that contains every point within the radius. A candidate set that is\n * too big costs a haversine call per extra row; one that is too small is\n * a WRONG ANSWER, and no post-filter can put a dropped record back.\n * `__tests__/geo-superset.test.ts` is the property that pins it.\n *\n * Pure, portable, dependency-free — no Node built-ins, no npm math lib.\n */\n\n/** A WGS-84 point. Latitude in [-90, 90], longitude in [-180, 180]. */\nexport interface GeoPoint {\n readonly lat: number\n readonly lng: number\n}\n\n/** A latitude/longitude rectangle. Never wraps: {@link boundingBox} splits at the antimeridian instead. */\nexport interface GeoBox {\n readonly minLat: number\n readonly maxLat: number\n readonly minLng: number\n readonly maxLng: number\n}\n\n/** Mean Earth radius (IUGG), km — the same constant every reference haversine uses. */\nexport const EARTH_RADIUS_KM = 6371.0088\n\n/** The geohash alphabet: base-32 with `a`, `i`, `l`, `o` removed. */\nconst BASE32 = '0123456789bcdefghjkmnpqrstuvwxyz'\n\n/** Widest geohash precision this module encodes. 12 chars ≈ 3.7cm — past any GPS fix. */\nexport const MAX_PRECISION = 12\n\nconst DEG = Math.PI / 180\n\n/** True when `p` is a usable point. Rejects NaN, infinities and out-of-range values. */\nexport function isGeoPoint(p: unknown): p is GeoPoint {\n if (typeof p !== 'object' || p === null) return false\n const { lat, lng } = p as { lat?: unknown; lng?: unknown }\n return (\n typeof lat === 'number' && Number.isFinite(lat) && lat >= -90 && lat <= 90 &&\n typeof lng === 'number' && Number.isFinite(lng) && lng >= -180 && lng <= 180\n )\n}\n\n/**\n * Great-circle distance in kilometres.\n *\n * Haversine rather than the law of cosines: the two agree to metres at\n * continental scale, but `acos` loses all its significant digits for\n * nearby points (`cos d → 1`), which is exactly the regime a `near()`\n * query lives in.\n */\nexport function haversineKm(a: GeoPoint, b: GeoPoint): number {\n const dLat = (b.lat - a.lat) * DEG\n const dLng = (b.lng - a.lng) * DEG\n const lat1 = a.lat * DEG\n const lat2 = b.lat * DEG\n const h = Math.sin(dLat / 2) ** 2 + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLng / 2) ** 2\n return 2 * EARTH_RADIUS_KM * Math.asin(Math.min(1, Math.sqrt(h)))\n}\n\n/**\n * Encode a point as a geohash of `precision` characters.\n *\n * Bits interleave longitude-first, which is what makes a shared prefix\n * mean \"the same cell\" and therefore what makes the sorted index's\n * `startsWith` slice a spatial answer.\n */\nexport function encodeGeohash(point: GeoPoint, precision: number): string {\n if (!isGeoPoint(point)) throw new RangeError(`encodeGeohash: not a point: ${JSON.stringify(point)}`)\n const p = clampPrecision(precision)\n let latMin = -90, latMax = 90, lngMin = -180, lngMax = 180\n let hash = '', bits = 0, ch = 0, evenBit = true\n while (hash.length < p) {\n if (evenBit) {\n const mid = (lngMin + lngMax) / 2\n if (point.lng >= mid) { ch = (ch << 1) + 1; lngMin = mid } else { ch <<= 1; lngMax = mid }\n } else {\n const mid = (latMin + latMax) / 2\n if (point.lat >= mid) { ch = (ch << 1) + 1; latMin = mid } else { ch <<= 1; latMax = mid }\n }\n evenBit = !evenBit\n if (++bits === 5) { hash += BASE32[ch]; bits = 0; ch = 0 }\n }\n return hash\n}\n\n/** The cell a geohash names. Throws on a character outside the alphabet. */\nexport function decodeGeohashBox(hash: string): GeoBox {\n let latMin = -90, latMax = 90, lngMin = -180, lngMax = 180\n let evenBit = true\n for (const c of hash) {\n const idx = BASE32.indexOf(c)\n if (idx < 0) throw new RangeError(`decodeGeohashBox: \"${c}\" is not a geohash character`)\n for (let n = 4; n >= 0; n--) {\n const bit = (idx >> n) & 1\n if (evenBit) {\n const mid = (lngMin + lngMax) / 2\n if (bit === 1) lngMin = mid; else lngMax = mid\n } else {\n const mid = (latMin + latMax) / 2\n if (bit === 1) latMin = mid; else latMax = mid\n }\n evenBit = !evenBit\n }\n }\n return { minLat: latMin, maxLat: latMax, minLng: lngMin, maxLng: lngMax }\n}\n\n/** How many latitude / longitude bits a `precision`-character hash spends. */\nexport function gridBits(precision: number): { latBits: number; lngBits: number } {\n const total = clampPrecision(precision) * 5\n return { latBits: Math.floor(total / 2), lngBits: Math.ceil(total / 2) }\n}\n\n/**\n * The boxes enclosing every point within `radiusKm` of `center`.\n *\n * Returns TWO boxes when the circle crosses the antimeridian, and one\n * spanning the full longitude range when it reaches a pole — a rectangle\n * in lat/lng cannot express either case, and quietly clipping would\n * violate the superset law at exactly the coordinates nobody tests by\n * hand.\n */\nexport function boundingBox(center: GeoPoint, radiusKm: number): GeoBox[] {\n if (!isGeoPoint(center)) throw new RangeError(`boundingBox: not a point: ${JSON.stringify(center)}`)\n if (!Number.isFinite(radiusKm) || radiusKm < 0) throw new RangeError(`boundingBox: radiusKm must be a non-negative number, got ${radiusKm}`)\n // A hair of slack absorbs the float error between this box's arithmetic\n // and the haversine that post-filters against it. One superset-law\n // violation is a dropped record; one extra candidate is one more\n // haversine call.\n const eps = 1e-9\n const angular = radiusKm / EARTH_RADIUS_KM\n if (angular >= Math.PI) return [{ minLat: -90, maxLat: 90, minLng: -180, maxLng: 180 }]\n const latDelta = angular / DEG + eps\n const minLat = center.lat - latDelta\n const maxLat = center.lat + latDelta\n if (minLat <= -90 || maxLat >= 90) {\n // Pole inside the circle: every longitude is within reach.\n return [{ minLat: Math.max(-90, minLat), maxLat: Math.min(90, maxLat), minLng: -180, maxLng: 180 }]\n }\n // The widest longitude offset is taken at the edge of the band CLOSEST to\n // a pole, not at the centre's own latitude — a circle is fatter in\n // longitude there, and using the centre would clip its top corners.\n const worstLat = Math.max(Math.abs(minLat), Math.abs(maxLat)) * DEG\n const ratio = Math.sin(angular) / Math.cos(worstLat)\n if (!(ratio < 1)) return [{ minLat, maxLat, minLng: -180, maxLng: 180 }]\n const lngDelta = Math.asin(ratio) / DEG + eps\n const minLng = center.lng - lngDelta\n const maxLng = center.lng + lngDelta\n if (maxLng - minLng >= 360) return [{ minLat, maxLat, minLng: -180, maxLng: 180 }]\n if (minLng < -180) return [{ minLat, maxLat, minLng: -180, maxLng }, { minLat, maxLat, minLng: minLng + 360, maxLng: 180 }]\n if (maxLng > 180) return [{ minLat, maxLat, minLng, maxLng: 180 }, { minLat, maxLat, minLng: -180, maxLng: maxLng - 360 }]\n return [{ minLat, maxLat, minLng, maxLng }]\n}\n\n/** Number of `precision`-cells the boxes touch — computed from grid indices, never by enumerating. */\nexport function coverSize(boxes: readonly GeoBox[], precision: number): number {\n const { latBits, lngBits } = gridBits(precision)\n const latCells = 2 ** latBits\n const lngCells = 2 ** lngBits\n let total = 0\n for (const box of boxes) {\n const i0 = cellIndex(box.minLat, -90, 180, latCells)\n const i1 = cellIndex(box.maxLat, -90, 180, latCells)\n const j0 = cellIndex(box.minLng, -180, 360, lngCells)\n const j1 = cellIndex(box.maxLng, -180, 360, lngCells)\n total += (i1 - i0 + 1) * (j1 - j0 + 1)\n }\n return total\n}\n\n/**\n * The geohash prefixes whose cells cover `boxes` at `precision`.\n *\n * Every returned prefix is exactly `precision` characters, so the set can\n * be handed to the sorted index one `startsWith` at a time and unioned.\n */\nexport function coverPrefixes(boxes: readonly GeoBox[], precision: number): string[] {\n const p = clampPrecision(precision)\n const { latBits, lngBits } = gridBits(p)\n const latCells = 2 ** latBits\n const lngCells = 2 ** lngBits\n const latStep = 180 / latCells\n const lngStep = 360 / lngCells\n const out = new Set<string>()\n for (const box of boxes) {\n const i0 = cellIndex(box.minLat, -90, 180, latCells)\n const i1 = cellIndex(box.maxLat, -90, 180, latCells)\n const j0 = cellIndex(box.minLng, -180, 360, lngCells)\n const j1 = cellIndex(box.maxLng, -180, 360, lngCells)\n for (let i = i0; i <= i1; i++) {\n // The cell's CENTRE, so no rounding at a boundary can name a neighbour.\n const lat = -90 + (i + 0.5) * latStep\n for (let j = j0; j <= j1; j++) {\n const lng = -180 + (j + 0.5) * lngStep\n out.add(encodeGeohash({ lat, lng }, p))\n }\n }\n }\n return [...out].sort()\n}\n\n/**\n * The finest cover of `center`/`radiusKm` that stays within `maxCells`\n * prefixes, capped at `maxPrecision`.\n *\n * Finer is better: the prefixes ARE the candidate set, so a coarser cover\n * hands more rows to the haversine post-filter. The search always\n * terminates — precision 1 is a 4×8 grid, so 32 cells cover the planet.\n */\nexport function prefixesForRadius(\n center: GeoPoint,\n radiusKm: number,\n maxPrecision: number,\n maxCells: number,\n): { prefixes: string[]; precision: number } {\n const boxes = boundingBox(center, radiusKm)\n const ceiling = Math.max(1, maxCells)\n for (let p = clampPrecision(maxPrecision); p > 1; p--) {\n if (coverSize(boxes, p) <= ceiling) return { prefixes: coverPrefixes(boxes, p), precision: p }\n }\n return { prefixes: coverPrefixes(boxes, 1), precision: 1 }\n}\n\nfunction cellIndex(value: number, origin: number, span: number, cells: number): number {\n const raw = Math.floor(((value - origin) / span) * cells)\n return Math.min(cells - 1, Math.max(0, raw))\n}\n\nfunction clampPrecision(precision: number): number {\n if (!Number.isInteger(precision) || precision < 1 || precision > MAX_PRECISION) {\n throw new RangeError(`geo: precision must be an integer in 1..${MAX_PRECISION}, got ${precision}`)\n }\n return precision\n}\n","/**\n * `where(field, 'near', { lat, lng, radiusKm })` — the geo binding's query\n * participation (#1355).\n *\n * Two halves, and the split is the whole design:\n *\n * - {@link geoFieldClause} turns a `near` operand into a PREFIX COVER at build\n * time, once. `geoIndexProbe` hands that cover to the sorted index as a\n * union of `startsWith` slices — a candidate SUPERSET.\n * - {@link evaluateGeoClause} is the exact answer: one haversine per\n * candidate. It runs on every record the executor offers it, index or\n * scan, so the query returns the same rows either way.\n *\n * ⛔ The `near` clause is NEVER consumed by the index — `candidateRecords()`\n * (`kernel/query/builder.ts`) keeps a prefix-probed clause in\n * `remainingClauses` precisely because a cell cover is round and a circle\n * is not. Dropping it would return the bounding cells' corners as matches.\n *\n * ⭐⭐ AND THE BINDING CLAIMS EVERY OTHER OPERATOR TOO, delegating them\n * straight back to the kernel's generic comparison. That looks like\n * ceremony and is not: a geo field's INDEX KEY is a geohash string\n * (`canonicalizeIndexKey`), while its STORED value is an object. Leaving,\n * say, `startsWith` unclaimed would leave `clause.via` unset, which is\n * exactly the signal `candidateRecords()` reads as \"the sorted index may\n * serve this\" — and the index would answer over geohash strings while the\n * scan compares an object, so the two would disagree about the same query.\n * Claiming the operator sets `clause.via` with NO index probe, which sends\n * it to the scan and keeps one answer.\n */\nimport { ValidationError } from '../../kernel/errors.js'\nimport { evaluateOperator, type Operator } from '../../kernel/query/predicate.js'\nimport type { ViaPrefixProbe } from '../../kernel/via/index.js'\nimport type { GeoDescriptor } from './descriptor.js'\nimport { haversineKm, isGeoPoint, prefixesForRadius, type GeoPoint } from './geohash.js'\n\n/** The `near` operand: a centre and a radius in kilometres. */\nexport interface NearOperand extends GeoPoint {\n readonly radiusKm: number\n}\n\n/** A `near` clause: the centre, the radius, and the cover the index probes. */\nexport interface GeoNearOperand {\n readonly kind: 'near'\n readonly center: GeoPoint\n readonly radiusKm: number\n readonly prefixes: readonly string[]\n /** Cover precision actually chosen — reported by `describeFragment()`, not used to match. */\n readonly precision: number\n}\n\n/** Any other operator over a geo field: claimed, un-probed, generically compared. */\nexport interface GeoPassthroughOperand {\n readonly kind: 'passthrough'\n readonly value: unknown\n}\n\n/** The opaque payload `buildClause` produces and `evaluateClause` consumes. */\nexport type GeoWhereOperand = GeoNearOperand | GeoPassthroughOperand\n\n/**\n * Build the payload for a clause over a geo field. A `near` operand is\n * validated and covered here; every other operator is captured verbatim.\n *\n * A malformed `near` operand throws at the `where()` CALL SITE (money's\n * precedent) — a silently-empty result set is the worst possible answer to\n * a typo'd coordinate.\n */\nexport function geoFieldClause(field: string, op: Operator, value: unknown, desc: GeoDescriptor): GeoWhereOperand {\n if (op !== 'near') return { kind: 'passthrough', value }\n if (typeof value !== 'object' || value === null) {\n throw new ValidationError(`where(\"${field}\", 'near', …): operand must be { lat, lng, radiusKm }, got ${JSON.stringify(value)}`)\n }\n const { lat, lng, radiusKm } = value as { lat?: unknown; lng?: unknown; radiusKm?: unknown }\n const center = { lat, lng } as GeoPoint\n if (!isGeoPoint(center)) {\n throw new ValidationError(`where(\"${field}\", 'near', …): lat must be in [-90, 90] and lng in [-180, 180], got ${JSON.stringify({ lat, lng })}`)\n }\n if (typeof radiusKm !== 'number' || !Number.isFinite(radiusKm) || radiusKm < 0) {\n throw new ValidationError(`where(\"${field}\", 'near', …): radiusKm must be a non-negative number, got ${JSON.stringify(radiusKm)}`)\n }\n const { prefixes, precision } = prefixesForRadius(center, radiusKm, desc.precision, desc.maxPrefixes)\n return { kind: 'near', center, radiusKm, prefixes, precision }\n}\n\n/**\n * Exact membership: the stored point is within `radiusKm` of the centre.\n *\n * A value that is not a point — absent, nullish, or written before the\n * field was declared `geo()` — matches nothing. That is the same posture\n * every other operator takes on a type mismatch, and it is what keeps the\n * index sound: such a record has no geohash key either, so it is absent\n * from the candidate set AND from the answer.\n */\nexport function evaluateGeoClause(actual: unknown, op: string, payload: GeoWhereOperand): boolean {\n if (payload.kind === 'passthrough') return evaluateOperator(actual, op as Operator, payload.value)\n if (op !== 'near') return false\n if (!isGeoPoint(actual)) return false\n return haversineKm(actual, payload.center) <= payload.radiusKm\n}\n\n/**\n * The index operand: a prefix cover the sorted index can slice.\n *\n * `undefined` for any other operator, which sends the clause to the scan\n * — the geo binding claims no fast path it cannot make sound.\n */\nexport function geoIndexProbe(op: string, payload: GeoWhereOperand): ViaPrefixProbe | undefined {\n if (op !== 'near' || payload.kind !== 'near') return undefined\n if (payload.prefixes.length === 0) return undefined\n return { kind: 'via-prefixes', prefixes: payload.prefixes }\n}\n","/**\n * The geo `NoydbVia` (#1355) — wires the geohash engine into the kernel's\n * generic Via port. `geo()` (descriptor.ts) calls {@link linkGeoVia} at\n * declaration time, the same #553 static-link pattern money/lookup/computed\n * use.\n *\n * ⭐ WHERE THE GEOHASH ACTUALLY LIVES, and why in two places:\n *\n * - `ingest` writes it BESIDE `{ lat, lng }` in the record, so the stored\n * document is self-describing: an export, a `crdt` merge or a consumer\n * reading the raw shape sees the cell without re-deriving it.\n * - `canonicalizeIndexKey` DERIVES it from `lat`/`lng` rather than reading\n * that stored field. Deriving is what makes MIXED-ERA data land in the\n * right bucket (money's #672 story, same shape): a record written before\n * the field was declared `geo()` carries no `geohash` at all, and one\n * written at a different `precision` carries the wrong-length one. Both\n * index correctly because the coordinate — not the cached cell — is the\n * source of truth for the key.\n *\n * The index key is therefore always a geohash STRING, so the field's\n * entries live in one key space and `startsWith` over it is a spatial\n * slice.\n */\nimport type { NoydbVia } from '../../kernel/via/index.js'\nimport { installViaBinder } from '../../kernel/via/index.js'\nimport type { GeoDescriptor } from './descriptor.js'\nimport { GeoPointError } from './descriptor.js'\nimport { encodeGeohash, isGeoPoint } from './geohash.js'\nimport { evaluateGeoClause, geoFieldClause, geoIndexProbe, type GeoWhereOperand } from './where.js'\nimport type { Operator } from '../../kernel/query/predicate.js'\n\n/** The geo binder's config bag: field name → its descriptor. */\nexport interface GeoBindingConfig {\n readonly geoFields: Record<string, GeoDescriptor>\n}\n\nexport function geoVia(geoFields: Record<string, GeoDescriptor>): NoydbVia {\n return {\n brand: 'geo',\n // A coordinate is ordinary envelope-encrypted content; the ORDERED\n // posture is what the geohash key earns — a prefix slice is a range\n // answer, never a plaintext coordinate the store can read.\n posture: { encryptedAtRest: 'envelope', queryable: 'ordered', exportable: true, forgettable: true },\n covers: (field) => field in geoFields,\n coveredFields: Object.keys(geoFields), // #1447\n ingest: (record) => {\n let out = record\n for (const [field, desc] of Object.entries(geoFields)) {\n const value = record[field]\n if (value === null || value === undefined) continue\n if (!isGeoPoint(value)) throw new GeoPointError(field, value)\n const geohash = encodeGeohash(value, desc.precision)\n if (out === record) out = { ...record }\n // Spread FIRST so any sibling key on the point (a label, an altitude)\n // survives, and the derived cell always wins over a stale stored one.\n out[field] = { ...(value as unknown as Record<string, unknown>), geohash }\n }\n return out\n },\n // Claims EVERY operator on a covered field, not just `near` — see the\n // header of `where.ts` for why an unclaimed operator on a field whose\n // index key is rewritten is a soundness hole rather than a gap.\n buildClause: (field, op, value) => {\n const desc = geoFields[field]\n if (!desc) return undefined\n return geoFieldClause(field, op as Operator, value, desc)\n },\n evaluateClause: (actual, op, payload) => evaluateGeoClause(actual, op, payload as GeoWhereOperand),\n indexProbe: (op, payload) => geoIndexProbe(op, payload as GeoWhereOperand),\n canonicalizeIndexKey: (field, rawValue) => {\n const desc = geoFields[field]\n if (!desc || !isGeoPoint(rawValue)) return undefined\n return encodeGeohash(rawValue, desc.precision)\n },\n describeFragment: () => ({\n geo: Object.fromEntries(\n Object.entries(geoFields).map(([field, d]) => [field, { precision: d.precision, maxPrefixes: d.maxPrefixes }]),\n ),\n }),\n }\n}\n\nexport function linkGeoVia(): void {\n installViaBinder('geo', (cfg) => geoVia((cfg as GeoBindingConfig).geoFields))\n}\n","/**\n * `geo()` — the field descriptor for a `{ lat, lng }` point (#1355).\n *\n * A branded schema-layer descriptor, a sibling of `money()` / `lookup()`.\n * It owns one decision: at what geohash PRECISION this field is indexed\n * and stored. The math lives in {@link ./geohash}; the query participation\n * in {@link ./where}.\n *\n * Declared through the `via()` composer:\n *\n * ```ts\n * vault.collection('places', {\n * viaFields: { at: via(geo()) },\n * indexes: [{ fields: ['at'], kind: 'sorted' }],\n * })\n * ```\n *\n * The sorted index is what makes `near()` cheaper than a scan; without it\n * the query still returns the RIGHT answer, just by walking every record.\n */\nimport { NoydbError } from '../../kernel/errors.js'\nimport type { ViaDescriptor } from '../../kernel/via/index.js'\nimport { MAX_PRECISION } from './geohash.js'\nimport { linkGeoVia } from './binding.js'\n\nexport interface GeoOptions {\n /**\n * Geohash characters stored and indexed per record. Default 9\n * (≈ 4.8m × 4.8m) — finer than any consumer GPS fix and still short\n * enough that a prefix cover of a city-scale radius is a handful of\n * cells.\n */\n readonly precision?: number\n /**\n * Ceiling on how many geohash prefixes one `near()` query may probe.\n * Default 32. Raising it buys a tighter candidate set at the cost of\n * more index slices per query; lowering it does the reverse. It never\n * affects CORRECTNESS — the cover is a superset at every precision and\n * the haversine post-filter is the exact answer either way.\n */\n readonly maxPrefixes?: number\n}\n\nexport interface GeoDescriptor extends ViaDescriptor {\n readonly _viaBrand: 'geo'\n readonly precision: number\n readonly maxPrefixes: number\n}\n\n/** Raised when a written value is not a usable `{ lat, lng }` point. */\nexport class GeoPointError extends NoydbError {\n constructor(\n public readonly field: string,\n public readonly value: unknown,\n ) {\n super(\n 'GEO_POINT',\n `geo: field \"${field}\" expects { lat, lng } with lat in [-90, 90] and lng in [-180, 180], ` +\n `got ${JSON.stringify(value)}`,\n )\n this.name = 'GeoPointError'\n }\n}\n\n/** Create a {@link GeoDescriptor}. */\nexport function geo(options: GeoOptions = {}): GeoDescriptor {\n // Same #553 static-link discipline as `money()` / `computed()`: constructing\n // the descriptor is the binding's opt-in unit, so whichever module instance\n // produced this descriptor also holds the binder the pipeline will resolve.\n linkGeoVia()\n const precision = options.precision ?? 9\n if (!Number.isInteger(precision) || precision < 1 || precision > MAX_PRECISION) {\n throw new TypeError(`geo: precision must be an integer in 1..${MAX_PRECISION}, got ${String(precision)}`)\n }\n const maxPrefixes = options.maxPrefixes ?? 32\n if (!Number.isInteger(maxPrefixes) || maxPrefixes < 1) {\n throw new TypeError(`geo: maxPrefixes must be a positive integer, got ${String(maxPrefixes)}`)\n }\n return { _viaBrand: 'geo', precision, maxPrefixes }\n}\n\n/** Runtime predicate for detecting a {@link GeoDescriptor}. */\nexport function isGeoDescriptor(x: unknown): x is GeoDescriptor {\n return typeof x === 'object' && x !== null && (x as { _viaBrand?: unknown })._viaBrand === 'geo'\n}\n","/**\n * computed() — the declaration factory for a field whose value is DERIVED\n * from other fields on the same record (#638 Task 7, spec §6). Composes\n * with `via()` (the locked grammar since phase A: `via(computed(fn, { deps,\n * mode }), money('EUR'))`), grouped by `_viaBrand` like every other via\n * feature (`kernel/via/compose.ts#mergeViaFields`).\n *\n * `mode` picks where the function runs:\n * - `'materialized'` (default) — TODAY's stage-5 write-time eager compute\n * (`with-formula/computed/index.ts#evalComputedFields`), stored like any\n * other field. Byte-for-byte the existing `computed: { field: fn }` sugar.\n * - `'virtual'` — rides the `present` read phase (the money-`Formatted`/\n * i18n-`Label` precedent, seam map Part 4): computed fresh on every\n * read, NEVER stored, `queryable: 'none'`, excluded from export unless\n * its declared `deps` permit (identical taint rule to materialized —\n * see `via/computed/binding.ts`).\n *\n * `deps` names the OTHER fields `fn` reads — feeds `ViaGraph` (Task 1/2) so\n * a source's taint (e.g. a classified field) propagates to this derived\n * field. A depsless entry is fine UNLESS the collection also declares\n * classified fields (`kernel/collection-config.ts#resolveComputedEdges`\n * refuses it — closes the #636 opaque-function leak).\n */\nimport type { ViaDescriptor } from '../../kernel/via/index.js'\nimport { linkComputedVia } from './binding.js'\n\nexport interface ComputedDescriptor extends ViaDescriptor {\n readonly _viaBrand: 'computed'\n readonly fn: (record: Record<string, unknown>) => unknown\n readonly deps?: readonly string[]\n readonly mode: 'materialized' | 'virtual'\n}\n\nexport function computed(\n fn: (record: Record<string, unknown>) => unknown,\n opts?: { readonly deps?: readonly string[]; readonly mode?: 'materialized' | 'virtual' },\n): ComputedDescriptor {\n // Self-link, exactly as `money()` and `lookup()` do (#813). Until this call\n // existed, `computed` was the only via feature whose binder was installed by a\n // DIFFERENT module — `port/with/computed-strategy.ts` — rather than by its own\n // declaration factory. That works whenever the kernel spine and the consumer's\n // `computed` import resolve to one module instance, and fails when they do not:\n // under vitest's `server.deps.inline`, a consumer got the descriptor from one\n // transformed instance while the binder registry consulted at bind time lived in\n // another, producing `VIA_NOT_LINKED` for a descriptor `isComputedDescriptor()`\n // accepted. money/i18n/lookup were immune precisely because they self-link.\n //\n // Constructing a descriptor is the binding's opt-in unit, so linking here makes\n // the guarantee local: whatever instance produced the descriptor also has the\n // binder. `installViaBinder` is idempotent + first-wins, so the eager call in\n // `port/with/computed-strategy.ts` stays harmless.\n linkComputedVia()\n return {\n _viaBrand: 'computed',\n fn,\n ...(opts?.deps !== undefined ? { deps: opts.deps } : {}),\n mode: opts?.mode ?? 'materialized',\n }\n}\n\nexport function isComputedDescriptor(x: unknown): x is ComputedDescriptor {\n return typeof x === 'object' && x !== null && (x as { _viaBrand?: unknown })._viaBrand === 'computed'\n}\n","/**\n * The `'lookup'` `NoydbVia` — wires the lookup engine (present-time label\n * dressing across all three backing tiers) into the kernel's generic Via\n * port. Mirrors `via/i18n/binding.ts`'s #553 static-link pattern; the\n * present-time label-dressing algorithm below is adapted from\n * `via-i18n/binding.ts:253-337` (the same wildcard/array/scalar handling,\n * the same `onMissing`/`substitute` policy engine), generalized to branch on\n * `backing` instead of a static-vs-dynamic descriptor-shape check. For the\n * `'static'` and `'reserved'` tiers this delegates to `cfg.lookupLabelResolver`\n * — the SAME vault-built closure the i18n binding's `dictLabelResolver` uses\n * (static table first, else the `vault.dictionary()` handle) — so a native\n * `dict()`/`lookup(static)` field resolves through the identical label data\n * as its `dictKey()`/`staticDict()` alias (the byte-equivalence lock).\n *\n * `lookup()`/`enumOf()`/`dict()` each call {@link linkLookupVia} first — the\n * same #553 pattern `money()`/`dictKey()` use.\n *\n * `buildClause` (label-predicate queries) is still undeclared — out of scope\n * for #650. `compareForOrder` (#650 Task 6, spec §5; matrix tier added Task\n * 7) resolves a `sortBy`-declared field's ordering via `cfg.snapshotFor`'s\n * sync snapshot; the hook signature is UNCHANGED (`via/index.ts:128-129` — no\n * locale param), so it closes over each descriptor's own `displayLocale`\n * (the same locale-less-hinge default `runLookupPresent`'s\n * `hasStaticDisplay` branch already uses). `resolveOrderLabel` (#650 Task\n * 7) is the PER-CALL-locale sibling `orderBy(..., {by:'label'})` needs —\n * see its own doc comment below. `describeFragment` (#650 Task 7) is the\n * first-ever consumed `NoydbVia.describeFragment` implementation — see\n * `with-shape/introspection/describe.ts`'s `buildDescription`.\n */\nimport type { NoydbVia, ViaReadCtx } from '../../kernel/via/index.js'\nimport { installViaBinder } from '../../kernel/via/index.js'\nimport type { LookupDescriptor, LookupBacking, Vocabulary, OnDelete } from './descriptor.js'\nimport { resolvePolicy, type Layer } from '../i18n/policy.js'\nimport { LocaleNotSpecifiedError, UnknownLookupKeyError, ValidationError } from '../../kernel/errors.js'\nimport { getAtPath, setAtPathInPlace } from '../../kernel/paths.js'\nimport type { MaterializedBacking } from './registry.js'\nimport { buildLookupSnapshot } from './snapshot.js'\n\n/**\n * Config a collection's lookup declarations resolve to — the binding's\n * construction input. `lookupLabelResolver`/`getLookupBacking`/`membership`/\n * `snapshotFor` are vault-built closures (never a `Collection` handle,\n * keyring, or DEK/CEK — the zero-knowledge boundary).\n */\nexport interface LookupViaConfig {\n readonly lookupFields: Record<string, LookupDescriptor>\n readonly lookupLabelResolver?: (dimension: string, key: string, locale: string, fallback?: unknown) => Promise<string | undefined>\n /**\n * The matrix (collection) tier's present-time backing-row source, keyed by the full\n * descriptor (not a bare dimension name) so the closure can resolve by `descriptor.key`,\n * not the backing row's PUT-id (#651 Task 3 — the same descriptor-gaining dispatch Task 7\n * already applied to `snapshotFor`).\n */\n readonly getLookupBacking?: (descriptor: LookupDescriptor) => (key: string) => Promise<Record<string, unknown> | undefined>\n /** Closed-vocabulary write-time membership test (#650 Task 3) — `(field, key) => known?`. */\n readonly membership?: (field: string, key: string) => boolean | Promise<boolean>\n /** Sync per-descriptor altKey index — `ingest`'s normalization source (#650 Task 3). */\n readonly getAltIndex?: (desc: LookupDescriptor) => MaterializedBacking | undefined\n /**\n * Sync materialized `key -> row` rows for a lookup descriptor (#650 Task\n * 6, spec §5; matrix-tier routing added #650 Task 7) — `compareForOrder`\n * and `resolveOrderLabel` below, and `snapshot.ts`'s `presentForJoin`\n * builder, all read this same vault-built closure. Reserved AND\n * collection (matrix) tier route here (the vault wires\n * `dimension -> LookupHandle.snapshotEntries()` / `dimension ->\n * collection.querySourceForJoin().snapshot()` respectively, keyed by\n * `descriptor.key` for the matrix case — see `registry.ts`'s\n * `buildLookupSnapshotRows`); static tier is resolved locally from\n * `descriptor.table` without calling this.\n */\n readonly snapshotFor?: (descriptor: LookupDescriptor) => ReadonlyMap<string, Record<string, unknown>> | undefined\n readonly collectionName: string\n}\n\n/** Enum tier (`backing:'static'`, no `table`) has no label source at all — never dressed. */\nfunction hasLabelSource(desc: LookupDescriptor): boolean {\n return !(desc.backing === 'static' && desc.table === undefined)\n}\n\n/**\n * Resolve one key's label. `'static'`/`'reserved'` both go through\n * `cfg.lookupLabelResolver` (mirrors `dictLabelResolver`'s own static-table-\n * first-else-reserved-handle branching — the SAME closure is reused, see\n * `kernel/vault.ts`). `'collection'` (matrix tier) reads the declared\n * `present.label` off the backing row via `cfg.getLookupBacking`; when\n * `present.by` is set, that field's value is a `{ locale -> label }` map\n * indexed by the effective locale.\n */\nasync function fetchLookupLabel(\n desc: LookupDescriptor,\n key: string,\n effLocale: string,\n fieldFallback: string | readonly string[] | undefined,\n cfg: LookupViaConfig,\n): Promise<string | undefined> {\n if (desc.backing === 'collection') {\n const getRow = cfg.getLookupBacking?.(desc)\n const row = getRow ? await getRow(key) : undefined\n const labelField = desc.present?.label\n if (!row || labelField === undefined) return undefined\n const raw = row[labelField]\n if (desc.present?.by !== undefined) {\n return raw && typeof raw === 'object' ? (raw as Record<string, unknown>)[effLocale] as string | undefined : undefined\n }\n return typeof raw === 'string' ? raw : undefined\n }\n return cfg.lookupLabelResolver?.(desc.dimension, key, effLocale, fieldFallback)\n}\n\n/** `present` — resolve `<field>Label` for every declared lookup field. Adapted from `via-i18n/binding.ts:253-337`. */\nasync function runLookupPresent(\n record: Record<string, unknown>,\n ctx: ViaReadCtx,\n cfg: LookupViaConfig,\n): Promise<Record<string, unknown>> {\n const fields = Object.entries(cfg.lookupFields).filter(([, d]) => hasLabelSource(d))\n if (fields.length === 0) return record\n\n const locale = typeof ctx.locale === 'string' ? ctx.locale : undefined\n const fallback = ctx.fallback as string | readonly string[] | undefined\n const layer = ctx.layer as Layer\n\n // `{ locale: 'raw' }` wants the untouched record — mirrors\n // `via-i18n/binding.ts`'s `locale !== 'raw'` dict-label gate exactly (no\n // synthetic `<field>Label` derivative on a raw read).\n if (locale === 'raw') return record\n\n // Static-display hybrid hinge: a `backing:'static'` field with a declared\n // `displayLocale` resolves its `<field>Label` even under a locale-less\n // read (mirrors staticDict's `hasStaticDisplay` gate).\n const hasStaticDisplay = fields.some(([, d]) => d.backing === 'static' && d.displayLocale !== undefined)\n if (!locale && !hasStaticDisplay) return record\n\n let result = record\n const withLabels = { ...result }\n\n for (const [field, desc] of fields) {\n const policy = desc.onMissing ? resolvePolicy(desc.onMissing, layer) : 'null'\n const fieldFallback = policy === 'substitute' ? (fallback ?? desc.substitute) : fallback\n const effLocale = locale ?? (desc.backing === 'static' ? desc.displayLocale : undefined)\n\n const resolveKey = async (key: string): Promise<string | null> => {\n if (!effLocale) {\n if (policy === 'throw') {\n throw new LocaleNotSpecifiedError(field, `lookup \"${field}\": no locale active to resolve key \"${key}\".`)\n }\n return null\n }\n const label = await fetchLookupLabel(desc, key, effLocale, fieldFallback, cfg)\n if (label === undefined) {\n if (policy === 'throw') {\n throw new LocaleNotSpecifiedError(field, `lookup \"${field}\": no label for key \"${key}\" in locale \"${effLocale}\".`)\n }\n return null\n }\n return label\n }\n\n if (field.includes('[].')) {\n const parts = field.split('[].')\n const arrayKey = parts[0]!\n const leaf = parts[1]\n if (!leaf || leaf.includes('.')) continue\n const arr = (withLabels as Record<string, unknown>)[arrayKey]\n if (!Array.isArray(arr)) continue\n const labelKey = `${leaf}Label`\n ;(withLabels as Record<string, unknown>)[arrayKey] = await Promise.all(\n arr.map(async (el) => {\n if (!el || typeof el !== 'object' || Array.isArray(el)) return el\n const k = (el as Record<string, unknown>)[leaf]\n if (typeof k !== 'string') return el\n return { ...(el as Record<string, unknown>), [labelKey]: await resolveKey(k) }\n }),\n )\n continue\n }\n\n const val = result[field]\n if (Array.isArray(val)) {\n withLabels[`${field}Label`] = await Promise.all(\n val.map(async (k) => ({ key: k, label: typeof k === 'string' ? await resolveKey(k) : null })),\n )\n } else if (typeof val === 'string') {\n const label = await resolveKey(val)\n if (label !== null) withLabels[`${field}Label`] = label\n }\n }\n\n result = withLabels\n return result\n}\n\n/**\n * One field's `lookup` descriptor as it appears on a `NoydbVia.\n * describeFragment()` payload (#650 Task 7 — the first real consumer,\n * `with-shape/introspection/describe.ts`'s `buildDescription`, imports this\n * type directly; `describe.ts` is NOT under `kernel/**`, so it's free to\n * import concrete via/ types the way it already does for\n * `LookupDescriptor`/`MoneyDescriptor`/etc.). `dimension` is OMITTED (not\n * emitted as `''`) for a bare `enumOf()` descriptor — the #650 Task 2\n * `dimension:''` sentinel resolved: no dimension name means no `dimension`\n * key, not a meaningless empty string (T2 carry, #650 Task 7).\n */\nexport interface LookupDescribeFragmentEntry {\n readonly dimension?: string\n readonly backing: LookupBacking\n readonly vocabulary: Vocabulary\n readonly key: string\n readonly altKeys?: readonly string[]\n readonly present?: { readonly label: string; readonly by?: string }\n readonly sortBy?: string\n readonly onDelete: OnDelete\n /** Statically-known closed-vocabulary key set (declared `keys`, or a static table's own keys). Omitted when membership lives only in the backing collection/dictionary (open vocabulary, or closed with no declared `keys`). */\n readonly keys?: readonly string[]\n}\n\n/** The `'lookup'` binding's `describeFragment()` payload shape. */\nexport interface LookupDescribeFragment {\n readonly lookupFields: Record<string, LookupDescribeFragmentEntry>\n}\n\nfunction buildLookupDescribeFragment(cfg: LookupViaConfig): Record<string, unknown> {\n const lookupFields: Record<string, LookupDescribeFragmentEntry> = {}\n for (const [field, desc] of Object.entries(cfg.lookupFields)) {\n lookupFields[field] = {\n ...(desc.dimension !== '' ? { dimension: desc.dimension } : {}),\n backing: desc.backing,\n vocabulary: desc.vocabulary,\n key: desc.key,\n onDelete: desc.onDelete,\n ...(desc.altKeys !== undefined ? { altKeys: desc.altKeys } : {}),\n ...(desc.present !== undefined ? { present: desc.present } : {}),\n ...(desc.sortBy !== undefined ? { sortBy: desc.sortBy } : {}),\n // #657 — static tier: when no `keys` was explicitly declared but a\n // `table` was (the staticDict()-equivalent `lookup(dim, {backing:\n // 'static', table})` shape), the table's own key set IS the\n // statically-known closed-vocabulary set the DescribedField.lookup\n // docblock promises (\"declared `keys`, OR a static table's own\n // keys\"). Reserved/matrix tiers never carry `table`, so this branch\n // never fires for them — their `keys` emission is unchanged.\n ...(desc.keys !== undefined\n ? { keys: desc.keys }\n : desc.backing === 'static' && desc.table !== undefined ? { keys: Object.keys(desc.table) } : {}),\n }\n }\n return { lookupFields }\n}\n\n/**\n * `cfg.getAltIndex(desc)` (matrix tier) reads the backing collection's cache\n * via `querySourceForJoin()` (`buildLookupAltIndex`, registry.ts) — which\n * throws a `.join()`-branded message when that collection was opened\n * `{prefetch:false}` (lazy mode is unsupported for altKey normalization).\n * Normalization must never silently not happen (the banned silent-no-op\n * class, #650 Task 3 review, Important 2) — detect that specific failure\n * and surface a CLEAR, lookup-branded `ValidationError` at the point of\n * failure instead of letting the confusing join-branded one leak onto an\n * unrelated `put()`. Any OTHER error (e.g. `materializeBackingTable`'s own\n * altKey-collision `ValidationError`) propagates unchanged.\n */\nfunction getAltIndexOrThrow(field: string, desc: LookupDescriptor, cfg: LookupViaConfig): MaterializedBacking | undefined {\n try {\n return cfg.getAltIndex?.(desc)\n } catch (err) {\n if (err instanceof Error && err.message.includes('lazy-mode')) {\n throw new ValidationError(\n `lookup: altKeys on \"${field}\" require the backing collection \"${desc.dimension}\" to be ` +\n `prefetch-enabled (lazy mode unsupported); open it without {prefetch:false} or drop altKeys.`,\n )\n }\n throw err\n }\n}\n\n/**\n * `ingest` — altKey candidate values normalize to the canonical key (#650\n * Task 3, spec §3). Pure, sync, idempotent (a canonical key maps to\n * itself); no store read — consults the pre-materialized\n * `cfg.getAltIndex(desc)`. The money `canonicalizeIncomingMoney` precedent\n * (`via/index.ts:108`).\n *\n * A `[].`-wildcard multi-value path (`getAtPath` resolves >1 entries — an\n * array of nested objects, e.g. `'lines[].country'`, the same wildcard\n * convention `runLookupPresent` above already handles) normalizes EVERY\n * element's leaf value, not just a lone scalar (#652 fix — this used to bail\n * out entirely here while `runLookupEnforceWrite` below validated every\n * value unnormalized, so a legitimate altKey in an array position was\n * wrongly refused by closed-vocabulary enforcement). `setAtPathInPlace`\n * can't write into a `[].`-wildcard path, so the array is reconstructed\n * immutably instead, mirroring `runLookupPresent`'s own `field.includes\n * ('[].')` branch. A plain field whose OWN value is a bare top-level array\n * (not a `[].`-wildcard path) gets the SAME element-wise normalization\n * against `backing.altIndex` (#661 fix — `getAtPath` resolves it to one\n * opaque value, so the array itself is `values[0]`; a non-string element is\n * left untouched, mirroring the scalar branch's own `typeof !== 'string'`\n * skip — no parallel coercion invented for this shape).\n */\nfunction runLookupIngest(record: Record<string, unknown>, cfg: LookupViaConfig): Record<string, unknown> {\n const withAltKeys = Object.entries(cfg.lookupFields).filter(([, d]) => (d.altKeys?.length ?? 0) > 0)\n if (withAltKeys.length === 0) return record\n\n let result = record\n for (const [field, desc] of withAltKeys) {\n const backing = getAltIndexOrThrow(field, desc, cfg)\n if (!backing || backing.altIndex.size === 0) continue\n\n if (field.includes('[].')) {\n const [arrayKey, leaf] = field.split('[].')\n if (!leaf || leaf.includes('.')) continue\n const arr = record[arrayKey!]\n if (!Array.isArray(arr)) continue\n let changed = false\n const normalized = arr.map((item) => {\n if (!item || typeof item !== 'object' || Array.isArray(item)) return item\n const value = (item as Record<string, unknown>)[leaf]\n if (typeof value !== 'string') return item\n const canonical = backing.altIndex.get(value)\n if (canonical === undefined || canonical === value) return item\n changed = true\n return { ...(item as Record<string, unknown>), [leaf]: canonical }\n })\n if (!changed) continue\n if (result === record) result = { ...record }\n result[arrayKey!] = normalized\n continue\n }\n\n const values = getAtPath(record, field)\n if (values.length !== 1) continue\n const value = values[0]\n\n // `getAtPath`/`setAtPathInPlace` resolve `field` generically, dotted\n // paths included (e.g. 'meta.tags') — do not rewrite this branch to a\n // direct `record[field]` bracket access, which would silently stop\n // normalizing/enforcing a dotted-non-wildcard bare-array field (#661).\n if (Array.isArray(value)) {\n if (value.length === 0) continue\n let changed = false\n const normalized = value.map((el) => {\n if (typeof el !== 'string') return el\n const canonical = backing.altIndex.get(el)\n if (canonical === undefined || canonical === el) return el\n changed = true\n return canonical\n })\n if (!changed) continue\n if (result === record) result = { ...record }\n setAtPathInPlace(result, field, normalized)\n continue\n }\n\n if (typeof value !== 'string') continue\n const canonical = backing.altIndex.get(value)\n if (canonical === undefined || canonical === value) continue\n if (result === record) result = { ...record }\n setAtPathInPlace(result, field, canonical)\n }\n return result\n}\n\n/**\n * `enforceWrite` — closed-vocabulary write refusal (#650 Task 3, spec §3).\n * Runs only for `vocabulary:'closed'` fields; `'open'` (the dictKey/dict\n * default) skips the check entirely, so #649's fix is additive — existing\n * dictKey/staticDict collections are unaffected. `ctx` carries no\n * cross-collection door (`id`/`vault`/`prior`/`emit` only, unchanged) —\n * membership is a vault-built closure on `cfg`, per spec.\n */\nasync function runLookupEnforceWrite(record: Record<string, unknown>, cfg: LookupViaConfig): Promise<void> {\n for (const [field, desc] of Object.entries(cfg.lookupFields)) {\n if (desc.vocabulary !== 'closed') continue\n // Checks every value `getAtPath` returns — for a `[].`-wildcard\n // multi-value path, that's every element's leaf value.\n // `runLookupIngest` above now normalizes each of those elements first\n // (#652), so what lands here for a `[].`-wildcard field is already\n // canonical; this loop's job stays membership, not normalization.\n for (const value of getAtPath(record, field)) {\n // A plain field whose OWN value is a bare top-level array (#661) —\n // `runLookupIngest` above has already normalized its elements'\n // altKeys, so membership-check each element through the SAME\n // `cfg.membership` closure the scalar branch below uses, refusing on\n // the first unknown one. A non-string element is skipped, mirroring\n // the scalar branch's own skip.\n if (Array.isArray(value)) {\n for (const el of value) {\n if (typeof el !== 'string') continue\n const known = cfg.membership ? await cfg.membership(field, el) : true\n if (!known) throw new UnknownLookupKeyError(desc.dimension, field, el)\n }\n continue\n }\n if (typeof value !== 'string') continue\n const known = cfg.membership ? await cfg.membership(field, value) : true\n if (!known) throw new UnknownLookupKeyError(desc.dimension, field, value)\n }\n }\n}\n\n/**\n * `compareForOrder` — exact ordering for a `sortBy`-declared lookup field\n * against the sync snapshot (#650 Task 6, spec §5, conflict resolution 4;\n * matrix-tier coverage added #650 Task 7). Opt-in: undeclared `sortBy`\n * (every dictKey/staticDict alias and every lookup field declared before\n * Task 6) returns `undefined` — falls through to the generic stored-value\n * comparator, byte-identical to today. Static tier reads `descriptor.table`\n * directly; reserved AND matrix (collection) tier both read `cfg.snapshotFor`\n * (the SAME live cache `presentForJoin`'s lookup half reads — see\n * `snapshot.ts`'s file header). The hook has no locale parameter\n * (`via/index.ts:128-129`, unchanged) — closes over the descriptor's own\n * `displayLocale` (the same locale-less-hinge default `runLookupPresent`\n * already uses); a `sortBy` field whose value isn't locale-keyed\n * (`present.by` undefined) never needs one. A `by`-keyed `sortBy` field\n * with NO declared `displayLocale` degrades to comparing the raw canonical\n * keys (silent — `LookupSnapshot.compareKeys` never throws; declare-time\n * warning at `descriptor.ts`'s `lookup()` factory; use\n * `orderBy(field, dir, {by:'label'})` — `resolveOrderLabel` below — for a\n * PER-CALL locale instead).\n */\nfunction compareLookupOrder(field: string, a: unknown, b: unknown, cfg: LookupViaConfig): number | undefined {\n if (typeof a !== 'string' || typeof b !== 'string') return undefined\n const desc = cfg.lookupFields[field]\n if (!desc || desc.sortBy === undefined) return undefined\n const rows = desc.backing === 'static'\n ? (desc.table ? new Map(Object.entries(desc.table)) : undefined)\n : cfg.snapshotFor?.(desc)\n if (!rows) return undefined\n return buildLookupSnapshot(desc.dimension, rows, desc).compareKeys(a, b, desc.displayLocale ?? '')\n}\n\n/**\n * `resolveOrderLabel` — per-key, PER-CALL-locale label resolution for\n * `orderBy(field, dir, { by: 'label' })` (#650 Task 7, spec §6 / seam map\n * Part 10 surprise 6's option (b)) — the channel `compareForOrder` above\n * structurally cannot serve, since `NoydbVia.compareForOrder` carries no\n * locale parameter. Consumed by `kernel/query/builder.ts`'s\n * `buildOrderLabelMaps` as the fallback for lookup fields the legacy dict\n * registries don't bridge (matrix tier; reserved/static tier already\n * resolves via that bridge — `JoinContext.resolveDictSource` — tried\n * FIRST by the caller, see `registry.ts`'s `collectLookupDictCompat` doc\n * comment). Reuses the exact same `cfg.snapshotFor`/`buildLookupSnapshot`\n * machinery as `compareLookupOrder` above, just with the per-call `locale`\n * in place of the descriptor's own `displayLocale` — falling back to\n * `displayLocale` only when the call itself is locale-less, the same\n * hinge order `runLookupPresent` already uses.\n */\nfunction resolveLookupOrderLabel(field: string, key: string, locale: string | undefined, cfg: LookupViaConfig): string | undefined {\n const desc = cfg.lookupFields[field]\n if (!desc) return undefined\n const rows = desc.backing === 'static'\n ? (desc.table ? new Map(Object.entries(desc.table)) : undefined)\n : cfg.snapshotFor?.(desc)\n if (!rows) return undefined\n return buildLookupSnapshot(desc.dimension, rows, desc).label(key, locale ?? desc.displayLocale ?? '')\n}\n\nexport function lookupVia(cfg: LookupViaConfig): NoydbVia {\n return {\n brand: 'lookup',\n posture: { encryptedAtRest: 'envelope', queryable: 'full', exportable: true, forgettable: false },\n reservedPrefixes: ['_dict_', '_lookup_'],\n covers: (field) => field in cfg.lookupFields,\n coveredFields: Object.keys(cfg.lookupFields), // #1447\n ingest: (record) => runLookupIngest(record, cfg),\n enforceWrite: (record) => runLookupEnforceWrite(record, cfg),\n present: async (record, ctx) => runLookupPresent(record, ctx, cfg),\n compareForOrder: (field, a, b) => compareLookupOrder(field, a, b, cfg),\n resolveOrderLabel: (field, key, locale) => resolveLookupOrderLabel(field, key, locale, cfg),\n describeFragment: () => buildLookupDescribeFragment(cfg),\n }\n}\n\nexport function linkLookupVia(): void {\n installViaBinder('lookup', (c) => lookupVia(c as LookupViaConfig))\n}\n","/**\n * `lookup()` / `enumOf()` / `dict()` descriptors — the three declaration\n * surfaces for the `'lookup'` via binding (#650 Task 2, phase D of the Via\n * port). One `LookupDescriptor` shape; the tiers are `backing` details:\n *\n * - `lookup(dimension, opts?)` — matrix tier: first-class collection backing\n * (default `backing:'collection'`) — a reference-collection dimension\n * (e.g. `countries`), open vocabulary by default.\n * - `enumOf(keys)` — enum tier: static in-config table, CLOSED\n * vocabulary, no backing store at all (no dimension name — pure inline\n * keys). Exported as `enumOf`; the barrel (`index.ts`) re-exports it as\n * `enum` (`enum` is a reserved word, so it can't be the function's own\n * name).\n * - `dict(dimension, opts?)` — dict tier: reserved `_dict_<dimension>`\n * micro-collection backing (the `vault.dictionary(name)` engine), open\n * vocabulary by default.\n *\n * Each factory calls {@link linkLookupVia} first — the declaration IS the\n * via binding's opt-in unit (#553), same pattern as `money()`/`i18nText()`/\n * `dictKey()`.\n */\n\nimport type { OnMissingPolicy } from '../i18n/policy.js'\nimport { linkLookupVia } from './binding.js'\n\n/** `'closed'` = enum semantics (membership enforced, Task 3); `'open'` permits unknown keys. */\nexport type Vocabulary = 'open' | 'closed'\n\n/** Where a dimension's rows live: static in-config table / reserved micro-collection / first-class collection. */\nexport type LookupBacking = 'static' | 'reserved' | 'collection'\n\n/** Delete-time referential policy for the backing dimension (default `'restrict'`, enforced in Task 5). */\nexport type OnDelete = 'restrict' | 'cascade' | 'nullify'\n\n/** The one descriptor shape every tier compiles to — tiers differ only by `backing`. */\nexport interface LookupDescriptor<Keys extends string = string> {\n readonly _viaBrand: 'lookup'\n /** Dimension/dictionary/target name. Empty for a bare `enumOf()` (no backing store, no name). */\n readonly dimension: string\n /** Canonical key field on the row (default `'id'`). */\n readonly key: string\n /** Candidate keys normalized to `key` on ingest (Task 3). */\n readonly altKeys?: readonly string[]\n readonly vocabulary: Vocabulary\n /** Dressing dimension: which backing-row field supplies `<field>Label`, optionally keyed `by` a sub-field (e.g. locale). */\n readonly present?: { readonly label: string; readonly by?: string }\n /** Field to sort by against the snapshot (Task 6). */\n readonly sortBy?: string\n readonly backing: LookupBacking\n readonly onDelete: OnDelete\n /** Static/enum inline key set. */\n readonly keys?: readonly Keys[]\n /** Static tier only: in-code `key -> { locale -> label }` table. */\n readonly table?: Readonly<Record<string, Readonly<Record<string, string>>>>\n /** Static hybrid hinge (the `staticDict` alias) — locale-less `<field>Label`. */\n readonly displayLocale?: string\n readonly onMissing?: OnMissingPolicy\n readonly substitute?: readonly string[]\n /** Inline display labels (value -> label), the dict-tier sync fallback (mirrors `dictKey`'s `labels`). */\n readonly labels?: Record<string, string>\n}\n\n/**\n * `sortBy`/`present.by` coupling warning (#650 Task 7, T6 minor — task-6-\n * report.md Concern #4). A `by`-keyed `present` (locale-map) field used as\n * `sortBy` needs a declared `displayLocale` for the locale-less\n * `compareForOrder` sort hook (a plain `orderBy(field)`, no `{by:'label'}`)\n * to resolve anything — without one it silently degrades to comparing the\n * raw canonical keys (never throws — `LookupSnapshot.compareKeys`'s\n * contract). `orderBy(field, dir, {by:'label'})` doesn't need this (it\n * carries its own per-call locale via `NoydbVia.resolveOrderLabel`,\n * #650 Task 7) — only a sortBy-driven PLAIN orderBy does. Warn once at\n * declare time rather than degrade silently at query time.\n */\nfunction warnIfSortByNeedsDisplayLocale(\n dimension: string,\n opts?: { sortBy?: string; present?: { by?: string }; displayLocale?: string },\n): void {\n if (opts?.sortBy !== undefined && opts.present?.by !== undefined && opts.displayLocale === undefined) {\n console.warn(\n `[noy-db] lookup(\"${dimension}\"): sortBy \"${opts.sortBy}\" is locale-keyed (present.by is set) but no ` +\n `displayLocale is declared — a locale-less orderBy() will silently sort by the raw stored key instead ` +\n `of the resolved label. Declare displayLocale, or sort via orderBy(field, dir, { by: 'label' }), which ` +\n `resolves at the query's own per-call locale.`,\n )\n }\n}\n\n/**\n * Matrix tier — first-class collection backing (default `backing:'collection'`).\n * `dimension` names the backing collection (e.g. `'countries'`).\n *\n * `backing` may be overridden to construct any tier through this one\n * factory — e.g. `lookup(name, { backing:'static', table, displayLocale })`\n * is the table-bearing static tier `staticDict()` compiles onto. The\n * `table`/`displayLocale`/`keys`/`onMissing`/`substitute`/`labels` options\n * are a superset of the brief's literal opts list: `LookupDescriptor`\n * already carries these fields for exactly this purpose, and without them\n * `backing:'static'` would be unreachable stand-alone through `lookup()`\n * (see task-2-report.md's \"Design decisions\").\n *\n * **`altKeys` caveat (matrix tier only)**: normalizing an altKey candidate\n * to its canonical `key` requires the backing `dimension` collection to be\n * open in EAGER mode (the default; `{ prefetch: false }` — lazy mode — is\n * unsupported). A `put()` on a field with `altKeys` whose backing collection\n * is lazy throws a `ValidationError` naming the field and dimension; open\n * the backing collection without `{ prefetch: false }`, or drop `altKeys`.\n */\nexport function lookup<Keys extends string>(\n dimension: string,\n opts?: {\n key?: string\n altKeys?: readonly string[]\n vocabulary?: Vocabulary\n present?: { label: string; by?: string }\n sortBy?: string\n backing?: LookupBacking\n onDelete?: OnDelete\n keys?: readonly Keys[]\n table?: Readonly<Record<string, Readonly<Record<string, string>>>>\n displayLocale?: string\n onMissing?: OnMissingPolicy\n substitute?: readonly string[]\n labels?: Record<string, string>\n },\n): LookupDescriptor<Keys> {\n linkLookupVia()\n warnIfSortByNeedsDisplayLocale(dimension, opts)\n return {\n _viaBrand: 'lookup',\n dimension,\n key: opts?.key ?? 'id',\n vocabulary: opts?.vocabulary ?? 'open',\n backing: opts?.backing ?? 'collection',\n onDelete: opts?.onDelete ?? 'restrict',\n ...(opts?.altKeys !== undefined ? { altKeys: opts.altKeys } : {}),\n ...(opts?.present !== undefined ? { present: opts.present } : {}),\n ...(opts?.sortBy !== undefined ? { sortBy: opts.sortBy } : {}),\n ...(opts?.keys !== undefined ? { keys: opts.keys } : {}),\n ...(opts?.table !== undefined ? { table: opts.table } : {}),\n ...(opts?.displayLocale !== undefined ? { displayLocale: opts.displayLocale } : {}),\n ...(opts?.onMissing !== undefined ? { onMissing: opts.onMissing } : {}),\n ...(opts?.substitute !== undefined ? { substitute: opts.substitute } : {}),\n ...(opts?.labels !== undefined ? { labels: opts.labels } : {}),\n }\n}\n\n/**\n * Enum tier — static in-config table, CLOSED vocabulary, no backing store.\n * No dimension name (pure inline keys) — `dimension` is `''`.\n */\nexport function enumOf<const Keys extends readonly string[]>(keys: Keys): LookupDescriptor<Keys[number]> {\n linkLookupVia()\n return {\n _viaBrand: 'lookup',\n dimension: '',\n key: 'id',\n vocabulary: 'closed',\n backing: 'static',\n onDelete: 'restrict',\n keys,\n }\n}\n\n/**\n * Dict tier — reserved `_dict_<dimension>` micro-collection backing (the\n * `vault.dictionary(dimension)` engine), open vocabulary by default. The\n * native equivalent of `dictKey()`.\n *\n * Unlike `lookup()`'s matrix tier, `dict()` has no `altKeys` option — its\n * `_dict_<dimension>` backing is the always-synchronous `LookupHandle`\n * write-through cache, never a `vault.collection()` that can be opened\n * `{ prefetch: false }`, so the matrix tier's lazy-mode altKeys restriction\n * does not apply here.\n */\nexport function dict<Keys extends string>(\n dimension: string,\n opts?: {\n keys?: readonly Keys[]\n vocabulary?: Vocabulary\n present?: { label: string; by?: string }\n onDelete?: OnDelete\n onMissing?: OnMissingPolicy\n substitute?: readonly string[]\n },\n): LookupDescriptor<Keys> {\n linkLookupVia()\n return {\n _viaBrand: 'lookup',\n dimension,\n key: 'id',\n vocabulary: opts?.vocabulary ?? 'open',\n backing: 'reserved',\n onDelete: opts?.onDelete ?? 'restrict',\n ...(opts?.keys !== undefined ? { keys: opts.keys } : {}),\n ...(opts?.present !== undefined ? { present: opts.present } : {}),\n ...(opts?.onMissing !== undefined ? { onMissing: opts.onMissing } : {}),\n ...(opts?.substitute !== undefined ? { substitute: opts.substitute } : {}),\n }\n}\n","/**\n * _sync_credentials reserved collection —\n *\n * Stores per-adapter OAuth tokens (and any other long-lived sync secrets) as\n * encrypted records inside the vault itself. Tokens are wrapped with the\n * compartment's own DEK, live on disk as ciphertext like any other record, and\n * are accessed only through the dedicated API in this module — never via\n * `vault.collection('_sync_credentials')`.\n *\n * Design decisions\n * ────────────────\n *\n * **Why a reserved collection, not a separate store?**\n * The compartment's existing encryption stack (AES-256-GCM + collection DEK)\n * is exactly the right primitive for protecting OAuth tokens at rest. Using a\n * separate store would require a new encryption surface, new adapter calls,\n * and a new backup/restore path — all of which already exist for collections.\n *\n * **Why not exposed as a regular collection?**\n * The same reason `_keyring` and `_ledger` aren't: they have invariants that\n * must be enforced (naming scheme, no cross-user leakage, no schema\n * validation, no history/ledger writes for privacy). Routing through a\n * dedicated API enforces those invariants.\n *\n * **Token lifecycle:**\n * - `putCredential(vault, adapterId, token)` — store or overwrite\n * - `getCredential(vault, adapterId)` — load and decrypt\n * - `deleteCredential(vault, adapterId)` — remove\n * - `listCredentials(vault)` — enumerate adapter IDs (not tokens)\n *\n * The `adapterId` is the record ID within the `_sync_credentials` collection.\n * It should be a stable, human-readable identifier for the adapter instance\n * (e.g. `'google-drive'`, `'dropbox'`, `'s3-prod'`).\n *\n * **ACL:** only `owner` and `admin` roles can read/write sync credentials.\n * Operators, viewers, and clients cannot call this API. The check is made\n * against the caller's keyring role at call time.\n */\n\nimport { buildRecordAad, buildRecordEnvelope } from '../capsule/index.js'\nimport type { NoydbStore, EncryptedEnvelope } from '../kernel/types.js'\nimport type { UnlockedKeyring } from '../with-party/team/keyring.js'\nimport { encrypt, openEnvelopeJson } from '../capsule/index.js'\nimport { ensureCollectionDEK } from '../with-party/team/keyring.js'\nimport { PermissionDeniedError } from '../kernel/errors.js'\n\n/**\n * The reserved collection name. Never collides with user collections.\n * Canonical definition lives in `reserved-secret-collections.ts` (shared with\n * the `vault.collection()` guard and grant DEK-propagation); re-exported here\n * for existing consumers.\n */\nexport { SYNC_CREDENTIALS_COLLECTION } from '../with-party/team/reserved-secret-collections.js'\nimport { SYNC_CREDENTIALS_COLLECTION } from '../with-party/team/reserved-secret-collections.js'\n\n// ─── Token types ──────────────────────────────────────────────────────\n\n/**\n * An OAuth/auth token stored in `_sync_credentials`.\n *\n * Fields mirror the OAuth2 token response shape. `customData` is an escape\n * hatch for adapter-specific secrets (API keys, connection strings, etc.)\n * that don't fit the OAuth2 shape.\n */\nexport interface SyncCredential {\n /** Stable identifier for the adapter instance (e.g. 'google-drive'). */\n readonly adapterId: string\n /** OAuth token type, usually 'Bearer'. */\n readonly tokenType: string\n /** The access token. Expires at `expiresAt` if set. */\n readonly accessToken: string\n /** Long-lived refresh token for renewing the access token. */\n readonly refreshToken?: string\n /** ISO timestamp when `accessToken` expires. Absent means \"no expiry\". */\n readonly expiresAt?: string\n /** Space-separated OAuth scopes. */\n readonly scopes?: string\n /** Adapter-specific opaque data (API keys, endpoints, etc.). */\n readonly customData?: Record<string, string>\n}\n\n// ─── Access check ─────────────────────────────────────────────────────\n\nfunction requireAdminAccess(keyring: UnlockedKeyring): void {\n // FR-6: custodian is INTENTIONALLY excluded. Sync credentials are the\n // firm's hosting/infrastructure secrets (OAuth tokens, connection strings) —\n // not the custodian's operational scope. A custodian operates the DATA but\n // must never mint or read transport credentials that could be used to\n // re-home or impersonate the firm's vault. Do NOT add 'custodian' here.\n if (keyring.role !== 'owner' && keyring.role !== 'admin') {\n throw new PermissionDeniedError(\n `Sync credentials require owner or admin role. Current role: \"${keyring.role}\"`,\n )\n }\n}\n\n// ─── Public API ────────────────────────────────────────────────────────\n\n/**\n * Store or overwrite a sync credential for the given adapter.\n *\n * The credential is encrypted with the `_sync_credentials` collection DEK\n * (auto-generated on first use). The record ID is the `adapterId`.\n *\n * Requires owner or admin role.\n */\nexport async function putCredential(\n adapter: NoydbStore,\n vault: string,\n keyring: UnlockedKeyring,\n credential: SyncCredential,\n): Promise<void> {\n requireAdminAccess(keyring)\n\n const getDek = await ensureCollectionDEK(adapter, vault, keyring)\n const dek = await getDek(SYNC_CREDENTIALS_COLLECTION)\n\n // The version is resolved BEFORE the identity, because it is now part of it:\n // sealing under one version and stamping another produces a record no reader\n // can open (#1093).\n const existing = await adapter.get(vault, SYNC_CREDENTIALS_COLLECTION, credential.adapterId)\n const version = existing ? existing._v + 1 : 1\n\n const identity = { collection: SYNC_CREDENTIALS_COLLECTION, id: credential.adapterId, version }\n const { iv, data } = await encrypt(JSON.stringify(credential), dek, buildRecordAad(identity))\n\n const envelope: EncryptedEnvelope = buildRecordEnvelope(identity, { iv, data })\n\n await adapter.put(\n vault,\n SYNC_CREDENTIALS_COLLECTION,\n credential.adapterId,\n envelope,\n existing ? existing._v : undefined,\n )\n}\n\n/**\n * Load and decrypt a sync credential for the given adapter ID.\n *\n * Returns `null` if no credential exists for this adapter.\n * Requires owner or admin role.\n */\nexport async function getCredential(\n adapter: NoydbStore,\n vault: string,\n keyring: UnlockedKeyring,\n adapterId: string,\n): Promise<SyncCredential | null> {\n requireAdminAccess(keyring)\n\n const getDek = await ensureCollectionDEK(adapter, vault, keyring)\n const dek = await getDek(SYNC_CREDENTIALS_COLLECTION)\n\n const envelope = await adapter.get(vault, SYNC_CREDENTIALS_COLLECTION, adapterId)\n if (!envelope) return null\n\n const plaintext = await openEnvelopeJson({ collection: SYNC_CREDENTIALS_COLLECTION, id: adapterId }, envelope, dek)\n return JSON.parse(plaintext) as SyncCredential\n}\n\n/**\n * Delete a sync credential by adapter ID.\n *\n * No-op if the credential doesn't exist. Requires owner or admin role.\n */\nexport async function deleteCredential(\n adapter: NoydbStore,\n vault: string,\n keyring: UnlockedKeyring,\n adapterId: string,\n): Promise<void> {\n requireAdminAccess(keyring)\n await adapter.delete(vault, SYNC_CREDENTIALS_COLLECTION, adapterId)\n}\n\n/**\n * List all adapter IDs that have stored credentials.\n *\n * Returns only the IDs, never the credential payloads. Useful for\n * displaying \"connected adapters\" in UI without decrypting tokens.\n * Requires owner or admin role.\n */\nexport async function listCredentials(\n adapter: NoydbStore,\n vault: string,\n keyring: UnlockedKeyring,\n): Promise<string[]> {\n requireAdminAccess(keyring)\n return adapter.list(vault, SYNC_CREDENTIALS_COLLECTION)\n}\n\n/**\n * Check whether a credential exists and whether its access token has expired.\n *\n * Returns `{ exists: false }` if no credential is stored, or\n * `{ exists: true, expired: boolean }` based on the `expiresAt` field.\n * Requires owner or admin role.\n */\nexport async function credentialStatus(\n adapter: NoydbStore,\n vault: string,\n keyring: UnlockedKeyring,\n adapterId: string,\n): Promise<{ exists: false } | { exists: true; expired: boolean }> {\n const credential = await getCredential(adapter, vault, keyring, adapterId)\n if (!credential) return { exists: false }\n\n const expired = credential.expiresAt\n ? Date.now() > new Date(credential.expiresAt).getTime()\n : false\n\n return { exists: true, expired }\n}\n","/**\n * Partitioned collections — the union read path and the declaration surface\n * (#1342, ADR 0007 \"partitioning is collection-shaped\").\n *\n * ## What was ruled, and what that left to build\n *\n * ADR 0007 ruled **NO** on lifting a partition value into a storage key or\n * into cleartext envelope metadata: it is a permanent per-record\n * classification handed to the backend, and it widens `@noy-db/hub/to` across\n * every `to-*` adapter and the conformance kit to buy a win on one read path.\n * `NoydbStore.listPage` is untouched by this file, and must stay untouched.\n *\n * It ruled instead that **a partition IS a collection**. The store already\n * sees collection names in cleartext — `listPage(vault, collection, cursor,\n * limit)` takes the name as a parameter — so `invoices@FY2026-Q1` prunes for\n * free: `listPage` never fetches an excluded partition because it is never\n * asked to. No seam change, no new leak class, and partition = collection =\n * DEK makes it a REAL boundary rather than an advisory one (per-collection\n * wrapping, #1004): a principal granted only Q1 cannot decrypt Q2, and a\n * closed period's DEK can be archived or dropped outright — something a\n * scoped predicate can never do.\n *\n * The honest cost of that ruling was three missing pieces. This module is\n * them:\n *\n * 1. **a cross-collection union read path** — there was none, so a query\n * spanning four quarters meant running four and merging by hand;\n * 2. **cheap partition enumeration** — `vault.collections()` is\n * `adapter.loadAll(vault)`, the WHOLE vault snapshot, so even LISTING\n * partitions cost a full load;\n * 3. **a declaration** binding a set of collections into one logical\n * collection with a partition key, so a `where` on that key can prune.\n *\n * ## Where the win actually is\n *\n * `collection.query()` runs over an already-decrypted in-memory cache with\n * hash / sorted / compound dispatch in front of it (#1344, #1345), so pruning\n * there is strictly weaker than an index that already ships. `scan()` is the\n * prize: every page is DECRYPTED, so a partition never fetched is a page\n * never decrypted. {@link PartitionedScan} is where the measured win lives;\n * {@link PartitionedQuery} exists because a union that only streams is not a\n * union read path.\n *\n * ## Why this is a free function and not `vault.partitioned()`\n *\n * `check-architecture`'s kernel-surface ratchet leaves `vault.ts` one line of\n * headroom, and a service that re-couples itself into the kernel is exactly\n * what that ratchet exists to catch. It is also not a `with*()` factory: once\n * ADR 0007 removed the storage-layout policy (there is no key prefixing to\n * configure — the partition is a collection), nothing is left to opt into.\n * What remains is a query-shaped helper over collections the caller already\n * owns, so it is a plain function, tree-shaken when unused.\n *\n * ## The immutability precondition, stated once\n *\n * ⛔ **A record's partition key must be immutable.** If a record can be edited\n * from one partition to another, a scope derived at plan time and a scope\n * derived at read time can disagree, and the difference is silently missing\n * rows. {@link PartitionedCollection.put} routes on `record[key]` and will\n * happily write the same id into two partitions if the key changes; it does\n * not police this, because it cannot see the prior value without reading\n * every partition — which is the cost the whole design exists to avoid.\n */\n\nimport type { Collection } from '../../kernel/collection.js'\nimport type { Vault } from '../../kernel/vault.js'\nimport type { Clause, Operator } from '../../kernel/query/predicate.js'\nimport type { OrderBy, QueryPlan } from '../../kernel/query/builder.js'\nimport { sortRecords } from '../../kernel/query/builder.js'\nimport type { ExplainNode, QueryExplanation } from '../../kernel/query/relate/explain.js'\nimport { renderExplainText } from '../../kernel/query/relate/explain.js'\nimport { ScanBuilder } from '../../kernel/query/scan-builder.js'\nimport type { ScanPageProvider } from '../../kernel/query/scan-builder.js'\nimport type { ReduceResult, ReduceSpec } from '../../with-lookup/reduce/reduction.js'\nimport { reduceRecords } from '../../with-lookup/reduce/reduction.js'\nimport {\n ALL_PARTITIONS,\n describePartitionScope,\n partitionsInScope,\n resolvePartitionScope,\n} from '../../kernel/query/relate/partition.js'\nimport type { PartitionScope } from '../../kernel/query/relate/partition.js'\n\n/**\n * The collection holding one registry record per partitioned logical\n * collection. A normal, ENCRYPTED collection — the partition list is record\n * content, not a record id, so declaring a partition set adds no cleartext\n * channel of its own. (The partition VALUES do become collection names, and\n * that exposure is ADR 0007's deliberate, developer-visible trade; this\n * registry does not widen it.)\n */\nexport const PARTITION_REGISTRY_COLLECTION = '_partition_sets'\n\ninterface PartitionRegistryRecord {\n readonly id: string\n readonly partitions: readonly string[]\n}\n\n/** How a partition value becomes a collection name. */\nexport type PartitionNamer = (logicalName: string, partition: string) => string\n\n/** The default: `invoices` + `FY2026-Q1` → `invoices@FY2026-Q1`. */\nexport const defaultPartitionNamer: PartitionNamer = (name, partition) => `${name}@${partition}`\n\nexport interface PartitionSpec<T> {\n /** The logical collection name. Never itself a stored collection. */\n readonly name: string\n /**\n * The field whose value names the partition. ⛔ Must be immutable per\n * record — see this module's header.\n */\n readonly key: keyof T & string\n /**\n * Partition values known to the caller. Merged with whatever the registry\n * already holds, so a caller may declare none and rely on the registry, or\n * declare the full set and never write one.\n */\n readonly partitions?: readonly string[]\n /** Override the partition → collection-name mapping. */\n readonly namer?: PartitionNamer\n /**\n * Options passed to every member `vault.collection()` — indexes, refs,\n * schema. Identical across partitions by construction: they are one logical\n * collection, and a per-partition shape would make the union unsound.\n */\n readonly collectionOptions?: unknown\n}\n\n/**\n * Bind a set of collections into one partitioned logical collection.\n *\n * ```ts\n * const invoices = partitioned<Invoice>(vault, {\n * name: 'invoices',\n * key: 'period',\n * partitions: ['FY2026-Q1', 'FY2026-Q2', 'FY2026-Q3', 'FY2026-Q4'],\n * })\n *\n * await invoices.put('inv-1', { id: 'inv-1', period: 'FY2026-Q1', amount: 100 })\n *\n * // reads ONE collection — the other three are never asked for\n * const q1 = await invoices.query().where('period', '==', 'FY2026-Q1').all()\n *\n * // reads all four, merged, sorted and paged AFTER the union\n * const top = await invoices.query().orderBy('amount', 'desc').limit(10).all()\n * ```\n */\nexport function partitioned<T>(vault: Vault, spec: PartitionSpec<T>): PartitionedCollection<T> {\n return new PartitionedCollection<T>(vault, spec)\n}\n\nexport class PartitionedCollection<T> {\n readonly name: string\n readonly key: string\n private readonly vault: Vault\n private readonly namer: PartitionNamer\n private readonly collectionOptions: unknown\n private readonly declared: string[]\n /**\n * Session cache of the REGISTRY's partition list — deliberately not of the\n * merged set. The two are different questions and conflating them cost a\n * red test: `ensurePartition` must persist a partition the caller DECLARED\n * but never wrote, and a cache of the merged set makes every declared value\n * look already-known, so the registry stays empty and a later session that\n * declares nothing enumerates nothing.\n */\n private stored: string[] | null = null\n\n constructor(vault: Vault, spec: PartitionSpec<T>) {\n this.vault = vault\n this.name = spec.name\n this.key = spec.key\n this.namer = spec.namer ?? defaultPartitionNamer\n this.collectionOptions = spec.collectionOptions\n this.declared = [...(spec.partitions ?? [])]\n }\n\n /** The member collection name for a partition value. */\n collectionNameOf(partition: string): string {\n return this.namer(this.name, partition)\n }\n\n /** The member `Collection` for one partition. */\n partition(value: string): Collection<T> {\n return this.vault.collection<T>(\n this.collectionNameOf(value),\n this.collectionOptions as never,\n ) as unknown as Collection<T>\n }\n\n /**\n * The declared partition set, in declaration order.\n *\n * ⭐ **This is the \"cheap enumeration\" half of #1342, and cheap means a\n * measured thing.** `vault.collections()` is `adapter.loadAll(vault)` — the\n * whole vault snapshot, every collection, every envelope — so enumerating\n * twelve quarters cost a full load before this existed. Here it is ONE\n * record read out of {@link PARTITION_REGISTRY_COLLECTION}, and zero reads\n * once the session has resolved it.\n * `__tests__/partitioned-collection.test.ts` asserts the `loadAll` count is\n * zero rather than trusting the sentence.\n */\n async partitions(): Promise<readonly string[]> {\n const stored = await this.loadStored()\n const merged = [...this.declared]\n for (const p of stored) if (!merged.includes(p)) merged.push(p)\n return merged\n }\n\n /**\n * Declare a partition, persisting it so a later session enumerates it\n * without the caller re-declaring. Idempotent, and keyed on what the\n * REGISTRY holds rather than on what this handle declared.\n */\n async ensurePartition(value: string): Promise<void> {\n const stored = await this.loadStored()\n if (stored.includes(value)) return\n stored.push(value)\n await this.registry().put(this.name, { id: this.name, partitions: [...stored] })\n }\n\n private async loadStored(): Promise<string[]> {\n if (this.stored === null) {\n this.stored = [...((await this.registry().get(this.name))?.partitions ?? [])]\n }\n return this.stored\n }\n\n /**\n * Write a record into the partition its key names, declaring that partition\n * if it is new.\n *\n * Throws when `record[key]` is not a string — a partition value names a\n * collection, and routing a record to a partition derived by coercion is\n * how a record ends up somewhere no query will look for it.\n */\n async put(id: string, record: T): Promise<void> {\n const value = (record as Record<string, unknown>)[this.key]\n if (typeof value !== 'string' || value === '') {\n throw new PartitionKeyError(this.name, this.key, value)\n }\n await this.ensurePartition(value)\n await this.partition(value).put(id, record as never)\n }\n\n /** A union query across the member collections, pruned by the predicate. */\n query(): PartitionedQuery<T> {\n return new PartitionedQuery<T>(this, [], [], undefined, 0)\n }\n\n /**\n * A union scan across the member collections, pruned by the predicate.\n * Pages are decrypted, so an excluded partition is decryption never paid.\n */\n scan(opts: { pageSize?: number } = {}): PartitionedScan<T> {\n return new PartitionedScan<T>(this, [], opts.pageSize ?? 100)\n }\n\n /** @internal — the normalizer for clause shapes, and the union's legs. */\n _registryName(): string {\n return PARTITION_REGISTRY_COLLECTION\n }\n\n private registry(): Collection<PartitionRegistryRecord> {\n return this.vault.collection<PartitionRegistryRecord>(\n PARTITION_REGISTRY_COLLECTION,\n ) as unknown as Collection<PartitionRegistryRecord>\n }\n}\n\n/** `record[partitionKey]` was absent, empty, or not a string. */\nexport class PartitionKeyError extends Error {\n constructor(collection: string, key: string, value: unknown) {\n super(\n `[noy-db] partitioned(\"${collection}\"): record.${key} must be a non-empty string ` +\n `naming its partition, got ${typeof value === 'string' ? '\"\"' : String(value)}. ` +\n `A partition value names a collection; it is never coerced.`,\n )\n this.name = 'PartitionKeyError'\n }\n}\n\n/**\n * One recorded builder call, replayed onto each in-scope member's own\n * builder.\n *\n * ⭐ **Replay, not re-implementation.** The alternative was to build `Clause`\n * objects here, which would have meant a second copy of `Query.where()`'s\n * normalization — the `matches` lowering (#1357), the subquery resolution\n * (#1351), the Via posture gate and the operand rewrite. A second copy is a\n * second thing to drift. Instead every leg is a real `Query` / `ScanBuilder`\n * that normalized the call itself, and the PRUNING reads the normalized\n * `Clause[]` back off one of them — so the clause the pruner classifies is\n * byte-identical to the clause the executor evaluates.\n */\ntype Step<T> =\n | { readonly kind: 'where'; readonly field: string; readonly op: Operator; readonly value: unknown }\n | { readonly kind: 'filter'; readonly fn: (record: T) => boolean }\n\ninterface LegBuilder<B> {\n where(field: never, op: Operator, value: unknown): B\n filter(fn: never): B\n}\n\nfunction replay<T, B extends LegBuilder<B>>(builder: B, steps: readonly Step<T>[]): B {\n let out = builder\n for (const step of steps) {\n out = step.kind === 'where'\n ? out.where(step.field as never, step.op, step.value)\n : out.filter(step.fn as never)\n }\n return out\n}\n\n/**\n * The clauses a scope decision is taken over: the NORMALIZED top-level clause\n * list, obtained by replaying the recorded steps onto a real member query.\n *\n * When the partition set is empty there is no member to normalize against —\n * and no partition to prune to either, so the scope is empty regardless.\n */\nfunction normalizedClauses<T>(\n col: PartitionedCollection<T>,\n declared: readonly string[],\n steps: readonly Step<T>[],\n): readonly Clause[] {\n if (declared.length === 0) return []\n const probe = replay(col.partition(declared[0]!).query() as never, steps) as unknown as {\n _plan(): QueryPlan\n }\n return probe._plan().clauses\n}\n\n/**\n * A union query across a partitioned collection's members.\n *\n * **Filtering runs per leg; ordering and paging run AFTER the union** — the\n * same shape `orderBy('client.name')` needed when the sort moved after the\n * join legs (#1337). A `limit` is deliberately NOT pushed down: the top ten\n * of the union is not the top ten of any one leg, and a leg-local limit would\n * be correct only for an unordered query, which is the case nobody writes.\n */\nexport class PartitionedQuery<T> {\n constructor(\n private readonly col: PartitionedCollection<T>,\n private readonly steps: readonly Step<T>[],\n private readonly orderBys: readonly OrderBy[],\n private readonly limitN: number | undefined,\n private readonly offsetN: number,\n ) {}\n\n private with(\n patch: Partial<{\n steps: readonly Step<T>[]\n orderBys: readonly OrderBy[]\n limitN: number | undefined\n offsetN: number\n }>,\n ): PartitionedQuery<T> {\n return new PartitionedQuery<T>(\n this.col,\n patch.steps ?? this.steps,\n patch.orderBys ?? this.orderBys,\n 'limitN' in patch ? patch.limitN : this.limitN,\n patch.offsetN ?? this.offsetN,\n )\n }\n\n where(field: keyof T & string, op: Operator, value: unknown): PartitionedQuery<T> {\n return this.with({ steps: [...this.steps, { kind: 'where', field, op, value }] })\n }\n\n filter(fn: (record: T) => boolean): PartitionedQuery<T> {\n return this.with({ steps: [...this.steps, { kind: 'filter', fn }] })\n }\n\n orderBy(field: keyof T & string, direction: 'asc' | 'desc' = 'asc'): PartitionedQuery<T> {\n return this.with({ orderBys: [...this.orderBys, { field, direction }] })\n }\n\n limit(n: number): PartitionedQuery<T> {\n return this.with({ limitN: n })\n }\n\n offset(n: number): PartitionedQuery<T> {\n return this.with({ offsetN: n })\n }\n\n /** The pruning decision for this query, and the set it was taken against. */\n async scope(): Promise<{ declared: readonly string[]; scope: PartitionScope }> {\n const declared = await this.col.partitions()\n const clauses = normalizedClauses(this.col, declared, this.steps)\n return { declared, scope: resolvePartitionScope(clauses, this.col.key, declared) }\n }\n\n /**\n * The matched rows, unordered and unpaged — the set every reduce-shaped\n * terminal reports over, matching `Query.count()`'s rule that orderBy /\n * limit / offset describe a page and a reduction is not paginated.\n */\n private async matched(): Promise<T[]> {\n const { declared, scope } = await this.scope()\n const rows: T[] = []\n for (const p of partitionsInScope(scope, declared)) {\n const leg = replay(this.col.partition(p).query() as never, this.steps) as unknown as {\n toArray(): T[]\n }\n rows.push(...leg.toArray())\n }\n return rows\n }\n\n /** The union, sorted then paged. */\n async all(): Promise<T[]> {\n let rows = await this.matched()\n if (this.orderBys.length > 0) rows = sortRecords(rows, this.orderBys) as T[]\n if (this.offsetN > 0) rows = rows.slice(this.offsetN)\n if (this.limitN !== undefined) rows = rows.slice(0, this.limitN)\n return rows\n }\n\n async first(): Promise<T | null> {\n return (await this.all())[0] ?? null\n }\n\n async count(): Promise<number> {\n return (await this.matched()).length\n }\n\n async aggregate<Spec extends ReduceSpec>(spec: Spec): Promise<ReduceResult<Spec>> {\n return reduceRecords(await this.matched(), spec)\n }\n\n /**\n * The plan, with the partition decision as its first line:\n *\n * ```\n * partitions partitions: 1 of 12 scanned [partitions:pruned] -- key \"period\"; FY2026-Q1\n * source snapshot (no indexes) [source] rows=500\n * where period == \"FY2026-Q1\" [scan] rows=500\n * ```\n *\n * ⭐ The dispatch label is decided by {@link resolvePartitionScope} — the\n * SAME call the executor makes, not a mirror of it. `explain.ts`'s header\n * warns that its index dispatch mirrors `candidateRecords`; #1375 deleted\n * one such mirror, and a partition dispatch would have been a third site.\n *\n * The nodes after the partition line are the FIRST in-scope member's own\n * explanation. Every member runs the same plan over the same shape, so one\n * leg's nodes describe them all; the partition line is what says how many\n * legs there are.\n */\n async explain(): Promise<QueryExplanation> {\n const { declared, scope } = await this.scope()\n const inScope = partitionsInScope(scope, declared)\n const pruned = scope !== ALL_PARTITIONS && inScope.length < declared.length\n const notes = [`key \"${this.col.key}\"`]\n notes.push(\n inScope.length === 0\n ? 'no partition admits this predicate — nothing is read'\n : inScope.join(', '),\n )\n if (!pruned && declared.length > 0) {\n notes.push('predicate proves no narrowing — every partition is read')\n }\n const head: ExplainNode = {\n op: 'partitions',\n dispatch: pruned ? 'partitions:pruned' : 'partitions:all',\n detail: describePartitionScope(scope, declared),\n estimatedRows: undefined,\n notes,\n children: [],\n }\n const legNodes: readonly ExplainNode[] = inScope.length === 0\n ? []\n : (replay(this.col.partition(inScope[0]!).query() as never, this.steps) as unknown as {\n explain(): QueryExplanation\n }).explain().nodes\n const nodes = [head, ...legNodes]\n return { nodes, caps: [], reducerRewrite: [], text: renderExplainText(nodes) }\n }\n}\n\n/**\n * A union scan across a partitioned collection's members — **the path where\n * pruning pays.**\n *\n * Each page is fetched through the member collection's `listPage`, which\n * DECRYPTS it. An excluded partition is therefore not merely a store call\n * skipped, it is every envelope in that partition never decrypted. That is\n * the whole return on ADR 0007, and `__tests__/partitioned-scan-cost.test.ts`\n * measures it rather than asserting it.\n *\n * The builder records `where`/`filter` and only materializes a\n * {@link ScanBuilder} at the terminal, because the partition set cannot be\n * decided before the predicate is known — a provider fixed at `scan()` time\n * would already have committed to every partition.\n */\nexport class PartitionedScan<T> {\n constructor(\n private readonly col: PartitionedCollection<T>,\n private readonly steps: readonly Step<T>[],\n private readonly pageSize: number,\n ) {}\n\n where(field: keyof T & string, op: Operator, value: unknown): PartitionedScan<T> {\n return new PartitionedScan<T>(\n this.col,\n [...this.steps, { kind: 'where', field, op, value }],\n this.pageSize,\n )\n }\n\n filter(fn: (record: T) => boolean): PartitionedScan<T> {\n return new PartitionedScan<T>(this.col, [...this.steps, { kind: 'filter', fn }], this.pageSize)\n }\n\n /** The pruning decision for this scan, and the set it was taken against. */\n async scope(): Promise<{ declared: readonly string[]; scope: PartitionScope }> {\n const declared = await this.col.partitions()\n const clauses = normalizedClauses(this.col, declared, this.steps)\n return { declared, scope: resolvePartitionScope(clauses, this.col.key, declared) }\n }\n\n /**\n * The union as a single {@link ScanBuilder} — so `.aggregate()`,\n * `.groupBy()` and `for await` come from the streaming machinery that\n * already exists, at its existing O(reducers) memory bound, rather than\n * from a second implementation of it.\n */\n async builder(): Promise<ScanBuilder<T>> {\n const { declared, scope } = await this.scope()\n const members = partitionsInScope(scope, declared).map((p) => this.col.partition(p))\n return replay(\n new ScanBuilder<T>(unionPageProvider(members), this.pageSize) as never,\n this.steps,\n ) as unknown as ScanBuilder<T>\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n yield* await this.builder()\n }\n\n async aggregate<Spec extends ReduceSpec>(spec: Spec): Promise<ReduceResult<Spec>> {\n return (await this.builder()).aggregate(spec)\n }\n\n /**\n * **ASYNC here, unlike `Query.toArray()` (#1413).** Same method name, a\n * different contract, because the surface underneath differs: this one\n * genuinely fetches across every partition leg, so it genuinely awaits. `Query`'s terminal reads an\n * already-decrypted in-memory cache and returns `T[]` synchronously.\n */\n async toArray(): Promise<T[]> {\n const out: T[] = []\n for await (const record of this) out.push(record)\n return out\n }\n}\n\n/**\n * Walk a list of member collections as ONE paged stream.\n *\n * The composite cursor is `\"<memberIndex>|<memberCursor>\"`. Two properties\n * make it safe to hand back to a consumer that stores it:\n *\n * - it is opaque in exactly the way a store's own cursor is — the member\n * cursor is passed through verbatim and never parsed;\n * - a member's LAST page returns a cursor pointing at the NEXT member with\n * an empty inner cursor, so exhaustion is detected once, not per page.\n *\n * ⚠️ A member that returns an empty page with a non-null cursor is walked\n * again rather than treated as exhausted — the store contract explicitly\n * allows a store to return fewer items than the limit while more exist.\n */\nexport function unionPageProvider<T>(members: readonly Collection<T>[]): ScanPageProvider<T> {\n return {\n async listPage(opts: { cursor?: string; limit?: number }) {\n let index = 0\n let inner: string | undefined\n if (opts.cursor !== undefined) {\n const at = opts.cursor.indexOf('|')\n index = Number.parseInt(opts.cursor.slice(0, at), 10)\n const rest = opts.cursor.slice(at + 1)\n inner = rest === '' ? undefined : rest\n }\n while (index < members.length) {\n const page = await (members[index]! as unknown as {\n listPage(o: { cursor?: string; limit?: number }): Promise<{ items: T[]; nextCursor: string | null }>\n }).listPage({ ...(inner !== undefined ? { cursor: inner } : {}), ...(opts.limit !== undefined ? { limit: opts.limit } : {}) })\n if (page.nextCursor !== null) {\n return { items: page.items, nextCursor: `${index}|${page.nextCursor}` }\n }\n index += 1\n inner = undefined\n if (page.items.length > 0) {\n return { items: page.items, nextCursor: index < members.length ? `${index}|` : null }\n }\n }\n return { items: [], nextCursor: null }\n },\n }\n}\n"],"mappings":"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","names":["value","canonical","known"]}
@@ -8,12 +8,15 @@ import {
8
8
  decodeIdxId,
9
9
  encodeIdxId,
10
10
  isIdxId
11
- } from "../chunk-KTFRCC5C.js";
11
+ } from "../chunk-V7ADQF5O.js";
12
12
  import {
13
13
  CollectionIndexes
14
- } from "../chunk-I3ISCYT7.js";
15
- import "../chunk-NSITFOCJ.js";
16
- import "../chunk-7O3Y4PPD.js";
14
+ } from "../chunk-2AFX33YA.js";
15
+ import "../chunk-SUZKW6UR.js";
16
+ import "../chunk-LGNDFRYC.js";
17
+ import "../chunk-5WWDGFOS.js";
18
+ import "../chunk-SYNY3VB5.js";
19
+ import "../chunk-37EPTBBR.js";
17
20
 
18
21
  // src/with-lookup/indexing/active.ts
19
22
  function withIndexing() {
@@ -31,7 +34,12 @@ function withIndexing() {
31
34
  } else if (Array.isArray(def)) {
32
35
  for (const f of def) eager.declare(f);
33
36
  } else {
34
- for (const f of def.fields) eager.declare(f);
37
+ const obj = def;
38
+ for (const f of obj.fields) {
39
+ eager.declare(f);
40
+ if (obj.kind === "sorted") eager.declareSorted(f, { persist: obj.persist === true });
41
+ }
42
+ if (obj.kind === "sorted") eager.declareCompound(obj.fields, { persist: obj.persist === true });
35
43
  }
36
44
  }
37
45
  return makeEagerState(eager);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/with-lookup/indexing/active.ts"],"sourcesContent":["/**\n * Active indexing strategy factory. Calling `withIndexing()` returns\n * an `IndexingStrategy` whose `createState` constructs a real\n * `CollectionIndexes` (eager) or `PersistedCollectionIndex` (lazy)\n * per Collection, depending on the collection's `prefetch` mode and\n * its declared `IndexDef[]`.\n *\n * This module is only reachable through the `@noy-db/hub/indexing`\n * subpath — a consumer that never imports the subpath ships none of\n * this (ESM tree-shaking + hub's `\"sideEffects\": false`).\n */\n\nimport { CollectionIndexes } from './eager-indexes.js'\nimport type { IndexDef } from './eager-indexes.js'\nimport { PersistedCollectionIndex } from './persisted-indexes.js'\nimport type { IndexingStrategy, IndexState } from './strategy.js'\n\n/**\n * Build the default indexing strategy. Pass into\n * `createNoydb({ indexingStrategy: withIndexing() })` to light up the\n * eager-mode `==/in` fast-path on `.query()` and the full lazy-mode\n * `.lazyQuery()` + rebuild / reconcile / auto-reconcile surface.\n *\n * @example\n * ```ts\n * import { createNoydb } from '@noy-db/hub'\n * import { withIndexing } from '@noy-db/hub/indexing'\n *\n * const db = await createNoydb({\n * store, user, secret,\n * indexingStrategy: withIndexing(),\n * })\n * ```\n */\nexport function withIndexing(): IndexingStrategy {\n return {\n createState({ defs, lazy }) {\n if (lazy) {\n const persisted = new PersistedCollectionIndex()\n declareAll(persisted, defs)\n return makeLazyState(persisted)\n }\n const eager = new CollectionIndexes()\n for (const def of defs) {\n if (typeof def === 'string') {\n eager.declare(def)\n } else if (Array.isArray(def)) {\n for (const f of def as readonly string[]) eager.declare(f)\n } else {\n for (const f of (def as { fields: readonly string[] }).fields) eager.declare(f)\n }\n }\n return makeEagerState(eager)\n },\n }\n}\n\nfunction declareAll(persisted: PersistedCollectionIndex, defs: readonly IndexDef[]): void {\n for (const def of defs) {\n if (typeof def === 'string') {\n persisted.declare(def)\n } else {\n const fields = Array.isArray(def) ? (def as readonly string[]) : (def as { fields: readonly string[] }).fields\n // #698: decompose a composite into its component single-field indexes\n // (like the eager branch above), so a composite-only declaration still\n // provides the single-field driver the #696 Via-covered fall-through\n // and single-field queries need. The composite mirror is kept for the\n // multi-field fast path.\n for (const f of fields) persisted.declare(f)\n persisted.declareComposite(fields)\n }\n }\n}\n\nfunction makeEagerState(eager: CollectionIndexes): IndexState {\n return {\n isEnabled: true,\n getEagerIndexes: () => eager,\n getPersistedIndexes: () => null,\n }\n}\n\nfunction makeLazyState(persisted: PersistedCollectionIndex): IndexState {\n return {\n isEnabled: true,\n getEagerIndexes: () => null,\n getPersistedIndexes: () => persisted,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkCO,SAAS,eAAiC;AAC/C,SAAO;AAAA,IACL,YAAY,EAAE,MAAM,KAAK,GAAG;AAC1B,UAAI,MAAM;AACR,cAAM,YAAY,IAAI,yBAAyB;AAC/C,mBAAW,WAAW,IAAI;AAC1B,eAAO,cAAc,SAAS;AAAA,MAChC;AACA,YAAM,QAAQ,IAAI,kBAAkB;AACpC,iBAAW,OAAO,MAAM;AACtB,YAAI,OAAO,QAAQ,UAAU;AAC3B,gBAAM,QAAQ,GAAG;AAAA,QACnB,WAAW,MAAM,QAAQ,GAAG,GAAG;AAC7B,qBAAW,KAAK,IAA0B,OAAM,QAAQ,CAAC;AAAA,QAC3D,OAAO;AACL,qBAAW,KAAM,IAAsC,OAAQ,OAAM,QAAQ,CAAC;AAAA,QAChF;AAAA,MACF;AACA,aAAO,eAAe,KAAK;AAAA,IAC7B;AAAA,EACF;AACF;AAEA,SAAS,WAAW,WAAqC,MAAiC;AACxF,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,QAAQ,UAAU;AAC3B,gBAAU,QAAQ,GAAG;AAAA,IACvB,OAAO;AACL,YAAM,SAAS,MAAM,QAAQ,GAAG,IAAK,MAA6B,IAAsC;AAMxG,iBAAW,KAAK,OAAQ,WAAU,QAAQ,CAAC;AAC3C,gBAAU,iBAAiB,MAAM;AAAA,IACnC;AAAA,EACF;AACF;AAEA,SAAS,eAAe,OAAsC;AAC5D,SAAO;AAAA,IACL,WAAW;AAAA,IACX,iBAAiB,MAAM;AAAA,IACvB,qBAAqB,MAAM;AAAA,EAC7B;AACF;AAEA,SAAS,cAAc,WAAiD;AACtE,SAAO;AAAA,IACL,WAAW;AAAA,IACX,iBAAiB,MAAM;AAAA,IACvB,qBAAqB,MAAM;AAAA,EAC7B;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/with-lookup/indexing/active.ts"],"sourcesContent":["/**\n * Active indexing strategy factory. Calling `withIndexing()` returns\n * an `IndexingStrategy` whose `createState` constructs a real\n * `CollectionIndexes` (eager) or `PersistedCollectionIndex` (lazy)\n * per Collection, depending on the collection's `prefetch` mode and\n * its declared `IndexDef[]`.\n *\n * This module is only reachable through the `@noy-db/hub/indexing`\n * subpath — a consumer that never imports the subpath ships none of\n * this (ESM tree-shaking + hub's `\"sideEffects\": false`).\n */\n\nimport { CollectionIndexes } from './eager-indexes.js'\nimport type { IndexDef } from './eager-indexes.js'\nimport { PersistedCollectionIndex } from './persisted-indexes.js'\nimport type { IndexingStrategy, IndexState } from './strategy.js'\n\n/**\n * Build the default indexing strategy. Pass into\n * `createNoydb({ indexingStrategy: withIndexing() })` to light up the\n * eager-mode `==/in` fast-path on `.query()` and the full lazy-mode\n * `.lazyQuery()` + rebuild / reconcile / auto-reconcile surface.\n *\n * @example\n * ```ts\n * import { createNoydb } from '@noy-db/hub'\n * import { withIndexing } from '@noy-db/hub/indexing'\n *\n * const db = await createNoydb({\n * store, user, secret,\n * indexingStrategy: withIndexing(),\n * })\n * ```\n */\nexport function withIndexing(): IndexingStrategy {\n return {\n createState({ defs, lazy }) {\n if (lazy) {\n const persisted = new PersistedCollectionIndex()\n declareAll(persisted, defs)\n return makeLazyState(persisted)\n }\n const eager = new CollectionIndexes()\n for (const def of defs) {\n if (typeof def === 'string') {\n eager.declare(def)\n } else if (Array.isArray(def)) {\n for (const f of def as readonly string[]) eager.declare(f)\n } else {\n // `kind: 'sorted'` (#1344) additionally builds the ordered array\n // that drives `<`/`>`/`between`/`startsWith`/`orderBy+limit`. The\n // hash index is declared either way, so `==`/`in` stay O(1).\n const obj = def as { fields: readonly string[]; kind?: 'hash' | 'sorted'; persist?: boolean }\n for (const f of obj.fields) {\n eager.declare(f)\n // `persist: true` (#1359) opts the SORTED structures into an\n // encrypted sidecar so a restart reuses them. The hash index is\n // never persisted — the flag is inert without `kind: 'sorted'`.\n if (obj.kind === 'sorted') eager.declareSorted(f, { persist: obj.persist === true })\n }\n // A MULTI-FIELD `kind: 'sorted'` declaration additionally builds the\n // tuple-keyed compound index (#1345) that drives an equality prefix\n // plus a range or `orderBy` on the next component. The per-field\n // indexes above are kept too, so a query touching only one component\n // keeps its existing plan.\n if (obj.kind === 'sorted') eager.declareCompound(obj.fields, { persist: obj.persist === true })\n }\n }\n return makeEagerState(eager)\n },\n }\n}\n\nfunction declareAll(persisted: PersistedCollectionIndex, defs: readonly IndexDef[]): void {\n for (const def of defs) {\n if (typeof def === 'string') {\n persisted.declare(def)\n } else {\n const fields = Array.isArray(def) ? (def as readonly string[]) : (def as { fields: readonly string[] }).fields\n // #698: decompose a composite into its component single-field indexes\n // (like the eager branch above), so a composite-only declaration still\n // provides the single-field driver the #696 Via-covered fall-through\n // and single-field queries need. The composite mirror is kept for the\n // multi-field fast path.\n for (const f of fields) persisted.declare(f)\n persisted.declareComposite(fields)\n }\n }\n}\n\nfunction makeEagerState(eager: CollectionIndexes): IndexState {\n return {\n isEnabled: true,\n getEagerIndexes: () => eager,\n getPersistedIndexes: () => null,\n }\n}\n\nfunction makeLazyState(persisted: PersistedCollectionIndex): IndexState {\n return {\n isEnabled: true,\n getEagerIndexes: () => null,\n getPersistedIndexes: () => persisted,\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAkCO,SAAS,eAAiC;AAC/C,SAAO;AAAA,IACL,YAAY,EAAE,MAAM,KAAK,GAAG;AAC1B,UAAI,MAAM;AACR,cAAM,YAAY,IAAI,yBAAyB;AAC/C,mBAAW,WAAW,IAAI;AAC1B,eAAO,cAAc,SAAS;AAAA,MAChC;AACA,YAAM,QAAQ,IAAI,kBAAkB;AACpC,iBAAW,OAAO,MAAM;AACtB,YAAI,OAAO,QAAQ,UAAU;AAC3B,gBAAM,QAAQ,GAAG;AAAA,QACnB,WAAW,MAAM,QAAQ,GAAG,GAAG;AAC7B,qBAAW,KAAK,IAA0B,OAAM,QAAQ,CAAC;AAAA,QAC3D,OAAO;AAIL,gBAAM,MAAM;AACZ,qBAAW,KAAK,IAAI,QAAQ;AAC1B,kBAAM,QAAQ,CAAC;AAIf,gBAAI,IAAI,SAAS,SAAU,OAAM,cAAc,GAAG,EAAE,SAAS,IAAI,YAAY,KAAK,CAAC;AAAA,UACrF;AAMA,cAAI,IAAI,SAAS,SAAU,OAAM,gBAAgB,IAAI,QAAQ,EAAE,SAAS,IAAI,YAAY,KAAK,CAAC;AAAA,QAChG;AAAA,MACF;AACA,aAAO,eAAe,KAAK;AAAA,IAC7B;AAAA,EACF;AACF;AAEA,SAAS,WAAW,WAAqC,MAAiC;AACxF,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,QAAQ,UAAU;AAC3B,gBAAU,QAAQ,GAAG;AAAA,IACvB,OAAO;AACL,YAAM,SAAS,MAAM,QAAQ,GAAG,IAAK,MAA6B,IAAsC;AAMxG,iBAAW,KAAK,OAAQ,WAAU,QAAQ,CAAC;AAC3C,gBAAU,iBAAiB,MAAM;AAAA,IACnC;AAAA,EACF;AACF;AAEA,SAAS,eAAe,OAAsC;AAC5D,SAAO;AAAA,IACL,WAAW;AAAA,IACX,iBAAiB,MAAM;AAAA,IACvB,qBAAqB,MAAM;AAAA,EAC7B;AACF;AAEA,SAAS,cAAc,WAAiD;AACtE,SAAO;AAAA,IACL,WAAW;AAAA,IACX,iBAAiB,MAAM;AAAA,IACvB,qBAAqB,MAAM;AAAA,EAC7B;AACF;","names":[]}
@@ -1,7 +1,7 @@
1
1
  import "../chunk-UBSFPGVJ.js";
2
2
  import {
3
3
  dumpVaultSchema
4
- } from "../chunk-FET5XCAT.js";
4
+ } from "../chunk-PP3K67AJ.js";
5
5
  import {
6
6
  applyListProjection
7
7
  } from "../chunk-VG2ZSFYD.js";
@@ -9,18 +9,17 @@ import "../chunk-RXLYKVTF.js";
9
9
  import {
10
10
  jsonSchemaToFields
11
11
  } from "../chunk-VYYM3MEN.js";
12
- import "../chunk-ACAQ2DSG.js";
12
+ import "../chunk-747G6CT3.js";
13
13
  import "../chunk-Y2NBBT6K.js";
14
- import "../chunk-SGZAIJCV.js";
15
- import "../chunk-4ZS56W5S.js";
16
- import "../chunk-SZJ3DLZA.js";
17
- import "../chunk-BRLKZUBT.js";
18
- import "../chunk-BTDR2PXY.js";
19
- import "../chunk-CHQCZZWC.js";
20
- import "../chunk-LP7BEXCT.js";
21
- import "../chunk-HPVZCW43.js";
22
- import "../chunk-7MG7SJT7.js";
23
- import "../chunk-7O3Y4PPD.js";
14
+ import "../chunk-3L2NBKDR.js";
15
+ import "../chunk-EZGV6F47.js";
16
+ import "../chunk-OIEO4WDL.js";
17
+ import "../chunk-Q2XRFWOI.js";
18
+ import "../chunk-NH2UOV3B.js";
19
+ import "../chunk-42ALPZ2B.js";
20
+ import "../chunk-QMWY2FDS.js";
21
+ import "../chunk-SV2PM2OY.js";
22
+ import "../chunk-37EPTBBR.js";
24
23
  export {
25
24
  applyListProjection,
26
25
  dumpVaultSchema,