@noy-db/hub 0.2.0-pre.9 → 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 (615) hide show
  1. package/README.md +129 -3
  2. package/dist/aggregate/index.d.ts +5 -2
  3. package/dist/aggregate/index.js +25 -16
  4. package/dist/aggregate/index.js.map +1 -1
  5. package/dist/api-TX2EX2FX.js +20 -0
  6. package/dist/as/index.d.ts +6 -0
  7. package/dist/as/index.js +30 -0
  8. package/dist/at/index.d.ts +4 -0
  9. package/dist/at/index.js +1 -0
  10. package/dist/attestation/index.d.ts +14 -47
  11. package/dist/attestation/index.js +60 -10
  12. package/dist/attestation/index.js.map +1 -1
  13. package/dist/backup-R7NTDFKY.js +225 -0
  14. package/dist/backup-R7NTDFKY.js.map +1 -0
  15. package/dist/blobs/index.d.ts +5 -8
  16. package/dist/blobs/index.js +25 -12
  17. package/dist/blobs/index.js.map +1 -1
  18. package/dist/bundle/index.d.ts +15 -70
  19. package/dist/bundle/index.js +45 -476
  20. package/dist/bundle/index.js.map +1 -1
  21. package/dist/{ulid-CJ8RzRrm.d.ts → bundle-D6GxiUfq.d.ts} +31 -86
  22. package/dist/by/index.d.ts +1 -0
  23. package/dist/by/index.js +11 -0
  24. package/dist/cargo/index.d.ts +7 -0
  25. package/dist/cargo/index.js +95 -0
  26. package/dist/chunk-2OV5NVE7.js +95 -0
  27. package/dist/chunk-2OV5NVE7.js.map +1 -0
  28. package/dist/chunk-2OZXVKVP.js +367 -0
  29. package/dist/chunk-2OZXVKVP.js.map +1 -0
  30. package/dist/{chunk-HNRHLRDC.js → chunk-2REPHKET.js} +6 -5
  31. package/dist/chunk-2REPHKET.js.map +1 -0
  32. package/dist/{chunk-PE2FR4J3.js → chunk-3JXPAHOZ.js} +17 -17
  33. package/dist/chunk-3JXPAHOZ.js.map +1 -0
  34. package/dist/{chunk-H2X3ISXG.js → chunk-3MATJ6O4.js} +7 -7
  35. package/dist/chunk-3MATJ6O4.js.map +1 -0
  36. package/dist/{chunk-PP6W64Y3.js → chunk-3OPY6MK2.js} +132 -3
  37. package/dist/chunk-3OPY6MK2.js.map +1 -0
  38. package/dist/{chunk-T7JEBOGN.js → chunk-3QSIU3UT.js} +49 -71
  39. package/dist/chunk-3QSIU3UT.js.map +1 -0
  40. package/dist/{chunk-ZYWZWG6G.js → chunk-4OMCIY6F.js} +32 -12
  41. package/dist/chunk-4OMCIY6F.js.map +1 -0
  42. package/dist/chunk-4Q6HSHHL.js +90 -0
  43. package/dist/chunk-4Q6HSHHL.js.map +1 -0
  44. package/dist/chunk-5I35DOHK.js +94 -0
  45. package/dist/chunk-5I35DOHK.js.map +1 -0
  46. package/dist/chunk-5VG4IJR7.js +235 -0
  47. package/dist/chunk-5VG4IJR7.js.map +1 -0
  48. package/dist/chunk-5YESYH2C.js +155 -0
  49. package/dist/chunk-5YESYH2C.js.map +1 -0
  50. package/dist/chunk-6G5ORS5D.js +202 -0
  51. package/dist/chunk-6G5ORS5D.js.map +1 -0
  52. package/dist/{chunk-VTKGMEPP.js → chunk-6P5XCKSD.js} +13 -3
  53. package/dist/chunk-6P5XCKSD.js.map +1 -0
  54. package/dist/{chunk-J66GRPNH.js → chunk-6S7T6WC4.js} +2 -2
  55. package/dist/chunk-6S7T6WC4.js.map +1 -0
  56. package/dist/{chunk-U26HQ6KJ.js → chunk-7BWJHO2A.js} +4 -4
  57. package/dist/chunk-7BWJHO2A.js.map +1 -0
  58. package/dist/chunk-7P2SDJG3.js +279 -0
  59. package/dist/chunk-7P2SDJG3.js.map +1 -0
  60. package/dist/chunk-ANB77BVV.js +150 -0
  61. package/dist/chunk-ANB77BVV.js.map +1 -0
  62. package/dist/chunk-AURFOK3D.js +35 -0
  63. package/dist/chunk-AURFOK3D.js.map +1 -0
  64. package/dist/chunk-BKARNZJN.js +382 -0
  65. package/dist/chunk-BKARNZJN.js.map +1 -0
  66. package/dist/{chunk-3BFJOWSU.js → chunk-BQISD5ZV.js} +35 -7
  67. package/dist/chunk-BQISD5ZV.js.map +1 -0
  68. package/dist/{chunk-2GLDA55J.js → chunk-BUAQ7YI3.js} +260 -135
  69. package/dist/chunk-BUAQ7YI3.js.map +1 -0
  70. package/dist/{chunk-2WUSG3IT.js → chunk-CB7CWSKW.js} +5 -5
  71. package/dist/chunk-CB7CWSKW.js.map +1 -0
  72. package/dist/chunk-CHFZDSE4.js +1 -0
  73. package/dist/{aggregate/index.cjs → chunk-DFVUTGT2.js} +206 -222
  74. package/dist/chunk-DFVUTGT2.js.map +1 -0
  75. package/dist/chunk-DJ7KIPLV.js +23 -0
  76. package/dist/chunk-DJ7KIPLV.js.map +1 -0
  77. package/dist/chunk-DSKDQP3G.js +14066 -0
  78. package/dist/chunk-DSKDQP3G.js.map +1 -0
  79. package/dist/{chunk-5T22KDPN.js → chunk-DV4HUP5G.js} +10 -8
  80. package/dist/chunk-DV4HUP5G.js.map +1 -0
  81. package/dist/chunk-EOXAAJTY.js +621 -0
  82. package/dist/chunk-EOXAAJTY.js.map +1 -0
  83. package/dist/chunk-ET67AY6B.js +74 -0
  84. package/dist/chunk-ET67AY6B.js.map +1 -0
  85. package/dist/chunk-F4CEK5YM.js +123 -0
  86. package/dist/chunk-F4CEK5YM.js.map +1 -0
  87. package/dist/chunk-FORYWFN6.js +130 -0
  88. package/dist/chunk-FORYWFN6.js.map +1 -0
  89. package/dist/{chunk-JWRVQKRZ.js → chunk-FRP6D2DM.js} +21 -20
  90. package/dist/chunk-FRP6D2DM.js.map +1 -0
  91. package/dist/chunk-FUOE7UUV.js +341 -0
  92. package/dist/chunk-FUOE7UUV.js.map +1 -0
  93. package/dist/chunk-G4JYND6L.js +42 -0
  94. package/dist/chunk-G4JYND6L.js.map +1 -0
  95. package/dist/{chunk-53XBRIRT.js → chunk-G6XV4H65.js} +9 -9
  96. package/dist/chunk-G6XV4H65.js.map +1 -0
  97. package/dist/chunk-GHVIKOHT.js +1 -0
  98. package/dist/{chunk-PX35GA7L.js → chunk-GNMXXTMN.js} +11 -9
  99. package/dist/chunk-GNMXXTMN.js.map +1 -0
  100. package/dist/chunk-GYGLAVCX.js +19 -0
  101. package/dist/chunk-GYGLAVCX.js.map +1 -0
  102. package/dist/chunk-HPWKV3YB.js +21 -0
  103. package/dist/chunk-HPWKV3YB.js.map +1 -0
  104. package/dist/chunk-HY3AUMFI.js +41 -0
  105. package/dist/chunk-HY3AUMFI.js.map +1 -0
  106. package/dist/chunk-HYR4WZZ3.js +69 -0
  107. package/dist/chunk-HYR4WZZ3.js.map +1 -0
  108. package/dist/chunk-I7FD46FF.js +9 -0
  109. package/dist/chunk-I7FD46FF.js.map +1 -0
  110. package/dist/{chunk-TFBP23BX.js → chunk-ICXIFFYZ.js} +66 -7
  111. package/dist/chunk-ICXIFFYZ.js.map +1 -0
  112. package/dist/{chunk-TV3YZ35S.js → chunk-IGJCYUT5.js} +17 -8
  113. package/dist/chunk-IGJCYUT5.js.map +1 -0
  114. package/dist/{chunk-F3GDRNUT.js → chunk-IVLTXX4W.js} +36 -68
  115. package/dist/chunk-IVLTXX4W.js.map +1 -0
  116. package/dist/{chunk-DONMZAD2.js → chunk-J4LPNIGK.js} +62 -169
  117. package/dist/chunk-J4LPNIGK.js.map +1 -0
  118. package/dist/chunk-JJZ2LW6T.js +36 -0
  119. package/dist/chunk-JJZ2LW6T.js.map +1 -0
  120. package/dist/chunk-JK733I5V.js +23 -0
  121. package/dist/chunk-JK733I5V.js.map +1 -0
  122. package/dist/{chunk-3YPCK6JX.js → chunk-KJ2BCBTL.js} +181 -422
  123. package/dist/chunk-KJ2BCBTL.js.map +1 -0
  124. package/dist/chunk-KNZB6JMR.js +129 -0
  125. package/dist/chunk-KNZB6JMR.js.map +1 -0
  126. package/dist/{chunk-OIF6LZUR.js → chunk-KPZS5QAQ.js} +30 -11
  127. package/dist/chunk-KPZS5QAQ.js.map +1 -0
  128. package/dist/chunk-LB7FD65R.js +163 -0
  129. package/dist/chunk-LB7FD65R.js.map +1 -0
  130. package/dist/{chunk-DO7C2TOG.js → chunk-LEJIKBBB.js} +3 -3
  131. package/dist/{chunk-DO7C2TOG.js.map → chunk-LEJIKBBB.js.map} +1 -1
  132. package/dist/{chunk-O3VZPBZG.js → chunk-LL2NIVUR.js} +56 -13
  133. package/dist/chunk-LL2NIVUR.js.map +1 -0
  134. package/dist/chunk-LP7BEXCT.js +32 -0
  135. package/dist/chunk-LP7BEXCT.js.map +1 -0
  136. package/dist/chunk-MCHVVJIA.js +968 -0
  137. package/dist/chunk-MCHVVJIA.js.map +1 -0
  138. package/dist/chunk-NO272T7Q.js +194 -0
  139. package/dist/chunk-NO272T7Q.js.map +1 -0
  140. package/dist/{chunk-22DWZL57.js → chunk-NUEQU36L.js} +70 -267
  141. package/dist/chunk-NUEQU36L.js.map +1 -0
  142. package/dist/chunk-O45M6LDB.js +38 -0
  143. package/dist/chunk-O45M6LDB.js.map +1 -0
  144. package/dist/chunk-OBKWYKYC.js +117 -0
  145. package/dist/chunk-OBKWYKYC.js.map +1 -0
  146. package/dist/{chunk-DJHHA6XH.js → chunk-OHHKHSJP.js} +50 -20
  147. package/dist/chunk-OHHKHSJP.js.map +1 -0
  148. package/dist/chunk-OT76OZL6.js +45 -0
  149. package/dist/chunk-OT76OZL6.js.map +1 -0
  150. package/dist/chunk-OVYRLHPE.js +150 -0
  151. package/dist/chunk-OVYRLHPE.js.map +1 -0
  152. package/dist/{chunk-ML236QKC.js → chunk-OXCSVM3B.js} +5 -5
  153. package/dist/chunk-OXCSVM3B.js.map +1 -0
  154. package/dist/chunk-P33LUIML.js +205 -0
  155. package/dist/chunk-P33LUIML.js.map +1 -0
  156. package/dist/{chunk-DL3HWOQ5.js → chunk-PLS64NCS.js} +10 -8
  157. package/dist/chunk-PLS64NCS.js.map +1 -0
  158. package/dist/{chunk-SYMWGEET.js → chunk-PS2NEWEX.js} +3 -3
  159. package/dist/chunk-PS2NEWEX.js.map +1 -0
  160. package/dist/chunk-PY4KJPYU.js +9 -0
  161. package/dist/chunk-PY4KJPYU.js.map +1 -0
  162. package/dist/chunk-PZ5AY32C.js +10 -0
  163. package/dist/chunk-QA2KUPCP.js +45 -0
  164. package/dist/chunk-QA2KUPCP.js.map +1 -0
  165. package/dist/chunk-QOC3VYL2.js +30 -0
  166. package/dist/chunk-QOC3VYL2.js.map +1 -0
  167. package/dist/{chunk-BVRYKATC.js → chunk-QSFOZUYL.js} +62 -34
  168. package/dist/chunk-QSFOZUYL.js.map +1 -0
  169. package/dist/chunk-RHK32N73.js +30 -0
  170. package/dist/chunk-RHK32N73.js.map +1 -0
  171. package/dist/{chunk-K3DK3NU5.js → chunk-RW3Y22MW.js} +20 -5
  172. package/dist/chunk-RW3Y22MW.js.map +1 -0
  173. package/dist/{chunk-B6PB7JLN.js → chunk-S7VFUQM2.js} +541 -6
  174. package/dist/chunk-S7VFUQM2.js.map +1 -0
  175. package/dist/chunk-SVLR4POP.js +64 -0
  176. package/dist/chunk-SVLR4POP.js.map +1 -0
  177. package/dist/chunk-T7WSLRAU.js +49 -0
  178. package/dist/chunk-T7WSLRAU.js.map +1 -0
  179. package/dist/{chunk-WPLVTJ5D.js → chunk-TAKWLZZX.js} +285 -63
  180. package/dist/chunk-TAKWLZZX.js.map +1 -0
  181. package/dist/chunk-THNJ3IKU.js +17 -0
  182. package/dist/chunk-THNJ3IKU.js.map +1 -0
  183. package/dist/{chunk-XJFLDA7A.js → chunk-TMBXVJKT.js} +9 -6
  184. package/dist/chunk-TMBXVJKT.js.map +1 -0
  185. package/dist/chunk-TWKKOM55.js +54 -0
  186. package/dist/chunk-TWKKOM55.js.map +1 -0
  187. package/dist/chunk-U3WZCU7E.js +14 -0
  188. package/dist/chunk-U3WZCU7E.js.map +1 -0
  189. package/dist/{chunk-Z6FNBOTC.js → chunk-UF362QVH.js} +15 -17
  190. package/dist/chunk-UF362QVH.js.map +1 -0
  191. package/dist/chunk-UN4FVIBH.js +135 -0
  192. package/dist/chunk-UN4FVIBH.js.map +1 -0
  193. package/dist/chunk-VEAVKDDB.js +29 -0
  194. package/dist/chunk-VEAVKDDB.js.map +1 -0
  195. package/dist/chunk-VEPTFUJY.js +29 -0
  196. package/dist/chunk-VEPTFUJY.js.map +1 -0
  197. package/dist/chunk-VJV7GKQK.js +662 -0
  198. package/dist/chunk-VJV7GKQK.js.map +1 -0
  199. package/dist/{chunk-2QR2PQTT.js → chunk-VQNJ7UZL.js} +5 -3
  200. package/dist/chunk-VQNJ7UZL.js.map +1 -0
  201. package/dist/chunk-VQRAIPYF.js +50 -0
  202. package/dist/chunk-VQRAIPYF.js.map +1 -0
  203. package/dist/{chunk-DFMLEQZB.js → chunk-VRIYFLBA.js} +5 -10
  204. package/dist/chunk-VRIYFLBA.js.map +1 -0
  205. package/dist/chunk-VWM3DAVB.js +265 -0
  206. package/dist/chunk-VWM3DAVB.js.map +1 -0
  207. package/dist/{chunk-NONAAENK.js → chunk-VWRRVE6D.js} +11 -4
  208. package/dist/chunk-VWRRVE6D.js.map +1 -0
  209. package/dist/chunk-VYYM3MEN.js +98 -0
  210. package/dist/chunk-VYYM3MEN.js.map +1 -0
  211. package/dist/chunk-WBJIQSLL.js +167 -0
  212. package/dist/chunk-WBJIQSLL.js.map +1 -0
  213. package/dist/chunk-WIGQB62E.js +164 -0
  214. package/dist/chunk-WIGQB62E.js.map +1 -0
  215. package/dist/{chunk-EMIGCR7X.js → chunk-WXSYDNBT.js} +2 -2
  216. package/dist/chunk-WXSYDNBT.js.map +1 -0
  217. package/dist/chunk-WZSCE6RM.js +466 -0
  218. package/dist/chunk-WZSCE6RM.js.map +1 -0
  219. package/dist/chunk-XGDAPN6M.js +255 -0
  220. package/dist/chunk-XGDAPN6M.js.map +1 -0
  221. package/dist/{chunk-QODLLGQ7.js → chunk-XH7XP3OL.js} +372 -37
  222. package/dist/chunk-XH7XP3OL.js.map +1 -0
  223. package/dist/chunk-XREOISSI.js +40 -0
  224. package/dist/chunk-XREOISSI.js.map +1 -0
  225. package/dist/chunk-XUBPSPKD.js +164 -0
  226. package/dist/chunk-XUBPSPKD.js.map +1 -0
  227. package/dist/chunk-Y3A5CB5G.js +247 -0
  228. package/dist/chunk-Y3A5CB5G.js.map +1 -0
  229. package/dist/{chunk-I5FOWO4J.js → chunk-YCXCR7VG.js} +52 -73
  230. package/dist/chunk-YCXCR7VG.js.map +1 -0
  231. package/dist/{chunk-A3JMGXPG.js → chunk-YMUGBZN2.js} +2 -2
  232. package/dist/chunk-YMUGBZN2.js.map +1 -0
  233. package/dist/chunk-YMVQD5Q5.js +453 -0
  234. package/dist/chunk-YMVQD5Q5.js.map +1 -0
  235. package/dist/chunk-YN5IAHN6.js +32 -0
  236. package/dist/chunk-YN5IAHN6.js.map +1 -0
  237. package/dist/{chunk-FZU343FL.js → chunk-ZJADGNYF.js} +2 -2
  238. package/dist/chunk-ZJADGNYF.js.map +1 -0
  239. package/dist/chunk-ZYJ55N7N.js +86 -0
  240. package/dist/chunk-ZYJ55N7N.js.map +1 -0
  241. package/dist/classified/index.d.ts +16 -0
  242. package/dist/classified/index.js +40 -0
  243. package/dist/classified-marker-H6YSHYNK.js +24 -0
  244. package/dist/classified-marker-H6YSHYNK.js.map +1 -0
  245. package/dist/collection-facade-LVD22JLM.js +39 -0
  246. package/dist/computed-EXDMQODG.js +11 -0
  247. package/dist/consent/index.d.ts +4 -7
  248. package/dist/consent/index.js +13 -5
  249. package/dist/consent/index.js.map +1 -1
  250. package/dist/crdt/index.d.ts +5 -2
  251. package/dist/crdt/index.js +3 -2
  252. package/dist/crdt/index.js.map +1 -1
  253. package/dist/dead-filter-HQIE2YG7.js +28 -0
  254. package/dist/dead-filter-HQIE2YG7.js.map +1 -0
  255. package/dist/decrypt-partition-IHtxEnTi.d.ts +21 -0
  256. package/dist/delegation-BJP73GAP.js +25 -0
  257. package/dist/derivations/index.d.ts +6 -9
  258. package/dist/derivations/index.js +18 -6
  259. package/dist/derive-BME7HDWO.js +21 -0
  260. package/dist/{dev-unlock-B4kDxep_.d.ts → dev-unlock-Bmm2pgJ0.d.ts} +1 -1
  261. package/dist/discriminant-BN9REW3o.d.ts +60 -0
  262. package/dist/enclave-NHORSWSF.js +125 -0
  263. package/dist/executor-FE6X4LFX.js +9 -0
  264. package/dist/executor-KSHKRJXP.js +25 -0
  265. package/dist/executor-ZHTJJICG.js +9 -0
  266. package/dist/export-accessible-DACHM5VT.js +23 -0
  267. package/dist/extract-partition-RNENZZ4T.js +36 -0
  268. package/dist/fanout-sidecar-OFWN3NM7.js +74 -0
  269. package/dist/fanout-sidecar-OFWN3NM7.js.map +1 -0
  270. package/dist/fence-watcher-DHQ775JB.js +69 -0
  271. package/dist/fence-watcher-DHQ775JB.js.map +1 -0
  272. package/dist/find-BNGBJNKP.js +11 -0
  273. package/dist/forget/index.d.ts +36 -0
  274. package/dist/forget/index.js +25 -0
  275. package/dist/forget/index.js.map +1 -0
  276. package/dist/guards/index.d.ts +12 -9
  277. package/dist/guards/index.js +12 -5
  278. package/dist/{hash-DdpVypUp.d.cts → hash-DAJjMsCE.d.ts} +10 -1
  279. package/dist/history/index.d.ts +5 -8
  280. package/dist/history/index.js +25 -12
  281. package/dist/history/index.js.map +1 -1
  282. package/dist/i18n/index.d.ts +25 -8
  283. package/dist/i18n/index.js +137 -29
  284. package/dist/i18n/index.js.map +1 -1
  285. package/dist/in/index.d.ts +4 -0
  286. package/dist/in/index.js +1 -0
  287. package/dist/in/index.js.map +1 -0
  288. package/dist/index-B9QdHytu.d.ts +123 -0
  289. package/dist/index-DjWbxsjb.d.ts +23579 -0
  290. package/dist/index-qwuNvO2B.d.ts +144 -0
  291. package/dist/index.d.ts +1179 -449
  292. package/dist/index.js +2524 -312
  293. package/dist/index.js.map +1 -1
  294. package/dist/indexing/index.d.ts +5 -3
  295. package/dist/indexing/index.js +6 -5
  296. package/dist/indexing/index.js.map +1 -1
  297. package/dist/issue-NDI4CVZU.js +19 -0
  298. package/dist/issue-NDI4CVZU.js.map +1 -0
  299. package/dist/json-schema-I22JCYCG.js +44 -0
  300. package/dist/json-schema-I22JCYCG.js.map +1 -0
  301. package/dist/lazy/index.d.ts +20 -0
  302. package/dist/lazy/index.js +12 -0
  303. package/dist/lazy/index.js.map +1 -0
  304. package/dist/ledger-6NDS2EO4.js +42 -0
  305. package/dist/ledger-6NDS2EO4.js.map +1 -0
  306. package/dist/liberate-HN3RIGIP.js +24 -0
  307. package/dist/liberate-HN3RIGIP.js.map +1 -0
  308. package/dist/link-set-SJB2MVJV.js +31 -0
  309. package/dist/link-set-SJB2MVJV.js.map +1 -0
  310. package/dist/materialized-views/index.d.ts +23 -20
  311. package/dist/materialized-views/index.js +26 -12
  312. package/dist/mime-magic-bBj5OgUC.d.ts +103 -0
  313. package/dist/noydb-BWF6EPIR.js +66 -0
  314. package/dist/noydb-BWF6EPIR.js.map +1 -0
  315. package/dist/on/index.d.ts +4 -0
  316. package/dist/on/index.js +17 -0
  317. package/dist/on/index.js.map +1 -0
  318. package/dist/overlay-views/index.d.ts +26 -11
  319. package/dist/overlay-views/index.js +7 -6
  320. package/dist/periods/index.d.ts +4 -7
  321. package/dist/periods/index.js +27 -9
  322. package/dist/pod/index.d.ts +62 -0
  323. package/dist/pod/index.js +67 -0
  324. package/dist/pod/index.js.map +1 -0
  325. package/dist/policy-WGNAG5H6.js +41 -0
  326. package/dist/policy-WGNAG5H6.js.map +1 -0
  327. package/dist/portability/index.d.ts +19 -0
  328. package/dist/portability/index.js +43 -0
  329. package/dist/portability/index.js.map +1 -0
  330. package/dist/post-register-CWKBQRC7.js +55 -0
  331. package/dist/post-register-CWKBQRC7.js.map +1 -0
  332. package/dist/{public-envelope-BW6OXORV.js → public-envelope-EJLVIFX7.js} +6 -5
  333. package/dist/public-envelope-EJLVIFX7.js.map +1 -0
  334. package/dist/query/index.d.ts +4 -3
  335. package/dist/query/index.js +24 -13
  336. package/dist/read-only-facade-CHCKSEPD.js +8 -0
  337. package/dist/read-only-facade-CHCKSEPD.js.map +1 -0
  338. package/dist/register-SBIX7TVV.js +23 -0
  339. package/dist/register-SBIX7TVV.js.map +1 -0
  340. package/dist/registry-3EQG6OOE.js +18 -0
  341. package/dist/registry-3EQG6OOE.js.map +1 -0
  342. package/dist/registry-CA327ACV.js +9 -0
  343. package/dist/registry-CA327ACV.js.map +1 -0
  344. package/dist/registry-E7OXOTSV.js +19 -0
  345. package/dist/registry-E7OXOTSV.js.map +1 -0
  346. package/dist/registry-VW6P6A3J.js +8 -0
  347. package/dist/registry-VW6P6A3J.js.map +1 -0
  348. package/dist/request-withdrawal-KAH2AAXC.js +31 -0
  349. package/dist/request-withdrawal-KAH2AAXC.js.map +1 -0
  350. package/dist/reveal-R3JLHMUF.js +38 -0
  351. package/dist/reveal-R3JLHMUF.js.map +1 -0
  352. package/dist/revoke-IXLOJ3IH.js +24 -0
  353. package/dist/revoke-IXLOJ3IH.js.map +1 -0
  354. package/dist/satellites/index.d.ts +4 -0
  355. package/dist/satellites/index.js +8 -0
  356. package/dist/satellites/index.js.map +1 -0
  357. package/dist/sealed-record/index.d.ts +68 -0
  358. package/dist/sealed-record/index.js +71 -0
  359. package/dist/sealed-record/index.js.map +1 -0
  360. package/dist/session/index.d.ts +5 -8
  361. package/dist/session/index.js +13 -5
  362. package/dist/session/index.js.map +1 -1
  363. package/dist/shadow/index.d.ts +4 -7
  364. package/dist/shadow/index.js +4 -3
  365. package/dist/shadow/index.js.map +1 -1
  366. package/dist/signer-Y46N2GJ3.js +25 -0
  367. package/dist/signer-Y46N2GJ3.js.map +1 -0
  368. package/dist/snapshots/index.d.ts +5 -8
  369. package/dist/snapshots/index.js +19 -11
  370. package/dist/snapshots/index.js.map +1 -1
  371. package/dist/{stale-6ZDBTQT7.js → stale-Z7IW6RIL.js} +3 -2
  372. package/dist/stale-Z7IW6RIL.js.map +1 -0
  373. package/dist/storage-ADNP2UWI.js +23 -0
  374. package/dist/storage-ADNP2UWI.js.map +1 -0
  375. package/dist/store-coordination-provider-DTDMI6VL.js +142 -0
  376. package/dist/store-coordination-provider-DTDMI6VL.js.map +1 -0
  377. package/dist/subject-index-CyOgGMJL.d.ts +380 -0
  378. package/dist/sync/index.d.ts +3 -6
  379. package/dist/sync/index.js +13 -6
  380. package/dist/sync/index.js.map +1 -1
  381. package/dist/team/index.d.ts +46 -10
  382. package/dist/team/index.js +35 -18
  383. package/dist/tiers/index.d.ts +4 -0
  384. package/dist/tiers/index.js +39 -0
  385. package/dist/tiers/index.js.map +1 -0
  386. package/dist/to/index.d.ts +4 -0
  387. package/dist/to/index.js +16 -0
  388. package/dist/to/index.js.map +1 -0
  389. package/dist/transition-guard-DI-krBsZ.d.ts +165 -0
  390. package/dist/tx/index.d.ts +22 -9
  391. package/dist/tx/index.js +13 -8
  392. package/dist/tx/index.js.map +1 -1
  393. package/dist/ui/index.d.ts +4 -0
  394. package/dist/ui/index.js +1 -0
  395. package/dist/ui/index.js.map +1 -0
  396. package/dist/ulid-DRH25k3y.d.ts +66 -0
  397. package/dist/ulid-PTAIMDG4.js +10 -0
  398. package/dist/ulid-PTAIMDG4.js.map +1 -0
  399. package/dist/util/index.d.ts +2 -0
  400. package/dist/util/index.js +7 -2
  401. package/dist/util/index.js.map +1 -1
  402. package/dist/validators-BUcli5Nh.d.ts +101 -0
  403. package/dist/vault-diff-Z2DUayMe.d.ts +147 -0
  404. package/dist/verify-JPF2YR5E.js +139 -0
  405. package/dist/verify-JPF2YR5E.js.map +1 -0
  406. package/dist/walk-XYA2O3LW.js +241 -0
  407. package/dist/walk-XYA2O3LW.js.map +1 -0
  408. package/dist/with/index.d.ts +37 -0
  409. package/dist/with/index.js +31 -0
  410. package/dist/with/index.js.map +1 -0
  411. package/dist/{with-materialized-view-BLkQxoQN.d.ts → with-materialized-view-BUmzlXue.d.ts} +1 -1
  412. package/dist/{with-overlayed-view-CRsSEwHR.d.ts → with-overlayed-view-m4FaXXTO.d.ts} +2 -3
  413. package/dist/with-rollup-DEKGI9vb.d.ts +47 -0
  414. package/dist/withdraw-accessible-WLV4MTEN.js +28 -0
  415. package/dist/withdraw-accessible-WLV4MTEN.js.map +1 -0
  416. package/dist/zod-HAJM7LMS.js +14763 -0
  417. package/dist/zod-HAJM7LMS.js.map +1 -0
  418. package/package.json +122 -202
  419. package/dist/aggregate/index.cjs.map +0 -1
  420. package/dist/aggregate/index.d.cts +0 -38
  421. package/dist/attestation/index.cjs +0 -305
  422. package/dist/attestation/index.cjs.map +0 -1
  423. package/dist/attestation/index.d.cts +0 -52
  424. package/dist/blobs/index.cjs +0 -1480
  425. package/dist/blobs/index.cjs.map +0 -1
  426. package/dist/blobs/index.d.cts +0 -46
  427. package/dist/bundle/index.cjs +0 -19264
  428. package/dist/bundle/index.cjs.map +0 -1
  429. package/dist/bundle/index.d.cts +0 -176
  430. package/dist/chunk-22DWZL57.js.map +0 -1
  431. package/dist/chunk-2GLDA55J.js.map +0 -1
  432. package/dist/chunk-2QR2PQTT.js.map +0 -1
  433. package/dist/chunk-2WUSG3IT.js.map +0 -1
  434. package/dist/chunk-3BFJOWSU.js.map +0 -1
  435. package/dist/chunk-3YPCK6JX.js.map +0 -1
  436. package/dist/chunk-53XBRIRT.js.map +0 -1
  437. package/dist/chunk-5T22KDPN.js.map +0 -1
  438. package/dist/chunk-5XHKQ56N.js +0 -340
  439. package/dist/chunk-5XHKQ56N.js.map +0 -1
  440. package/dist/chunk-6CME4UEK.js +0 -10329
  441. package/dist/chunk-6CME4UEK.js.map +0 -1
  442. package/dist/chunk-6STK5TQP.js +0 -139
  443. package/dist/chunk-6STK5TQP.js.map +0 -1
  444. package/dist/chunk-A3JMGXPG.js.map +0 -1
  445. package/dist/chunk-B6PB7JLN.js.map +0 -1
  446. package/dist/chunk-BVRYKATC.js.map +0 -1
  447. package/dist/chunk-DE6GKS6G.js +0 -79
  448. package/dist/chunk-DE6GKS6G.js.map +0 -1
  449. package/dist/chunk-DFMLEQZB.js.map +0 -1
  450. package/dist/chunk-DJHHA6XH.js.map +0 -1
  451. package/dist/chunk-DL3HWOQ5.js.map +0 -1
  452. package/dist/chunk-DONMZAD2.js.map +0 -1
  453. package/dist/chunk-EMIGCR7X.js.map +0 -1
  454. package/dist/chunk-F3GDRNUT.js.map +0 -1
  455. package/dist/chunk-FZU343FL.js.map +0 -1
  456. package/dist/chunk-H2X3ISXG.js.map +0 -1
  457. package/dist/chunk-HNRHLRDC.js.map +0 -1
  458. package/dist/chunk-I5FOWO4J.js.map +0 -1
  459. package/dist/chunk-J66GRPNH.js.map +0 -1
  460. package/dist/chunk-JWRVQKRZ.js.map +0 -1
  461. package/dist/chunk-K3DK3NU5.js.map +0 -1
  462. package/dist/chunk-ML236QKC.js.map +0 -1
  463. package/dist/chunk-NONAAENK.js.map +0 -1
  464. package/dist/chunk-O3VZPBZG.js.map +0 -1
  465. package/dist/chunk-OIF6LZUR.js.map +0 -1
  466. package/dist/chunk-OQ6PIGHA.js +0 -19
  467. package/dist/chunk-OQ6PIGHA.js.map +0 -1
  468. package/dist/chunk-PE2FR4J3.js.map +0 -1
  469. package/dist/chunk-PP6W64Y3.js.map +0 -1
  470. package/dist/chunk-PX35GA7L.js.map +0 -1
  471. package/dist/chunk-QEILDE6R.js +0 -793
  472. package/dist/chunk-QEILDE6R.js.map +0 -1
  473. package/dist/chunk-QODLLGQ7.js.map +0 -1
  474. package/dist/chunk-RAZ4OVLL.js +0 -51
  475. package/dist/chunk-RAZ4OVLL.js.map +0 -1
  476. package/dist/chunk-SYMWGEET.js.map +0 -1
  477. package/dist/chunk-T7JEBOGN.js.map +0 -1
  478. package/dist/chunk-TFBP23BX.js.map +0 -1
  479. package/dist/chunk-TV3YZ35S.js.map +0 -1
  480. package/dist/chunk-U26HQ6KJ.js.map +0 -1
  481. package/dist/chunk-UF3BUNQZ.js +0 -1
  482. package/dist/chunk-UMLVJTYV.js +0 -20
  483. package/dist/chunk-UMLVJTYV.js.map +0 -1
  484. package/dist/chunk-VTKGMEPP.js.map +0 -1
  485. package/dist/chunk-W6EQLGMB.js +0 -100
  486. package/dist/chunk-W6EQLGMB.js.map +0 -1
  487. package/dist/chunk-WIRRPTFH.js +0 -17
  488. package/dist/chunk-WIRRPTFH.js.map +0 -1
  489. package/dist/chunk-WPLVTJ5D.js.map +0 -1
  490. package/dist/chunk-XJFLDA7A.js.map +0 -1
  491. package/dist/chunk-Z6FNBOTC.js.map +0 -1
  492. package/dist/chunk-ZYWZWG6G.js.map +0 -1
  493. package/dist/consent/index.cjs +0 -204
  494. package/dist/consent/index.cjs.map +0 -1
  495. package/dist/consent/index.d.cts +0 -25
  496. package/dist/crdt/index.cjs +0 -152
  497. package/dist/crdt/index.cjs.map +0 -1
  498. package/dist/crdt/index.d.cts +0 -30
  499. package/dist/crypto-HTZ4FJOP.js +0 -44
  500. package/dist/delegation-RI54P6I5.js +0 -17
  501. package/dist/derivations/index.cjs +0 -351
  502. package/dist/derivations/index.cjs.map +0 -1
  503. package/dist/derivations/index.d.cts +0 -72
  504. package/dist/dev-unlock-BIoEFbwm.d.cts +0 -263
  505. package/dist/executor-5PNY7LGW.js +0 -8
  506. package/dist/executor-B4QIYGZX.js +0 -8
  507. package/dist/executor-BWXXDQ7K.js +0 -11
  508. package/dist/fanout-sidecar-OKPMMPLG.js +0 -51
  509. package/dist/fanout-sidecar-OKPMMPLG.js.map +0 -1
  510. package/dist/guards/index.cjs +0 -322
  511. package/dist/guards/index.cjs.map +0 -1
  512. package/dist/guards/index.d.cts +0 -31
  513. package/dist/hash-HJqD14vS.d.ts +0 -63
  514. package/dist/history/index.cjs +0 -1222
  515. package/dist/history/index.cjs.map +0 -1
  516. package/dist/history/index.d.cts +0 -63
  517. package/dist/i18n/index.cjs +0 -1100
  518. package/dist/i18n/index.cjs.map +0 -1
  519. package/dist/i18n/index.d.cts +0 -39
  520. package/dist/index-4fBVt8j9.d.cts +0 -2387
  521. package/dist/index-D8I_pyJD.d.ts +0 -2387
  522. package/dist/index.cjs +0 -24487
  523. package/dist/index.cjs.map +0 -1
  524. package/dist/index.d.cts +0 -776
  525. package/dist/indexing/index.cjs +0 -742
  526. package/dist/indexing/index.cjs.map +0 -1
  527. package/dist/indexing/index.d.cts +0 -36
  528. package/dist/issue-VGDPP4B5.js +0 -12
  529. package/dist/lazy-builder-7tIpFyWN.d.ts +0 -304
  530. package/dist/lazy-builder-wY4pMCEe.d.cts +0 -304
  531. package/dist/ledger-TMRZYNVJ.js +0 -33
  532. package/dist/materialized-views/index.cjs +0 -854
  533. package/dist/materialized-views/index.cjs.map +0 -1
  534. package/dist/materialized-views/index.d.cts +0 -186
  535. package/dist/mime-magic-CBBSOkjm.d.cts +0 -50
  536. package/dist/mime-magic-CBBSOkjm.d.ts +0 -50
  537. package/dist/noydb-G725ZSZG.js +0 -34
  538. package/dist/overlay-views/index.cjs +0 -359
  539. package/dist/overlay-views/index.cjs.map +0 -1
  540. package/dist/overlay-views/index.d.cts +0 -82
  541. package/dist/periods/index.cjs +0 -1041
  542. package/dist/periods/index.cjs.map +0 -1
  543. package/dist/periods/index.d.cts +0 -22
  544. package/dist/predicate-BSAGEyu5.d.cts +0 -209
  545. package/dist/predicate-BSAGEyu5.d.ts +0 -209
  546. package/dist/query/index.cjs +0 -2375
  547. package/dist/query/index.cjs.map +0 -1
  548. package/dist/query/index.d.cts +0 -3
  549. package/dist/read-only-facade-ITU6L7BL.js +0 -7
  550. package/dist/registry-3QP3YKQS.js +0 -8
  551. package/dist/registry-DKEXOJVO.js +0 -7
  552. package/dist/registry-OJIOSBV6.js +0 -10
  553. package/dist/registry-USRVT6YF.js +0 -8
  554. package/dist/revoke-JCC7N56X.js +0 -17
  555. package/dist/session/index.cjs +0 -495
  556. package/dist/session/index.cjs.map +0 -1
  557. package/dist/session/index.d.cts +0 -46
  558. package/dist/shadow/index.cjs +0 -133
  559. package/dist/shadow/index.cjs.map +0 -1
  560. package/dist/shadow/index.d.cts +0 -17
  561. package/dist/signer-72QAUSVW.js +0 -18
  562. package/dist/snapshots/index.cjs +0 -937
  563. package/dist/snapshots/index.cjs.map +0 -1
  564. package/dist/snapshots/index.d.cts +0 -28
  565. package/dist/store/index.cjs +0 -1083
  566. package/dist/store/index.cjs.map +0 -1
  567. package/dist/store/index.d.cts +0 -492
  568. package/dist/store/index.d.ts +0 -492
  569. package/dist/store/index.js +0 -37
  570. package/dist/strategy-BSxFXGzb.d.cts +0 -110
  571. package/dist/strategy-BSxFXGzb.d.ts +0 -110
  572. package/dist/strategy-DSTrsZ8t.d.cts +0 -601
  573. package/dist/strategy-DSTrsZ8t.d.ts +0 -601
  574. package/dist/sync/index.cjs +0 -1062
  575. package/dist/sync/index.cjs.map +0 -1
  576. package/dist/sync/index.d.cts +0 -43
  577. package/dist/team/index.cjs +0 -2798
  578. package/dist/team/index.cjs.map +0 -1
  579. package/dist/team/index.d.cts +0 -118
  580. package/dist/tx/index.cjs +0 -544
  581. package/dist/tx/index.cjs.map +0 -1
  582. package/dist/tx/index.d.cts +0 -21
  583. package/dist/types-Df28QFKb.d.ts +0 -12818
  584. package/dist/types-DyXYr8rE.d.cts +0 -12818
  585. package/dist/ulid-COREQ2RQ.js +0 -9
  586. package/dist/ulid-Drr7ykr6.d.cts +0 -603
  587. package/dist/util/index.cjs +0 -230
  588. package/dist/util/index.cjs.map +0 -1
  589. package/dist/util/index.d.cts +0 -77
  590. package/dist/with-derivation-DFnFByiQ.d.ts +0 -13
  591. package/dist/with-derivation-DU3Sjazm.d.cts +0 -13
  592. package/dist/with-guard-ByyxmEe7.d.cts +0 -18
  593. package/dist/with-guard-qube6BMI.d.ts +0 -18
  594. package/dist/with-materialized-view-BmEToIR1.d.cts +0 -27
  595. package/dist/with-overlayed-view-BMsQQbWm.d.cts +0 -13
  596. /package/dist/{chunk-UF3BUNQZ.js.map → api-TX2EX2FX.js.map} +0 -0
  597. /package/dist/{store → as}/index.js.map +0 -0
  598. /package/dist/{crypto-HTZ4FJOP.js.map → at/index.js.map} +0 -0
  599. /package/dist/{delegation-RI54P6I5.js.map → by/index.js.map} +0 -0
  600. /package/dist/{executor-5PNY7LGW.js.map → cargo/index.js.map} +0 -0
  601. /package/dist/{executor-B4QIYGZX.js.map → chunk-CHFZDSE4.js.map} +0 -0
  602. /package/dist/{executor-BWXXDQ7K.js.map → chunk-GHVIKOHT.js.map} +0 -0
  603. /package/dist/{issue-VGDPP4B5.js.map → chunk-PZ5AY32C.js.map} +0 -0
  604. /package/dist/{ledger-TMRZYNVJ.js.map → classified/index.js.map} +0 -0
  605. /package/dist/{noydb-G725ZSZG.js.map → collection-facade-LVD22JLM.js.map} +0 -0
  606. /package/dist/{public-envelope-BW6OXORV.js.map → computed-EXDMQODG.js.map} +0 -0
  607. /package/dist/{read-only-facade-ITU6L7BL.js.map → delegation-BJP73GAP.js.map} +0 -0
  608. /package/dist/{registry-3QP3YKQS.js.map → derive-BME7HDWO.js.map} +0 -0
  609. /package/dist/{registry-DKEXOJVO.js.map → enclave-NHORSWSF.js.map} +0 -0
  610. /package/dist/{registry-OJIOSBV6.js.map → executor-FE6X4LFX.js.map} +0 -0
  611. /package/dist/{registry-USRVT6YF.js.map → executor-KSHKRJXP.js.map} +0 -0
  612. /package/dist/{revoke-JCC7N56X.js.map → executor-ZHTJJICG.js.map} +0 -0
  613. /package/dist/{signer-72QAUSVW.js.map → export-accessible-DACHM5VT.js.map} +0 -0
  614. /package/dist/{stale-6ZDBTQT7.js.map → extract-partition-RNENZZ4T.js.map} +0 -0
  615. /package/dist/{ulid-COREQ2RQ.js.map → find-BNGBJNKP.js.map} +0 -0
@@ -0,0 +1,382 @@
1
+ import {
2
+ listUserEnvelopeIds,
3
+ loadUserEnvelope,
4
+ persistUserVisibility,
5
+ readUserVisibility,
6
+ saveUserEnvelope
7
+ } from "./chunk-OVYRLHPE.js";
8
+ import {
9
+ PolicyDeniedError
10
+ } from "./chunk-S7VFUQM2.js";
11
+
12
+ // src/with-party/directory/user-envelope/api.ts
13
+ var UserApi = class {
14
+ /** keyringId → set of listeners. Wildcard '*' fires on every change. */
15
+ listeners = /* @__PURE__ */ new Map();
16
+ adapter;
17
+ vaultName;
18
+ /** The writer's own keyringId. Frozen at construction time. */
19
+ writerKeyringId;
20
+ getDek;
21
+ /**
22
+ * Policy-gate validator. When omitted, gates are skipped — useful
23
+ * for low-level tests that exercise the storage layer directly.
24
+ * Production paths always wire the Noydb-backed implementation.
25
+ */
26
+ checkGate;
27
+ /**
28
+ * Noydb-backed `exportMyAccessibleData`, injected by the Vault
29
+ * (which holds the keyring + bundle machinery). Omitted in low-level tests.
30
+ */
31
+ exportAccessible;
32
+ /**
33
+ * Noydb-backed `unilateralWithdrawal`, injected by the Vault.
34
+ * Destructive — extract + dispose (delete | freeze). Omitted in low-level tests.
35
+ */
36
+ unilateralWithdraw;
37
+ /**
38
+ * Noydb-backed two-party withdrawal ceremony, injected by the
39
+ * Vault. requestWithdraw = requester side; the rest = owner side.
40
+ */
41
+ requestWithdraw;
42
+ listWithdrawals;
43
+ approveWithdraw;
44
+ rejectWithdraw;
45
+ constructor(deps) {
46
+ this.adapter = deps.adapter;
47
+ this.vaultName = deps.vaultName;
48
+ this.writerKeyringId = deps.writerKeyringId;
49
+ this.getDek = deps.getDek;
50
+ this.checkGate = deps.checkGate;
51
+ this.exportAccessible = deps.exportAccessible;
52
+ this.unilateralWithdraw = deps.unilateralWithdraw;
53
+ this.requestWithdraw = deps.requestWithdraw;
54
+ this.listWithdrawals = deps.listWithdrawals;
55
+ this.approveWithdraw = deps.approveWithdraw;
56
+ this.rejectWithdraw = deps.rejectWithdraw;
57
+ }
58
+ /**
59
+ * File a two-party withdrawal request for the caller's accessible
60
+ * scope. Non-destructive (writes a pending request); an owner later approves
61
+ * or rejects. This is the path for read-only roles (`client`/`viewer`) that
62
+ * cannot self-serve a destructive `unilateralWithdrawal`. Gated by
63
+ * `user-request-withdrawal` (enabled by default).
64
+ */
65
+ async requestWithdrawal(opts = {}) {
66
+ if (this.checkGate) await this.checkGate("user-request-withdrawal");
67
+ if (!this.requestWithdraw) {
68
+ throw new Error("requestWithdrawal requires a Noydb-backed vault (not a bare UserApi)");
69
+ }
70
+ return this.requestWithdraw(opts);
71
+ }
72
+ /** Owner side: list filed withdrawal requests (optionally by status). */
73
+ async listWithdrawalRequests(opts = {}) {
74
+ if (!this.listWithdrawals) {
75
+ throw new Error("listWithdrawalRequests requires a Noydb-backed vault (not a bare UserApi)");
76
+ }
77
+ return this.listWithdrawals(opts);
78
+ }
79
+ /**
80
+ * Owner side: approve a pending request. Extracts the requester's
81
+ * recorded scope under firm authority, disposes of the source per the
82
+ * request's disposition, and returns the re-keyed bundle to hand back. Gated
83
+ * by `approve-user-withdrawal` (tier-2 default) + owner/admin role.
84
+ */
85
+ async approveWithdrawal(requestId, opts = {}) {
86
+ if (this.checkGate) await this.checkGate("approve-user-withdrawal");
87
+ if (!this.approveWithdraw) {
88
+ throw new Error("approveWithdrawal requires a Noydb-backed vault (not a bare UserApi)");
89
+ }
90
+ return this.approveWithdraw(requestId, opts);
91
+ }
92
+ /** Owner side: reject a pending request (no data is touched). */
93
+ async rejectWithdrawal(requestId, opts = {}) {
94
+ if (this.checkGate) await this.checkGate("approve-user-withdrawal");
95
+ if (!this.rejectWithdraw) {
96
+ throw new Error("rejectWithdrawal requires a Noydb-backed vault (not a bare UserApi)");
97
+ }
98
+ return this.rejectWithdraw(requestId, opts);
99
+ }
100
+ /**
101
+ * Single-party withdrawal: export the caller's accessible scope
102
+ * (re-keyed) and dispose of the source (`delete` or `freeze`). Gated by the
103
+ * fail-closed built-in `client-unilateral-withdraw` policy — undefined or
104
+ * disabled → throws (use `requestWithdrawal`). The firm enables it at vault
105
+ * creation.
106
+ */
107
+ async unilateralWithdrawal(opts) {
108
+ if (this.checkGate) await this.checkGate("client-unilateral-withdraw");
109
+ if (!this.unilateralWithdraw) {
110
+ throw new Error("unilateralWithdrawal requires a Noydb-backed vault (not a bare UserApi)");
111
+ }
112
+ return this.unilateralWithdraw(opts);
113
+ }
114
+ /**
115
+ * Export the calling user's accessible scope as a portable, re-keyed
116
+ * `.noydb` bundle. Non-destructive and **always allowed** (data sovereignty
117
+ * by construction) but audited. Scope = the caller's DEK access set.
118
+ */
119
+ async exportMyAccessibleData(opts = {}) {
120
+ if (!this.exportAccessible) {
121
+ throw new Error("exportMyAccessibleData requires a Noydb-backed vault (not a bare UserApi)");
122
+ }
123
+ return this.exportAccessible(opts);
124
+ }
125
+ // ─── Write-self ──────────────────────────────────────────────────────
126
+ /** Read the writer's own envelope. Returns null if never written. */
127
+ async me() {
128
+ const dek = await this.getDek();
129
+ return loadUserEnvelope(this.adapter, this.vaultName, this.writerKeyringId, dek);
130
+ }
131
+ /**
132
+ * Deep-merge a partial patch into the writer's own envelope. Creates
133
+ * the envelope on first call. Optimistic-concurrency safe — a stale
134
+ * `_v` (parallel writer on another device) throws `ConflictError`.
135
+ *
136
+ * Patch semantics:
137
+ * - `undefined` (or omitted key) — skip; existing value preserved
138
+ * - `null` — delete the field from the merged result
139
+ * - any other value — overwrite (deep-merge for plain objects,
140
+ * replace for primitives / arrays)
141
+ *
142
+ * To clear a field, pass `null` rather than `undefined`. Callers
143
+ * with shape `T = string | null` where `null` is a meaningful value
144
+ * should use `setMe` for that specific field instead — `null` here
145
+ * always means delete.
146
+ *
147
+ * Gated by the `edit-own-profile` policy gate (default `minTier: 3`).
148
+ * Pass `presented` to satisfy tightened policies that require a
149
+ * factor proof (e.g. STRICT_POLICY's TOTP requirement).
150
+ */
151
+ async updateMe(patch, presented) {
152
+ if (this.checkGate) await this.checkGate("edit-own-profile", presented);
153
+ const dek = await this.getDek();
154
+ const current = await loadUserEnvelope(
155
+ this.adapter,
156
+ this.vaultName,
157
+ this.writerKeyringId,
158
+ dek
159
+ );
160
+ const merged = current ? deepMerge(current.data, patch) : patch;
161
+ const written = await saveUserEnvelope(
162
+ this.adapter,
163
+ this.vaultName,
164
+ this.writerKeyringId,
165
+ merged,
166
+ dek,
167
+ current?._v ?? 0
168
+ );
169
+ this.fireChange(this.writerKeyringId, written);
170
+ return written;
171
+ }
172
+ /**
173
+ * Replace the writer's own envelope with `payload`. Use sparingly —
174
+ * `updateMe` is the canonical mutation. No `expectedVersion` check;
175
+ * callers explicitly take last-write-wins semantics.
176
+ *
177
+ * Gated by `edit-own-profile`. See `updateMe` for `presented` usage.
178
+ */
179
+ async setMe(payload, presented) {
180
+ if (this.checkGate) await this.checkGate("edit-own-profile", presented);
181
+ const dek = await this.getDek();
182
+ const written = await saveUserEnvelope(
183
+ this.adapter,
184
+ this.vaultName,
185
+ this.writerKeyringId,
186
+ payload,
187
+ dek
188
+ );
189
+ this.fireChange(this.writerKeyringId, written);
190
+ return written;
191
+ }
192
+ // ─── Visibility ──────────────────────────────────────────────────────
193
+ /**
194
+ * Read the current user's visibility flag from
195
+ * `_meta/visibility/<keyringId>`. Returns `{ hidden: false }` when no
196
+ * document has been persisted (the default-visible case).
197
+ */
198
+ async getMyVisibility() {
199
+ const persisted = await readUserVisibility(this.adapter, this.vaultName, this.writerKeyringId);
200
+ return persisted ?? { hidden: false };
201
+ }
202
+ /**
203
+ * Update the current user's visibility in the team directory.
204
+ *
205
+ * - `hidden: true` — opt out of the default `listUsersWithEnvelopes`
206
+ * listing. `owner`/`admin` callers can still see the user by passing
207
+ * `{ includeHidden: true }`.
208
+ * - `hidden: false` — opt back in.
209
+ *
210
+ * Own-only by construction: the keyringId argument doesn't exist on
211
+ * this method, so no caller can hide or unhide another principal.
212
+ *
213
+ * Honest caveat: this is a UX flag, not a privacy guarantee. The
214
+ * envelope ciphertext at `_users/<keyringId>` and the keyring file at
215
+ * `_keyring/<userId>` are both still observable to anyone with direct
216
+ * store read access. See `https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/user-envelope.md` →
217
+ * "Directory visibility".
218
+ */
219
+ async setMyVisibility(visibility) {
220
+ await persistUserVisibility(
221
+ this.adapter,
222
+ this.vaultName,
223
+ this.writerKeyringId,
224
+ { hidden: visibility.hidden }
225
+ );
226
+ }
227
+ // ─── Read-anyone ─────────────────────────────────────────────────────
228
+ /**
229
+ * Read another principal's envelope by their keyringId. Returns null
230
+ * if the principal exists but has no envelope yet, or if the
231
+ * keyringId does not exist at all.
232
+ *
233
+ * Gated by `view-team-profiles` (default `minTier: 2`) — but ONLY for
234
+ * cross-principal reads. Reading your own envelope (`keyringId ===
235
+ * self`) is never gated; that's just `me()` written long-form.
236
+ */
237
+ async get(keyringId, presented) {
238
+ if (this.checkGate && keyringId !== this.writerKeyringId) {
239
+ await this.checkGate("view-team-profiles", presented);
240
+ }
241
+ const dek = await this.getDek();
242
+ return loadUserEnvelope(this.adapter, this.vaultName, keyringId, dek);
243
+ }
244
+ /**
245
+ * Read every persisted envelope in the vault. Order is store-defined.
246
+ *
247
+ * Gated by `view-team-profiles`. Default policy (`minTier: 2`) lets
248
+ * any authenticated session read all envelopes. Two privacy-strict
249
+ * opt-outs:
250
+ *
251
+ * - `view-team-profiles.enabled: false` → list() returns only the
252
+ * caller's own envelope (silent self-fallback, no thrown error).
253
+ * - `view-team-profiles.minTier: 1` + insufficient tier → throws
254
+ * `PolicyDeniedError` with `reason: 'insufficient-tier'`. The
255
+ * caller is expected to elevate, not silently degrade.
256
+ *
257
+ * The asymmetry is deliberate: `enabled: false` is a deliberate
258
+ * design choice ("nobody sees teammate profiles in this app");
259
+ * `insufficient-tier` is "you need to authenticate further". Different
260
+ * UX prompts for different intents.
261
+ */
262
+ async list(presented) {
263
+ if (this.checkGate) {
264
+ try {
265
+ await this.checkGate("view-team-profiles", presented);
266
+ } catch (err) {
267
+ if (err instanceof PolicyDeniedError && err.reason === "disabled") {
268
+ const me = await this.me();
269
+ return me ? [me] : [];
270
+ }
271
+ throw err;
272
+ }
273
+ }
274
+ const dek = await this.getDek();
275
+ const ids = await listUserEnvelopeIds(this.adapter, this.vaultName);
276
+ const envelopes = await Promise.all(
277
+ ids.map((id) => loadUserEnvelope(this.adapter, this.vaultName, id, dek))
278
+ );
279
+ return envelopes.filter((e) => e !== null);
280
+ }
281
+ // ─── Reactive ────────────────────────────────────────────────────────
282
+ /**
283
+ * Listen for changes to a specific keyringId's envelope. The callback
284
+ * fires synchronously after every successful local `updateMe` /
285
+ * `setMe` for that principal.
286
+ *
287
+ * Cross-instance changes (a teammate edits their profile on their
288
+ * device, the sync engine pulls the diff onto this device) will fire
289
+ * subscribers when the sync layer replays the write through this API.
290
+ * In v1, subscribers do NOT fire on raw store changes — wire your sync
291
+ * layer to call back through `vault.user.setMe` / `updateMe` if you
292
+ * need that.
293
+ *
294
+ * Pass keyringId `'*'` to fire on every change in the vault.
295
+ */
296
+ subscribe(keyringId, cb) {
297
+ let listeners = this.listeners.get(keyringId);
298
+ if (!listeners) {
299
+ listeners = /* @__PURE__ */ new Set();
300
+ this.listeners.set(keyringId, listeners);
301
+ }
302
+ const wrapped = cb;
303
+ listeners.add(wrapped);
304
+ return () => {
305
+ listeners?.delete(wrapped);
306
+ if (listeners && listeners.size === 0) {
307
+ this.listeners.delete(keyringId);
308
+ }
309
+ };
310
+ }
311
+ /**
312
+ * Reactive handle that caches the current value and re-reads on every
313
+ * change for the given keyringId. Convenient for framework bindings:
314
+ *
315
+ * const live = vault.user.live<UserShape>(vault.userId)
316
+ * live.subscribe(env => render(env?.data))
317
+ *
318
+ * Initial value is `null` until the first `current()` call materializes
319
+ * it via `vault.user.get()`. Call `stop()` when done to release the
320
+ * subscription.
321
+ */
322
+ live(keyringId) {
323
+ let value = null;
324
+ let primed = false;
325
+ const unsubscribe = this.subscribe(keyringId, (env) => {
326
+ value = env;
327
+ });
328
+ return {
329
+ current() {
330
+ if (!primed) {
331
+ primed = true;
332
+ }
333
+ return value;
334
+ },
335
+ subscribe: (cb) => this.subscribe(keyringId, cb),
336
+ stop: unsubscribe
337
+ };
338
+ }
339
+ // ─── Internal: change emission ───────────────────────────────────────
340
+ fireChange(keyringId, env) {
341
+ const targeted = this.listeners.get(keyringId);
342
+ if (targeted) for (const l of targeted) l(env);
343
+ const wildcard = this.listeners.get("*");
344
+ if (wildcard) for (const l of wildcard) l(env);
345
+ }
346
+ };
347
+ var createUserApi = (deps) => new UserApi(deps);
348
+ function deepMerge(source, patch) {
349
+ if (!isPlainObject(source) || !isPlainObject(patch)) {
350
+ return patch;
351
+ }
352
+ const out = { ...source };
353
+ for (const [key, patchVal] of Object.entries(patch)) {
354
+ if (patchVal === void 0) {
355
+ continue;
356
+ }
357
+ if (patchVal === null) {
358
+ delete out[key];
359
+ continue;
360
+ }
361
+ const sourceVal = source[key];
362
+ if (isPlainObject(patchVal)) {
363
+ const recurseSource = isPlainObject(sourceVal) ? sourceVal : {};
364
+ out[key] = deepMerge(recurseSource, patchVal);
365
+ } else {
366
+ out[key] = patchVal;
367
+ }
368
+ }
369
+ return out;
370
+ }
371
+ function isPlainObject(x) {
372
+ if (x === null || typeof x !== "object") return false;
373
+ if (Array.isArray(x)) return false;
374
+ const proto = Object.getPrototypeOf(x);
375
+ return proto === Object.prototype || proto === null;
376
+ }
377
+
378
+ export {
379
+ UserApi,
380
+ createUserApi
381
+ };
382
+ //# sourceMappingURL=chunk-BKARNZJN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-party/directory/user-envelope/api.ts"],"sourcesContent":["/**\n * Public `vault.user.*` API surface.\n *\n * Three families:\n * - Write-self: `me` / `updateMe` / `setMe` — always target the writer's\n * own keyringId. **Own-only write rule** is structural — no method\n * exists to write someone else's envelope.\n * - Read-anyone: `get` / `list` — read other principals' envelopes\n * (subject to `view-team-profiles` policy gate).\n * - Reactive: `subscribe` / `live` — in-process event emission on local\n * writes. Cross-instance updates land via the team/sync engine and\n * surface to subscribers when the sync diff replays through this API.\n *\n * @see docs/superpowers/specs/2026-05-05-user-envelope-design.md\n *\n * @module\n */\nimport { PolicyDeniedError } from '../../../kernel/errors.js'\nimport {\n loadUserEnvelope,\n saveUserEnvelope,\n listUserEnvelopeIds,\n} from './storage.js'\nimport type {\n UserEnvelope,\n DeepPartialOrNull,\n Unsubscribe,\n UserEnvelopePresented,\n LiveUserEnvelope,\n VaultUserApi,\n UserApiDeps,\n UserApiFactory,\n} from '../../../kernel/types.js'\nimport {\n persistUserVisibility,\n readUserVisibility,\n} from '../visibility.js'\nimport type { UserVisibility } from '../types.js'\nimport type { ExportAccessibleOptions } from '../../../with-audit/portability/export-accessible.js'\nimport type { WithdrawAccessibleOptions, WithdrawResult } from '../../../with-audit/portability/withdraw-accessible.js'\nimport type {\n RequestWithdrawalOptions,\n RequestWithdrawalResult,\n WithdrawalRequest,\n WithdrawalRequestStatus,\n ApproveWithdrawalOptions,\n RejectWithdrawalOptions,\n} from '../../../with-audit/portability/request-withdrawal.js'\n\ninterface ChangeListener<T = unknown> {\n (env: UserEnvelope<T> | null): void\n}\n\n/**\n * Implementation behind `vault.user`. Constructed once per Vault via\n * {@link createUserApi}, holds the writer's keyringId in closure so\n * `updateMe`/`setMe` cannot target any other principal — the own-only\n * rule is enforced at the type level (no `set(otherKeyringId, …)`\n * method) AND at runtime (the keyringId argument simply doesn't exist\n * on the write path).\n */\nexport class UserApi implements VaultUserApi {\n /** keyringId → set of listeners. Wildcard '*' fires on every change. */\n private readonly listeners = new Map<string, Set<ChangeListener>>()\n\n private readonly adapter: UserApiDeps['adapter']\n private readonly vaultName: UserApiDeps['vaultName']\n /** The writer's own keyringId. Frozen at construction time. */\n private readonly writerKeyringId: UserApiDeps['writerKeyringId']\n private readonly getDek: UserApiDeps['getDek']\n /**\n * Policy-gate validator. When omitted, gates are skipped — useful\n * for low-level tests that exercise the storage layer directly.\n * Production paths always wire the Noydb-backed implementation.\n */\n private readonly checkGate?: UserApiDeps['checkGate']\n /**\n * Noydb-backed `exportMyAccessibleData`, injected by the Vault\n * (which holds the keyring + bundle machinery). Omitted in low-level tests.\n */\n private readonly exportAccessible?: UserApiDeps['exportAccessible']\n /**\n * Noydb-backed `unilateralWithdrawal`, injected by the Vault.\n * Destructive — extract + dispose (delete | freeze). Omitted in low-level tests.\n */\n private readonly unilateralWithdraw?: UserApiDeps['unilateralWithdraw']\n /**\n * Noydb-backed two-party withdrawal ceremony, injected by the\n * Vault. requestWithdraw = requester side; the rest = owner side.\n */\n private readonly requestWithdraw?: UserApiDeps['requestWithdraw']\n private readonly listWithdrawals?: UserApiDeps['listWithdrawals']\n private readonly approveWithdraw?: UserApiDeps['approveWithdraw']\n private readonly rejectWithdraw?: UserApiDeps['rejectWithdraw']\n\n constructor(deps: UserApiDeps) {\n this.adapter = deps.adapter\n this.vaultName = deps.vaultName\n this.writerKeyringId = deps.writerKeyringId\n this.getDek = deps.getDek\n this.checkGate = deps.checkGate\n this.exportAccessible = deps.exportAccessible\n this.unilateralWithdraw = deps.unilateralWithdraw\n this.requestWithdraw = deps.requestWithdraw\n this.listWithdrawals = deps.listWithdrawals\n this.approveWithdraw = deps.approveWithdraw\n this.rejectWithdraw = deps.rejectWithdraw\n }\n\n /**\n * File a two-party withdrawal request for the caller's accessible\n * scope. Non-destructive (writes a pending request); an owner later approves\n * or rejects. This is the path for read-only roles (`client`/`viewer`) that\n * cannot self-serve a destructive `unilateralWithdrawal`. Gated by\n * `user-request-withdrawal` (enabled by default).\n */\n async requestWithdrawal(opts: RequestWithdrawalOptions = {}): Promise<RequestWithdrawalResult> {\n if (this.checkGate) await this.checkGate('user-request-withdrawal')\n if (!this.requestWithdraw) {\n throw new Error('requestWithdrawal requires a Noydb-backed vault (not a bare UserApi)')\n }\n return this.requestWithdraw(opts)\n }\n\n /** Owner side: list filed withdrawal requests (optionally by status). */\n async listWithdrawalRequests(opts: { status?: WithdrawalRequestStatus } = {}): Promise<WithdrawalRequest[]> {\n if (!this.listWithdrawals) {\n throw new Error('listWithdrawalRequests requires a Noydb-backed vault (not a bare UserApi)')\n }\n return this.listWithdrawals(opts)\n }\n\n /**\n * Owner side: approve a pending request. Extracts the requester's\n * recorded scope under firm authority, disposes of the source per the\n * request's disposition, and returns the re-keyed bundle to hand back. Gated\n * by `approve-user-withdrawal` (tier-2 default) + owner/admin role.\n */\n async approveWithdrawal(requestId: string, opts: ApproveWithdrawalOptions = {}): Promise<WithdrawResult> {\n if (this.checkGate) await this.checkGate('approve-user-withdrawal')\n if (!this.approveWithdraw) {\n throw new Error('approveWithdrawal requires a Noydb-backed vault (not a bare UserApi)')\n }\n return this.approveWithdraw(requestId, opts)\n }\n\n /** Owner side: reject a pending request (no data is touched). */\n async rejectWithdrawal(requestId: string, opts: RejectWithdrawalOptions = {}): Promise<WithdrawalRequest> {\n if (this.checkGate) await this.checkGate('approve-user-withdrawal')\n if (!this.rejectWithdraw) {\n throw new Error('rejectWithdrawal requires a Noydb-backed vault (not a bare UserApi)')\n }\n return this.rejectWithdraw(requestId, opts)\n }\n\n /**\n * Single-party withdrawal: export the caller's accessible scope\n * (re-keyed) and dispose of the source (`delete` or `freeze`). Gated by the\n * fail-closed built-in `client-unilateral-withdraw` policy — undefined or\n * disabled → throws (use `requestWithdrawal`). The firm enables it at vault\n * creation.\n */\n async unilateralWithdrawal(opts: WithdrawAccessibleOptions): Promise<WithdrawResult> {\n if (this.checkGate) await this.checkGate('client-unilateral-withdraw')\n if (!this.unilateralWithdraw) {\n throw new Error('unilateralWithdrawal requires a Noydb-backed vault (not a bare UserApi)')\n }\n return this.unilateralWithdraw(opts)\n }\n\n /**\n * Export the calling user's accessible scope as a portable, re-keyed\n * `.noydb` bundle. Non-destructive and **always allowed** (data sovereignty\n * by construction) but audited. Scope = the caller's DEK access set.\n */\n async exportMyAccessibleData(opts: ExportAccessibleOptions = {}): Promise<Uint8Array> {\n if (!this.exportAccessible) {\n throw new Error('exportMyAccessibleData requires a Noydb-backed vault (not a bare UserApi)')\n }\n return this.exportAccessible(opts)\n }\n\n // ─── Write-self ──────────────────────────────────────────────────────\n\n /** Read the writer's own envelope. Returns null if never written. */\n async me<T = unknown>(): Promise<UserEnvelope<T> | null> {\n const dek = await this.getDek()\n return loadUserEnvelope<T>(this.adapter, this.vaultName, this.writerKeyringId, dek)\n }\n\n /**\n * Deep-merge a partial patch into the writer's own envelope. Creates\n * the envelope on first call. Optimistic-concurrency safe — a stale\n * `_v` (parallel writer on another device) throws `ConflictError`.\n *\n * Patch semantics:\n * - `undefined` (or omitted key) — skip; existing value preserved\n * - `null` — delete the field from the merged result\n * - any other value — overwrite (deep-merge for plain objects,\n * replace for primitives / arrays)\n *\n * To clear a field, pass `null` rather than `undefined`. Callers\n * with shape `T = string | null` where `null` is a meaningful value\n * should use `setMe` for that specific field instead — `null` here\n * always means delete.\n *\n * Gated by the `edit-own-profile` policy gate (default `minTier: 3`).\n * Pass `presented` to satisfy tightened policies that require a\n * factor proof (e.g. STRICT_POLICY's TOTP requirement).\n */\n async updateMe<T extends object = Record<string, unknown>>(\n patch: DeepPartialOrNull<T>,\n presented?: UserEnvelopePresented,\n ): Promise<UserEnvelope<T>> {\n if (this.checkGate) await this.checkGate('edit-own-profile', presented)\n const dek = await this.getDek()\n const current = await loadUserEnvelope<T>(\n this.adapter,\n this.vaultName,\n this.writerKeyringId,\n dek,\n )\n const merged: T = current ? deepMerge(current.data, patch) : (patch as unknown as T)\n const written = await saveUserEnvelope<T>(\n this.adapter,\n this.vaultName,\n this.writerKeyringId,\n merged,\n dek,\n current?._v ?? 0,\n )\n this.fireChange(this.writerKeyringId, written)\n return written\n }\n\n /**\n * Replace the writer's own envelope with `payload`. Use sparingly —\n * `updateMe` is the canonical mutation. No `expectedVersion` check;\n * callers explicitly take last-write-wins semantics.\n *\n * Gated by `edit-own-profile`. See `updateMe` for `presented` usage.\n */\n async setMe<T = unknown>(\n payload: T,\n presented?: UserEnvelopePresented,\n ): Promise<UserEnvelope<T>> {\n if (this.checkGate) await this.checkGate('edit-own-profile', presented)\n const dek = await this.getDek()\n const written = await saveUserEnvelope<T>(\n this.adapter,\n this.vaultName,\n this.writerKeyringId,\n payload,\n dek,\n )\n this.fireChange(this.writerKeyringId, written)\n return written\n }\n\n // ─── Visibility ──────────────────────────────────────────────────────\n\n /**\n * Read the current user's visibility flag from\n * `_meta/visibility/<keyringId>`. Returns `{ hidden: false }` when no\n * document has been persisted (the default-visible case).\n */\n async getMyVisibility(): Promise<UserVisibility> {\n const persisted = await readUserVisibility(this.adapter, this.vaultName, this.writerKeyringId)\n return persisted ?? { hidden: false }\n }\n\n /**\n * Update the current user's visibility in the team directory.\n *\n * - `hidden: true` — opt out of the default `listUsersWithEnvelopes`\n * listing. `owner`/`admin` callers can still see the user by passing\n * `{ includeHidden: true }`.\n * - `hidden: false` — opt back in.\n *\n * Own-only by construction: the keyringId argument doesn't exist on\n * this method, so no caller can hide or unhide another principal.\n *\n * Honest caveat: this is a UX flag, not a privacy guarantee. The\n * envelope ciphertext at `_users/<keyringId>` and the keyring file at\n * `_keyring/<userId>` are both still observable to anyone with direct\n * store read access. See `https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/user-envelope.md` →\n * \"Directory visibility\".\n */\n async setMyVisibility(visibility: UserVisibility): Promise<void> {\n await persistUserVisibility(\n this.adapter,\n this.vaultName,\n this.writerKeyringId,\n { hidden: visibility.hidden },\n )\n }\n\n // ─── Read-anyone ─────────────────────────────────────────────────────\n\n /**\n * Read another principal's envelope by their keyringId. Returns null\n * if the principal exists but has no envelope yet, or if the\n * keyringId does not exist at all.\n *\n * Gated by `view-team-profiles` (default `minTier: 2`) — but ONLY for\n * cross-principal reads. Reading your own envelope (`keyringId ===\n * self`) is never gated; that's just `me()` written long-form.\n */\n async get<T = unknown>(\n keyringId: string,\n presented?: UserEnvelopePresented,\n ): Promise<UserEnvelope<T> | null> {\n if (this.checkGate && keyringId !== this.writerKeyringId) {\n await this.checkGate('view-team-profiles', presented)\n }\n const dek = await this.getDek()\n return loadUserEnvelope<T>(this.adapter, this.vaultName, keyringId, dek)\n }\n\n /**\n * Read every persisted envelope in the vault. Order is store-defined.\n *\n * Gated by `view-team-profiles`. Default policy (`minTier: 2`) lets\n * any authenticated session read all envelopes. Two privacy-strict\n * opt-outs:\n *\n * - `view-team-profiles.enabled: false` → list() returns only the\n * caller's own envelope (silent self-fallback, no thrown error).\n * - `view-team-profiles.minTier: 1` + insufficient tier → throws\n * `PolicyDeniedError` with `reason: 'insufficient-tier'`. The\n * caller is expected to elevate, not silently degrade.\n *\n * The asymmetry is deliberate: `enabled: false` is a deliberate\n * design choice (\"nobody sees teammate profiles in this app\");\n * `insufficient-tier` is \"you need to authenticate further\". Different\n * UX prompts for different intents.\n */\n async list<T = unknown>(presented?: UserEnvelopePresented): Promise<UserEnvelope<T>[]> {\n if (this.checkGate) {\n try {\n await this.checkGate('view-team-profiles', presented)\n } catch (err) {\n if (err instanceof PolicyDeniedError && err.reason === 'disabled') {\n // Privacy-strict opt-out: quietly return only self.\n const me = await this.me<T>()\n return me ? [me] : []\n }\n throw err\n }\n }\n const dek = await this.getDek()\n const ids = await listUserEnvelopeIds(this.adapter, this.vaultName)\n const envelopes = await Promise.all(\n ids.map((id) => loadUserEnvelope<T>(this.adapter, this.vaultName, id, dek)),\n )\n return envelopes.filter((e): e is UserEnvelope<T> => e !== null)\n }\n\n // ─── Reactive ────────────────────────────────────────────────────────\n\n /**\n * Listen for changes to a specific keyringId's envelope. The callback\n * fires synchronously after every successful local `updateMe` /\n * `setMe` for that principal.\n *\n * Cross-instance changes (a teammate edits their profile on their\n * device, the sync engine pulls the diff onto this device) will fire\n * subscribers when the sync layer replays the write through this API.\n * In v1, subscribers do NOT fire on raw store changes — wire your sync\n * layer to call back through `vault.user.setMe` / `updateMe` if you\n * need that.\n *\n * Pass keyringId `'*'` to fire on every change in the vault.\n */\n subscribe<T = unknown>(\n keyringId: string,\n cb: (env: UserEnvelope<T> | null) => void,\n ): Unsubscribe {\n let listeners = this.listeners.get(keyringId)\n if (!listeners) {\n listeners = new Set()\n this.listeners.set(keyringId, listeners)\n }\n const wrapped: ChangeListener = cb as ChangeListener\n listeners.add(wrapped)\n return () => {\n listeners?.delete(wrapped)\n if (listeners && listeners.size === 0) {\n this.listeners.delete(keyringId)\n }\n }\n }\n\n /**\n * Reactive handle that caches the current value and re-reads on every\n * change for the given keyringId. Convenient for framework bindings:\n *\n * const live = vault.user.live<UserShape>(vault.userId)\n * live.subscribe(env => render(env?.data))\n *\n * Initial value is `null` until the first `current()` call materializes\n * it via `vault.user.get()`. Call `stop()` when done to release the\n * subscription.\n */\n live<T = unknown>(keyringId: string): LiveUserEnvelope<T> {\n let value: UserEnvelope<T> | null = null\n let primed = false\n const unsubscribe = this.subscribe<T>(keyringId, (env) => {\n value = env\n })\n\n return {\n current(): UserEnvelope<T> | null {\n if (!primed) {\n primed = true\n // First call: kick off a read but return synchronously. The\n // subscriber will be re-fired by the next write or the caller\n // can await `vault.user.get()` directly for an immediate read.\n }\n return value\n },\n subscribe: (cb) => this.subscribe<T>(keyringId, cb),\n stop: unsubscribe,\n }\n }\n\n // ─── Internal: change emission ───────────────────────────────────────\n\n private fireChange<T>(keyringId: string, env: UserEnvelope<T> | null): void {\n const targeted = this.listeners.get(keyringId)\n if (targeted) for (const l of targeted) l(env)\n const wildcard = this.listeners.get('*')\n if (wildcard) for (const l of wildcard) l(env)\n }\n}\n\n/**\n * Build the `vault.user` API implementation from its dependencies. This is\n * the real {@link UserApiFactory} — `createNoydb()` dynamically imports it\n * and stashes it on the `Noydb` instance so `Vault`'s constructor can call\n * it synchronously.\n */\nexport const createUserApi: UserApiFactory = (deps: UserApiDeps): VaultUserApi => new UserApi(deps)\n\n/**\n * Recursive plain-object deep merge with delete intent.\n *\n * Patch semantics:\n * - `undefined` — skip the key; source value preserved\n * - `null` — delete the key from output (lodash `_.merge` /\n * Firestore `FieldValue.delete()` semantics)\n * - plain object — recurse (deep merge)\n * - any other value — replace (arrays are replaced, not concatenated)\n *\n * Safe against the JS quirk where an own property explicitly set to\n * `undefined` is iterated by `Object.entries`. We dispatch on the value\n * BEFORE writing, so `{ k: undefined }` triggers the skip branch rather\n * than overwriting `out[k]` with undefined.\n */\nfunction deepMerge<T>(source: T, patch: DeepPartialOrNull<T>): T {\n if (!isPlainObject(source) || !isPlainObject(patch)) {\n // Top-level non-object replace. `null` patch at the leaf level\n // would have been caught by the parent recursion's branch table;\n // at the top level it means \"set the whole envelope to null,\"\n // which the type system already prevents (T extends object).\n return patch as unknown as T\n }\n const out: Record<string, unknown> = { ...(source as Record<string, unknown>) }\n for (const [key, patchVal] of Object.entries(patch as Record<string, unknown>)) {\n if (patchVal === undefined) {\n // Skip — preserve the source value at this key. Matches the\n // pre-existing behavior so callers who never used `null` see no diff.\n continue\n }\n if (patchVal === null) {\n // Delete intent. `delete` rather than `out[key] = undefined`\n // because JSON.stringify drops undefined fields silently and\n // we want the deletion to be visible to consumers iterating\n // the merged object (e.g. `Object.keys(merged.profile)`).\n delete out[key]\n continue\n }\n const sourceVal = (source as Record<string, unknown>)[key]\n if (isPlainObject(patchVal)) {\n // Recurse for any plain-object patch — including the \"source is\n // missing this key\" case. Without recursing through a synthetic\n // empty source, nested `null` deletions in the patch would land\n // as literal `null` values instead of triggering the delete\n // branch (e.g. `{ app: { signature: null } }` against a missing\n // `app` would emit `{ app: { signature: null } }` instead of\n // `{ app: {} }`).\n const recurseSource = isPlainObject(sourceVal) ? sourceVal : {}\n out[key] = deepMerge(recurseSource, patchVal as DeepPartialOrNull<typeof recurseSource>)\n } else {\n out[key] = patchVal\n }\n }\n return out as T\n}\n\nfunction isPlainObject(x: unknown): x is Record<string, unknown> {\n if (x === null || typeof x !== 'object') return false\n if (Array.isArray(x)) return false\n const proto = Object.getPrototypeOf(x) as object | null\n return proto === Object.prototype || proto === null\n}\n"],"mappings":"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","names":[]}
@@ -1,11 +1,11 @@
1
- import {
2
- NOYDB_FORMAT_VERSION
3
- } from "./chunk-WIRRPTFH.js";
4
1
  import {
5
2
  encrypt
6
- } from "./chunk-PP6W64Y3.js";
3
+ } from "./chunk-3OPY6MK2.js";
4
+ import {
5
+ NOYDB_FORMAT_VERSION
6
+ } from "./chunk-YN5IAHN6.js";
7
7
 
8
- // src/blobs/export-blobs.ts
8
+ // src/with-shape/blobs/export-blobs.ts
9
9
  var ExportBlobsAbortedError = class extends Error {
10
10
  constructor(reason) {
11
11
  super(`exportBlobs aborted: ${reason}`);
@@ -107,7 +107,7 @@ function generateBatchId() {
107
107
  return `batch-${Date.now().toString(36)}-${s.slice(0, 12)}`;
108
108
  }
109
109
 
110
- // src/blobs/blob-compaction.ts
110
+ // src/with-shape/blobs/blob-compaction.ts
111
111
  var BLOB_EVICTION_AUDIT_COLLECTION = "_blob_eviction_audit";
112
112
  async function runCompaction(ctx, options = {}) {
113
113
  const now = options.now ?? /* @__PURE__ */ new Date();
@@ -118,6 +118,7 @@ async function runCompaction(ctx, options = {}) {
118
118
  let evicted = 0;
119
119
  let records = 0;
120
120
  let auditEntries = 0;
121
+ let held = 0;
121
122
  let collectionsWithPolicy = 0;
122
123
  outer: for (const collectionName of allCollections) {
123
124
  if (collectionName.startsWith("_")) continue;
@@ -141,6 +142,10 @@ async function runCompaction(ctx, options = {}) {
141
142
  if (!policy) continue;
142
143
  const reason = evaluatePolicy(policy, record, slot, now);
143
144
  if (!reason) continue;
145
+ if (isHeld(policy, record, now)) {
146
+ held += 1;
147
+ continue;
148
+ }
144
149
  if (!dryRun) {
145
150
  await ctx.deleteSlot(collectionName, recordId, slot.name);
146
151
  await writeAuditEntry(ctx, {
@@ -165,9 +170,32 @@ async function runCompaction(ctx, options = {}) {
165
170
  records,
166
171
  collections: collectionsWithPolicy,
167
172
  auditEntries,
173
+ held,
168
174
  byCollection
169
175
  };
170
176
  }
177
+ function isHeld(policy, record, now) {
178
+ if (policy.legalHold) {
179
+ try {
180
+ if (policy.legalHold(record)) return true;
181
+ } catch {
182
+ return true;
183
+ }
184
+ }
185
+ if (policy.retainUntil) {
186
+ try {
187
+ const until = policy.retainUntil(record);
188
+ if (until !== null && until !== void 0) {
189
+ const t = until instanceof Date ? until.getTime() : typeof until === "number" ? until : Date.parse(String(until));
190
+ if (!Number.isFinite(t)) return true;
191
+ if (t > now.getTime()) return true;
192
+ }
193
+ } catch {
194
+ return true;
195
+ }
196
+ }
197
+ return false;
198
+ }
171
199
  function evaluatePolicy(policy, record, slot, now) {
172
200
  let ttlTriggered = false;
173
201
  let predicateTriggered = false;
@@ -230,4 +258,4 @@ export {
230
258
  BLOB_EVICTION_AUDIT_COLLECTION,
231
259
  runCompaction
232
260
  };
233
- //# sourceMappingURL=chunk-3BFJOWSU.js.map
261
+ //# sourceMappingURL=chunk-BQISD5ZV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-shape/blobs/export-blobs.ts","../src/with-shape/blobs/blob-compaction.ts"],"sourcesContent":["/**\n * `vault.exportBlobs()` — bulk blob extraction primitive.\n *\n * Async-iterable handle over every blob attached to records in a\n * vault, optionally filtered by collection allowlist and per-record\n * predicate. Emits tuples of `{ blobId, recordRef, bytes, meta }` so\n * the consumer can pipe into any sink (zip stream, S3 multipart, USB\n * copy, cold-storage tape) without pulling the whole export into\n * memory.\n *\n * ## Auth + audit\n *\n * - Capability check runs **once** at handle creation via\n * `Vault.assertCanExport('plaintext', 'blob')`. An operator whose\n * keyring lacks that bit fails before a single byte of ciphertext\n * is decrypted.\n * - Audit entry lands in `_export_audit` at handle creation: the\n * actor, start timestamp, target collections, predicate presence,\n * and batch mechanism. **No content hashes** — per the spec\n * non-correlation invariant.\n *\n * ## Abort + resume\n *\n * - `handle.abort()` flips the internal signal; the next iteration\n * boundary throws `AbortError`. Consumers already in `for await`\n * can catch and exit cleanly.\n * - Restart after a partial failure with `{ afterBlobId }` — the\n * iterator skips tuples up to (and including) that blob id before\n * yielding again. Combined with a blob-count ceiling it supports\n * idempotent batch re-runs.\n *\n * @module\n */\n\nimport type { Collection } from '../../kernel/collection.js'\nimport type { SlotInfo } from '../../kernel/types.js'\n\n// ─── Types ──────────────────────────────────────────────────────────────\n\nexport interface ExportBlobsOptions {\n /**\n * Collection allowlist. Omit to export blobs from every collection\n * the caller has read access to.\n */\n readonly collections?: readonly string[]\n /**\n * Per-record predicate. Called on the decrypted record BEFORE any\n * blob bytes are read for that record — returning false skips the\n * record and all its slots without touching their chunks.\n */\n readonly where?: (record: unknown, context: { collection: string; id: string }) => boolean\n /**\n * Resume after a specific blob id. The iterator skips tuples up to\n * and including this id, then yields. Format of the id is the same\n * as `ExportedBlob.blobId` (the HMAC-keyed eTag).\n */\n readonly afterBlobId?: string\n /**\n * External abort signal. When fired, the next iterator tick throws\n * `ExportBlobsAbortedError`. Honored alongside `handle.abort()`.\n */\n readonly signal?: AbortSignal\n}\n\nexport interface ExportedBlob {\n /** Opaque blob identifier — HMAC-keyed eTag, stable across vaults. */\n readonly blobId: string\n /** Where this blob came from in the vault. */\n readonly recordRef: {\n readonly collection: string\n readonly id: string\n readonly slot: string\n }\n /** Decrypted plaintext bytes. */\n readonly bytes: Uint8Array\n /** Best-effort metadata (from the blob slot record). */\n readonly meta: {\n readonly size: number\n /**\n * User-visible filename stored on the slot. Often equal to the\n * slot name; differs when the caller supplied an explicit\n * `filename` to `BlobSet.put()`.\n */\n readonly filename: string\n readonly mimeType?: string\n readonly createdAt?: string\n }\n}\n\nexport interface ExportBlobsHandle extends AsyncIterable<ExportedBlob> {\n /** Abort the export. Safe to call multiple times. */\n abort(): void\n /** True once `abort()` has fired or the external signal aborted. */\n readonly aborted: boolean\n}\n\nexport class ExportBlobsAbortedError extends Error {\n constructor(reason: string) {\n super(`exportBlobs aborted: ${reason}`)\n this.name = 'ExportBlobsAbortedError'\n }\n}\n\n// ─── Audit ──────────────────────────────────────────────────────────────\n\nexport const EXPORT_AUDIT_COLLECTION = '_export_audit'\n\nexport interface ExportBlobsAuditEntry {\n readonly id: string\n readonly mechanism: 'exportBlobs'\n readonly actor: string\n readonly startedAt: string\n readonly collections: readonly string[] | null\n readonly predicate: boolean\n readonly afterBlobId: string | null\n}\n\n// ─── Implementation ─────────────────────────────────────────────────────\n\n/**\n * Build the handle. Factored out of `Vault.exportBlobs` so the\n * implementation can be unit-tested without going through the\n * compartment lifecycle.\n */\nexport function createExportBlobsHandle(\n actor: string,\n listAccessibleCollections: () => Promise<string[]>,\n getCollection: <T>(name: string) => Collection<T>,\n writeAudit: (entry: ExportBlobsAuditEntry) => Promise<void>,\n options: ExportBlobsOptions,\n): ExportBlobsHandle {\n let aborted = false\n\n const abort = (): void => {\n aborted = true\n }\n\n if (options.signal) {\n if (options.signal.aborted) aborted = true\n options.signal.addEventListener('abort', () => { aborted = true })\n }\n\n function assertLive(): void {\n if (aborted) throw new ExportBlobsAbortedError('aborted by caller')\n }\n\n const allowlist = options.collections ? new Set(options.collections) : null\n\n // Write the audit entry BEFORE the first yield so a blocked\n // iteration still leaves an audit trail that the export started.\n let auditPromise: Promise<void> | null = null\n function writeAuditOnce(): Promise<void> {\n if (!auditPromise) {\n auditPromise = writeAudit({\n id: generateBatchId(),\n mechanism: 'exportBlobs',\n actor,\n startedAt: new Date().toISOString(),\n collections: options.collections ?? null,\n predicate: Boolean(options.where),\n afterBlobId: options.afterBlobId ?? null,\n })\n }\n return auditPromise\n }\n\n async function* generate(): AsyncGenerator<ExportedBlob> {\n await writeAuditOnce()\n assertLive()\n\n // Resolve target collections lazily — also keeps the call async.\n const allCollections = await listAccessibleCollections()\n const targets = allCollections.filter(name => {\n if (name.startsWith('_')) return false\n if (allowlist && !allowlist.has(name)) return false\n return true\n })\n\n let resumeCursorHit = options.afterBlobId === undefined\n\n for (const collectionName of targets) {\n if (aborted) return\n\n const coll = getCollection<Record<string, unknown>>(collectionName)\n const records = await coll.list().catch(() => [])\n for (const record of records) {\n if (aborted) return\n assertLive()\n\n const idField = (record as { id?: unknown }).id\n if (typeof idField !== 'string') continue\n\n if (options.where && !options.where(record, { collection: collectionName, id: idField })) continue\n\n const blobSet = coll.blob(idField)\n const slots = await blobSet.list().catch(() => [] as SlotInfo[])\n for (const slot of slots) {\n if (aborted) return\n\n if (!resumeCursorHit) {\n if (slot.eTag === options.afterBlobId) {\n resumeCursorHit = true\n }\n continue\n }\n\n const bytes = await blobSet.get(slot.name)\n if (!bytes) continue\n\n const item: ExportedBlob = {\n blobId: slot.eTag,\n recordRef: { collection: collectionName, id: idField, slot: slot.name },\n bytes,\n meta: {\n size: slot.size,\n filename: slot.filename,\n ...(slot.mimeType !== undefined && { mimeType: slot.mimeType }),\n ...(slot.uploadedAt !== undefined && { createdAt: slot.uploadedAt }),\n },\n }\n yield item\n }\n }\n }\n }\n\n const handle: ExportBlobsHandle = {\n abort,\n get aborted() { return aborted },\n [Symbol.asyncIterator]: () => generate(),\n }\n return handle\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────\n\nfunction generateBatchId(): string {\n // 16 bytes of crypto randomness, URL-safe base64, no padding.\n const raw = globalThis.crypto.getRandomValues(new Uint8Array(16))\n let s = ''\n for (const b of raw) s += b.toString(16).padStart(2, '0')\n return `batch-${Date.now().toString(36)}-${s.slice(0, 12)}`\n}\n","/**\n * Blob retention + compaction.\n *\n * Declarative per-collection / per-slot eviction policy. Two\n * triggers:\n *\n * - **`retainDays`** — age-based TTL. A slot uploaded more than N\n * days ago is evicted.\n * - **`evictWhen(record)`** — predicate over the **decrypted**\n * record. Lets consumers express \"the image is safe to drop once\n * the structured invoice has been reviewed and confirmed.\"\n *\n * Either trigger (or both) causes the slot to evict. Eviction removes\n * the slot entry from `_blob_slots_{collection}`, decrements the\n * blob's refCount (so unreferenced chunks can be GC'd by the next\n * sweep), and writes one entry to the `_blob_eviction_audit`\n * collection for tamper-evident record-keeping.\n *\n * The audit entry carries the eTag of the evicted blob (opaque HMAC\n * of plaintext under the vault's `_blob` DEK) — no plaintext leakage,\n * per the SPEC non-correlation invariant. Consumers reconstructing\n * \"what used to be attached\" can look up the audit entry by record\n * id.\n *\n * Compaction is **consumer-scheduled** — noy-db never runs a\n * background daemon. Call `vault.compact()` whenever your workflow\n * allows (cron, manual \"tidy\" button, cold-storage export prep, …).\n *\n * @module\n */\n\nimport type { NoydbStore, EncryptedEnvelope, SlotInfo } from '../../kernel/types.js'\nimport { NOYDB_FORMAT_VERSION } from '../../kernel/types.js'\nimport { encrypt, type EnclaveKey } from '../../kernel/enclave/index.js'\n\n// ─── Config types ───────────────────────────────────────────────────────\n\nexport interface BlobFieldPolicy<T = unknown> {\n /**\n * Via port brand marker — lets a `BlobFieldPolicy` satisfy the kernel's\n * opaque `ViaDescriptor` (#629 Task 7). Optional (the\n * `ClassifiedFieldSpec._viaBrand` precedent): `blobFields` policies are\n * plain object literals with no declaration factory to stamp it, so a\n * mandatory field would break every existing declaration.\n */\n readonly _viaBrand?: 'blob'\n /**\n * Age-based TTL in days. A slot whose `uploadedAt` is older than\n * `now - retainDays × 86400s` evicts on the next `vault.compact()`.\n * Omit to disable age-based eviction.\n */\n readonly retainDays?: number\n /**\n * Predicate evaluated against the decrypted record. When it returns\n * `true`, every matching slot on that record evicts. Omit to\n * disable predicate-based eviction.\n */\n readonly evictWhen?: (record: T) => boolean\n /**\n * **Legal hold.** When this predicate returns `true`, the slot is\n * never evicted — `retainDays`/`evictWhen` are overridden. Use for a\n * litigation / audit hold on a fiscal document: the blob stays until\n * the predicate returns `false` (the hold is released). Fail-closed:\n * if the predicate throws, the slot is treated as held.\n */\n readonly legalHold?: (record: T) => boolean\n /**\n * **Period-bound retention.** Returns the date (Date / ISO string /\n * epoch ms) until which the slot must be retained — typically derived\n * from the record's fiscal period (e.g. period end + 10 years). While\n * `now < retainUntil`, the slot is never evicted, regardless of\n * `retainDays`. Return `null`/`undefined` to impose no floor.\n * Fail-closed: a throwing function holds the slot.\n */\n readonly retainUntil?: (record: T) => Date | string | number | null | undefined\n /**\n * **External projection.** When `true`, this field's bytes are stored in the\n * vault's `ObjectProjection` (`createNoydb({ objectStore })`) as a single raw,\n * **unencrypted** object — servable directly from S3/CDN and processable by\n * native tooling — instead of the encrypted-chunk path. The encrypted slot\n * record remains the catalog (anchoring invariant). Requires an `objectStore`;\n * **outside the zero-knowledge guarantee** — use only for assets meant to\n * leave the vault. See the as-aws-s3 design spec.\n */\n readonly external?: boolean\n /**\n * For an `external` field: make the object world-readable (CDN origin) rather\n * than presigned-only. Default `false` (presigned). Ignored unless `external`.\n */\n readonly public?: boolean\n /**\n * For an `external` field: how to stamp a **backlink** (this record's\n * vault/collection/id/field) onto the object's metadata — the self-describing\n * \"secondary store\" that powers reconcile / DR / import re-pairing.\n * - `'opaque-token'` (default): a random id; preserves the opaque-bucket\n * property (no names leak); the token is also recorded on the slot.\n * - `'encrypted'`: the reference encrypted under the blob DEK (ZK-preserving;\n * falls back to `'opaque-token'` on a plaintext vault).\n * - `'plain'`: the reference in cleartext metadata — **leaks structure** to\n * bucket readers; only for non-sensitive deployments.\n * - `'none'`: no backlink.\n */\n readonly backlink?: 'opaque-token' | 'encrypted' | 'plain' | 'none'\n}\n\nexport type BlobFieldsConfig<T = unknown> = Record<string, BlobFieldPolicy<T>>\n\n// ─── Audit collection ──────────────────────────────────────────────────\n\nexport const BLOB_EVICTION_AUDIT_COLLECTION = '_blob_eviction_audit'\n\nexport interface BlobEvictionEntry {\n readonly id: string\n readonly collection: string\n readonly recordId: string\n readonly slotName: string\n readonly blobHash: string\n readonly reason: 'ttl' | 'predicate' | 'both'\n readonly evictedAt: string\n readonly actor: string\n}\n\n// ─── Compaction result ──────────────────────────────────────────────────\n\nexport interface CompactionResult {\n /** Number of blob slots evicted across all collections. */\n readonly evicted: number\n /** Number of records touched (iterated + policy checked). */\n readonly records: number\n /** Number of collections with `blobFields` configured. */\n readonly collections: number\n /** Number of audit entries written. Equal to `evicted`. */\n readonly auditEntries: number\n /**\n * Number of slots that would have evicted (TTL/predicate triggered)\n * but were retained by a `legalHold` or `retainUntil` floor.\n */\n readonly held: number\n /** Per-collection breakdown for diagnostics. */\n readonly byCollection: Record<string, { records: number; evicted: number }>\n}\n\n// ─── Core ──────────────────────────────────────────────────────────────\n\nexport interface CompactRunOptions {\n /** Override \"now\" for deterministic testing. */\n readonly now?: Date\n /**\n * Stop after this many evictions. Useful for capped batches / cron\n * jobs that need to fit in a time window. `undefined` = unbounded.\n */\n readonly maxEvictions?: number\n /**\n * Dry-run — evaluate policies and return the counts, but do NOT\n * delete slots or write audit entries. Lets a consumer preview\n * what would happen.\n */\n readonly dryRun?: boolean\n}\n\nexport interface CompactionContext {\n readonly adapter: NoydbStore\n readonly vault: string\n readonly actor: string\n readonly encrypted: boolean\n readonly getDEK: (collection: string) => Promise<EnclaveKey>\n /**\n * Resolve a collection's declared `blobFields` config. Returns an\n * empty map for collections without the config — the walk skips\n * those.\n */\n readonly getBlobFields: <T>(collection: string) => BlobFieldsConfig<T> | null\n /** List collection names in the vault. */\n readonly listCollections: () => Promise<string[]>\n /** List record ids in a collection. */\n readonly listRecords: (collection: string) => Promise<string[]>\n /** Decrypt and return the record. Null when absent. */\n readonly getRecord: <T>(collection: string, id: string) => Promise<T | null>\n /** Return the BlobSet-like handle for a record's slots. */\n readonly listSlots: (collection: string, id: string) => Promise<SlotInfo[]>\n /** Delete a slot and decrement its blob's refCount. */\n readonly deleteSlot: (collection: string, id: string, slotName: string) => Promise<void>\n}\n\nexport async function runCompaction(\n ctx: CompactionContext,\n options: CompactRunOptions = {},\n): Promise<CompactionResult> {\n const now = options.now ?? new Date()\n const maxEvictions = options.maxEvictions ?? Infinity\n const dryRun = options.dryRun === true\n\n const allCollections = await ctx.listCollections()\n const byCollection: Record<string, { records: number; evicted: number }> = {}\n let evicted = 0\n let records = 0\n let auditEntries = 0\n let held = 0\n let collectionsWithPolicy = 0\n\n outer: for (const collectionName of allCollections) {\n if (collectionName.startsWith('_')) continue\n const config = ctx.getBlobFields(collectionName)\n if (!config) continue\n const configuredSlots = Object.keys(config)\n if (configuredSlots.length === 0) continue\n collectionsWithPolicy += 1\n byCollection[collectionName] = { records: 0, evicted: 0 }\n\n const ids = await ctx.listRecords(collectionName)\n for (const recordId of ids) {\n if (evicted >= maxEvictions) break outer\n\n const record = await ctx.getRecord(collectionName, recordId).catch(() => null)\n if (record === null) continue\n records += 1\n byCollection[collectionName].records += 1\n\n const slots = await ctx.listSlots(collectionName, recordId).catch(() => [])\n for (const slot of slots) {\n if (evicted >= maxEvictions) break outer\n const policy = config[slot.name]\n if (!policy) continue\n\n const reason = evaluatePolicy(policy, record, slot, now)\n if (!reason) continue\n\n // Retention floor: a legal hold or period-bound retainUntil\n // blocks an otherwise-due eviction. Counted, never evicted.\n if (isHeld(policy, record, now)) {\n held += 1\n continue\n }\n\n if (!dryRun) {\n await ctx.deleteSlot(collectionName, recordId, slot.name)\n await writeAuditEntry(ctx, {\n id: generateEvictionId(collectionName, recordId, slot.name),\n collection: collectionName,\n recordId,\n slotName: slot.name,\n blobHash: slot.eTag,\n reason,\n evictedAt: now.toISOString(),\n actor: ctx.actor,\n })\n auditEntries += 1\n }\n evicted += 1\n byCollection[collectionName].evicted += 1\n }\n }\n }\n\n return {\n evicted,\n records,\n collections: collectionsWithPolicy,\n auditEntries,\n held,\n byCollection,\n }\n}\n\n/**\n * Whether a retention floor (legal hold or period-bound `retainUntil`)\n * currently blocks eviction of this record's slots. Fail-closed: a\n * throwing predicate holds the slot.\n */\nfunction isHeld<T>(policy: BlobFieldPolicy<T>, record: T, now: Date): boolean {\n if (policy.legalHold) {\n try {\n if (policy.legalHold(record)) return true\n } catch {\n return true\n }\n }\n if (policy.retainUntil) {\n try {\n const until = policy.retainUntil(record)\n if (until !== null && until !== undefined) {\n const t = until instanceof Date ? until.getTime() : typeof until === 'number' ? until : Date.parse(String(until))\n if (!Number.isFinite(t)) return true // fail-closed: unparseable retainUntil holds the slot\n if (t > now.getTime()) return true\n }\n } catch {\n return true\n }\n }\n return false\n}\n\nfunction evaluatePolicy<T>(\n policy: BlobFieldPolicy<T>,\n record: T,\n slot: SlotInfo,\n now: Date,\n): 'ttl' | 'predicate' | 'both' | null {\n let ttlTriggered = false\n let predicateTriggered = false\n\n if (policy.retainDays !== undefined && policy.retainDays > 0) {\n const uploadedAt = Date.parse(slot.uploadedAt)\n if (Number.isFinite(uploadedAt)) {\n const ageMs = now.getTime() - uploadedAt\n const limitMs = policy.retainDays * 86_400_000\n if (ageMs > limitMs) ttlTriggered = true\n }\n }\n\n if (policy.evictWhen) {\n try {\n if (policy.evictWhen(record)) predicateTriggered = true\n } catch {\n // Predicate error → do NOT evict. Fail closed.\n }\n }\n\n if (ttlTriggered && predicateTriggered) return 'both'\n if (ttlTriggered) return 'ttl'\n if (predicateTriggered) return 'predicate'\n return null\n}\n\nfunction generateEvictionId(collection: string, recordId: string, slotName: string): string {\n const rand = globalThis.crypto.getRandomValues(new Uint8Array(8))\n let suffix = ''\n for (const b of rand) suffix += b.toString(16).padStart(2, '0')\n return `${collection}__${recordId}__${slotName}__${suffix}`\n}\n\nasync function writeAuditEntry(ctx: CompactionContext, entry: BlobEvictionEntry): Promise<void> {\n const json = JSON.stringify(entry)\n let envelope: EncryptedEnvelope\n if (ctx.encrypted) {\n const dek = await ctx.getDEK(BLOB_EVICTION_AUDIT_COLLECTION)\n const { iv, data } = await encrypt(json, dek)\n envelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: 1,\n _ts: entry.evictedAt,\n _iv: iv,\n _data: data,\n _by: entry.actor,\n }\n } else {\n envelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: 1,\n _ts: entry.evictedAt,\n _iv: '',\n _data: json,\n _by: entry.actor,\n }\n }\n await ctx.adapter.put(ctx.vault, BLOB_EVICTION_AUDIT_COLLECTION, entry.id, envelope)\n}\n"],"mappings":";;;;;;;;AAgGO,IAAM,0BAAN,cAAsC,MAAM;AAAA,EACjD,YAAY,QAAgB;AAC1B,UAAM,wBAAwB,MAAM,EAAE;AACtC,SAAK,OAAO;AAAA,EACd;AACF;AAIO,IAAM,0BAA0B;AAmBhC,SAAS,wBACd,OACA,2BACA,eACA,YACA,SACmB;AACnB,MAAI,UAAU;AAEd,QAAM,QAAQ,MAAY;AACxB,cAAU;AAAA,EACZ;AAEA,MAAI,QAAQ,QAAQ;AAClB,QAAI,QAAQ,OAAO,QAAS,WAAU;AACtC,YAAQ,OAAO,iBAAiB,SAAS,MAAM;AAAE,gBAAU;AAAA,IAAK,CAAC;AAAA,EACnE;AAEA,WAAS,aAAmB;AAC1B,QAAI,QAAS,OAAM,IAAI,wBAAwB,mBAAmB;AAAA,EACpE;AAEA,QAAM,YAAY,QAAQ,cAAc,IAAI,IAAI,QAAQ,WAAW,IAAI;AAIvE,MAAI,eAAqC;AACzC,WAAS,iBAAgC;AACvC,QAAI,CAAC,cAAc;AACjB,qBAAe,WAAW;AAAA,QACxB,IAAI,gBAAgB;AAAA,QACpB,WAAW;AAAA,QACX;AAAA,QACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClC,aAAa,QAAQ,eAAe;AAAA,QACpC,WAAW,QAAQ,QAAQ,KAAK;AAAA,QAChC,aAAa,QAAQ,eAAe;AAAA,MACtC,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAEA,kBAAgB,WAAyC;AACvD,UAAM,eAAe;AACrB,eAAW;AAGX,UAAM,iBAAiB,MAAM,0BAA0B;AACvD,UAAM,UAAU,eAAe,OAAO,UAAQ;AAC5C,UAAI,KAAK,WAAW,GAAG,EAAG,QAAO;AACjC,UAAI,aAAa,CAAC,UAAU,IAAI,IAAI,EAAG,QAAO;AAC9C,aAAO;AAAA,IACT,CAAC;AAED,QAAI,kBAAkB,QAAQ,gBAAgB;AAE9C,eAAW,kBAAkB,SAAS;AACpC,UAAI,QAAS;AAEb,YAAM,OAAO,cAAuC,cAAc;AAClE,YAAM,UAAU,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,CAAC,CAAC;AAChD,iBAAW,UAAU,SAAS;AAC5B,YAAI,QAAS;AACb,mBAAW;AAEX,cAAM,UAAW,OAA4B;AAC7C,YAAI,OAAO,YAAY,SAAU;AAEjC,YAAI,QAAQ,SAAS,CAAC,QAAQ,MAAM,QAAQ,EAAE,YAAY,gBAAgB,IAAI,QAAQ,CAAC,EAAG;AAE1F,cAAM,UAAU,KAAK,KAAK,OAAO;AACjC,cAAM,QAAQ,MAAM,QAAQ,KAAK,EAAE,MAAM,MAAM,CAAC,CAAe;AAC/D,mBAAW,QAAQ,OAAO;AACxB,cAAI,QAAS;AAEb,cAAI,CAAC,iBAAiB;AACpB,gBAAI,KAAK,SAAS,QAAQ,aAAa;AACrC,gCAAkB;AAAA,YACpB;AACA;AAAA,UACF;AAEA,gBAAM,QAAQ,MAAM,QAAQ,IAAI,KAAK,IAAI;AACzC,cAAI,CAAC,MAAO;AAEZ,gBAAM,OAAqB;AAAA,YACzB,QAAQ,KAAK;AAAA,YACb,WAAW,EAAE,YAAY,gBAAgB,IAAI,SAAS,MAAM,KAAK,KAAK;AAAA,YACtE;AAAA,YACA,MAAM;AAAA,cACJ,MAAM,KAAK;AAAA,cACX,UAAU,KAAK;AAAA,cACf,GAAI,KAAK,aAAa,UAAa,EAAE,UAAU,KAAK,SAAS;AAAA,cAC7D,GAAI,KAAK,eAAe,UAAa,EAAE,WAAW,KAAK,WAAW;AAAA,YACpE;AAAA,UACF;AACA,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAA4B;AAAA,IAChC;AAAA,IACA,IAAI,UAAU;AAAE,aAAO;AAAA,IAAQ;AAAA,IAC/B,CAAC,OAAO,aAAa,GAAG,MAAM,SAAS;AAAA,EACzC;AACA,SAAO;AACT;AAIA,SAAS,kBAA0B;AAEjC,QAAM,MAAM,WAAW,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC;AAChE,MAAI,IAAI;AACR,aAAW,KAAK,IAAK,MAAK,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AACxD,SAAO,SAAS,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,EAAE,CAAC;AAC3D;;;ACrIO,IAAM,iCAAiC;AA2E9C,eAAsB,cACpB,KACA,UAA6B,CAAC,GACH;AAC3B,QAAM,MAAM,QAAQ,OAAO,oBAAI,KAAK;AACpC,QAAM,eAAe,QAAQ,gBAAgB;AAC7C,QAAM,SAAS,QAAQ,WAAW;AAElC,QAAM,iBAAiB,MAAM,IAAI,gBAAgB;AACjD,QAAM,eAAqE,CAAC;AAC5E,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,eAAe;AACnB,MAAI,OAAO;AACX,MAAI,wBAAwB;AAE5B,QAAO,YAAW,kBAAkB,gBAAgB;AAClD,QAAI,eAAe,WAAW,GAAG,EAAG;AACpC,UAAM,SAAS,IAAI,cAAc,cAAc;AAC/C,QAAI,CAAC,OAAQ;AACb,UAAM,kBAAkB,OAAO,KAAK,MAAM;AAC1C,QAAI,gBAAgB,WAAW,EAAG;AAClC,6BAAyB;AACzB,iBAAa,cAAc,IAAI,EAAE,SAAS,GAAG,SAAS,EAAE;AAExD,UAAM,MAAM,MAAM,IAAI,YAAY,cAAc;AAChD,eAAW,YAAY,KAAK;AAC1B,UAAI,WAAW,aAAc,OAAM;AAEnC,YAAM,SAAS,MAAM,IAAI,UAAU,gBAAgB,QAAQ,EAAE,MAAM,MAAM,IAAI;AAC7E,UAAI,WAAW,KAAM;AACrB,iBAAW;AACX,mBAAa,cAAc,EAAE,WAAW;AAExC,YAAM,QAAQ,MAAM,IAAI,UAAU,gBAAgB,QAAQ,EAAE,MAAM,MAAM,CAAC,CAAC;AAC1E,iBAAW,QAAQ,OAAO;AACxB,YAAI,WAAW,aAAc,OAAM;AACnC,cAAM,SAAS,OAAO,KAAK,IAAI;AAC/B,YAAI,CAAC,OAAQ;AAEb,cAAM,SAAS,eAAe,QAAQ,QAAQ,MAAM,GAAG;AACvD,YAAI,CAAC,OAAQ;AAIb,YAAI,OAAO,QAAQ,QAAQ,GAAG,GAAG;AAC/B,kBAAQ;AACR;AAAA,QACF;AAEA,YAAI,CAAC,QAAQ;AACX,gBAAM,IAAI,WAAW,gBAAgB,UAAU,KAAK,IAAI;AACxD,gBAAM,gBAAgB,KAAK;AAAA,YACzB,IAAI,mBAAmB,gBAAgB,UAAU,KAAK,IAAI;AAAA,YAC1D,YAAY;AAAA,YACZ;AAAA,YACA,UAAU,KAAK;AAAA,YACf,UAAU,KAAK;AAAA,YACf;AAAA,YACA,WAAW,IAAI,YAAY;AAAA,YAC3B,OAAO,IAAI;AAAA,UACb,CAAC;AACD,0BAAgB;AAAA,QAClB;AACA,mBAAW;AACX,qBAAa,cAAc,EAAE,WAAW;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAOA,SAAS,OAAU,QAA4B,QAAW,KAAoB;AAC5E,MAAI,OAAO,WAAW;AACpB,QAAI;AACF,UAAI,OAAO,UAAU,MAAM,EAAG,QAAO;AAAA,IACvC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI,OAAO,aAAa;AACtB,QAAI;AACF,YAAM,QAAQ,OAAO,YAAY,MAAM;AACvC,UAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,cAAM,IAAI,iBAAiB,OAAO,MAAM,QAAQ,IAAI,OAAO,UAAU,WAAW,QAAQ,KAAK,MAAM,OAAO,KAAK,CAAC;AAChH,YAAI,CAAC,OAAO,SAAS,CAAC,EAAG,QAAO;AAChC,YAAI,IAAI,IAAI,QAAQ,EAAG,QAAO;AAAA,MAChC;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eACP,QACA,QACA,MACA,KACqC;AACrC,MAAI,eAAe;AACnB,MAAI,qBAAqB;AAEzB,MAAI,OAAO,eAAe,UAAa,OAAO,aAAa,GAAG;AAC5D,UAAM,aAAa,KAAK,MAAM,KAAK,UAAU;AAC7C,QAAI,OAAO,SAAS,UAAU,GAAG;AAC/B,YAAM,QAAQ,IAAI,QAAQ,IAAI;AAC9B,YAAM,UAAU,OAAO,aAAa;AACpC,UAAI,QAAQ,QAAS,gBAAe;AAAA,IACtC;AAAA,EACF;AAEA,MAAI,OAAO,WAAW;AACpB,QAAI;AACF,UAAI,OAAO,UAAU,MAAM,EAAG,sBAAqB;AAAA,IACrD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,MAAI,gBAAgB,mBAAoB,QAAO;AAC/C,MAAI,aAAc,QAAO;AACzB,MAAI,mBAAoB,QAAO;AAC/B,SAAO;AACT;AAEA,SAAS,mBAAmB,YAAoB,UAAkB,UAA0B;AAC1F,QAAM,OAAO,WAAW,OAAO,gBAAgB,IAAI,WAAW,CAAC,CAAC;AAChE,MAAI,SAAS;AACb,aAAW,KAAK,KAAM,WAAU,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC9D,SAAO,GAAG,UAAU,KAAK,QAAQ,KAAK,QAAQ,KAAK,MAAM;AAC3D;AAEA,eAAe,gBAAgB,KAAwB,OAAyC;AAC9F,QAAM,OAAO,KAAK,UAAU,KAAK;AACjC,MAAI;AACJ,MAAI,IAAI,WAAW;AACjB,UAAM,MAAM,MAAM,IAAI,OAAO,8BAA8B;AAC3D,UAAM,EAAE,IAAI,KAAK,IAAI,MAAM,QAAQ,MAAM,GAAG;AAC5C,eAAW;AAAA,MACT,QAAQ;AAAA,MACR,IAAI;AAAA,MACJ,KAAK,MAAM;AAAA,MACX,KAAK;AAAA,MACL,OAAO;AAAA,MACP,KAAK,MAAM;AAAA,IACb;AAAA,EACF,OAAO;AACL,eAAW;AAAA,MACT,QAAQ;AAAA,MACR,IAAI;AAAA,MACJ,KAAK,MAAM;AAAA,MACX,KAAK;AAAA,MACL,OAAO;AAAA,MACP,KAAK,MAAM;AAAA,IACb;AAAA,EACF;AACA,QAAM,IAAI,QAAQ,IAAI,IAAI,OAAO,gCAAgC,MAAM,IAAI,QAAQ;AACrF;","names":[]}