@noy-db/hub 0.3.0-pre.1 → 0.3.0-pre.10

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 (435) hide show
  1. package/dist/aggregate/index.d.ts +3 -4
  2. package/dist/aggregate/index.js +9 -8
  3. package/dist/aggregate/index.js.map +1 -1
  4. package/dist/api-TX2EX2FX.js +20 -0
  5. package/dist/as/index.d.ts +4 -5
  6. package/dist/as/index.js +12 -6
  7. package/dist/at/index.d.ts +2 -3
  8. package/dist/attestation/index.d.ts +3 -4
  9. package/dist/attestation/index.js +19 -13
  10. package/dist/attestation/index.js.map +1 -1
  11. package/dist/{backup-XV3IOEGB.js → backup-R7NTDFKY.js} +14 -6
  12. package/dist/backup-R7NTDFKY.js.map +1 -0
  13. package/dist/blobs/index.d.ts +4 -5
  14. package/dist/blobs/index.js +12 -6
  15. package/dist/blobs/index.js.map +1 -1
  16. package/dist/bundle/index.d.ts +5 -6
  17. package/dist/bundle/index.js +21 -15
  18. package/dist/bundle/index.js.map +1 -1
  19. package/dist/{bundle-CH-H06dp.d.ts → bundle-D6GxiUfq.d.ts} +1 -1
  20. package/dist/by/index.js +2 -2
  21. package/dist/cargo/index.d.ts +4 -6
  22. package/dist/cargo/index.js +27 -21
  23. package/dist/chunk-2OV5NVE7.js +95 -0
  24. package/dist/chunk-2OV5NVE7.js.map +1 -0
  25. package/dist/{chunk-5N6CZTCY.js → chunk-2OZXVKVP.js} +3 -3
  26. package/dist/{chunk-BG3SPSR4.js → chunk-2REPHKET.js} +5 -4
  27. package/dist/chunk-2REPHKET.js.map +1 -0
  28. package/dist/{chunk-LXQT4WMP.js → chunk-3JXPAHOZ.js} +8 -6
  29. package/dist/{chunk-LXQT4WMP.js.map → chunk-3JXPAHOZ.js.map} +1 -1
  30. package/dist/{chunk-UAG5KWVA.js → chunk-3MATJ6O4.js} +3 -3
  31. package/dist/chunk-3OPY6MK2.js +404 -0
  32. package/dist/chunk-3OPY6MK2.js.map +1 -0
  33. package/dist/{chunk-62QYRORB.js → chunk-3QSIU3UT.js} +34 -63
  34. package/dist/chunk-3QSIU3UT.js.map +1 -0
  35. package/dist/{chunk-DGDI2D4M.js → chunk-4OMCIY6F.js} +29 -9
  36. package/dist/chunk-4OMCIY6F.js.map +1 -0
  37. package/dist/chunk-5I35DOHK.js +94 -0
  38. package/dist/chunk-5I35DOHK.js.map +1 -0
  39. package/dist/{chunk-2P2HZEXU.js → chunk-5VG4IJR7.js} +11 -9
  40. package/dist/{chunk-2P2HZEXU.js.map → chunk-5VG4IJR7.js.map} +1 -1
  41. package/dist/{chunk-AZAOEIKW.js → chunk-5YESYH2C.js} +2 -2
  42. package/dist/{chunk-GYGWYIOZ.js → chunk-6G5ORS5D.js} +7 -5
  43. package/dist/{chunk-GYGWYIOZ.js.map → chunk-6G5ORS5D.js.map} +1 -1
  44. package/dist/{chunk-VCTFO5CO.js → chunk-6P5XCKSD.js} +2 -2
  45. package/dist/{chunk-IO6GRPT6.js → chunk-7BWJHO2A.js} +2 -2
  46. package/dist/{chunk-IPB7FTQX.js → chunk-7P2SDJG3.js} +15 -9
  47. package/dist/chunk-7P2SDJG3.js.map +1 -0
  48. package/dist/{chunk-SRB2XEWB.js → chunk-ANB77BVV.js} +6 -4
  49. package/dist/chunk-ANB77BVV.js.map +1 -0
  50. package/dist/{chunk-UDRIWL7A.js → chunk-BKARNZJN.js} +3 -3
  51. package/dist/{chunk-Y22T3KQE.js → chunk-BQISD5ZV.js} +3 -3
  52. package/dist/chunk-BQISD5ZV.js.map +1 -0
  53. package/dist/{chunk-UIU2THRG.js → chunk-BUAQ7YI3.js} +138 -378
  54. package/dist/chunk-BUAQ7YI3.js.map +1 -0
  55. package/dist/{chunk-V7RWQRG7.js → chunk-CB7CWSKW.js} +3 -3
  56. package/dist/{chunk-LV7M27WM.js → chunk-DFVUTGT2.js} +14 -201
  57. package/dist/chunk-DFVUTGT2.js.map +1 -0
  58. package/dist/{chunk-CWPPNPOH.js → chunk-DJ7KIPLV.js} +2 -2
  59. package/dist/{chunk-5R5JW2JT.js → chunk-DSKDQP3G.js} +3480 -1916
  60. package/dist/chunk-DSKDQP3G.js.map +1 -0
  61. package/dist/{chunk-VFQGRQIH.js → chunk-DV4HUP5G.js} +7 -5
  62. package/dist/{chunk-VFQGRQIH.js.map → chunk-DV4HUP5G.js.map} +1 -1
  63. package/dist/{chunk-5LUY7UTV.js → chunk-EOXAAJTY.js} +289 -48
  64. package/dist/chunk-EOXAAJTY.js.map +1 -0
  65. package/dist/chunk-ET67AY6B.js +74 -0
  66. package/dist/chunk-ET67AY6B.js.map +1 -0
  67. package/dist/{chunk-TA66UMI4.js → chunk-F4CEK5YM.js} +2 -2
  68. package/dist/chunk-FORYWFN6.js +130 -0
  69. package/dist/chunk-FORYWFN6.js.map +1 -0
  70. package/dist/{chunk-IELYAOGG.js → chunk-FRP6D2DM.js} +19 -6
  71. package/dist/chunk-FRP6D2DM.js.map +1 -0
  72. package/dist/chunk-FUOE7UUV.js +341 -0
  73. package/dist/chunk-FUOE7UUV.js.map +1 -0
  74. package/dist/{chunk-SM3AVUHC.js → chunk-G4JYND6L.js} +2 -2
  75. package/dist/{chunk-AXRXJTE2.js → chunk-G6XV4H65.js} +5 -5
  76. package/dist/{chunk-I2NOIW44.js → chunk-GNMXXTMN.js} +8 -6
  77. package/dist/{chunk-I2NOIW44.js.map → chunk-GNMXXTMN.js.map} +1 -1
  78. package/dist/chunk-GYGLAVCX.js +19 -0
  79. package/dist/chunk-GYGLAVCX.js.map +1 -0
  80. package/dist/{chunk-UV5MFVO3.js → chunk-HPWKV3YB.js} +2 -2
  81. package/dist/chunk-HY3AUMFI.js +41 -0
  82. package/dist/chunk-HY3AUMFI.js.map +1 -0
  83. package/dist/chunk-HYR4WZZ3.js +69 -0
  84. package/dist/chunk-HYR4WZZ3.js.map +1 -0
  85. package/dist/{chunk-SKF73JOP.js → chunk-ICXIFFYZ.js} +3 -3
  86. package/dist/chunk-IGJCYUT5.js +99 -0
  87. package/dist/chunk-IGJCYUT5.js.map +1 -0
  88. package/dist/{chunk-MD3Y6J3L.js → chunk-IVLTXX4W.js} +7 -5
  89. package/dist/{chunk-MD3Y6J3L.js.map → chunk-IVLTXX4W.js.map} +1 -1
  90. package/dist/{chunk-WWGT2MDV.js → chunk-J4LPNIGK.js} +26 -11
  91. package/dist/chunk-J4LPNIGK.js.map +1 -0
  92. package/dist/chunk-JJZ2LW6T.js +36 -0
  93. package/dist/chunk-JJZ2LW6T.js.map +1 -0
  94. package/dist/{chunk-RUIMKQTA.js → chunk-JK733I5V.js} +1 -1
  95. package/dist/chunk-JK733I5V.js.map +1 -0
  96. package/dist/{chunk-UPJNJGGA.js → chunk-KJ2BCBTL.js} +25 -8
  97. package/dist/chunk-KJ2BCBTL.js.map +1 -0
  98. package/dist/{chunk-LMTH2RM6.js → chunk-KNZB6JMR.js} +2 -2
  99. package/dist/{chunk-I3TIKTJO.js → chunk-KPZS5QAQ.js} +29 -10
  100. package/dist/chunk-KPZS5QAQ.js.map +1 -0
  101. package/dist/{chunk-PKHL44ER.js → chunk-LEJIKBBB.js} +2 -2
  102. package/dist/{chunk-AQTBSL7R.js → chunk-LL2NIVUR.js} +14 -7
  103. package/dist/chunk-LL2NIVUR.js.map +1 -0
  104. package/dist/chunk-LP7BEXCT.js +32 -0
  105. package/dist/chunk-LP7BEXCT.js.map +1 -0
  106. package/dist/{chunk-5O3AOPDT.js → chunk-MCHVVJIA.js} +443 -467
  107. package/dist/chunk-MCHVVJIA.js.map +1 -0
  108. package/dist/chunk-NO272T7Q.js +194 -0
  109. package/dist/chunk-NO272T7Q.js.map +1 -0
  110. package/dist/{chunk-LFLXAY2W.js → chunk-NUEQU36L.js} +71 -93
  111. package/dist/chunk-NUEQU36L.js.map +1 -0
  112. package/dist/chunk-O45M6LDB.js +38 -0
  113. package/dist/chunk-O45M6LDB.js.map +1 -0
  114. package/dist/{chunk-PSMV73A5.js → chunk-OBKWYKYC.js} +5 -5
  115. package/dist/{chunk-CMGR4ZEW.js → chunk-OHHKHSJP.js} +2 -2
  116. package/dist/{chunk-HCIPRAGS.js → chunk-OT76OZL6.js} +2 -2
  117. package/dist/{chunk-ITNUCOXM.js → chunk-OVYRLHPE.js} +7 -5
  118. package/dist/{chunk-ITNUCOXM.js.map → chunk-OVYRLHPE.js.map} +1 -1
  119. package/dist/{chunk-SMXWYP24.js → chunk-OXCSVM3B.js} +3 -3
  120. package/dist/{chunk-IGUYVGGI.js → chunk-P33LUIML.js} +3 -3
  121. package/dist/{chunk-JNUWZ6D3.js → chunk-PLS64NCS.js} +7 -5
  122. package/dist/{chunk-JNUWZ6D3.js.map → chunk-PLS64NCS.js.map} +1 -1
  123. package/dist/{chunk-EIZUR2XW.js → chunk-PS2NEWEX.js} +2 -2
  124. package/dist/chunk-QA2KUPCP.js +45 -0
  125. package/dist/chunk-QA2KUPCP.js.map +1 -0
  126. package/dist/{chunk-WYSO2NIH.js → chunk-QOC3VYL2.js} +2 -2
  127. package/dist/{chunk-FISN7WE4.js → chunk-QSFOZUYL.js} +30 -5
  128. package/dist/{chunk-FISN7WE4.js.map → chunk-QSFOZUYL.js.map} +1 -1
  129. package/dist/{chunk-KVOXU4T5.js → chunk-RHK32N73.js} +2 -2
  130. package/dist/{chunk-3YFXJ3ZP.js → chunk-RW3Y22MW.js} +2 -2
  131. package/dist/{chunk-ZYUC53LT.js → chunk-S7VFUQM2.js} +117 -3
  132. package/dist/chunk-S7VFUQM2.js.map +1 -0
  133. package/dist/chunk-T7WSLRAU.js +49 -0
  134. package/dist/chunk-T7WSLRAU.js.map +1 -0
  135. package/dist/{chunk-IUEN57TV.js → chunk-TAKWLZZX.js} +280 -58
  136. package/dist/chunk-TAKWLZZX.js.map +1 -0
  137. package/dist/chunk-THNJ3IKU.js +17 -0
  138. package/dist/chunk-THNJ3IKU.js.map +1 -0
  139. package/dist/{chunk-MTMJVJ5W.js → chunk-TMBXVJKT.js} +5 -3
  140. package/dist/chunk-TMBXVJKT.js.map +1 -0
  141. package/dist/{chunk-QHJW5EXU.js → chunk-TWKKOM55.js} +2 -2
  142. package/dist/{chunk-M6OST55S.js → chunk-U3WZCU7E.js} +2 -2
  143. package/dist/{chunk-AIWULCUO.js → chunk-UF362QVH.js} +5 -3
  144. package/dist/{chunk-AIWULCUO.js.map → chunk-UF362QVH.js.map} +1 -1
  145. package/dist/{chunk-KXGNJJXB.js → chunk-UN4FVIBH.js} +7 -7
  146. package/dist/chunk-VEAVKDDB.js +29 -0
  147. package/dist/chunk-VEAVKDDB.js.map +1 -0
  148. package/dist/chunk-VEPTFUJY.js +29 -0
  149. package/dist/chunk-VEPTFUJY.js.map +1 -0
  150. package/dist/{chunk-TEILUWOI.js → chunk-VJV7GKQK.js} +10 -12
  151. package/dist/chunk-VJV7GKQK.js.map +1 -0
  152. package/dist/chunk-VQRAIPYF.js +50 -0
  153. package/dist/chunk-VQRAIPYF.js.map +1 -0
  154. package/dist/{chunk-NF5JWERG.js → chunk-VRIYFLBA.js} +2 -2
  155. package/dist/chunk-VWM3DAVB.js +265 -0
  156. package/dist/chunk-VWM3DAVB.js.map +1 -0
  157. package/dist/{chunk-RUEKROOS.js → chunk-VWRRVE6D.js} +2 -2
  158. package/dist/chunk-VYYM3MEN.js +98 -0
  159. package/dist/chunk-VYYM3MEN.js.map +1 -0
  160. package/dist/chunk-WBJIQSLL.js +167 -0
  161. package/dist/chunk-WBJIQSLL.js.map +1 -0
  162. package/dist/{chunk-XXYIOFUB.js → chunk-WIGQB62E.js} +5 -5
  163. package/dist/chunk-WZSCE6RM.js +466 -0
  164. package/dist/chunk-WZSCE6RM.js.map +1 -0
  165. package/dist/{chunk-5R3ERCDH.js → chunk-XGDAPN6M.js} +25 -9
  166. package/dist/{chunk-5R3ERCDH.js.map → chunk-XGDAPN6M.js.map} +1 -1
  167. package/dist/{chunk-DFEMTNPJ.js → chunk-XH7XP3OL.js} +8 -6
  168. package/dist/{chunk-DFEMTNPJ.js.map → chunk-XH7XP3OL.js.map} +1 -1
  169. package/dist/{chunk-IAGBDSCS.js → chunk-XREOISSI.js} +2 -2
  170. package/dist/chunk-XUBPSPKD.js +164 -0
  171. package/dist/chunk-XUBPSPKD.js.map +1 -0
  172. package/dist/chunk-Y3A5CB5G.js +247 -0
  173. package/dist/chunk-Y3A5CB5G.js.map +1 -0
  174. package/dist/{chunk-ZCGAHGUS.js → chunk-YCXCR7VG.js} +2 -2
  175. package/dist/{chunk-76722EBH.js → chunk-YMVQD5Q5.js} +11 -9
  176. package/dist/{chunk-76722EBH.js.map → chunk-YMVQD5Q5.js.map} +1 -1
  177. package/dist/{chunk-5TDJ56JE.js → chunk-YN5IAHN6.js} +1 -1
  178. package/dist/chunk-YN5IAHN6.js.map +1 -0
  179. package/dist/{chunk-TJYQIGAP.js → chunk-ZYJ55N7N.js} +9 -5
  180. package/dist/chunk-ZYJ55N7N.js.map +1 -0
  181. package/dist/classified/index.d.ts +16 -0
  182. package/dist/classified/index.js +40 -0
  183. package/dist/classified-marker-H6YSHYNK.js +24 -0
  184. package/dist/classified-marker-H6YSHYNK.js.map +1 -0
  185. package/dist/collection-facade-LVD22JLM.js +39 -0
  186. package/dist/computed-EXDMQODG.js +11 -0
  187. package/dist/consent/index.d.ts +3 -4
  188. package/dist/consent/index.js +10 -4
  189. package/dist/consent/index.js.map +1 -1
  190. package/dist/crdt/index.d.ts +3 -4
  191. package/dist/dead-filter-HQIE2YG7.js +28 -0
  192. package/dist/dead-filter-HQIE2YG7.js.map +1 -0
  193. package/dist/delegation-BJP73GAP.js +25 -0
  194. package/dist/derivations/index.d.ts +4 -5
  195. package/dist/derivations/index.js +13 -6
  196. package/dist/derive-BME7HDWO.js +21 -0
  197. package/dist/{dev-unlock-C9Ro3v_O.d.ts → dev-unlock-Bmm2pgJ0.d.ts} +1 -1
  198. package/dist/{enclave-UL5LW66V.js → enclave-NHORSWSF.js} +55 -18
  199. package/dist/executor-FE6X4LFX.js +9 -0
  200. package/dist/executor-KSHKRJXP.js +25 -0
  201. package/dist/executor-ZHTJJICG.js +9 -0
  202. package/dist/export-accessible-DACHM5VT.js +23 -0
  203. package/dist/extract-partition-RNENZZ4T.js +36 -0
  204. package/dist/{fanout-sidecar-GF3DJ6KR.js → fanout-sidecar-OFWN3NM7.js} +17 -14
  205. package/dist/fanout-sidecar-OFWN3NM7.js.map +1 -0
  206. package/dist/fence-watcher-DHQ775JB.js +69 -0
  207. package/dist/fence-watcher-DHQ775JB.js.map +1 -0
  208. package/dist/find-BNGBJNKP.js +11 -0
  209. package/dist/forget/index.d.ts +2 -2
  210. package/dist/forget/index.js +10 -4
  211. package/dist/forget/index.js.map +1 -1
  212. package/dist/guards/index.d.ts +4 -5
  213. package/dist/guards/index.js +4 -4
  214. package/dist/{hash-Cp5uwiox.d.ts → hash-DAJjMsCE.d.ts} +7 -2
  215. package/dist/history/index.d.ts +4 -5
  216. package/dist/history/index.js +12 -6
  217. package/dist/history/index.js.map +1 -1
  218. package/dist/i18n/index.d.ts +24 -5
  219. package/dist/i18n/index.js +50 -31
  220. package/dist/i18n/index.js.map +1 -1
  221. package/dist/in/index.d.ts +2 -3
  222. package/dist/{index-BzUo1B6n.d.ts → index-DjWbxsjb.d.ts} +8596 -5747
  223. package/dist/{index-BF9_96A5.d.ts → index-qwuNvO2B.d.ts} +26 -5
  224. package/dist/index.d.ts +116 -24
  225. package/dist/index.js +1479 -139
  226. package/dist/index.js.map +1 -1
  227. package/dist/indexing/index.d.ts +3 -4
  228. package/dist/indexing/index.js +4 -4
  229. package/dist/issue-NDI4CVZU.js +19 -0
  230. package/dist/json-schema-I22JCYCG.js +44 -0
  231. package/dist/json-schema-I22JCYCG.js.map +1 -0
  232. package/dist/lazy/index.d.ts +20 -0
  233. package/dist/lazy/index.js +12 -0
  234. package/dist/{ledger-RYI35CDS.js → ledger-6NDS2EO4.js} +12 -6
  235. package/dist/liberate-HN3RIGIP.js +24 -0
  236. package/dist/link-set-SJB2MVJV.js +31 -0
  237. package/dist/materialized-views/index.d.ts +22 -6
  238. package/dist/materialized-views/index.js +20 -10
  239. package/dist/{mime-magic-CGhw37_E.d.ts → mime-magic-bBj5OgUC.d.ts} +1 -1
  240. package/dist/noydb-BWF6EPIR.js +66 -0
  241. package/dist/on/index.d.ts +2 -3
  242. package/dist/on/index.js +10 -4
  243. package/dist/overlay-views/index.d.ts +4 -5
  244. package/dist/overlay-views/index.js +4 -4
  245. package/dist/periods/index.d.ts +3 -4
  246. package/dist/periods/index.js +21 -7
  247. package/dist/pod/index.d.ts +3 -4
  248. package/dist/pod/index.js +12 -6
  249. package/dist/{policy-IXK4FVXP.js → policy-WGNAG5H6.js} +5 -5
  250. package/dist/portability/index.d.ts +3 -4
  251. package/dist/portability/index.js +8 -8
  252. package/dist/post-register-CWKBQRC7.js +55 -0
  253. package/dist/post-register-CWKBQRC7.js.map +1 -0
  254. package/dist/{public-envelope-JHDQCPSX.js → public-envelope-EJLVIFX7.js} +4 -4
  255. package/dist/query/index.d.ts +2 -3
  256. package/dist/query/index.js +9 -6
  257. package/dist/{read-only-facade-5ADRJVTM.js → read-only-facade-CHCKSEPD.js} +2 -2
  258. package/dist/register-SBIX7TVV.js +23 -0
  259. package/dist/registry-3EQG6OOE.js +18 -0
  260. package/dist/registry-CA327ACV.js +9 -0
  261. package/dist/registry-E7OXOTSV.js +19 -0
  262. package/dist/request-withdrawal-KAH2AAXC.js +31 -0
  263. package/dist/reveal-R3JLHMUF.js +38 -0
  264. package/dist/reveal-R3JLHMUF.js.map +1 -0
  265. package/dist/revoke-IXLOJ3IH.js +24 -0
  266. package/dist/satellites/index.d.ts +4 -0
  267. package/dist/satellites/index.js +8 -0
  268. package/dist/sealed-record/index.d.ts +3 -4
  269. package/dist/sealed-record/index.js +13 -7
  270. package/dist/sealed-record/index.js.map +1 -1
  271. package/dist/session/index.d.ts +4 -5
  272. package/dist/session/index.js +10 -4
  273. package/dist/session/index.js.map +1 -1
  274. package/dist/shadow/index.d.ts +3 -4
  275. package/dist/shadow/index.js +2 -2
  276. package/dist/signer-Y46N2GJ3.js +25 -0
  277. package/dist/signer-Y46N2GJ3.js.map +1 -0
  278. package/dist/snapshots/index.d.ts +3 -4
  279. package/dist/snapshots/index.js +11 -5
  280. package/dist/snapshots/index.js.map +1 -1
  281. package/dist/{stale-3JWHNDIY.js → stale-Z7IW6RIL.js} +2 -2
  282. package/dist/stale-Z7IW6RIL.js.map +1 -0
  283. package/dist/storage-ADNP2UWI.js +23 -0
  284. package/dist/storage-ADNP2UWI.js.map +1 -0
  285. package/dist/{store-coordination-provider-3I7XWZZK.js → store-coordination-provider-DTDMI6VL.js} +3 -3
  286. package/dist/{subject-index-O75wKshW.d.ts → subject-index-CyOgGMJL.d.ts} +18 -0
  287. package/dist/sync/index.d.ts +2 -3
  288. package/dist/sync/index.js +10 -4
  289. package/dist/sync/index.js.map +1 -1
  290. package/dist/team/index.d.ts +45 -7
  291. package/dist/team/index.js +25 -12
  292. package/dist/tiers/index.d.ts +2 -3
  293. package/dist/tiers/index.js +11 -5
  294. package/dist/to/index.d.ts +2 -3
  295. package/dist/to/index.js +1 -2
  296. package/dist/{transition-guard-C7ol6oPw.d.ts → transition-guard-DI-krBsZ.d.ts} +1 -1
  297. package/dist/tx/index.d.ts +3 -4
  298. package/dist/tx/index.js +3 -3
  299. package/dist/ui/index.d.ts +4 -1
  300. package/dist/util/index.js +1 -1
  301. package/dist/validators-BUcli5Nh.d.ts +101 -0
  302. package/dist/{vault-diff-B5fYNBL7.d.ts → vault-diff-Z2DUayMe.d.ts} +1 -1
  303. package/dist/verify-JPF2YR5E.js +139 -0
  304. package/dist/verify-JPF2YR5E.js.map +1 -0
  305. package/dist/walk-XYA2O3LW.js +241 -0
  306. package/dist/walk-XYA2O3LW.js.map +1 -0
  307. package/dist/with/index.d.ts +3 -4
  308. package/dist/with/index.js +12 -6
  309. package/dist/{with-materialized-view-6p0Fk8bL.d.ts → with-materialized-view-BUmzlXue.d.ts} +1 -1
  310. package/dist/{with-overlayed-view-BJ6mXGMd.d.ts → with-overlayed-view-m4FaXXTO.d.ts} +1 -1
  311. package/dist/{with-rollup-BvQo3ROo.d.ts → with-rollup-DEKGI9vb.d.ts} +1 -1
  312. package/dist/withdraw-accessible-WLV4MTEN.js +28 -0
  313. package/dist/withdraw-accessible-WLV4MTEN.js.map +1 -0
  314. package/package.json +16 -16
  315. package/dist/adapter/index.d.ts +0 -5
  316. package/dist/adapter/index.js +0 -15
  317. package/dist/api-RW3KP7WU.js +0 -14
  318. package/dist/backup-XV3IOEGB.js.map +0 -1
  319. package/dist/chunk-26LGBE4T.js +0 -42
  320. package/dist/chunk-26LGBE4T.js.map +0 -1
  321. package/dist/chunk-5LUY7UTV.js.map +0 -1
  322. package/dist/chunk-5O3AOPDT.js.map +0 -1
  323. package/dist/chunk-5R5JW2JT.js.map +0 -1
  324. package/dist/chunk-5TDJ56JE.js.map +0 -1
  325. package/dist/chunk-62QYRORB.js.map +0 -1
  326. package/dist/chunk-AQTBSL7R.js.map +0 -1
  327. package/dist/chunk-BG3SPSR4.js.map +0 -1
  328. package/dist/chunk-BGIZAFY7.js +0 -1
  329. package/dist/chunk-DGDI2D4M.js.map +0 -1
  330. package/dist/chunk-I3TIKTJO.js.map +0 -1
  331. package/dist/chunk-IELYAOGG.js.map +0 -1
  332. package/dist/chunk-IPB7FTQX.js.map +0 -1
  333. package/dist/chunk-IUEN57TV.js.map +0 -1
  334. package/dist/chunk-K2WCO3NX.js +0 -1
  335. package/dist/chunk-LFLXAY2W.js.map +0 -1
  336. package/dist/chunk-LV7M27WM.js.map +0 -1
  337. package/dist/chunk-M2YKN37S.js +0 -524
  338. package/dist/chunk-M2YKN37S.js.map +0 -1
  339. package/dist/chunk-MTMJVJ5W.js.map +0 -1
  340. package/dist/chunk-Q7SS3IME.js +0 -120
  341. package/dist/chunk-Q7SS3IME.js.map +0 -1
  342. package/dist/chunk-RUIMKQTA.js.map +0 -1
  343. package/dist/chunk-SRB2XEWB.js.map +0 -1
  344. package/dist/chunk-TEILUWOI.js.map +0 -1
  345. package/dist/chunk-TJYQIGAP.js.map +0 -1
  346. package/dist/chunk-UIU2THRG.js.map +0 -1
  347. package/dist/chunk-UPJNJGGA.js.map +0 -1
  348. package/dist/chunk-WWGT2MDV.js.map +0 -1
  349. package/dist/chunk-Y22T3KQE.js.map +0 -1
  350. package/dist/chunk-ZYUC53LT.js.map +0 -1
  351. package/dist/collection-facade-GQAOGJP2.js +0 -33
  352. package/dist/delegation-UL5HKLER.js +0 -19
  353. package/dist/describe/index.d.ts +0 -1
  354. package/dist/describe/index.js +0 -1
  355. package/dist/describe-aBkJR2sd.d.ts +0 -131
  356. package/dist/executor-2FWQRLMG.js +0 -15
  357. package/dist/executor-QZ7BXICW.js +0 -9
  358. package/dist/executor-Z5ZLJVTV.js +0 -9
  359. package/dist/export-accessible-KRV5W4GH.js +0 -17
  360. package/dist/extract-partition-GLKBOXFQ.js +0 -30
  361. package/dist/fanout-sidecar-GF3DJ6KR.js.map +0 -1
  362. package/dist/issue-Y6UVIR43.js +0 -13
  363. package/dist/kernel/index.d.ts +0 -32
  364. package/dist/kernel/index.js +0 -53
  365. package/dist/liberate-CRPZEV7O.js +0 -18
  366. package/dist/noydb-367AM4HT.js +0 -50
  367. package/dist/registry-45RJNWGU.js +0 -9
  368. package/dist/registry-5GRV5VXI.js +0 -13
  369. package/dist/registry-WEUCHBO4.js +0 -11
  370. package/dist/request-withdrawal-GBPH2FDY.js +0 -25
  371. package/dist/revoke-TUFRGI6S.js +0 -18
  372. package/dist/signer-PNKTBVF7.js +0 -19
  373. package/dist/withdraw-accessible-FFS46EOD.js +0 -22
  374. /package/dist/{adapter/index.js.map → api-TX2EX2FX.js.map} +0 -0
  375. /package/dist/{chunk-5N6CZTCY.js.map → chunk-2OZXVKVP.js.map} +0 -0
  376. /package/dist/{chunk-UAG5KWVA.js.map → chunk-3MATJ6O4.js.map} +0 -0
  377. /package/dist/{chunk-AZAOEIKW.js.map → chunk-5YESYH2C.js.map} +0 -0
  378. /package/dist/{chunk-VCTFO5CO.js.map → chunk-6P5XCKSD.js.map} +0 -0
  379. /package/dist/{chunk-IO6GRPT6.js.map → chunk-7BWJHO2A.js.map} +0 -0
  380. /package/dist/{chunk-UDRIWL7A.js.map → chunk-BKARNZJN.js.map} +0 -0
  381. /package/dist/{chunk-V7RWQRG7.js.map → chunk-CB7CWSKW.js.map} +0 -0
  382. /package/dist/{chunk-CWPPNPOH.js.map → chunk-DJ7KIPLV.js.map} +0 -0
  383. /package/dist/{chunk-TA66UMI4.js.map → chunk-F4CEK5YM.js.map} +0 -0
  384. /package/dist/{chunk-SM3AVUHC.js.map → chunk-G4JYND6L.js.map} +0 -0
  385. /package/dist/{chunk-AXRXJTE2.js.map → chunk-G6XV4H65.js.map} +0 -0
  386. /package/dist/{chunk-UV5MFVO3.js.map → chunk-HPWKV3YB.js.map} +0 -0
  387. /package/dist/{chunk-SKF73JOP.js.map → chunk-ICXIFFYZ.js.map} +0 -0
  388. /package/dist/{chunk-LMTH2RM6.js.map → chunk-KNZB6JMR.js.map} +0 -0
  389. /package/dist/{chunk-PKHL44ER.js.map → chunk-LEJIKBBB.js.map} +0 -0
  390. /package/dist/{chunk-PSMV73A5.js.map → chunk-OBKWYKYC.js.map} +0 -0
  391. /package/dist/{chunk-CMGR4ZEW.js.map → chunk-OHHKHSJP.js.map} +0 -0
  392. /package/dist/{chunk-HCIPRAGS.js.map → chunk-OT76OZL6.js.map} +0 -0
  393. /package/dist/{chunk-SMXWYP24.js.map → chunk-OXCSVM3B.js.map} +0 -0
  394. /package/dist/{chunk-IGUYVGGI.js.map → chunk-P33LUIML.js.map} +0 -0
  395. /package/dist/{chunk-EIZUR2XW.js.map → chunk-PS2NEWEX.js.map} +0 -0
  396. /package/dist/{chunk-WYSO2NIH.js.map → chunk-QOC3VYL2.js.map} +0 -0
  397. /package/dist/{chunk-KVOXU4T5.js.map → chunk-RHK32N73.js.map} +0 -0
  398. /package/dist/{chunk-3YFXJ3ZP.js.map → chunk-RW3Y22MW.js.map} +0 -0
  399. /package/dist/{chunk-QHJW5EXU.js.map → chunk-TWKKOM55.js.map} +0 -0
  400. /package/dist/{chunk-M6OST55S.js.map → chunk-U3WZCU7E.js.map} +0 -0
  401. /package/dist/{chunk-KXGNJJXB.js.map → chunk-UN4FVIBH.js.map} +0 -0
  402. /package/dist/{chunk-NF5JWERG.js.map → chunk-VRIYFLBA.js.map} +0 -0
  403. /package/dist/{chunk-RUEKROOS.js.map → chunk-VWRRVE6D.js.map} +0 -0
  404. /package/dist/{chunk-XXYIOFUB.js.map → chunk-WIGQB62E.js.map} +0 -0
  405. /package/dist/{chunk-IAGBDSCS.js.map → chunk-XREOISSI.js.map} +0 -0
  406. /package/dist/{chunk-ZCGAHGUS.js.map → chunk-YCXCR7VG.js.map} +0 -0
  407. /package/dist/{describe → classified}/index.js.map +0 -0
  408. /package/dist/{api-RW3KP7WU.js.map → collection-facade-LVD22JLM.js.map} +0 -0
  409. /package/dist/{chunk-BGIZAFY7.js.map → computed-EXDMQODG.js.map} +0 -0
  410. /package/dist/{chunk-K2WCO3NX.js.map → delegation-BJP73GAP.js.map} +0 -0
  411. /package/dist/{collection-facade-GQAOGJP2.js.map → derive-BME7HDWO.js.map} +0 -0
  412. /package/dist/{delegation-UL5HKLER.js.map → enclave-NHORSWSF.js.map} +0 -0
  413. /package/dist/{enclave-UL5LW66V.js.map → executor-FE6X4LFX.js.map} +0 -0
  414. /package/dist/{executor-2FWQRLMG.js.map → executor-KSHKRJXP.js.map} +0 -0
  415. /package/dist/{executor-QZ7BXICW.js.map → executor-ZHTJJICG.js.map} +0 -0
  416. /package/dist/{executor-Z5ZLJVTV.js.map → export-accessible-DACHM5VT.js.map} +0 -0
  417. /package/dist/{export-accessible-KRV5W4GH.js.map → extract-partition-RNENZZ4T.js.map} +0 -0
  418. /package/dist/{extract-partition-GLKBOXFQ.js.map → find-BNGBJNKP.js.map} +0 -0
  419. /package/dist/{issue-Y6UVIR43.js.map → issue-NDI4CVZU.js.map} +0 -0
  420. /package/dist/{kernel → lazy}/index.js.map +0 -0
  421. /package/dist/{ledger-RYI35CDS.js.map → ledger-6NDS2EO4.js.map} +0 -0
  422. /package/dist/{liberate-CRPZEV7O.js.map → liberate-HN3RIGIP.js.map} +0 -0
  423. /package/dist/{noydb-367AM4HT.js.map → link-set-SJB2MVJV.js.map} +0 -0
  424. /package/dist/{policy-IXK4FVXP.js.map → noydb-BWF6EPIR.js.map} +0 -0
  425. /package/dist/{public-envelope-JHDQCPSX.js.map → policy-WGNAG5H6.js.map} +0 -0
  426. /package/dist/{read-only-facade-5ADRJVTM.js.map → public-envelope-EJLVIFX7.js.map} +0 -0
  427. /package/dist/{registry-45RJNWGU.js.map → read-only-facade-CHCKSEPD.js.map} +0 -0
  428. /package/dist/{registry-5GRV5VXI.js.map → register-SBIX7TVV.js.map} +0 -0
  429. /package/dist/{registry-WEUCHBO4.js.map → registry-3EQG6OOE.js.map} +0 -0
  430. /package/dist/{request-withdrawal-GBPH2FDY.js.map → registry-CA327ACV.js.map} +0 -0
  431. /package/dist/{revoke-TUFRGI6S.js.map → registry-E7OXOTSV.js.map} +0 -0
  432. /package/dist/{signer-PNKTBVF7.js.map → request-withdrawal-KAH2AAXC.js.map} +0 -0
  433. /package/dist/{stale-3JWHNDIY.js.map → revoke-IXLOJ3IH.js.map} +0 -0
  434. /package/dist/{withdraw-accessible-FFS46EOD.js.map → satellites/index.js.map} +0 -0
  435. /package/dist/{store-coordination-provider-3I7XWZZK.js.map → store-coordination-provider-DTDMI6VL.js.map} +0 -0
@@ -1,120 +0,0 @@
1
- import {
2
- sha256Hex
3
- } from "./chunk-5O3AOPDT.js";
4
- import {
5
- DerivationCycleError
6
- } from "./chunk-ZYUC53LT.js";
7
-
8
- // src/with-formula/derivations/strategy-hash.ts
9
- async function computeStrategyHash(source, outputKeys, derive, sources) {
10
- const canonical = JSON.stringify({
11
- source,
12
- outputs: [...outputKeys].sort(),
13
- derive: derive.toString(),
14
- // Declared sibling sources — adding/removing a trigger
15
- // collection invalidates cached derived records. Omitted when empty
16
- // so strategies without siblings keep their existing hash.
17
- ...sources?.length ? { sources: [...sources].sort() } : {}
18
- });
19
- const bytes = new TextEncoder().encode(canonical);
20
- return sha256Hex(bytes);
21
- }
22
-
23
- // src/with-formula/derivations/registry.ts
24
- var DerivationRegistry = class {
25
- _bySource = /* @__PURE__ */ new Map();
26
- _byOutput = /* @__PURE__ */ new Map();
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
- async register(spec) {
29
- const outputKeys = Object.keys(spec.outputs);
30
- const strategyHash = await computeStrategyHash(spec.source, outputKeys, spec.derive, spec.sources);
31
- const reg = { spec, strategyHash };
32
- const fromSource = this._bySource.get(spec.source);
33
- if (fromSource) fromSource.push(reg);
34
- else this._bySource.set(spec.source, [reg]);
35
- for (const extra of spec.sources ?? []) {
36
- const fromExtra = this._bySource.get(extra);
37
- if (fromExtra) fromExtra.push(reg);
38
- else this._bySource.set(extra, [reg]);
39
- }
40
- for (const t of spec.triggerBy ?? []) {
41
- const fromTrigger = this._bySource.get(t.collection);
42
- if (fromTrigger) fromTrigger.push(reg);
43
- else this._bySource.set(t.collection, [reg]);
44
- }
45
- if (spec.rollup) {
46
- const fromRollup = this._bySource.get(spec.rollup.from);
47
- if (fromRollup) fromRollup.push(reg);
48
- else this._bySource.set(spec.rollup.from, [reg]);
49
- }
50
- for (const key of outputKeys) {
51
- const output = spec.outputs[key];
52
- if (!output) continue;
53
- const outputCollection = output.collection;
54
- const arr = this._byOutput.get(outputCollection);
55
- if (arr) arr.push(reg);
56
- else this._byOutput.set(outputCollection, [reg]);
57
- }
58
- }
59
- strategiesForSource(source) {
60
- return this._bySource.get(source) ?? [];
61
- }
62
- strategiesProducingOutput(collection) {
63
- return this._byOutput.get(collection) ?? [];
64
- }
65
- /**
66
- * All registered strategies as a flat, deduplicated array.
67
- * Each strategy is indexed once per source (not once per output key),
68
- * so iterating `_bySource.values()` naturally yields each strategy
69
- * exactly once per source — deduplication is handled by flattening
70
- * the per-source arrays and collecting into a Set by identity.
71
- *
72
- * Used by `dumpSchema()` / `describeDerivations()` in the introspection
73
- * walker to populate the derivations map.
74
- */
75
- all() {
76
- const seen = /* @__PURE__ */ new Set();
77
- for (const strategies of this._bySource.values()) {
78
- for (const s of strategies) seen.add(s);
79
- }
80
- return [...seen];
81
- }
82
- /**
83
- * Cycle detection over the source → output → … graph. Call after all
84
- * `register()` calls complete (i.e. at vault open). Throws
85
- * `DerivationCycleError` on the first cycle found.
86
- */
87
- validate() {
88
- const visited = /* @__PURE__ */ new Set();
89
- const stack = [];
90
- const visit = (node) => {
91
- if (stack.includes(node)) {
92
- const cycle = stack.slice(stack.indexOf(node)).concat(node);
93
- throw new DerivationCycleError(cycle);
94
- }
95
- if (visited.has(node)) return;
96
- stack.push(node);
97
- const strategies = this._bySource.get(node);
98
- if (strategies) {
99
- for (const s of strategies) {
100
- for (const key of Object.keys(s.spec.outputs)) {
101
- const output = s.spec.outputs[key];
102
- if (!output) continue;
103
- if (output.shape === "record" && output.collection === s.spec.source && output.denorm !== void 0) {
104
- continue;
105
- }
106
- visit(output.collection);
107
- }
108
- }
109
- }
110
- stack.pop();
111
- visited.add(node);
112
- };
113
- for (const src of this._bySource.keys()) visit(src);
114
- }
115
- };
116
-
117
- export {
118
- DerivationRegistry
119
- };
120
- //# sourceMappingURL=chunk-Q7SS3IME.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/with-formula/derivations/strategy-hash.ts","../src/with-formula/derivations/registry.ts"],"sourcesContent":["/**\n * Deterministic hash of a derivation strategy's \"shape\": source\n * collection, declared sibling sources, output keys, derive function\n * source. Used to detect\n * strategy drift: a record whose `_derivedFrom.strategyHash` doesn't\n * match the current strategy is considered stale.\n *\n * Web Crypto SHA-256 — no extra deps.\n */\nimport { sha256Hex } from '../../kernel/enclave/index.js'\n\nexport async function computeStrategyHash(\n source: string,\n outputKeys: readonly string[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n derive: (...args: any[]) => any,\n sources?: ReadonlyArray<string>,\n): Promise<string> {\n const canonical = JSON.stringify({\n source,\n outputs: [...outputKeys].sort(),\n derive: derive.toString(),\n // Declared sibling sources — adding/removing a trigger\n // collection invalidates cached derived records. Omitted when empty\n // so strategies without siblings keep their existing hash.\n ...(sources?.length ? { sources: [...sources].sort() } : {}),\n })\n const bytes = new TextEncoder().encode(canonical)\n return sha256Hex(bytes)\n}\n","import { DerivationCycleError } from '../../kernel/errors.js'\nimport { computeStrategyHash } from './strategy-hash.js'\nimport type { DerivationStrategy } from './types.js'\n\ninterface RegisteredStrategy {\n // Type-erased to allow the registry to hold heterogeneous strategies.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n spec: DerivationStrategy<any, any>\n strategyHash: string\n}\n\n/**\n * Vault-internal registry of derivation strategies. Owned by `Vault`;\n * not exported.\n *\n * @internal\n */\nexport class DerivationRegistry {\n private readonly _bySource = new Map<string, RegisteredStrategy[]>()\n private readonly _byOutput = new Map<string, RegisteredStrategy[]>()\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async register(spec: DerivationStrategy<any, any>): Promise<void> {\n const outputKeys = Object.keys(spec.outputs)\n const strategyHash = await computeStrategyHash(spec.source, outputKeys, spec.derive, spec.sources)\n const reg: RegisteredStrategy = { spec, strategyHash }\n\n const fromSource = this._bySource.get(spec.source)\n if (fromSource) fromSource.push(reg)\n else this._bySource.set(spec.source, [reg])\n\n // Declared sibling sources index the SAME `reg` under each\n // extra collection so `strategiesForSource(extra)` returns it and a\n // sibling write re-fires the derivation. Sibling keys also enter\n // `_bySource`, so `validate()`'s cycle DFS walks them automatically.\n for (const extra of spec.sources ?? []) {\n const fromExtra = this._bySource.get(extra)\n if (fromExtra) fromExtra.push(reg)\n else this._bySource.set(extra, [reg])\n }\n\n // FK triggers index the SAME `reg` under each parent collection so\n // a parent write re-fires the derivation (fanned out to matching source\n // records in `dispatchDerivations`). Like sources[], these keys enter\n // `_bySource` so the cycle DFS walks the trigger→output edge.\n for (const t of spec.triggerBy ?? []) {\n const fromTrigger = this._bySource.get(t.collection)\n if (fromTrigger) fromTrigger.push(reg)\n else this._bySource.set(t.collection, [reg])\n }\n\n // Rollup: a write to the child `from` collection recomputes\n // the parent (= spec.source = into) at id child[key]. Index under `from`\n // so a child write fires it; spec.source (into) is already indexed above,\n // so a parent write also recomputes its own aggregate (covers the\n // parent-created-after-children case). The from→into edge enters the cycle\n // DFS automatically.\n if (spec.rollup) {\n const fromRollup = this._bySource.get(spec.rollup.from)\n if (fromRollup) fromRollup.push(reg)\n else this._bySource.set(spec.rollup.from, [reg])\n }\n\n for (const key of outputKeys) {\n const output = spec.outputs[key]\n if (!output) continue\n const outputCollection = output.collection\n const arr = this._byOutput.get(outputCollection)\n if (arr) arr.push(reg)\n else this._byOutput.set(outputCollection, [reg])\n }\n }\n\n strategiesForSource(source: string): ReadonlyArray<RegisteredStrategy> {\n return this._bySource.get(source) ?? []\n }\n\n strategiesProducingOutput(collection: string): ReadonlyArray<RegisteredStrategy> {\n return this._byOutput.get(collection) ?? []\n }\n\n /**\n * All registered strategies as a flat, deduplicated array.\n * Each strategy is indexed once per source (not once per output key),\n * so iterating `_bySource.values()` naturally yields each strategy\n * exactly once per source — deduplication is handled by flattening\n * the per-source arrays and collecting into a Set by identity.\n *\n * Used by `dumpSchema()` / `describeDerivations()` in the introspection\n * walker to populate the derivations map.\n */\n all(): ReadonlyArray<RegisteredStrategy> {\n const seen = new Set<RegisteredStrategy>()\n for (const strategies of this._bySource.values()) {\n for (const s of strategies) seen.add(s)\n }\n return [...seen]\n }\n\n /**\n * Cycle detection over the source → output → … graph. Call after all\n * `register()` calls complete (i.e. at vault open). Throws\n * `DerivationCycleError` on the first cycle found.\n */\n validate(): void {\n const visited = new Set<string>()\n const stack: string[] = []\n\n const visit = (node: string): void => {\n if (stack.includes(node)) {\n const cycle = stack.slice(stack.indexOf(node)).concat(node)\n throw new DerivationCycleError(cycle)\n }\n if (visited.has(node)) return\n stack.push(node)\n const strategies = this._bySource.get(node)\n if (strategies) {\n for (const s of strategies) {\n for (const key of Object.keys(s.spec.outputs)) {\n const output = s.spec.outputs[key]\n if (!output) continue\n // Self-write reverse-denorm: an output back to its own\n // source is intentional, not an infinite cycle — the value-equality\n // guard in dispatch terminates it. Skip this edge so it isn't\n // flagged. (Self-write outputs are required to declare `denorm`.)\n if (\n output.shape === 'record' &&\n output.collection === s.spec.source &&\n output.denorm !== undefined\n ) {\n continue\n }\n visit(output.collection)\n }\n }\n }\n stack.pop()\n visited.add(node)\n }\n\n for (const src of this._bySource.keys()) visit(src)\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/with-audit/guards/read-only-facade.ts"],"sourcesContent":["import type { Vault } from '../../kernel/vault.js'\nimport type { Query } from '../../kernel/query/builder.js'\nimport type { Layer } from '../../with-shape/i18n/policy.js'\nimport type { ReadOnlyVaultFacade as ReadOnlyVaultFacadeContract } from './types.js'\n\n/**\n * Minimal read-only wrapper over a `Vault`. Used as `ctx.vault` inside\n * guard / derivation callbacks so they can fetch related records without\n * acquiring any write capability.\n *\n * The `layer` tags every `get`/`list` read with the resolution layer it\n * belongs to. A guard-seeded facade reads at `'guard'`, a\n * derivation-seeded one at `'derivation'`, so i18nText / dictKey fields\n * resolve under that layer's `onMissing` policy instead of the `'read'`\n * policy — e.g. a guard read can `substitute` a missing locale (lenient\n * default) while the same field `throw`s on an ordinary app read.\n *\n * `query()` is left untagged: the query/aggregate pipeline reads raw\n * `{locale}` maps (no resolution call site), so a layer tag there would be\n * inert. Routing `mv`/`join` resolution through the pipeline is tracked\n * separately.\n */\nexport class ReadOnlyVaultFacade implements ReadOnlyVaultFacadeContract {\n private readonly _vault: Vault\n private readonly _layer: Layer\n\n constructor(vault: Vault, layer: Layer = 'read') {\n this._vault = vault\n this._layer = layer\n }\n\n collection<T = unknown>(name: string): {\n get(id: string): Promise<T | null>\n list(): Promise<T[]>\n query(): Query<T>\n } {\n const c = this._vault.collection<T>(name)\n const layer = this._layer\n return {\n get: (id: string) => c.get(id, { _layer: layer }),\n list: () => c.list({ _layer: layer }),\n query: () => c.query(),\n }\n }\n}\n"],"mappings":";AAsBO,IAAM,sBAAN,MAAiE;AAAA,EACrD;AAAA,EACA;AAAA,EAEjB,YAAY,OAAc,QAAe,QAAQ;AAC/C,SAAK,SAAS;AACd,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,WAAwB,MAItB;AACA,UAAM,IAAI,KAAK,OAAO,WAAc,IAAI;AACxC,UAAM,QAAQ,KAAK;AACnB,WAAO;AAAA,MACL,KAAK,CAAC,OAAe,EAAE,IAAI,IAAI,EAAE,QAAQ,MAAM,CAAC;AAAA,MAChD,MAAM,MAAM,EAAE,KAAK,EAAE,QAAQ,MAAM,CAAC;AAAA,MACpC,OAAO,MAAM,EAAE,MAAM;AAAA,IACvB;AAAA,EACF;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/with-audit/forget/strategy.ts","../src/with-audit/forget/subject-index.ts"],"sourcesContent":["/**\n * `withForgetCascade` — declaration surface for GDPR right-to-erasure via\n * per-record CEK crypto-shred.\n *\n * This file holds only the *declaration* shape and the disabled sentinel.\n * The actual erasure machinery lives in:\n * - `subject-index.ts` — the encrypted `_subject_index` reserved collection\n * - `vault.ts` `forget()` — the per-record tombstone + ledger flow\n * - `collection.ts` `_writeTombstone` — the envelope rewrite\n *\n * A `ForgetStrategy` declares which collections carry erasable subject data\n * and the (dotted-path) field on each record that names the data subject.\n * Declaring a collection here ALSO forces `perRecordKeys: true` for it (a\n * shred can only erase a record whose body is keyed off a per-record CEK),\n * so adopters opt into the CEK foundation transitively.\n *\n * @module\n */\nimport type { LedgerEntry } from '../../with-commit/history/ledger/entry.js'\n\n/**\n * User-supplied declaration passed to {@link withForgetCascade}. Maps a\n * collection name to the record field (dotted path supported, e.g.\n * `'billing.buyerId'`) that identifies the data subject for erasure.\n *\n * ```ts\n * withForgetCascade({ subjects: { invoices: 'buyerId', contacts: 'id' } })\n * ```\n */\nexport interface SubjectDeclaration {\n readonly subjects: Record<string, string>\n}\n\n/**\n * Resolved forget strategy threaded through Noydb → every Vault. Carries\n * the same `subjects` map the user declared. `NO_FORGET` (empty map) is the\n * off-by-default sentinel; `vault.forget()` throws\n * `ForgetStrategyNotConfiguredError` when the map is empty.\n */\nexport interface ForgetStrategy {\n /** Collection → subject-field (dotted path). Empty under `NO_FORGET`. */\n readonly subjects: Readonly<Record<string, string>>\n}\n\n/**\n * Disabled sentinel — no collections declare a subject field. `vault.forget()`\n * refuses with `ForgetStrategyNotConfiguredError`; no write hooks register; no\n * collection is forced into `perRecordKeys`. Non-adopters pay nothing.\n */\nexport const NO_FORGET: ForgetStrategy = { subjects: {} }\n\n// The `withForgetCascade` factory lives in `active.ts` (canonical\n// strategy.ts/active.ts/index.ts split); this file holds only the\n// declaration shape + disabled sentinel.\n\n/**\n * The outcome of a `vault.forget(subjectId)` call.\n *\n * `unmigratedRecords` lists `collection:id` pairs that were tombstoned but\n * whose body had NOT been migrated to a per-record CEK at shred time (legacy\n * body still under the shared collection DEK). Those records are tombstoned\n * (live envelope + history stripped) but their pre-shred ciphertext, if it\n * leaked into a backup before migration, remains decryptable under the\n * collection DEK — so erasure-completeness is NOT guaranteed for them. Run\n * the per-record-CEK migration pass, then re-forget, to close the gap.\n *\n * Blob attachments: a shredded record's **erasable** blobs (on a\n * `perRecordKeys` collection) are crypto-shredded inline — `blobsShredded`\n * counts those taken to refCount 0 (BlobObject deleted → chunks permanently\n * undecryptable), `blobsRetainedShared` counts those still referenced by\n * another record (shared content legitimately persists for its other owner).\n * `blobResidueCollections` now lists only collections with blobs that could\n * NOT be crypto-shredded: **legacy** blobs (no per-blob `_cek`, chunks under\n * the shared `_blob` DEK — migrate them), or a session without the blob\n * service loaded. An all-erasable subject yields an empty residue list.\n */\nexport interface ForgetResult {\n /** The subject id passed to `forget()`. Echoed for caller convenience. */\n readonly subject: string\n /** Count of live records rewritten to a tombstone. */\n readonly recordsShredded: number\n /** Count of `_history` envelopes tombstoned across all shredded records. */\n readonly historyVersionsShredded: number\n /** Distinct collections that had at least one record shredded. */\n readonly collections: readonly string[]\n /** `collection:id` pairs shredded while still un-migrated (see type docs). */\n readonly unmigratedRecords: readonly string[]\n /** Count of erasable blobs crypto-shredded (refCount → 0, BlobObject deleted). */\n readonly blobsShredded: number\n /** Count of erasable blobs retained because still referenced elsewhere (shared). */\n readonly blobsRetainedShared: number\n /** Collections with blobs that could NOT be crypto-shredded — legacy (no `_cek`) or blobs disabled (see type docs). */\n readonly blobResidueCollections: readonly string[]\n /**\n * Count of persisted `_idx/<field>/<recordId>` index side-cars hard-deleted\n * across the shredded records. These live under the retained\n * collection DEK, so crypto-shred alone would leave the indexed field VALUES\n * readable — `forget()` must delete them.\n */\n readonly indexPostingsPurged: number\n /**\n * `collection:id:field` entries whose persisted `_idx` side-car could NOT be\n * deleted — index residue that still leaks the indexed value under the\n * retained collection DEK. Non-empty means erasure is INCOMPLETE: retry, or\n * purge the side-car out of band.\n */\n readonly indexResidue: readonly string[]\n /**\n * Count of `_sealed[field]` slots dropped from the live store across the\n * shredded records. For slots written under `sensitive` +\n * `perRecordKeys` (the current path), the key derives off the per-record CEK,\n * so tombstoning the record — which drops `_cek` and `_sealed` — also\n * crypto-shreds the value. A legacy slot (written before per-record CEKs) keys\n * off the collection DEK instead, so dropping it removes it from the live store but a\n * pre-forget backup remains recoverable by a DEK holder (same caveat `_data`\n * carries); migrate by re-`put`ting before forgetting for full crypto-shred.\n */\n readonly sealedFieldsShredded: number\n /** Count of `_sealed_cek` host-delivery envelopes deleted (#H-1). A record sealed to an\n * at-* host via sealRecordToHost persists its raw CEK there; forget() must destroy them. */\n readonly sealedCekEnvelopesPurged: number\n /** `collection:id` whose `_sealed_cek` purge failed (residue — the host-recoverable CEK may survive). */\n readonly sealedCekResidue: readonly string[]\n /** `collection:id:field` sealed slots that were DEK-derived (legacy, written before per-record CEKs) and thus NOT crypto-shredded\n * by dropping `_cek` — the collection DEK is retained, so synced/backup copies stay decryptable (#M-1). */\n readonly sealedResidue: readonly string[]\n /** The single `op:'forget'` ledger entry appended for this erasure. */\n readonly ledgerEntry: LedgerEntry\n}\n","/**\n * The encrypted subject index.\n *\n * GDPR crypto-shred needs to answer \"which records belong to data subject\n * X?\" portably (the index must travel with the vault/bundle) WITHOUT leaking\n * subject-equivalence to the store. The rejected alternative — an unencrypted\n * subject tag in envelope metadata — would let anyone with store access see\n * which records share a subject. Instead we keep a reserved `_subject_index`\n * collection, encrypted under its OWN DEK (`getDEK('_subject_index')`):\n *\n * - record id = `HMAC-SHA256(indexDEK, subjectId)` (M-2). A bare\n * `sha256Hex(subjectId)` would be offline-computable: an attacker with\n * store access and a candidate list (emails / customer ids are low-entropy)\n * could dictionary the hash to confirm \"subject X is present here.\" Keying\n * the id with the vault-only index DEK removes that capability — without the\n * DEK the id cannot be derived. (Legacy entries written before M-2 used the\n * bare sha256 id; the read/remove paths dual-look-up both forms.)\n * - record body = AES-GCM(JSON `{ r: [{ collection, id }], p }`) under the\n * index DEK, where `p` pads the plaintext to a bucketed length so the\n * ciphertext `_data` length does not leak the approximate record count.\n * Legacy bodies were a bare `[{ collection, id }]` array; reads accept both.\n *\n * ## Concurrency (RISK #3 — known v1 limitation)\n *\n * `addSubjectRef` / `removeSubjectRef` are read-modify-write with no CAS. The\n * design assumes a SINGLE WRITER (the noy-db single-process write model). Two\n * concurrent writers racing on the SAME subject can lose an entry (last-write\n * wins on the ref list). This is documented, not fixed in v1:\n * `rebuildSubjectIndex` performs a full scan to recover a correct index from\n * the canonical records, so a lost ref is recoverable. A CAS-backed index is\n * deferred to a later slice.\n *\n * @module\n */\nimport { encrypt, openEnvelopeJson, hmacSha256Hex, sha256Hex, type EnclaveKey } from '../../kernel/enclave/index.js'\nimport type { NoydbStore, EncryptedEnvelope } from '../../kernel/types.js'\nimport { NOYDB_FORMAT_VERSION } from '../../kernel/types.js'\n\n/** Reserved collection holding the encrypted subject → records index. */\nexport const SUBJECT_INDEX_COLLECTION = '_subject_index'\n\n/**\n * Bucket (bytes) the encrypted ref-list plaintext is padded up to, so the\n * ciphertext `_data` length leaks only `count` rounded up to a bucket — not the\n * exact record count. 256 keeps small subjects (the common case) indistinguishable.\n */\nconst REF_LIST_BUCKET = 256\n\n/** A single record reference held in a subject's index entry. */\nexport interface SubjectRef {\n readonly collection: string\n readonly id: string\n}\n\ntype GetDEK = (collectionName: string) => Promise<EnclaveKey>\n\n/** SHA-256 hex of a UTF-8 string. The LEGACY (pre-M-2) subject-index key. */\nasync function sha256HexString(input: string): Promise<string> {\n return sha256Hex(new TextEncoder().encode(input))\n}\n\n/**\n * The subject-index record id(s) to consult for a subject, most-current first.\n *\n * - Encrypted vault: the PRIMARY id is `HMAC-SHA256(indexDEK, subjectId)` (M-2)\n * — not offline-computable. The LEGACY `sha256Hex(subjectId)` id is also\n * returned so reads/removes still find entries written before M-2 (dual-lookup).\n * - Plaintext/debug vault: no DEK to key with, so the only id is the legacy\n * sha256 form (unchanged behaviour — plaintext mode is not zero-knowledge anyway).\n */\nasync function subjectKeys(getDEK: GetDEK, encrypted: boolean, subjectId: string): Promise<string[]> {\n const legacy = await sha256HexString(subjectId)\n if (!encrypted) return [legacy]\n const dek = await getDEK(SUBJECT_INDEX_COLLECTION)\n const keyed = await hmacSha256Hex(dek, new TextEncoder().encode(subjectId))\n return keyed === legacy ? [keyed] : [keyed, legacy]\n}\n\n/** The id new writes land under (keyed when encrypted, else legacy sha256). */\nasync function primarySubjectKey(getDEK: GetDEK, encrypted: boolean, subjectId: string): Promise<string> {\n return (await subjectKeys(getDEK, encrypted, subjectId))[0]!\n}\n\n/** Parse a stored ref-list body: new padded `{ r, p }` wrapper OR legacy bare array. */\nfunction parseRefs(json: string): SubjectRef[] {\n const parsed = JSON.parse(json) as SubjectRef[] | { r: SubjectRef[] }\n return Array.isArray(parsed) ? parsed : parsed.r\n}\n\n/** Serialize + pad the ref list to a bucket boundary (encrypted vaults only). */\nfunction serializeRefs(refs: SubjectRef[]): string {\n const base = JSON.stringify({ r: refs, p: '' })\n const pad = Math.ceil(base.length / REF_LIST_BUCKET) * REF_LIST_BUCKET - base.length\n return JSON.stringify({ r: refs, p: ' '.repeat(pad) })\n}\n\n/** Read + decrypt the ref list at a SINGLE index key. Returns `[]` when absent. */\nasync function readRefs(\n adapter: NoydbStore,\n vault: string,\n getDEK: GetDEK,\n encrypted: boolean,\n key: string,\n): Promise<SubjectRef[]> {\n const env = await adapter.get(vault, SUBJECT_INDEX_COLLECTION, key)\n if (!env || !env._data) return []\n if (!encrypted) return parseRefs(env._data)\n const dek = await getDEK(SUBJECT_INDEX_COLLECTION)\n const json = await openEnvelopeJson(env, dek)\n return parseRefs(json)\n}\n\n/** Encrypt + write a ref list for a subject under its derived key. */\nasync function writeRefs(\n adapter: NoydbStore,\n vault: string,\n getDEK: GetDEK,\n encrypted: boolean,\n key: string,\n refs: SubjectRef[],\n): Promise<void> {\n let env: EncryptedEnvelope\n if (!encrypted) {\n // Plaintext/debug vault: keep the legacy bare-array form (no padding needed).\n env = { _noydb: NOYDB_FORMAT_VERSION, _v: 1, _ts: new Date().toISOString(), _iv: '', _data: JSON.stringify(refs) }\n } else {\n const dek = await getDEK(SUBJECT_INDEX_COLLECTION)\n const { iv, data } = await encrypt(serializeRefs(refs), dek)\n env = { _noydb: NOYDB_FORMAT_VERSION, _v: 1, _ts: new Date().toISOString(), _iv: iv, _data: data }\n }\n await adapter.put(vault, SUBJECT_INDEX_COLLECTION, key, env)\n}\n\n/**\n * Add a `{ collection, id }` ref to a subject's index entry (idempotent —\n * a duplicate ref is not appended). Read-modify-write; see the concurrency\n * note in the module docstring.\n */\nexport async function addSubjectRef(\n adapter: NoydbStore,\n vault: string,\n getDEK: GetDEK,\n encrypted: boolean,\n subjectId: string,\n ref: SubjectRef,\n): Promise<void> {\n const key = await primarySubjectKey(getDEK, encrypted, subjectId)\n const refs = await readRefs(adapter, vault, getDEK, encrypted, key)\n if (refs.some((r) => r.collection === ref.collection && r.id === ref.id)) return\n refs.push(ref)\n await writeRefs(adapter, vault, getDEK, encrypted, key, refs)\n}\n\n/**\n * Remove a `{ collection, id }` ref from a subject's index entry. When the\n * last ref is removed the (now empty) entry is deleted so the store holds no\n * residual key for an erased subject.\n */\nexport async function removeSubjectRef(\n adapter: NoydbStore,\n vault: string,\n getDEK: GetDEK,\n encrypted: boolean,\n subjectId: string,\n ref: SubjectRef,\n): Promise<void> {\n // Dual-lookup: drop the ref from BOTH the keyed (M-2) and the legacy sha256\n // entry, so a pre-M-2 subject is still fully erased.\n for (const key of await subjectKeys(getDEK, encrypted, subjectId)) {\n const refs = await readRefs(adapter, vault, getDEK, encrypted, key)\n const next = refs.filter((r) => !(r.collection === ref.collection && r.id === ref.id))\n if (next.length === refs.length) continue\n if (next.length === 0) {\n await adapter.delete(vault, SUBJECT_INDEX_COLLECTION, key)\n } else {\n await writeRefs(adapter, vault, getDEK, encrypted, key, next)\n }\n }\n}\n\n/**\n * Look up every record ref for a subject. Returns `[]` when none exist. Unions\n * the keyed (M-2) and legacy sha256 entries (dual-lookup), deduplicated, so a\n * subject indexed before M-2 is still fully found.\n */\nexport async function lookupSubject(\n adapter: NoydbStore,\n vault: string,\n getDEK: GetDEK,\n encrypted: boolean,\n subjectId: string,\n): Promise<SubjectRef[]> {\n const keys = await subjectKeys(getDEK, encrypted, subjectId)\n const seen = new Set<string>()\n const out: SubjectRef[] = []\n for (const key of keys) {\n for (const ref of await readRefs(adapter, vault, getDEK, encrypted, key)) {\n const dedup = `${ref.collection}\\u0000${ref.id}`\n if (seen.has(dedup)) continue\n seen.add(dedup)\n out.push(ref)\n }\n }\n return out\n}\n\n/**\n * Rebuild the entire subject index from the canonical records (the recovery\n * path for the documented read-modify-write race). Scans each declared\n * collection, reads `record[subjectField]` (dotted path), and rewrites the\n * index from scratch. Tombstoned (already-shredded) records contribute no\n * ref — their body is gone, so they cannot be re-indexed.\n *\n * `decodeRecord` decrypts an envelope to a plain object (or returns null for\n * a tombstone / unreadable record); supplied by the caller so this module\n * stays free of Collection internals.\n */\nexport async function rebuildSubjectIndex(\n adapter: NoydbStore,\n vault: string,\n getDEK: GetDEK,\n encrypted: boolean,\n subjects: Readonly<Record<string, string>>,\n decodeRecord: (collection: string, id: string, env: EncryptedEnvelope) => Promise<Record<string, unknown> | null>,\n): Promise<number> {\n // Drop every existing index entry first so removed refs don't linger.\n const existing = await adapter.list(vault, SUBJECT_INDEX_COLLECTION)\n for (const k of existing) {\n await adapter.delete(vault, SUBJECT_INDEX_COLLECTION, k)\n }\n\n // subjectId → refs, accumulated across all declared collections.\n const bySubject = new Map<string, SubjectRef[]>()\n for (const [collection, field] of Object.entries(subjects)) {\n const ids = await adapter.list(vault, collection)\n for (const id of ids) {\n if (id.startsWith('_')) continue\n const env = await adapter.get(vault, collection, id)\n if (!env || !env._data) continue // missing or tombstone\n const record = await decodeRecord(collection, id, env)\n if (record === null) continue\n const subjectValue = readDottedPath(record, field)\n if (subjectValue === undefined || subjectValue === null) continue\n const subjectId = coerceSubjectId(subjectValue)\n const list = bySubject.get(subjectId) ?? []\n list.push({ collection, id })\n bySubject.set(subjectId, list)\n }\n }\n\n let entries = 0\n for (const [subjectId, refs] of bySubject) {\n const key = await primarySubjectKey(getDEK, encrypted, subjectId)\n await writeRefs(adapter, vault, getDEK, encrypted, key, refs)\n entries++\n }\n return entries\n}\n\n/**\n * Coerce a read subject-field value to a stable string id. Primitives use\n * their natural string form; objects/arrays are JSON-stringified so structural\n * subjects still get a deterministic key (avoids the `[object Object]` trap).\n */\nexport function coerceSubjectId(value: unknown): string {\n if (typeof value === 'string') return value\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {\n return String(value)\n }\n return JSON.stringify(value)\n}\n\n/** Read a (possibly dotted) field path from a plain record. */\nexport function readDottedPath(record: Record<string, unknown>, field: string): unknown {\n if (!field.includes('.')) return record[field]\n let cursor: unknown = record\n for (const segment of field.split('.')) {\n if (cursor === null || cursor === undefined) return undefined\n cursor = (cursor as Record<string, unknown>)[segment]\n }\n return cursor\n}\n"],"mappings":";;;;;;;;;;;AAiDO,IAAM,YAA4B,EAAE,UAAU,CAAC,EAAE;;;ACVjD,IAAM,2BAA2B;AAOxC,IAAM,kBAAkB;AAWxB,eAAe,gBAAgB,OAAgC;AAC7D,SAAO,UAAU,IAAI,YAAY,EAAE,OAAO,KAAK,CAAC;AAClD;AAWA,eAAe,YAAY,QAAgB,WAAoB,WAAsC;AACnG,QAAM,SAAS,MAAM,gBAAgB,SAAS;AAC9C,MAAI,CAAC,UAAW,QAAO,CAAC,MAAM;AAC9B,QAAM,MAAM,MAAM,OAAO,wBAAwB;AACjD,QAAM,QAAQ,MAAM,cAAc,KAAK,IAAI,YAAY,EAAE,OAAO,SAAS,CAAC;AAC1E,SAAO,UAAU,SAAS,CAAC,KAAK,IAAI,CAAC,OAAO,MAAM;AACpD;AAGA,eAAe,kBAAkB,QAAgB,WAAoB,WAAoC;AACvG,UAAQ,MAAM,YAAY,QAAQ,WAAW,SAAS,GAAG,CAAC;AAC5D;AAGA,SAAS,UAAU,MAA4B;AAC7C,QAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,SAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,OAAO;AACjD;AAGA,SAAS,cAAc,MAA4B;AACjD,QAAM,OAAO,KAAK,UAAU,EAAE,GAAG,MAAM,GAAG,GAAG,CAAC;AAC9C,QAAM,MAAM,KAAK,KAAK,KAAK,SAAS,eAAe,IAAI,kBAAkB,KAAK;AAC9E,SAAO,KAAK,UAAU,EAAE,GAAG,MAAM,GAAG,IAAI,OAAO,GAAG,EAAE,CAAC;AACvD;AAGA,eAAe,SACb,SACA,OACA,QACA,WACA,KACuB;AACvB,QAAM,MAAM,MAAM,QAAQ,IAAI,OAAO,0BAA0B,GAAG;AAClE,MAAI,CAAC,OAAO,CAAC,IAAI,MAAO,QAAO,CAAC;AAChC,MAAI,CAAC,UAAW,QAAO,UAAU,IAAI,KAAK;AAC1C,QAAM,MAAM,MAAM,OAAO,wBAAwB;AACjD,QAAM,OAAO,MAAM,iBAAiB,KAAK,GAAG;AAC5C,SAAO,UAAU,IAAI;AACvB;AAGA,eAAe,UACb,SACA,OACA,QACA,WACA,KACA,MACe;AACf,MAAI;AACJ,MAAI,CAAC,WAAW;AAEd,UAAM,EAAE,QAAQ,sBAAsB,IAAI,GAAG,MAAK,oBAAI,KAAK,GAAE,YAAY,GAAG,KAAK,IAAI,OAAO,KAAK,UAAU,IAAI,EAAE;AAAA,EACnH,OAAO;AACL,UAAM,MAAM,MAAM,OAAO,wBAAwB;AACjD,UAAM,EAAE,IAAI,KAAK,IAAI,MAAM,QAAQ,cAAc,IAAI,GAAG,GAAG;AAC3D,UAAM,EAAE,QAAQ,sBAAsB,IAAI,GAAG,MAAK,oBAAI,KAAK,GAAE,YAAY,GAAG,KAAK,IAAI,OAAO,KAAK;AAAA,EACnG;AACA,QAAM,QAAQ,IAAI,OAAO,0BAA0B,KAAK,GAAG;AAC7D;AAOA,eAAsB,cACpB,SACA,OACA,QACA,WACA,WACA,KACe;AACf,QAAM,MAAM,MAAM,kBAAkB,QAAQ,WAAW,SAAS;AAChE,QAAM,OAAO,MAAM,SAAS,SAAS,OAAO,QAAQ,WAAW,GAAG;AAClE,MAAI,KAAK,KAAK,CAAC,MAAM,EAAE,eAAe,IAAI,cAAc,EAAE,OAAO,IAAI,EAAE,EAAG;AAC1E,OAAK,KAAK,GAAG;AACb,QAAM,UAAU,SAAS,OAAO,QAAQ,WAAW,KAAK,IAAI;AAC9D;AAOA,eAAsB,iBACpB,SACA,OACA,QACA,WACA,WACA,KACe;AAGf,aAAW,OAAO,MAAM,YAAY,QAAQ,WAAW,SAAS,GAAG;AACjE,UAAM,OAAO,MAAM,SAAS,SAAS,OAAO,QAAQ,WAAW,GAAG;AAClE,UAAM,OAAO,KAAK,OAAO,CAAC,MAAM,EAAE,EAAE,eAAe,IAAI,cAAc,EAAE,OAAO,IAAI,GAAG;AACrF,QAAI,KAAK,WAAW,KAAK,OAAQ;AACjC,QAAI,KAAK,WAAW,GAAG;AACrB,YAAM,QAAQ,OAAO,OAAO,0BAA0B,GAAG;AAAA,IAC3D,OAAO;AACL,YAAM,UAAU,SAAS,OAAO,QAAQ,WAAW,KAAK,IAAI;AAAA,IAC9D;AAAA,EACF;AACF;AAOA,eAAsB,cACpB,SACA,OACA,QACA,WACA,WACuB;AACvB,QAAM,OAAO,MAAM,YAAY,QAAQ,WAAW,SAAS;AAC3D,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAoB,CAAC;AAC3B,aAAW,OAAO,MAAM;AACtB,eAAW,OAAO,MAAM,SAAS,SAAS,OAAO,QAAQ,WAAW,GAAG,GAAG;AACxE,YAAM,QAAQ,GAAG,IAAI,UAAU,KAAS,IAAI,EAAE;AAC9C,UAAI,KAAK,IAAI,KAAK,EAAG;AACrB,WAAK,IAAI,KAAK;AACd,UAAI,KAAK,GAAG;AAAA,IACd;AAAA,EACF;AACA,SAAO;AACT;AAaA,eAAsB,oBACpB,SACA,OACA,QACA,WACA,UACA,cACiB;AAEjB,QAAM,WAAW,MAAM,QAAQ,KAAK,OAAO,wBAAwB;AACnE,aAAW,KAAK,UAAU;AACxB,UAAM,QAAQ,OAAO,OAAO,0BAA0B,CAAC;AAAA,EACzD;AAGA,QAAM,YAAY,oBAAI,IAA0B;AAChD,aAAW,CAAC,YAAY,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC1D,UAAM,MAAM,MAAM,QAAQ,KAAK,OAAO,UAAU;AAChD,eAAW,MAAM,KAAK;AACpB,UAAI,GAAG,WAAW,GAAG,EAAG;AACxB,YAAM,MAAM,MAAM,QAAQ,IAAI,OAAO,YAAY,EAAE;AACnD,UAAI,CAAC,OAAO,CAAC,IAAI,MAAO;AACxB,YAAM,SAAS,MAAM,aAAa,YAAY,IAAI,GAAG;AACrD,UAAI,WAAW,KAAM;AACrB,YAAM,eAAe,eAAe,QAAQ,KAAK;AACjD,UAAI,iBAAiB,UAAa,iBAAiB,KAAM;AACzD,YAAM,YAAY,gBAAgB,YAAY;AAC9C,YAAM,OAAO,UAAU,IAAI,SAAS,KAAK,CAAC;AAC1C,WAAK,KAAK,EAAE,YAAY,GAAG,CAAC;AAC5B,gBAAU,IAAI,WAAW,IAAI;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,UAAU;AACd,aAAW,CAAC,WAAW,IAAI,KAAK,WAAW;AACzC,UAAM,MAAM,MAAM,kBAAkB,QAAQ,WAAW,SAAS;AAChE,UAAM,UAAU,SAAS,OAAO,QAAQ,WAAW,KAAK,IAAI;AAC5D;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,gBAAgB,OAAwB;AACtD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,aAAa,OAAO,UAAU,UAAU;AACxF,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,SAAO,KAAK,UAAU,KAAK;AAC7B;AAGO,SAAS,eAAe,QAAiC,OAAwB;AACtF,MAAI,CAAC,MAAM,SAAS,GAAG,EAAG,QAAO,OAAO,KAAK;AAC7C,MAAI,SAAkB;AACtB,aAAW,WAAW,MAAM,MAAM,GAAG,GAAG;AACtC,QAAI,WAAW,QAAQ,WAAW,OAAW,QAAO;AACpD,aAAU,OAAmC,OAAO;AAAA,EACtD;AACA,SAAO;AACT;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/with-lookup/embeddings/cosine.ts","../src/with-lookup/embeddings/descriptor.ts","../src/with-lookup/embeddings/vector-set.ts","../src/with-lookup/search/tokenize.ts","../src/with-lookup/search/scan.ts","../src/with-lookup/search/segment.ts","../src/with-lookup/search/inverted-index.ts","../src/with-lookup/search/snippet.ts","../src/with-lookup/search/index-store.ts","../src/with-lookup/search/build-docs.ts","../src/with-lookup/search/active.ts","../src/with-lookup/search/strategy.ts","../src/with-lookup/search/collection-facade.ts"],"sourcesContent":["/** Cosine similarity in [-1,1]; 0 on zero-norm or length mismatch (no NaN). (L2) */\nexport function cosine(a: Float32Array | number[], b: Float32Array | number[]): number {\n if (a.length !== b.length) return 0\n let dot = 0, na = 0, nb = 0\n for (let i = 0; i < a.length; i++) {\n const x = a[i]!, y = b[i]!\n dot += x * y; na += x * x; nb += y * y\n }\n if (na === 0 || nb === 0) return 0\n return dot / (Math.sqrt(na) * Math.sqrt(nb))\n}\n","/** Per-collection embedding config (L2). The encode hook is host/remote — no bundled model. */\nimport { getAtPath } from '../../with-shape/i18n/core.js'\n\nexport interface EmbeddingDescriptor {\n readonly source: string | readonly string[]\n readonly encode: (text: string) => Promise<Float32Array>\n readonly dim: number\n readonly model: string\n}\n\n/** Concatenate the record's source-field text (skips empties; supports nested/[]-wildcard paths). */\nexport function embeddingSourceText(record: Record<string, unknown>, source: string | readonly string[]): string {\n const fields = typeof source === 'string' ? [source] : source\n const parts: string[] = []\n for (const f of fields) {\n for (const leaf of getAtPath(record, f)) {\n if (typeof leaf === 'string' && leaf !== '') parts.push(leaf)\n }\n }\n return parts.join(' ')\n}\n","/** In-memory vector set for L2 semantic retrieval. Loaded once per session from\n * decrypted _vec sidecars (injected loader), brute-force cosine kNN, model-guarded. */\nimport { cosine } from './cosine.js'\nimport { EmbeddingModelMismatchError } from '../../kernel/errors.js'\n\nexport interface StoredVector { readonly id: string; readonly vec: Float32Array; readonly model: string }\nexport interface VectorHit { readonly id: string; readonly score: number }\n\nexport class VectorSet {\n private vectors: StoredVector[] | undefined\n get loaded(): boolean { return this.vectors !== undefined }\n\n async ensureLoaded(load: () => Promise<StoredVector[]>): Promise<void> {\n if (this.vectors === undefined) this.vectors = await load()\n }\n\n markDirty(): void { this.vectors = undefined }\n\n cosineTopK(query: Float32Array, k: number, opts: { minScore?: number; expectModel?: string } = {}): VectorHit[] {\n const all = this.vectors ?? []\n const minScore = opts.minScore ?? -Infinity\n const hits: VectorHit[] = []\n for (const v of all) {\n if (opts.expectModel !== undefined && v.model !== opts.expectModel) {\n throw new EmbeddingModelMismatchError(opts.expectModel, v.model)\n }\n const score = cosine(query, v.vec)\n if (score >= minScore) hits.push({ id: v.id, score })\n }\n hits.sort((a, b) => b.score - a.score)\n return hits.slice(0, k)\n }\n}\n","/**\n * Default text tokenizer for scan-mode search.\n *\n * NFKC-normalize → lowercase → split on Unicode letter/number runs. This is a\n * word-boundary tokenizer: it does **not** segment scripts written without\n * inter-word spaces (Thai, Lao, Khmer, CJK) — those collapse to one token per\n * run. For such data, a dictionary/ICU segmenter is the right `tokenizer`\n * (the engine takes one as a parameter); substring/`contains` matching is the\n * pragmatic fallback until then.\n */\nexport type Tokenizer = (text: string) => string[]\n\nconst WORD = /[\\p{L}\\p{N}]+/gu\n\nexport const tokenize: Tokenizer = (text: string): string[] => {\n if (!text) return []\n return text.normalize('NFKC').toLowerCase().match(WORD) ?? []\n}\n","/**\n * Scan-mode full-text search — ranks **already-decrypted** records by\n * BM25 against a tokenized query. Pure client-side: nothing is written to the\n * store, so this adds **zero** leakage (unlike a store-usable blind index,\n * which is a separate, gated opt-in).\n *\n * O(n) over the collection; intended for small/medium collections (the pilot's\n * scale) where moving the existing userland scan into the DB is the win.\n */\nimport { tokenize, type Tokenizer } from './tokenize.js'\n\nexport interface SearchOptions {\n /** Top-N by score (default: all matches). */\n readonly limit?: number\n /** `'any'` (default) = OR of query terms; `'all'` = every term must match. */\n readonly match?: 'any' | 'all'\n /** Treat the LAST query term as a prefix (typeahead). */\n readonly prefix?: boolean\n}\n\nexport interface SearchResult<T> {\n readonly id: string\n readonly score: number\n readonly record: T\n}\n\nexport interface SearchEntry<T> {\n readonly id: string\n readonly record: T\n}\n\nconst K1 = 1.2\nconst B = 0.75\n\n/** Coerce a field value to searchable text (numbers/booleans stringified). */\nfunction fieldText(record: unknown, field: string): string {\n const v = (record as Record<string, unknown>)[field]\n if (typeof v === 'string') return v\n if (v === null || v === undefined) return ''\n if (typeof v === 'number' || typeof v === 'boolean') return String(v)\n return ''\n}\n\nexport function searchScan<T>(\n entries: ReadonlyArray<SearchEntry<T>>,\n field: string,\n query: string,\n opts: SearchOptions = {},\n tokenizer: Tokenizer = tokenize,\n): SearchResult<T>[] {\n const queryTerms = tokenizer(query)\n if (queryTerms.length === 0) return []\n\n const match = opts.match ?? 'any'\n const usePrefix = opts.prefix ?? false\n const exactTerms = usePrefix ? queryTerms.slice(0, -1) : queryTerms\n const prefixTerm = usePrefix ? queryTerms[queryTerms.length - 1] : undefined\n\n // One tokenize pass per doc; collect corpus stats (df, avg length).\n const docs = entries.map((e) => ({ id: e.id, record: e.record, terms: tokenizer(fieldText(e.record, field)) }))\n const N = docs.length || 1\n const df = new Map<string, number>()\n let totalLen = 0\n for (const d of docs) {\n totalLen += d.terms.length\n for (const t of new Set(d.terms)) df.set(t, (df.get(t) ?? 0) + 1)\n }\n const avgdl = totalLen / N || 1\n\n // Document frequency for the prefix term: docs containing ANY term with it.\n let prefixDf = 0\n if (prefixTerm !== undefined) {\n for (const d of docs) {\n if (d.terms.some((t) => t.startsWith(prefixTerm))) prefixDf++\n }\n }\n\n const requiredCount = exactTerms.length + (prefixTerm !== undefined ? 1 : 0)\n const results: SearchResult<T>[] = []\n\n for (const d of docs) {\n const tf = new Map<string, number>()\n for (const t of d.terms) tf.set(t, (tf.get(t) ?? 0) + 1)\n\n const matched: { tf: number; df: number }[] = []\n for (const qt of exactTerms) {\n const c = tf.get(qt) ?? 0\n if (c > 0) matched.push({ tf: c, df: df.get(qt) ?? 0 })\n }\n if (prefixTerm !== undefined) {\n let ptf = 0\n for (const [t, c] of tf) if (t.startsWith(prefixTerm)) ptf += c\n if (ptf > 0) matched.push({ tf: ptf, df: prefixDf })\n }\n\n if (matched.length === 0) continue\n if (match === 'all' && matched.length < requiredCount) continue\n\n let score = 0\n for (const m of matched) {\n const idf = Math.log(1 + (N - m.df + 0.5) / (m.df + 0.5))\n const denom = m.tf + K1 * (1 - B + B * (d.terms.length / avgdl))\n score += idf * ((m.tf * (K1 + 1)) / (denom || 1))\n }\n results.push({ id: d.id, score, record: d.record })\n }\n\n results.sort((a, b) => b.score - a.score)\n return opts.limit !== undefined ? results.slice(0, opts.limit) : results\n}\n","/**\n * i18n word tokenizer for the L1 lexical index. Uses Intl.Segmenter\n * (standard ECMAScript — hub-portable) to dictionary-segment Thai/Lao/Khmer/CJK,\n * which the word-run `tokenize` cannot. Terms are matched in NFKC-lowercased form;\n * offsets index the ORIGINAL text so snippets slice the user's text.\n */\nimport type { Tokenizer } from './tokenize.js'\n\nconst SEGMENTER = new Intl.Segmenter(undefined, { granularity: 'word' })\n\nexport interface Token {\n readonly term: string\n readonly offset: number\n}\n\n/** Word-like tokens with NFKC-lowercased terms + original-text char offsets. */\nexport const segmentTokens = (text: string): Token[] => {\n const out: Token[] = []\n if (!text) return out\n for (const s of SEGMENTER.segment(text)) {\n if (s.isWordLike) out.push({ term: s.segment.normalize('NFKC').toLowerCase(), offset: s.index })\n }\n return out\n}\n\n/** Term-only tokenizer (the public `Tokenizer` shape) — for queries. */\nexport const segmentTokenizer: Tokenizer = (text: string): string[] =>\n segmentTokens(text).map((t) => t.term)\n","/**\n * In-memory inverted index for the L1 lexical retrieval layer. Built\n * client-side from already-decrypted records; nothing touches the store. BM25\n * mirrors src/search/scan.ts; multi-field with max-field combination so a record\n * ranks by its strongest field, which also supplies the snippet location.\n */\nimport { segmentTokens, segmentTokenizer } from './segment.js'\n\nconst K1 = 1.2\nconst B = 0.75\n\nexport interface IndexDoc {\n readonly id: string\n readonly fields: ReadonlyArray<{ readonly field: string; readonly locale?: string; readonly text: string }>\n}\n\nexport interface IndexHit {\n readonly id: string\n readonly score: number\n readonly field: string\n readonly locale?: string\n readonly text: string\n readonly offset: number\n}\n\nexport interface QueryOptions {\n readonly limit?: number\n readonly match?: 'any' | 'all'\n readonly prefix?: boolean\n readonly fields?: readonly string[]\n}\n\nexport interface IndexSnapshot {\n readonly v: 1\n readonly fieldStats: ReadonlyArray<[string, { df: [string, number][]; n: number; totalLen: number }]>\n readonly docs: ReadonlyArray<{\n id: string; field: string; locale?: string; text: string; len: number\n tf: [string, number][]; firstOffset: [string, number][]\n }>\n}\n\ninterface Doc {\n id: string\n field: string\n locale?: string\n text: string\n len: number\n tf: Map<string, number>\n firstOffset: Map<string, number>\n}\n\nexport class InvertedIndex {\n // per field: df (term -> #docs), N (#docs), totalLen\n private readonly fieldStats = new Map<string, { df: Map<string, number>; n: number; totalLen: number }>()\n private readonly docs: Doc[] = []\n\n static build(docs: ReadonlyArray<IndexDoc>): InvertedIndex {\n const idx = new InvertedIndex()\n for (const d of docs) {\n for (const f of d.fields) {\n const tokens = segmentTokens(f.text)\n const tf = new Map<string, number>()\n const firstOffset = new Map<string, number>()\n for (const t of tokens) {\n tf.set(t.term, (tf.get(t.term) ?? 0) + 1)\n if (!firstOffset.has(t.term)) firstOffset.set(t.term, t.offset)\n }\n const doc: Doc = { id: d.id, field: f.field, ...(f.locale !== undefined ? { locale: f.locale } : {}), text: f.text, len: tokens.length, tf, firstOffset }\n idx.docs.push(doc)\n let s = idx.fieldStats.get(f.field)\n if (!s) { s = { df: new Map(), n: 0, totalLen: 0 }; idx.fieldStats.set(f.field, s) }\n s.n += 1\n s.totalLen += doc.len\n for (const term of tf.keys()) s.df.set(term, (s.df.get(term) ?? 0) + 1)\n }\n }\n return idx\n }\n\n query(query: string, opts: QueryOptions = {}): IndexHit[] {\n const terms = segmentTokenizer(query)\n if (terms.length === 0) return []\n const usePrefix = opts.prefix ?? false\n const exact = usePrefix ? terms.slice(0, -1) : terms\n const prefix = usePrefix ? terms[terms.length - 1] : undefined\n const match = opts.match ?? 'any'\n const required = exact.length + (prefix !== undefined ? 1 : 0)\n\n // best (max-score) doc per record\n const best = new Map<string, IndexHit>()\n for (const doc of this.docs) {\n if (opts.fields !== undefined && !opts.fields.includes(doc.field)) continue\n const stats = this.fieldStats.get(doc.field)!\n const avgdl = stats.totalLen / stats.n || 1\n let score = 0\n let matchedCount = 0\n let snippetOffset = -1\n\n const scoreTerm = (tf: number, df: number, offset: number): void => {\n if (tf <= 0) return\n matchedCount += 1\n if (snippetOffset < 0 && offset >= 0) snippetOffset = offset\n const idf = Math.log(1 + (stats.n - df + 0.5) / (df + 0.5))\n const denom = tf + K1 * (1 - B + B * (doc.len / avgdl))\n score += idf * ((tf * (K1 + 1)) / (denom || 1))\n }\n\n for (const qt of exact) scoreTerm(doc.tf.get(qt) ?? 0, stats.df.get(qt) ?? 0, doc.firstOffset.get(qt) ?? -1)\n\n if (prefix !== undefined) {\n // Build a set of exact query terms so we don't double-count a term that\n // is both an exact match and starts with the prefix (defect 2 fix).\n const exactSet = new Set(exact)\n let ptf = 0\n let poff = -1\n for (const [term, c] of doc.tf) {\n if (term.startsWith(prefix) && !exactSet.has(term)) {\n ptf += c\n if (poff < 0) poff = doc.firstOffset.get(term) ?? -1\n }\n }\n if (ptf > 0) {\n // df for the prefix: count DISTINCT docs in this field that have any\n // prefix-matching term — mirrors scan.ts semantics (defect 1 fix).\n let pdf = 0\n for (const d of this.docs) {\n if (d.field === doc.field && [...d.tf.keys()].some((t) => t.startsWith(prefix))) pdf++\n }\n scoreTerm(ptf, pdf || 1, poff)\n }\n }\n\n if (matchedCount === 0) continue\n if (match === 'all' && matchedCount < required) continue\n\n const hit: IndexHit = {\n id: doc.id, score, field: doc.field, text: doc.text,\n offset: snippetOffset < 0 ? 0 : snippetOffset,\n ...(doc.locale !== undefined ? { locale: doc.locale } : {}),\n }\n const prev = best.get(doc.id)\n if (!prev || hit.score > prev.score) best.set(doc.id, hit)\n }\n\n const results = [...best.values()].sort((a, b) => b.score - a.score)\n return opts.limit !== undefined ? results.slice(0, opts.limit) : results\n }\n\n toSnapshot(): IndexSnapshot {\n return {\n v: 1,\n fieldStats: [...this.fieldStats].map(([f, s]) => [f, { df: [...s.df], n: s.n, totalLen: s.totalLen }]),\n docs: this.docs.map((d) => ({\n id: d.id, field: d.field, text: d.text, len: d.len,\n tf: [...d.tf], firstOffset: [...d.firstOffset],\n ...(d.locale !== undefined ? { locale: d.locale } : {}),\n })),\n }\n }\n\n static fromSnapshot(s: IndexSnapshot): InvertedIndex {\n const idx = new InvertedIndex()\n for (const [f, st] of s.fieldStats) idx.fieldStats.set(f, { df: new Map(st.df), n: st.n, totalLen: st.totalLen })\n for (const d of s.docs) {\n idx.docs.push({\n id: d.id, field: d.field, text: d.text, len: d.len,\n tf: new Map(d.tf), firstOffset: new Map(d.firstOffset),\n ...(d.locale !== undefined ? { locale: d.locale } : {}),\n })\n }\n return idx\n }\n}\n","/**\n * Minimal-disclosure snippet: a char-window around a match offset (L1).\n * Unicode-safe (operates on code points). `…` marks each truncated end.\n */\nexport function extractSnippet(text: string, offset: number, window = 80): string {\n const chars = Array.from(text)\n if (chars.length <= window) return text\n // offset is a UTF-16 index into `text`; map to a code-point index.\n const cpOffset = Array.from(text.slice(0, Math.max(0, offset))).length\n const half = Math.floor(window / 2)\n let start = Math.max(0, cpOffset - half)\n const end = Math.min(chars.length, start + window)\n start = Math.max(0, end - window)\n const body = chars.slice(start, end).join('')\n return `${start > 0 ? '…' : ''}${body}${end < chars.length ? '…' : ''}`\n}\n","/**\n * The index persistence seam (L1.5). MemoryIndexStore is session-scoped and\n * lazy; an opaque-blob backend implements the same interface so the\n * collection call-site is unchanged.\n */\nimport { InvertedIndex, type IndexDoc } from './inverted-index.js'\n\nexport interface IndexStore {\n ensureBuilt(build: () => ReadonlyArray<IndexDoc>): Promise<InvertedIndex>\n markDirty(): void\n flush(): Promise<void>\n readonly built: boolean\n}\n\nexport class MemoryIndexStore implements IndexStore {\n private index: InvertedIndex | undefined\n\n get built(): boolean { return this.index !== undefined }\n\n async ensureBuilt(build: () => ReadonlyArray<IndexDoc>): Promise<InvertedIndex> {\n if (this.index === undefined) this.index = InvertedIndex.build(build())\n return this.index\n }\n\n markDirty(): void { this.index = undefined }\n\n async flush(): Promise<void> { /* in-memory: nothing to persist */ }\n}\n","/**\n * Map a decrypted record's configured text fields → IndexDoc field entries\n * (L1). String, i18nText, dictKey, and blob-filename expansion. Uses\n * getAtPath for nested/[]-wildcard paths. Blob filenames are NOT inline on the\n * record — the collection pre-resolves them (one listSlots() per record, the\n * heaviest source) and feeds them to {@link buildBlobFieldEntries}.\n */\nimport { getAtPath } from '../../with-shape/i18n/core.js'\nimport type { I18nTextDescriptor } from '../../with-shape/i18n/core.js'\nimport type { DictKeyDescriptor, StaticDictDescriptor } from '../../with-shape/i18n/dictionary.js'\nimport type { IndexDoc } from './inverted-index.js'\n\ntype FieldEntry = IndexDoc['fields'][number]\n\nexport function buildStringFieldEntries(\n record: Record<string, unknown>,\n textIndexes: readonly string[],\n only?: readonly string[],\n): FieldEntry[] {\n const fields = only ? textIndexes.filter((f) => only.includes(f)) : textIndexes\n const out: FieldEntry[] = []\n for (const field of fields) {\n for (const leaf of getAtPath(record, field)) {\n if (typeof leaf === 'string' && leaf !== '') out.push({ field, text: leaf })\n }\n }\n return out\n}\n\nexport function buildI18nFieldEntries(\n record: Record<string, unknown>,\n i18nFields: Record<string, I18nTextDescriptor>,\n textIndexes: readonly string[],\n only?: readonly string[],\n): FieldEntry[] {\n const fields = (only ? textIndexes.filter((f) => only.includes(f)) : textIndexes).filter((f) => f in i18nFields)\n const out: FieldEntry[] = []\n for (const field of fields) {\n for (const leaf of getAtPath(record, field)) {\n if (!leaf || typeof leaf !== 'object' || Array.isArray(leaf)) continue\n for (const [locale, val] of Object.entries(leaf as Record<string, unknown>)) {\n if (typeof val === 'string' && val !== '') out.push({ field, locale, text: val })\n }\n }\n }\n return out\n}\n\n/** label map: field -> (key -> { locale -> label }). Precomputed in the collection (async for dynamic dicts). */\nexport function buildDictKeyFieldEntries(\n record: Record<string, unknown>,\n dictKeyFields: Record<string, DictKeyDescriptor | StaticDictDescriptor>,\n labelMaps: Map<string, Map<string, Record<string, string>>>,\n textIndexes: readonly string[],\n only?: readonly string[],\n): FieldEntry[] {\n const fields = (only ? textIndexes.filter((f) => only.includes(f)) : textIndexes).filter((f) => f in dictKeyFields)\n const out: FieldEntry[] = []\n for (const field of fields) {\n const map = labelMaps.get(field)\n if (!map) continue\n for (const leaf of getAtPath(record, field)) {\n const keys = typeof leaf === 'string' ? [leaf] : Array.isArray(leaf) ? leaf.filter((k): k is string => typeof k === 'string') : []\n for (const key of keys) {\n const labels = map.get(key)\n if (!labels) continue\n for (const [locale, label] of Object.entries(labels)) {\n if (label !== '') out.push({ field, locale, text: label })\n }\n }\n }\n }\n return out\n}\n\n/**\n * Blob filenames precomputed in the collection (`field -> filenames[]`, from one\n * async `listSlots()` per record — the heaviest source, see {@link buildBlobFieldEntries}'s\n * caller). Bytes are never tokenized; only the slot `filename` is indexed.\n */\nexport function buildBlobFieldEntries(filenamesByField: Map<string, string[]>): FieldEntry[] {\n const out: FieldEntry[] = []\n for (const [field, names] of filenamesByField) {\n for (const name of names) if (name !== '') out.push({ field, text: name })\n }\n return out\n}\n","/**\n * Enable the search / retrieval capability.\n * Pass to `createNoydb({ searchStrategy: withSearch() })` to make a collection's\n * `search` / `retrieve` / `similarTo` / `warmIndex` / `flushIndex` methods live,\n * and to enable the put()-time embedding-vector compute for collections that\n * declare an `embeddings` config. The search/retrieval engine is dynamically\n * imported here, so it stays out of the floor bundle until opted in.\n */\nimport type { SearchStrategy } from './strategy.js'\n\nexport function withSearch(): SearchStrategy {\n return {\n async search(ctx, field, query, opts) {\n const { search } = await import('./collection-facade.js')\n return search(ctx, field, query, opts)\n },\n async retrieve(ctx, query, opts) {\n const { retrieve } = await import('./collection-facade.js')\n return retrieve(ctx, query, opts)\n },\n async similarTo(ctx, vector, opts) {\n const { similarTo } = await import('./collection-facade.js')\n return similarTo(ctx, vector, opts)\n },\n async warmIndex(ctx) {\n const { warmIndex } = await import('./collection-facade.js')\n return warmIndex(ctx)\n },\n async flushIndex(ctx) {\n const { flushIndex } = await import('./collection-facade.js')\n return flushIndex(ctx)\n },\n async embedOnWrite(ctx, id, record, version) {\n const { embedOnWrite } = await import('./collection-facade.js')\n return embedOnWrite(ctx, id, record, version)\n },\n }\n}\n","/**\n * Search capability strategy — the on-demand collection-level retrieval\n * operations the `Collection` routes through: scan-mode full-text `search`,\n * unified `retrieve` (lexical | semantic | hybrid), raw-vector `similarTo`, and\n * the lexical-index lifecycle (`warmIndex` / `flushIndex`). The active engine\n * ({@link withSearch}) dynamically imports the search/retrieval facade (keeping\n * it out of the floor bundle); {@link NO_SEARCH} throws.\n *\n * The embedding write-hook (`embedOnWrite`) is paired here too: opting into\n * `withSearch()` enables both the query surface AND the put()-time vector\n * compute — a vector that no gated `similarTo` / semantic `retrieve` could read\n * is dead weight, so embedding compute is not separately gatable. `Collection`\n * always assembles the per-call {@link SearchContext} and delegates here, so an\n * un-opted-in caller hits `NO_SEARCH`'s throw.\n * @internal\n */\nimport type { SearchContext } from './collection-facade.js'\nimport type { SearchOptions, SearchResult } from './index.js'\nimport type { RetrieveOptions, RetrieveHit } from './retrieve-types.js'\nimport { SearchNotEnabledError } from '../../kernel/errors.js'\n\nexport interface SearchStrategy {\n search<T>(ctx: SearchContext<T>, field: string, query: string, opts?: SearchOptions): Promise<SearchResult<T>[]>\n retrieve<T>(ctx: SearchContext<T>, query: string, opts?: RetrieveOptions<T>): Promise<RetrieveHit<T>[]>\n similarTo<T>(ctx: SearchContext<T>, vector: Float32Array, opts?: { k?: number; minScore?: number; includeRecord?: boolean }): Promise<RetrieveHit<T>[]>\n warmIndex<T>(ctx: SearchContext<T>): Promise<void>\n flushIndex<T>(ctx: SearchContext<T>): Promise<void>\n embedOnWrite<T>(ctx: SearchContext<T>, id: string, record: T, version: number): Promise<void>\n}\n\n/**\n * No-op stub — the floor default. Every capability method (and the embedding\n * write-hook) throws {@link SearchNotEnabledError}; opt in with\n * `searchStrategy: withSearch()` in createNoydb. @internal\n */\nexport const NO_SEARCH: SearchStrategy = {\n async search() { throw new SearchNotEnabledError() },\n async retrieve() { throw new SearchNotEnabledError() },\n async similarTo() { throw new SearchNotEnabledError() },\n async warmIndex() { throw new SearchNotEnabledError() },\n async flushIndex() { throw new SearchNotEnabledError() },\n async embedOnWrite() { throw new SearchNotEnabledError() },\n}\n","/**\n * Collection-level search / retrieval (`search` / `retrieve` / `similarTo` +\n * the lexical-index build/flush/warm machinery).\n *\n * This is the retrieval surface: a pure client-side lexical scan\n * (`search`), the persisted-or-in-memory inverted-index lifecycle\n * (`flushIndex` / `warmIndex` / `buildRetrievalDocs` + the dict-label / blob-\n * filename resolvers that feed it), and the lexical / semantic / hybrid\n * `retrieve` fan-out plus raw-vector kNN (`similarTo`). None of it touches the\n * write path — it reads the live eager cache and the encrypted `_vec` / `_ftindex`\n * side-cars.\n *\n * Every function takes a small {@link SearchContext} instead of `this`,\n * mirroring the `record-keys/` siblings.\n *\n * The `cache` is the SAME `Map` reference `Collection` owns (passed by\n * reference, never copied) so the index always builds over the live working\n * set. {@link buildPersistedIndexCallbacks} is special: it is invoked from the\n * `Collection` constructor *before* `this.codec` exists, so it takes a context\n * THUNK and resolves the context lazily at each callback invocation.\n *\n * Internal service — not exported as a `@noy-db/hub/*` subpath.\n */\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { RecordCodec } from '../../kernel/enclave/index.js'\nimport { stripI18nFilled, type I18nTextDescriptor } from '../../with-shape/i18n/core.js'\nimport { isStaticDictDescriptor, type DictKeyDescriptor, type StaticDictDescriptor, type DictionaryHandle } from '../../with-shape/i18n/dictionary.js'\nimport type { BlobSet } from '../../with-shape/blobs/blob-set.js'\nimport type { BlobFieldsConfig } from '../../with-shape/blobs/blob-compaction.js'\nimport type { Query } from '../../kernel/query/index.js'\nimport { embeddingSourceText, type VectorSet, type EmbeddingDescriptor, type StoredVector } from '../embeddings/index.js'\nimport { EmbeddingDimMismatchError } from '../../kernel/errors.js'\nimport { searchScan, fuseRetrieval, type SearchOptions, type SearchResult } from './index.js'\nimport type { IndexStore } from './index-store.js'\nimport type { PersistedIndexCallbacks } from './persisted-index-store.js'\nimport { extractSnippet } from './snippet.js'\nimport { buildStringFieldEntries, buildI18nFieldEntries, buildDictKeyFieldEntries, buildBlobFieldEntries } from './build-docs.js'\nimport type { IndexDoc, IndexHit } from './inverted-index.js'\nimport type { RetrieveOptions, RetrieveHit } from './retrieve-types.js'\n\n/** Everything the moving search/retrieval methods touched on `this.*`. */\nexport interface SearchContext<T> {\n /** Collection name — error context + `_ftindex` row key. */\n readonly name: string\n /** Vault namespace the side-cars (`_vec`, `_ftindex`) live under. */\n readonly vault: string\n /** The ciphertext store. */\n readonly adapter: NoydbStore\n /** The record codec — decrypts the `_vec` / `_ftindex` side-car bodies. */\n readonly codec: RecordCodec<T>\n /** The eager working-set cache (SHARED `Map` reference, never copied). */\n readonly cache: Map<string, { record: T; version: number }>\n /** True in lazy mode — search/retrieve/warm require eager mode. */\n readonly lazy: boolean\n /** Declared text-index fields, or undefined. */\n readonly textIndexes: readonly string[] | undefined\n /** Declared i18n fields, or undefined. */\n readonly i18nFields: Record<string, I18nTextDescriptor> | undefined\n /** Declared dictionary-key fields, or undefined. */\n readonly dictKeyFields: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined\n /** Declared blob fields, or undefined. */\n readonly blobFields: BlobFieldsConfig | undefined\n /** Dictionary handle resolver (dynamic dict-key labels), or undefined. */\n readonly getDictionary: ((name: string) => Promise<DictionaryHandle>) | undefined\n /** The lexical inverted-index store (in-memory or persisted), or undefined. */\n readonly searchIndexStore: IndexStore | undefined\n /** The vector set for semantic retrieval, or undefined. */\n readonly vectorSet: VectorSet | undefined\n /** The embeddings descriptor, or undefined. */\n readonly embeddings: EmbeddingDescriptor | undefined\n /** Hydrate the eager cache before reading it. */\n ensureHydrated(): Promise<void>\n /** Open the blob facade for a record (used to list indexed blob filenames). */\n blob(id: string): BlobSet\n}\n\n/**\n * Client-side lexical scan over the live eager cache. Eager mode only;\n * nothing searchable is written to the store.\n */\nexport async function search<T>(ctx: SearchContext<T>, field: string, query: string, opts: SearchOptions = {}): Promise<SearchResult<T>[]> {\n if (ctx.lazy) {\n throw new Error(\n `Collection \"${ctx.name}\": search() (scan mode) requires eager mode (prefetch: true). ` +\n `A store-usable blind index for lazy / at-scale search is a separate gated opt-in (#308).`,\n )\n }\n await ctx.ensureHydrated()\n const entries: { id: string; record: T }[] = []\n // Strip the internal densify marker from the user-facing records.\n // Non-mutating: never touches the cached record object. The search index\n // is built over the same (marker-free) record, which is fine — the marker\n // is never a searchable field.\n for (const [id, e] of ctx.cache) entries.push({ id, record: stripI18nFilled(e.record as Record<string, unknown>) as T })\n return searchScan(entries, field, query, opts)\n}\n\n/** L1 — build IndexDoc[] for the configured text fields over the live cache. */\nexport function buildRetrievalDocs<T>(\n ctx: SearchContext<T>,\n labelMaps: Map<string, Map<string, Record<string, string>>>,\n blobFilenames: Map<string, Map<string, string[]>>,\n only?: readonly string[],\n): IndexDoc[] {\n const docs: IndexDoc[] = []\n for (const [id, e] of ctx.cache) {\n const rec = stripI18nFilled(e.record as Record<string, unknown>)\n const fields = buildStringFieldEntries(rec, ctx.textIndexes ?? [], only)\n if (ctx.i18nFields) fields.push(...buildI18nFieldEntries(rec, ctx.i18nFields, ctx.textIndexes ?? [], only))\n if (ctx.dictKeyFields) fields.push(...buildDictKeyFieldEntries(rec, ctx.dictKeyFields, labelMaps, ctx.textIndexes ?? [], only))\n const blobNames = blobFilenames.get(id)\n if (blobNames) fields.push(...buildBlobFieldEntries(blobNames))\n if (fields.length > 0) docs.push({ id, fields })\n }\n return docs\n}\n\n/** L1 — true iff any configured text index is also a blob field (gates ALL slot I/O). */\nexport function hasIndexedBlobFields<T>(ctx: SearchContext<T>, only?: readonly string[]): boolean {\n if (!ctx.blobFields || !ctx.textIndexes) return false\n const fields = only ? ctx.textIndexes.filter((f) => only.includes(f)) : ctx.textIndexes\n return fields.some((f) => f in ctx.blobFields!)\n}\n\n/**\n * L1 — resolve `recordId -> (blobField -> filenames[])` by listing slots\n * for the configured blob fields of each cached record. Blob slot metadata is\n * NOT inline on the record: it lives in a separate `_blob_slots_*` collection,\n * so this costs ONE `blob(id).list()` (a `listSlots`) per record at build time\n * — the heaviest indexing source. Fully gated by {@link hasIndexedBlobFields};\n * non-blob (and blob-but-not-indexed) collections do ZERO slot I/O.\n */\nasync function resolveBlobFilenames<T>(ctx: SearchContext<T>, only?: readonly string[]): Promise<Map<string, Map<string, string[]>>> {\n const out = new Map<string, Map<string, string[]>>()\n if (!hasIndexedBlobFields(ctx, only)) return out\n const indexed = (only ? ctx.textIndexes!.filter((f) => only.includes(f)) : ctx.textIndexes!)\n .filter((f) => f in ctx.blobFields!)\n const indexedSet = new Set(indexed)\n for (const id of ctx.cache.keys()) {\n let slots\n try {\n slots = await ctx.blob(id).list()\n } catch {\n continue\n }\n let byField: Map<string, string[]> | undefined\n for (const slot of slots) {\n if (!indexedSet.has(slot.name) || !slot.filename) continue\n if (!byField) { byField = new Map(); out.set(id, byField) }\n const names = byField.get(slot.name)\n if (names) names.push(slot.filename)\n else byField.set(slot.name, [slot.filename])\n }\n }\n return out\n}\n\n/** L1 — field -> (key -> {locale->label}) for dictKey fields; static from table, dynamic via getDictionary().list(). */\nasync function resolveDictLabelMaps<T>(ctx: SearchContext<T>): Promise<Map<string, Map<string, Record<string, string>>>> {\n const maps = new Map<string, Map<string, Record<string, string>>>()\n if (!ctx.dictKeyFields || !ctx.textIndexes) return maps\n for (const field of ctx.textIndexes) {\n const desc = ctx.dictKeyFields[field]\n if (!desc) continue\n const m = new Map<string, Record<string, string>>()\n if (isStaticDictDescriptor(desc)) {\n for (const [key, labels] of Object.entries(desc.table)) m.set(key, labels as Record<string, string>)\n } else {\n if (ctx.getDictionary) {\n const handle = await ctx.getDictionary(desc.name)\n for (const e of await handle.list()) m.set(e.key, e.labels)\n }\n }\n maps.set(field, m)\n }\n return maps\n}\n\n/** L1.5 — force-persist the lexical index now (e.g. on save/idle). Persists only when textIndexPersist is enabled; a no-op otherwise. */\nexport async function flushIndex<T>(ctx: SearchContext<T>): Promise<void> {\n if (!ctx.searchIndexStore) return\n await ctx.ensureHydrated()\n const labelMaps = await resolveDictLabelMaps(ctx)\n const blobFilenames = await resolveBlobFilenames(ctx)\n await ctx.searchIndexStore.ensureBuilt(() => buildRetrievalDocs(ctx, labelMaps, blobFilenames))\n await ctx.searchIndexStore.flush?.()\n}\n\n/** L2 — load + decrypt all _vec sidecars into StoredVector[] for the VectorSet. */\nfunction buildVectorLoad<T>(ctx: SearchContext<T>): () => Promise<StoredVector[]> {\n return async () => {\n const ids = await ctx.adapter.list(ctx.vault, '_vec')\n const out: StoredVector[] = []\n for (const id of ids) {\n const env = await ctx.adapter.get(ctx.vault, '_vec', id)\n if (!env) continue\n const body = await ctx.codec.decryptJsonString(env)\n if (body === null) continue\n const parsed = JSON.parse(body) as { vec: number[]; model: string }\n out.push({ id, vec: new Float32Array(parsed.vec), model: parsed.model })\n }\n return out\n }\n}\n\n/**\n * L1.5 — build the PersistedIndexCallbacks bridge: crypto lives here\n * (collection has getDEK / encryptJsonString / decryptJsonString / adapter),\n * the index store itself is crypto-free.\n *\n * Fingerprint encoding: body-wrap approach — save(json, fp) stores\n * JSON.stringify({ fp, idx: json }) as the encrypted body so the standard\n * EncryptedEnvelope shape is never extended. load() decrypts and JSON.parses\n * the wrapper back out.\n *\n * Cache shape: ctx.cache stores { record, version } — currentFingerprint()\n * iterates over e.version.\n *\n * NOTE: this factory is invoked from the `Collection` constructor *before*\n * `this.codec` is assigned, so it takes a context THUNK and resolves the\n * context lazily inside each callback — by the time a callback actually runs,\n * the codec and cache are fully wired.\n */\nexport function buildPersistedIndexCallbacks<T>(provideCtx: () => SearchContext<T>): PersistedIndexCallbacks {\n const FT = '_ftindex'\n return {\n load: async () => {\n const ctx = provideCtx()\n const env = await ctx.adapter.get(ctx.vault, FT, ctx.name)\n if (!env) return null\n const body = await ctx.codec.decryptJsonString(env)\n if (body === null) return null\n try {\n const wrapped = JSON.parse(body) as { fp: { count: number; maxVersion: number }; idx: string }\n return { json: wrapped.idx, fingerprint: wrapped.fp }\n } catch {\n return null\n }\n },\n save: async (json, fp) => {\n const ctx = provideCtx()\n const body = JSON.stringify({ fp, idx: json })\n const env = await ctx.codec.encryptJsonString(body, fp.count)\n await ctx.adapter.put(ctx.vault, FT, ctx.name, env)\n },\n remove: async () => { const ctx = provideCtx(); await ctx.adapter.delete(ctx.vault, FT, ctx.name) },\n currentFingerprint: () => {\n const ctx = provideCtx()\n let maxVersion = 0\n for (const e of ctx.cache.values()) if (e.version > maxVersion) maxVersion = e.version\n return { count: ctx.cache.size, maxVersion }\n },\n }\n}\n\n/** L1 — pre-build the lexical index (e.g. on open) so the first retrieve() pays no build scan. */\nexport async function warmIndex<T>(ctx: SearchContext<T>): Promise<void> {\n if (!ctx.searchIndexStore) return\n if (ctx.lazy) {\n throw new Error(\n `Collection \"${ctx.name}\": warmIndex() requires eager mode (prefetch: true).`,\n )\n }\n await ctx.ensureHydrated()\n const built = ctx.searchIndexStore.built\n const labelMaps = built ? new Map() : await resolveDictLabelMaps(ctx)\n const blobFilenames = built ? new Map() : await resolveBlobFilenames(ctx)\n await ctx.searchIndexStore.ensureBuilt(() => buildRetrievalDocs(ctx, labelMaps, blobFilenames))\n}\n\n/** Retrieval. mode: 'lexical' (default) | 'semantic' (L2) | 'hybrid' (L3). */\nexport async function retrieve<T>(ctx: SearchContext<T>, query: string, opts: RetrieveOptions<T> = {}): Promise<RetrieveHit<T>[]> {\n const hits =\n opts.mode === 'semantic' ? await retrieveSemantic(ctx, query, opts)\n : opts.mode === 'hybrid' ? await retrieveHybrid(ctx, query, opts)\n : await retrieveLexical(ctx, query, opts)\n return opts.within ? applyWithin(hits, opts.within) : hits\n}\n\n/** L3 — keep only hits whose id matches the structured query, re-rank 1-based. */\nfunction applyWithin<T>(hits: RetrieveHit<T>[], within: Query<T>): RetrieveHit<T>[] {\n const ids = new Set(within._idArray())\n return hits.filter(h => ids.has(h.id)).map((h, i) => ({ ...h, rank: i + 1 }))\n}\n\n/** L1 — client-side lexical retrieval; ranked { id, score, field, snippet, locale? }. */\nasync function retrieveLexical<T>(ctx: SearchContext<T>, query: string, opts: RetrieveOptions<T>): Promise<RetrieveHit<T>[]> {\n if (!ctx.searchIndexStore) {\n throw new Error(`Collection \"${ctx.name}\": retrieve() requires a textIndexes config.`)\n }\n if (ctx.lazy) {\n throw new Error(\n `Collection \"${ctx.name}\": retrieve() requires eager mode (prefetch: true).`,\n )\n }\n await ctx.ensureHydrated()\n const built = ctx.searchIndexStore.built\n const labelMaps = built ? new Map() : await resolveDictLabelMaps(ctx)\n const blobFilenames = built ? new Map() : await resolveBlobFilenames(ctx)\n const index = await ctx.searchIndexStore.ensureBuilt(() => buildRetrievalDocs(ctx, labelMaps, blobFilenames))\n const hits = index.query(query, {\n ...(opts.limit !== undefined ? { limit: opts.limit } : {}),\n ...(opts.match ? { match: opts.match } : {}),\n ...(opts.prefix ? { prefix: opts.prefix } : {}),\n ...(opts.fields ? { fields: opts.fields } : {}),\n })\n const window = opts.snippetWindow ?? 80\n return hits.map((h: IndexHit, i: number) => {\n const base: RetrieveHit<T> = {\n id: h.id,\n score: h.score,\n rank: i + 1,\n field: h.field,\n snippet: extractSnippet(h.text, h.offset, window),\n ...(h.locale !== undefined ? { locale: h.locale } : {}),\n ...(opts.includeRecord\n ? (() => {\n const e = ctx.cache.get(h.id)\n return e ? { record: stripI18nFilled(e.record as Record<string, unknown>) as T } : {}\n })()\n : {}),\n }\n return base\n })\n}\n\n/** L3 — hybrid: fuse lexical (L1) + semantic (L2) by RRF. Requires embeddings. */\nasync function retrieveHybrid<T>(ctx: SearchContext<T>, query: string, opts: RetrieveOptions<T>): Promise<RetrieveHit<T>[]> {\n if (!ctx.embeddings) {\n throw new Error(`Collection \"${ctx.name}\": retrieve({mode:'hybrid'}) requires an embeddings config.`)\n }\n const [lex, sem] = await Promise.all([\n retrieveLexical(ctx, query, opts),\n retrieveSemantic(ctx, query, opts),\n ])\n return fuseRetrieval([lex, sem], opts.limit !== undefined ? { limit: opts.limit } : {})\n}\n\n/** L2 — semantic branch of retrieve(): encode query → similarTo(). */\nasync function retrieveSemantic<T>(ctx: SearchContext<T>, query: string, opts: RetrieveOptions<T>): Promise<RetrieveHit<T>[]> {\n if (!ctx.embeddings) throw new Error(`Collection \"${ctx.name}\": retrieve({mode:'semantic'}) requires an embeddings config.`)\n if (ctx.lazy) throw new Error(`Collection \"${ctx.name}\": retrieve() requires eager mode (prefetch: true).`)\n const qVec = await ctx.embeddings.encode(query)\n return similarTo(ctx, qVec, {\n ...(opts.limit !== undefined ? { k: opts.limit } : {}),\n ...(opts.minScore !== undefined ? { minScore: opts.minScore } : {}),\n ...(opts.includeRecord ? { includeRecord: true } : {}),\n })\n}\n\n/** L2 — raw-vector kNN over the encrypted vector set (decrypted in the trusted tier).\n * Snippet is '' for vector hits in v1 (semantic match isn't span-located). */\nexport async function similarTo<T>(ctx: SearchContext<T>, vector: Float32Array, opts: { k?: number; minScore?: number; includeRecord?: boolean } = {}): Promise<RetrieveHit<T>[]> {\n if (!ctx.embeddings || !ctx.vectorSet) throw new Error(`Collection \"${ctx.name}\": similarTo() requires an embeddings config.`)\n if (ctx.lazy) throw new Error(`Collection \"${ctx.name}\": similarTo() requires eager mode (prefetch: true).`)\n await ctx.ensureHydrated()\n await ctx.vectorSet.ensureLoaded(buildVectorLoad(ctx))\n const hits = ctx.vectorSet.cosineTopK(vector, opts.k ?? 10, {\n ...(opts.minScore !== undefined ? { minScore: opts.minScore } : {}),\n expectModel: ctx.embeddings.model,\n })\n return hits.map((h, i) => {\n const base: RetrieveHit<T> = { id: h.id, score: h.score, rank: i + 1, field: '(vector)', snippet: '' }\n if (opts.includeRecord) { const e = ctx.cache.get(h.id); if (e) (base as { record?: T }).record = stripI18nFilled(e.record as Record<string, unknown>) as T }\n return base\n })\n}\n\n/**\n * L2 — the embedding write-hook: derive a record's embedding vector at\n * write and persist it as the encrypted `_vec` side-car. Routed through the\n * search strategy so it runs only when `withSearch()` is opted in — computing\n * vectors that no gated `similarTo` / semantic `retrieve` could query would be\n * dead weight, so the compute is paired with the search capability. The caller\n * (`Collection.put`) only invokes this when `embeddings` is declared.\n */\nexport async function embedOnWrite<T>(ctx: SearchContext<T>, id: string, record: T, version: number): Promise<void> {\n if (!ctx.embeddings) return\n const text = embeddingSourceText(record as Record<string, unknown>, ctx.embeddings.source)\n const vec = await ctx.embeddings.encode(text)\n if (vec.length !== ctx.embeddings.dim) throw new EmbeddingDimMismatchError('embeddings', ctx.embeddings.dim, vec.length)\n const body = JSON.stringify({ vec: Array.from(vec), model: ctx.embeddings.model, dim: ctx.embeddings.dim })\n const vecEnv = await ctx.codec.encryptJsonString(body, version)\n await ctx.adapter.put(ctx.vault, '_vec', id, vecEnv)\n ctx.vectorSet?.markDirty()\n}\n"],"mappings":"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","names":["K1","B","search","retrieve","similarTo","warmIndex","flushIndex","embedOnWrite"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/with-cargo/strategy.ts","../src/with-party/custody/active.ts","../src/with-party/custody/strategy.ts","../src/with-party/custody/index.ts"],"sourcesContent":["/**\n * Cargo capability strategy (FR-6/FR-7) — the source-side, owner-level\n * partition operation that requires a live {@link Vault}: extracting a re-keyed\n * transfer-sealed partition ({@link extractPartitionCore}). The active engine\n * ({@link withCargo}) dynamically imports that engine (keeping the extraction\n * crypto out of the floor bundle); {@link NO_CARGO} throws.\n *\n * The public free function `extractPartition` (which takes a `Vault`) delegates\n * here via `vault.cargoStrategy`, so an un-opted-in caller hits `NO_CARGO`'s\n * throw.\n *\n * Carve-out (mirrors `openSealedRecord` / `liberateVault`): the recipient-side\n * free functions `adoptPartition` and `decryptExtractedPartition` operate on\n * raw bundle bytes + a destination store — they carry NO source instance to\n * gate against, so they stay ungated host-side tooling. `diffVault` is likewise\n * ungated: it's shared import/merge infrastructure the `as-*` exporters call\n * internally, not a gated cargo capability.\n * @internal\n */\nimport type { Vault } from '../kernel/vault.js'\nimport type { ExtractPartitionResult, ExtractPartitionOptions } from './extract-partition.js'\nimport { CargoNotEnabledError } from '../kernel/errors.js'\n\nexport interface CargoStrategy {\n extractPartition(vault: Vault, opts: ExtractPartitionOptions): Promise<ExtractPartitionResult>\n}\n\n/**\n * No-op stub — the floor default. The source-side cargo op throws\n * {@link CargoNotEnabledError}; opt in with `cargoStrategy: withCargo()` in\n * createNoydb. @internal\n */\nexport const NO_CARGO: CargoStrategy = {\n async extractPartition() { throw new CargoNotEnabledError() },\n}\n","/**\n * Enable the sovereign-custody (FR-6) capability.\n * Pass to `createNoydb({ custodyStrategy: withCustody() })` to make\n * `db.grantCustodian` / `db.revokeCustodian` (and the `vault.custody.*` facade\n * that delegates to them) plus `vault.custody.liberate()` live. The heavy\n * `liberateVault` ceremony is dynamically imported here, so it is reached only\n * via opt-in; grant/revoke run the host's own gate + keyring engine.\n */\nimport type { CustodyStrategy } from './strategy.js'\n\nexport function withCustody(): CustodyStrategy {\n return {\n async grantCustodian(host, vault, options, factors) {\n return host._grantCustodianImpl(vault, options, factors)\n },\n async revokeCustodian(host, vault, options, factors) {\n return host._revokeCustodianImpl(vault, options, factors)\n },\n async liberate(vault, opts) {\n const { liberateVault } = await import('./liberate.js')\n return liberateVault(vault, opts)\n },\n }\n}\n","/**\n * Sovereign-custody (FR-6) capability strategy — the three on-demand\n * operations the custody surface routes through: minting a custodian\n * (`grantCustodian`), removing one (`revokeCustodian`), and the audited\n * ownership-claim ceremony (`liberate`). The active engine ({@link withCustody})\n * runs the grant/revoke impls the host exposes and dynamically imports the\n * heavy `liberateVault` ceremony (keeping it out of the floor bundle);\n * {@link NO_CUSTODY} throws.\n *\n * `Noydb.grantCustodian` / `Noydb.revokeCustodian` delegate here (passing\n * themselves as the {@link CustodyHost}), and `vault.custody.liberate` delegates\n * here with its {@link Vault}. An un-opted-in caller hits `NO_CUSTODY`'s throw.\n *\n * Note: the lower-level `liberateVault` FREE FUNCTION (exported from\n * `custody/liberate.ts`) stays ungated — it has no `createNoydb` instance to\n * gate against (the same carve-out as the `openSealedRecord` host opener). Only\n * the instance surfaces (`db.grantCustodian` / `db.revokeCustodian` /\n * `vault.custody.*`) are the capability.\n * @internal\n */\nimport type { RevokeOptions, FactorProofBundle } from '../../kernel/types.js'\nimport type { Vault } from '../../kernel/vault.js'\nimport type { GrantCustodianOptions } from './index.js'\nimport type { LiberateOptions, LiberateResult } from './liberate.js'\nimport { CustodyNotEnabledError } from '../../kernel/errors.js'\n\n/**\n * The grant/revoke engine the strategy runs when opted in — implemented by\n * `Noydb` (`_grantCustodianImpl` / `_revokeCustodianImpl` hold the gate +\n * keyring logic; the public `grantCustodian` / `revokeCustodian` route through\n * the strategy).\n */\nexport interface CustodyHost {\n _grantCustodianImpl(vault: string, options: GrantCustodianOptions, factors?: FactorProofBundle): Promise<void>\n _revokeCustodianImpl(vault: string, options: RevokeOptions, factors?: FactorProofBundle): Promise<void>\n}\n\nexport interface CustodyStrategy {\n grantCustodian(host: CustodyHost, vault: string, options: GrantCustodianOptions, factors?: FactorProofBundle): Promise<void>\n revokeCustodian(host: CustodyHost, vault: string, options: RevokeOptions, factors?: FactorProofBundle): Promise<void>\n liberate(vault: Vault, opts: LiberateOptions): Promise<LiberateResult>\n}\n\n/**\n * No-op stub — the floor default. Every custody operation throws\n * {@link CustodyNotEnabledError}; opt in with `custodyStrategy: withCustody()`\n * in createNoydb. @internal\n */\nexport const NO_CUSTODY: CustodyStrategy = {\n async grantCustodian() { throw new CustodyNotEnabledError() },\n async revokeCustodian() { throw new CustodyNotEnabledError() },\n async liberate() { throw new CustodyNotEnabledError() },\n}\n","/**\n * Public `vault.custody.*` API surface (FR-6).\n *\n * The custody namespace is the vault-instance face of the FR-6 sovereign-custody\n * model — it mirrors `vault.user.*` exactly: a thin delegation shell with NO\n * business logic. The Vault constructs one `CustodyApi` per session, injecting\n * closures that bind the vault name / keyring into the genuinely-core\n * implementations (`Noydb.grantCustodian` / `Noydb.revokeCustodian` and the\n * `liberateVault` ceremony). Each method just forwards to its injected callback.\n *\n * Three operations:\n * - `grantCustodian(opts)` — owner-only: mint a `custodian` who operates the\n * vault fully but can never grant / rotate / sever / extract.\n * - `revokeCustodian(opts)` — owner-only: remove a custodian.\n * - `liberate(opts)` — custodian-only: audited claim of ownership over a\n * sealed-owner (Deed) vault (mints a DISTINCT new owner; ledger-audited).\n *\n * Provisioning a Deed (`createDeedOwner`) is deliberately NOT on this class: it\n * is a store-level operation that mints the vault's first owner, so there is no\n * vault instance (and thus no custody namespace) yet — it stays the exported\n * `team/deed.ts` function.\n *\n * @see docs/superpowers/specs/2026-06-17-fr6-deed-custodian-liberate-design.md\n * @module\n */\nimport type { GrantOptions, RevokeOptions, FactorProofBundle } from '../../kernel/types.js'\nimport type { LiberateOptions, LiberateResult } from './liberate.js'\n\n/** Options for `vault.custody.grantCustodian` — a grant with the role fixed to `custodian`. */\nexport type GrantCustodianOptions = Omit<GrantOptions, 'role'>\n\n// Capability opt-in seam (S4): grant/revoke custodian + liberate throw\n// CustodyNotEnabledError unless `custodyStrategy: withCustody()` is opted in.\nexport { withCustody } from './active.js'\nexport { NO_CUSTODY, type CustodyStrategy, type CustodyHost } from './strategy.js'\nexport { CustodyNotEnabledError } from '../../kernel/errors.js'\n\n/**\n * Implementation behind `vault.custody`. Constructed once per Vault. Holds the\n * injected, vault-bound implementations in closure; every method delegates with\n * no added logic (the owner-only / custodian-only / gate checks all live in the\n * injected implementations — `Noydb.grantCustodian` etc. and `liberateVault`).\n */\nexport class CustodyApi {\n constructor(\n /** Bound `Noydb.grantCustodian(this.name, ...)` — owner-only, gated. */\n private readonly _grantCustodian: (options: GrantCustodianOptions, factors?: FactorProofBundle) => Promise<void>,\n /** Bound `Noydb.revokeCustodian(this.name, ...)` — owner-only, gated. */\n private readonly _revokeCustodian: (options: RevokeOptions, factors?: FactorProofBundle) => Promise<void>,\n /** Bound `liberateVault(this, ...)` — custodian-only audited ownership claim. */\n private readonly _liberate: (opts: LiberateOptions) => Promise<LiberateResult>,\n ) {}\n\n /**\n * Owner-only: grant the FR-6 `custodian` role. The custodian operates every\n * collection (rw + access) but is provably unable to grant / revoke / rotate /\n * extract-and-sever. Defended in depth (gate + owner-only role check) inside\n * the injected `Noydb.grantCustodian`.\n */\n async grantCustodian(options: GrantCustodianOptions, factors?: FactorProofBundle): Promise<void> {\n return this._grantCustodian(options, factors)\n }\n\n /** Owner-only: revoke a custodian. */\n async revokeCustodian(options: RevokeOptions, factors?: FactorProofBundle): Promise<void> {\n return this._revokeCustodian(options, factors)\n }\n\n /**\n * Custodian-only: the audited claim of ownership over a sealed-owner (Deed)\n * vault. Mints a DISTINCT new owner re-wrapping the incumbent DEKs under a\n * fresh KEK (the latent owner is never impersonated), ledger-audited. See\n * {@link liberateVault}.\n */\n async liberate(opts: LiberateOptions): Promise<LiberateResult> {\n return this._liberate(opts)\n }\n}\n"],"mappings":";;;;;;AAgCO,IAAM,WAA0B;AAAA,EACrC,MAAM,mBAAmB;AAAE,UAAM,IAAI,qBAAqB;AAAA,EAAE;AAC9D;;;ACxBO,SAAS,cAA+B;AAC7C,SAAO;AAAA,IACL,MAAM,eAAe,MAAM,OAAO,SAAS,SAAS;AAClD,aAAO,KAAK,oBAAoB,OAAO,SAAS,OAAO;AAAA,IACzD;AAAA,IACA,MAAM,gBAAgB,MAAM,OAAO,SAAS,SAAS;AACnD,aAAO,KAAK,qBAAqB,OAAO,SAAS,OAAO;AAAA,IAC1D;AAAA,IACA,MAAM,SAAS,OAAO,MAAM;AAC1B,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,wBAAe;AACtD,aAAO,cAAc,OAAO,IAAI;AAAA,IAClC;AAAA,EACF;AACF;;;ACyBO,IAAM,aAA8B;AAAA,EACzC,MAAM,iBAAiB;AAAE,UAAM,IAAI,uBAAuB;AAAA,EAAE;AAAA,EAC5D,MAAM,kBAAkB;AAAE,UAAM,IAAI,uBAAuB;AAAA,EAAE;AAAA,EAC7D,MAAM,WAAW;AAAE,UAAM,IAAI,uBAAuB;AAAA,EAAE;AACxD;;;ACTO,IAAM,aAAN,MAAiB;AAAA,EACtB,YAEmB,iBAEA,kBAEA,WACjB;AALiB;AAEA;AAEA;AAAA,EAChB;AAAA,EALgB;AAAA,EAEA;AAAA,EAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASnB,MAAM,eAAe,SAAgC,SAA4C;AAC/F,WAAO,KAAK,gBAAgB,SAAS,OAAO;AAAA,EAC9C;AAAA;AAAA,EAGA,MAAM,gBAAgB,SAAwB,SAA4C;AACxF,WAAO,KAAK,iBAAiB,SAAS,OAAO;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAAS,MAAgD;AAC7D,WAAO,KAAK,UAAU,IAAI;AAAA,EAC5B;AACF;","names":[]}