@noy-db/hub 0.2.0-pre.16 → 0.2.0-pre.17

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 (286) hide show
  1. package/dist/aggregate/index.cjs.map +1 -1
  2. package/dist/aggregate/index.d.cts +3 -2
  3. package/dist/aggregate/index.d.ts +3 -2
  4. package/dist/aggregate/index.js +4 -4
  5. package/dist/attestation/index.cjs.map +1 -1
  6. package/dist/attestation/index.d.cts +5 -3
  7. package/dist/attestation/index.d.ts +5 -3
  8. package/dist/attestation/index.js +6 -6
  9. package/dist/blobs/index.cjs +226 -11
  10. package/dist/blobs/index.cjs.map +1 -1
  11. package/dist/blobs/index.d.cts +6 -4
  12. package/dist/blobs/index.d.ts +6 -4
  13. package/dist/blobs/index.js +6 -5
  14. package/dist/blobs/index.js.map +1 -1
  15. package/dist/bundle/index.cjs +1087 -95
  16. package/dist/bundle/index.cjs.map +1 -1
  17. package/dist/bundle/index.d.cts +7 -5
  18. package/dist/bundle/index.d.ts +7 -5
  19. package/dist/bundle/index.js +21 -10
  20. package/dist/bundle/index.js.map +1 -1
  21. package/dist/{chunk-G4SCICH5.js → chunk-2FU2FTXD.js} +2 -2
  22. package/dist/{chunk-JD3OZAI4.js → chunk-3G3W65EQ.js} +2 -2
  23. package/dist/{chunk-XWH4MXIU.js → chunk-5AXTH4QZ.js} +2 -2
  24. package/dist/{chunk-4TBBMHVC.js → chunk-5LIROIDM.js} +2 -2
  25. package/dist/{chunk-L2BNJ6HM.js → chunk-7H2GEJ3O.js} +3 -3
  26. package/dist/{chunk-GNI5STXQ.js → chunk-AEIKD3PP.js} +52 -38
  27. package/dist/chunk-AEIKD3PP.js.map +1 -0
  28. package/dist/{chunk-QSUK7YWK.js → chunk-BH3X5L6A.js} +4 -4
  29. package/dist/{chunk-BQ65SS5A.js → chunk-BJSLBUJ7.js} +2 -2
  30. package/dist/{chunk-FFXM3ZIF.js → chunk-BL5GYANC.js} +3 -3
  31. package/dist/{chunk-6H2ZUNR7.js → chunk-BSZOCSDZ.js} +4 -4
  32. package/dist/{chunk-ZNQYHJXX.js → chunk-C3HYQPV4.js} +2 -2
  33. package/dist/{chunk-E2CDVKMH.js → chunk-CD2AVTEM.js} +5 -5
  34. package/dist/{chunk-667MB6AH.js → chunk-D77ZQSQQ.js} +769 -131
  35. package/dist/chunk-D77ZQSQQ.js.map +1 -0
  36. package/dist/{chunk-BR3AMFGS.js → chunk-DWEBTE2W.js} +5 -5
  37. package/dist/{chunk-Z4DO7YSI.js → chunk-DYYYUW5D.js} +2 -2
  38. package/dist/{chunk-SCJPI4Z5.js → chunk-E77UKJYL.js} +5 -5
  39. package/dist/{chunk-OMAMZKKD.js → chunk-F4G63NTZ.js} +2 -2
  40. package/dist/{chunk-TKIY625R.js → chunk-FEJDVE3Z.js} +2 -2
  41. package/dist/{chunk-7Z7KSVA5.js → chunk-GP3SDSH2.js} +2 -2
  42. package/dist/{chunk-IQLVUT37.js → chunk-H2MRGONI.js} +2 -2
  43. package/dist/{chunk-DUREQF5W.js → chunk-HGVSHKZW.js} +8 -5
  44. package/dist/chunk-HGVSHKZW.js.map +1 -0
  45. package/dist/chunk-I5IUYN7B.js +125 -0
  46. package/dist/chunk-I5IUYN7B.js.map +1 -0
  47. package/dist/{chunk-CJORTUJ2.js → chunk-J7RWBXFY.js} +2 -2
  48. package/dist/{chunk-AAVWKNZW.js → chunk-JDWE6JMX.js} +2 -2
  49. package/dist/{chunk-XL35NSEN.js → chunk-KCEHMDZF.js} +3 -3
  50. package/dist/{chunk-TS26M2SB.js → chunk-M476FOQ7.js} +2 -2
  51. package/dist/{chunk-F4OJZIWQ.js → chunk-NBBMMJ2H.js} +4 -4
  52. package/dist/{chunk-CZI2A4MQ.js → chunk-NYSYPFXJ.js} +3 -3
  53. package/dist/{chunk-OQSRJG6A.js → chunk-PDULVIBY.js} +2 -2
  54. package/dist/{chunk-Z6FNBOTC.js → chunk-PDVP3C2I.js} +1 -1
  55. package/dist/{chunk-Z6FNBOTC.js.map → chunk-PDVP3C2I.js.map} +1 -1
  56. package/dist/{chunk-DLZ2ONOD.js → chunk-QHM6XEAH.js} +6 -6
  57. package/dist/{chunk-HBXJ37ZY.js → chunk-QO6RGLLD.js} +4 -4
  58. package/dist/{chunk-7BQ4QWYX.js → chunk-ROPJVUG3.js} +23 -6
  59. package/dist/chunk-ROPJVUG3.js.map +1 -0
  60. package/dist/{chunk-42FEUPZQ.js → chunk-ROVO6NPJ.js} +2 -2
  61. package/dist/{chunk-6RR3MNMG.js → chunk-SHX5QBCI.js} +3 -3
  62. package/dist/{chunk-F3BPIPLS.js → chunk-SISBMAPO.js} +1 -1
  63. package/dist/chunk-SISBMAPO.js.map +1 -0
  64. package/dist/{chunk-3YWP3WBP.js → chunk-SNMJ7SB3.js} +5 -5
  65. package/dist/{chunk-IXBIFDEW.js → chunk-TIDXB5DF.js} +4 -4
  66. package/dist/chunk-U5QCMH3W.js +151 -0
  67. package/dist/chunk-U5QCMH3W.js.map +1 -0
  68. package/dist/{chunk-YULZKK4F.js → chunk-UNTGHX5A.js} +37 -2
  69. package/dist/chunk-UNTGHX5A.js.map +1 -0
  70. package/dist/{chunk-FWPKCXTN.js → chunk-WIAOUFFB.js} +2 -2
  71. package/dist/{chunk-KABJXG2F.js → chunk-WV7WV6JO.js} +195 -17
  72. package/dist/chunk-WV7WV6JO.js.map +1 -0
  73. package/dist/{chunk-X73VS74Y.js → chunk-XJV6OB4D.js} +2 -2
  74. package/dist/{chunk-VLMPU56Q.js → chunk-XMHUK5PN.js} +2 -2
  75. package/dist/{chunk-BI6ETQPF.js → chunk-XMVHEWF6.js} +4 -4
  76. package/dist/{chunk-HOR4R722.js → chunk-XPIHJ34I.js} +30 -4
  77. package/dist/chunk-XPIHJ34I.js.map +1 -0
  78. package/dist/{chunk-OB2ZJQ2D.js → chunk-YYVZYTWW.js} +3 -3
  79. package/dist/{chunk-535SSHBS.js → chunk-ZEGSDPB7.js} +81 -2
  80. package/dist/chunk-ZEGSDPB7.js.map +1 -0
  81. package/dist/{chunk-QVIEAYTP.js → chunk-ZNGPEV5J.js} +3 -3
  82. package/dist/consent/index.cjs.map +1 -1
  83. package/dist/consent/index.d.cts +6 -4
  84. package/dist/consent/index.d.ts +6 -4
  85. package/dist/consent/index.js +3 -3
  86. package/dist/{crypto-QXQOHMHF.js → crypto-7BN2HDWG.js} +7 -3
  87. package/dist/{delegation-NIQ43IPU.js → delegation-MGH5SODX.js} +5 -5
  88. package/dist/derivations/index.cjs.map +1 -1
  89. package/dist/derivations/index.d.cts +7 -5
  90. package/dist/derivations/index.d.ts +7 -5
  91. package/dist/derivations/index.js +4 -4
  92. package/dist/{dev-unlock-DR3upLd1.d.ts → dev-unlock-CI1ijTML.d.ts} +1 -1
  93. package/dist/{dev-unlock-8XzcD2Z4.d.cts → dev-unlock-iXbYFAWl.d.cts} +1 -1
  94. package/dist/{strategy-BtW8fAjz.d.ts → errors-Dz64FA65.d.cts} +98 -727
  95. package/dist/{strategy-BtW8fAjz.d.cts → errors-Dz64FA65.d.ts} +98 -727
  96. package/dist/executor-3W63Y44O.js +11 -0
  97. package/dist/executor-CFFWPWBJ.js +8 -0
  98. package/dist/executor-VDQQOR4F.js +8 -0
  99. package/dist/{fanout-sidecar-67CMI3UT.js → fanout-sidecar-FIJJ46YG.js} +2 -2
  100. package/dist/forget/index.cjs +43 -0
  101. package/dist/forget/index.cjs.map +1 -0
  102. package/dist/forget/index.d.cts +1 -0
  103. package/dist/forget/index.d.ts +1 -0
  104. package/dist/forget/index.js +14 -0
  105. package/dist/guards/index.cjs.map +1 -1
  106. package/dist/guards/index.d.cts +7 -5
  107. package/dist/guards/index.d.ts +7 -5
  108. package/dist/guards/index.js +6 -6
  109. package/dist/{hash-CDjye9KV.d.ts → hash-blk7Bkes.d.ts} +1 -1
  110. package/dist/{hash-DuQ88_5W.d.cts → hash-tEcM5fnv.d.cts} +1 -1
  111. package/dist/history/index.cjs +27 -4
  112. package/dist/history/index.cjs.map +1 -1
  113. package/dist/history/index.d.cts +7 -5
  114. package/dist/history/index.d.ts +7 -5
  115. package/dist/history/index.js +9 -7
  116. package/dist/history/index.js.map +1 -1
  117. package/dist/i18n/index.cjs +53 -0
  118. package/dist/i18n/index.cjs.map +1 -1
  119. package/dist/i18n/index.d.cts +6 -4
  120. package/dist/i18n/index.d.ts +6 -4
  121. package/dist/i18n/index.js +16 -8
  122. package/dist/i18n/index.js.map +1 -1
  123. package/dist/{immutable-guard-Dov3WvwF.d.ts → immutable-guard-B5M95nbq.d.ts} +1 -1
  124. package/dist/{immutable-guard-CRPvu24K.d.cts → immutable-guard-qN3zF8o1.d.cts} +1 -1
  125. package/dist/index-C-SSRIxP.d.cts +348 -0
  126. package/dist/index-C-SSRIxP.d.ts +348 -0
  127. package/dist/{index-nP99bXLg.d.ts → index-DpU6KWof.d.ts} +9 -1
  128. package/dist/{index-C8Bk3-VF.d.cts → index-u-kWzSrL.d.cts} +9 -1
  129. package/dist/index.cjs +7271 -6079
  130. package/dist/index.cjs.map +1 -1
  131. package/dist/index.d.cts +15 -12
  132. package/dist/index.d.ts +15 -12
  133. package/dist/index.js +130 -106
  134. package/dist/index.js.map +1 -1
  135. package/dist/indexing/index.cjs.map +1 -1
  136. package/dist/indexing/index.js +4 -4
  137. package/dist/issue-TTMGHQ2J.js +12 -0
  138. package/dist/{ledger-A3LL253R.js → ledger-LFVLHE5H.js} +6 -6
  139. package/dist/materialized-views/index.cjs.map +1 -1
  140. package/dist/materialized-views/index.d.cts +7 -5
  141. package/dist/materialized-views/index.d.ts +7 -5
  142. package/dist/materialized-views/index.js +12 -12
  143. package/dist/noydb-36S6GQNC.js +37 -0
  144. package/dist/overlay-views/index.cjs.map +1 -1
  145. package/dist/overlay-views/index.d.cts +7 -5
  146. package/dist/overlay-views/index.d.ts +7 -5
  147. package/dist/overlay-views/index.js +4 -4
  148. package/dist/periods/index.cjs.map +1 -1
  149. package/dist/periods/index.d.cts +6 -4
  150. package/dist/periods/index.d.ts +6 -4
  151. package/dist/periods/index.js +6 -6
  152. package/dist/{public-envelope-YP2UWMLG.js → public-envelope-RXZNP3V6.js} +4 -4
  153. package/dist/query/index.cjs +4 -1
  154. package/dist/query/index.cjs.map +1 -1
  155. package/dist/query/index.d.cts +3 -2
  156. package/dist/query/index.d.ts +3 -2
  157. package/dist/query/index.js +6 -6
  158. package/dist/registry-3YFLZ7WD.js +8 -0
  159. package/dist/{registry-UTA4CLQS.js → registry-SECUWSGY.js} +3 -3
  160. package/dist/registry-TGZISEWC.js +8 -0
  161. package/dist/{revoke-HNMQZSCL.js → revoke-B54H2S2W.js} +6 -6
  162. package/dist/sealed-record/index.cjs +139 -0
  163. package/dist/sealed-record/index.cjs.map +1 -0
  164. package/dist/sealed-record/index.d.cts +123 -0
  165. package/dist/sealed-record/index.d.ts +123 -0
  166. package/dist/sealed-record/index.js +42 -0
  167. package/dist/sealed-record/index.js.map +1 -0
  168. package/dist/session/index.cjs.map +1 -1
  169. package/dist/session/index.d.cts +7 -5
  170. package/dist/session/index.d.ts +7 -5
  171. package/dist/session/index.js +3 -3
  172. package/dist/shadow/index.cjs.map +1 -1
  173. package/dist/shadow/index.d.cts +6 -4
  174. package/dist/shadow/index.d.ts +6 -4
  175. package/dist/shadow/index.js +2 -2
  176. package/dist/{signer-DCMNKXSF.js → signer-YSXZT574.js} +5 -5
  177. package/dist/snapshots/index.cjs.map +1 -1
  178. package/dist/snapshots/index.d.cts +6 -4
  179. package/dist/snapshots/index.d.ts +6 -4
  180. package/dist/snapshots/index.js +4 -4
  181. package/dist/{stale-W5PQTRYH.js → stale-TOA36SRK.js} +2 -2
  182. package/dist/stale-TOA36SRK.js.map +1 -0
  183. package/dist/{state-vault-TMXZRTY5.js → state-vault-W2OEABNO.js} +3 -3
  184. package/dist/store/index.cjs.map +1 -1
  185. package/dist/store/index.d.cts +6 -4
  186. package/dist/store/index.d.ts +6 -4
  187. package/dist/store/index.js +2 -2
  188. package/dist/strategy-4M9jo172.d.ts +739 -0
  189. package/dist/strategy-CLC1j79g.d.cts +739 -0
  190. package/dist/sync/index.cjs.map +1 -1
  191. package/dist/sync/index.d.cts +5 -3
  192. package/dist/sync/index.d.ts +5 -3
  193. package/dist/sync/index.js +4 -4
  194. package/dist/team/index.cjs.map +1 -1
  195. package/dist/team/index.d.cts +6 -4
  196. package/dist/team/index.d.ts +6 -4
  197. package/dist/team/index.js +8 -8
  198. package/dist/tx/index.cjs.map +1 -1
  199. package/dist/tx/index.d.cts +6 -4
  200. package/dist/tx/index.d.ts +6 -4
  201. package/dist/tx/index.js +3 -3
  202. package/dist/{types-DrmBTscX.d.ts → types-CljIHm_J.d.ts} +789 -500
  203. package/dist/{types-Bze6vkwm.d.cts → types-CrSpRDuG.d.cts} +789 -500
  204. package/dist/{ulid-DbBVrNSt.d.ts → ulid-CWfL2Vfv.d.ts} +1 -1
  205. package/dist/{ulid-DfZlAh0u.d.cts → ulid-CrI7PPbA.d.cts} +1 -1
  206. package/dist/util/index.cjs.map +1 -1
  207. package/dist/util/index.js +1 -1
  208. package/dist/{vault-group-DX2HFQMX.js → vault-group-DHAHFX2A.js} +4 -4
  209. package/dist/{with-derivation-_lySGdlm.d.ts → with-derivation-BZ2y4bzF.d.ts} +1 -1
  210. package/dist/{with-derivation-CCqAchD5.d.cts → with-derivation-Bozs8DmD.d.cts} +1 -1
  211. package/dist/{with-materialized-view-QT1Tp7NO.d.ts → with-materialized-view-B892zYZV.d.ts} +1 -1
  212. package/dist/{with-materialized-view--4PsvMDu.d.cts → with-materialized-view-NzF71cG_.d.cts} +1 -1
  213. package/dist/{with-overlayed-view-BEXfpzSb.d.ts → with-overlayed-view-CR6m7CHe.d.ts} +1 -1
  214. package/dist/{with-overlayed-view-DlH5qmeB.d.cts → with-overlayed-view-UI8qSGL4.d.cts} +1 -1
  215. package/package.json +23 -3
  216. package/dist/chunk-535SSHBS.js.map +0 -1
  217. package/dist/chunk-667MB6AH.js.map +0 -1
  218. package/dist/chunk-7BQ4QWYX.js.map +0 -1
  219. package/dist/chunk-DUREQF5W.js.map +0 -1
  220. package/dist/chunk-F3BPIPLS.js.map +0 -1
  221. package/dist/chunk-GNI5STXQ.js.map +0 -1
  222. package/dist/chunk-HOR4R722.js.map +0 -1
  223. package/dist/chunk-KABJXG2F.js.map +0 -1
  224. package/dist/chunk-YULZKK4F.js.map +0 -1
  225. package/dist/executor-6ZDSDZ6V.js +0 -8
  226. package/dist/executor-AZLS3KBK.js +0 -11
  227. package/dist/executor-IDZDAFNH.js +0 -8
  228. package/dist/issue-RZP3VI6O.js +0 -12
  229. package/dist/noydb-WCMY2ZOW.js +0 -35
  230. package/dist/registry-EB6SISTA.js +0 -8
  231. package/dist/registry-IUZQVVBB.js +0 -8
  232. /package/dist/{chunk-G4SCICH5.js.map → chunk-2FU2FTXD.js.map} +0 -0
  233. /package/dist/{chunk-JD3OZAI4.js.map → chunk-3G3W65EQ.js.map} +0 -0
  234. /package/dist/{chunk-XWH4MXIU.js.map → chunk-5AXTH4QZ.js.map} +0 -0
  235. /package/dist/{chunk-4TBBMHVC.js.map → chunk-5LIROIDM.js.map} +0 -0
  236. /package/dist/{chunk-L2BNJ6HM.js.map → chunk-7H2GEJ3O.js.map} +0 -0
  237. /package/dist/{chunk-QSUK7YWK.js.map → chunk-BH3X5L6A.js.map} +0 -0
  238. /package/dist/{chunk-BQ65SS5A.js.map → chunk-BJSLBUJ7.js.map} +0 -0
  239. /package/dist/{chunk-FFXM3ZIF.js.map → chunk-BL5GYANC.js.map} +0 -0
  240. /package/dist/{chunk-6H2ZUNR7.js.map → chunk-BSZOCSDZ.js.map} +0 -0
  241. /package/dist/{chunk-ZNQYHJXX.js.map → chunk-C3HYQPV4.js.map} +0 -0
  242. /package/dist/{chunk-E2CDVKMH.js.map → chunk-CD2AVTEM.js.map} +0 -0
  243. /package/dist/{chunk-BR3AMFGS.js.map → chunk-DWEBTE2W.js.map} +0 -0
  244. /package/dist/{chunk-Z4DO7YSI.js.map → chunk-DYYYUW5D.js.map} +0 -0
  245. /package/dist/{chunk-SCJPI4Z5.js.map → chunk-E77UKJYL.js.map} +0 -0
  246. /package/dist/{chunk-OMAMZKKD.js.map → chunk-F4G63NTZ.js.map} +0 -0
  247. /package/dist/{chunk-TKIY625R.js.map → chunk-FEJDVE3Z.js.map} +0 -0
  248. /package/dist/{chunk-7Z7KSVA5.js.map → chunk-GP3SDSH2.js.map} +0 -0
  249. /package/dist/{chunk-IQLVUT37.js.map → chunk-H2MRGONI.js.map} +0 -0
  250. /package/dist/{chunk-CJORTUJ2.js.map → chunk-J7RWBXFY.js.map} +0 -0
  251. /package/dist/{chunk-AAVWKNZW.js.map → chunk-JDWE6JMX.js.map} +0 -0
  252. /package/dist/{chunk-XL35NSEN.js.map → chunk-KCEHMDZF.js.map} +0 -0
  253. /package/dist/{chunk-TS26M2SB.js.map → chunk-M476FOQ7.js.map} +0 -0
  254. /package/dist/{chunk-F4OJZIWQ.js.map → chunk-NBBMMJ2H.js.map} +0 -0
  255. /package/dist/{chunk-CZI2A4MQ.js.map → chunk-NYSYPFXJ.js.map} +0 -0
  256. /package/dist/{chunk-OQSRJG6A.js.map → chunk-PDULVIBY.js.map} +0 -0
  257. /package/dist/{chunk-DLZ2ONOD.js.map → chunk-QHM6XEAH.js.map} +0 -0
  258. /package/dist/{chunk-HBXJ37ZY.js.map → chunk-QO6RGLLD.js.map} +0 -0
  259. /package/dist/{chunk-42FEUPZQ.js.map → chunk-ROVO6NPJ.js.map} +0 -0
  260. /package/dist/{chunk-6RR3MNMG.js.map → chunk-SHX5QBCI.js.map} +0 -0
  261. /package/dist/{chunk-3YWP3WBP.js.map → chunk-SNMJ7SB3.js.map} +0 -0
  262. /package/dist/{chunk-IXBIFDEW.js.map → chunk-TIDXB5DF.js.map} +0 -0
  263. /package/dist/{chunk-FWPKCXTN.js.map → chunk-WIAOUFFB.js.map} +0 -0
  264. /package/dist/{chunk-X73VS74Y.js.map → chunk-XJV6OB4D.js.map} +0 -0
  265. /package/dist/{chunk-VLMPU56Q.js.map → chunk-XMHUK5PN.js.map} +0 -0
  266. /package/dist/{chunk-BI6ETQPF.js.map → chunk-XMVHEWF6.js.map} +0 -0
  267. /package/dist/{chunk-OB2ZJQ2D.js.map → chunk-YYVZYTWW.js.map} +0 -0
  268. /package/dist/{chunk-QVIEAYTP.js.map → chunk-ZNGPEV5J.js.map} +0 -0
  269. /package/dist/{crypto-QXQOHMHF.js.map → crypto-7BN2HDWG.js.map} +0 -0
  270. /package/dist/{delegation-NIQ43IPU.js.map → delegation-MGH5SODX.js.map} +0 -0
  271. /package/dist/{executor-6ZDSDZ6V.js.map → executor-3W63Y44O.js.map} +0 -0
  272. /package/dist/{executor-AZLS3KBK.js.map → executor-CFFWPWBJ.js.map} +0 -0
  273. /package/dist/{executor-IDZDAFNH.js.map → executor-VDQQOR4F.js.map} +0 -0
  274. /package/dist/{fanout-sidecar-67CMI3UT.js.map → fanout-sidecar-FIJJ46YG.js.map} +0 -0
  275. /package/dist/{issue-RZP3VI6O.js.map → forget/index.js.map} +0 -0
  276. /package/dist/{ledger-A3LL253R.js.map → issue-TTMGHQ2J.js.map} +0 -0
  277. /package/dist/{noydb-WCMY2ZOW.js.map → ledger-LFVLHE5H.js.map} +0 -0
  278. /package/dist/{public-envelope-YP2UWMLG.js.map → noydb-36S6GQNC.js.map} +0 -0
  279. /package/dist/{registry-EB6SISTA.js.map → public-envelope-RXZNP3V6.js.map} +0 -0
  280. /package/dist/{registry-IUZQVVBB.js.map → registry-3YFLZ7WD.js.map} +0 -0
  281. /package/dist/{registry-UTA4CLQS.js.map → registry-SECUWSGY.js.map} +0 -0
  282. /package/dist/{revoke-HNMQZSCL.js.map → registry-TGZISEWC.js.map} +0 -0
  283. /package/dist/{signer-DCMNKXSF.js.map → revoke-B54H2S2W.js.map} +0 -0
  284. /package/dist/{stale-W5PQTRYH.js.map → signer-YSXZT574.js.map} +0 -0
  285. /package/dist/{state-vault-TMXZRTY5.js.map → state-vault-W2OEABNO.js.map} +0 -0
  286. /package/dist/{vault-group-DX2HFQMX.js.map → vault-group-DHAHFX2A.js.map} +0 -0
@@ -1,7 +1,9 @@
1
1
  import { I as IndexStrategy, d as LazyQuery } from './lazy-builder-ChSqcF5t.js';
2
- import { a7 as NoydbError, o as LiveAggregation, f as AggregateSpec, e as AggregateResult, av as MoneyDescriptor, A as AggregateStrategy } from './strategy-BtW8fAjz.js';
2
+ import { L as LiveAggregation, b as AggregateSpec, a as AggregateResult, v as MoneyDescriptor, A as AggregateStrategy } from './strategy-4M9jo172.js';
3
3
  import { C as CrdtStrategy, a as CrdtMode, b as CrdtState } from './strategy-BSxFXGzb.js';
4
- import { L as LiveQuery, Q as Query, c as JoinStrategy, j as RefRegistry, R as RefDescriptor, d as JoinableSource, l as RefViolation, S as ScanBuilder } from './index-nP99bXLg.js';
4
+ import { L as LedgerEntry, F as ForgetStrategy, S as SubjectRef, b as ForgetResult } from './index-C-SSRIxP.js';
5
+ import { N as NoydbError } from './errors-Dz64FA65.js';
6
+ import { L as LiveQuery, Q as Query, c as JoinStrategy, j as RefRegistry, R as RefDescriptor, d as JoinableSource, l as RefViolation, S as ScanBuilder } from './index-DpU6KWof.js';
5
7
  import { I as IndexDef, O as Operator, F as FieldClause, C as CollectionIndexes } from './predicate-BmhBSPCH.js';
6
8
  import { AttestationFieldSchema, RevocationList } from '@noy-db/attestation';
7
9
 
@@ -415,6 +417,7 @@ declare class BlobSet {
415
417
  private readonly encrypted;
416
418
  private readonly userId;
417
419
  private readonly maxBlobBytes;
420
+ private readonly erasableBlobs;
418
421
  constructor(opts: {
419
422
  store: NoydbStore;
420
423
  vault: string;
@@ -424,7 +427,18 @@ declare class BlobSet {
424
427
  encrypted: boolean;
425
428
  userId?: string;
426
429
  maxBlobBytes?: number;
430
+ erasableBlobs?: boolean;
427
431
  });
432
+ /**
433
+ * Resolve the key the blob's CHUNKS are encrypted under.
434
+ *
435
+ * - `_cek` present (erasable blob) → unwrap the per-blob content CEK under
436
+ * the `_blob` DEK. Deleting the BlobObject (at `refCount → 0`) makes this
437
+ * key unrecoverable → the chunks are crypto-shredded.
438
+ * - `_cek` absent (legacy) → the `_blob` DEK encrypts chunks directly.
439
+ * - unencrypted vault → `null` (chunks stored as plaintext base64).
440
+ */
441
+ private resolveChunkKey;
428
442
  /** The internal collection that holds slot metadata for this collection's blobs. */
429
443
  private get slotsCollection();
430
444
  /** The internal collection that holds published versions for this collection's blobs. */
@@ -442,6 +456,73 @@ declare class BlobSet {
442
456
  * CAS retry loop for refCount changes on a BlobObject.
443
457
  */
444
458
  private casUpdateRefCount;
459
+ /**
460
+ * Release `n` references to a blob and reclaim it at refCount 0 (#365 slice 4).
461
+ *
462
+ * The single reclaim choke point for every reference-drop path — slot
463
+ * delete/overwrite, published-version delete, and `forget()` shred — so the
464
+ * refCount-0 policy is uniform:
465
+ * - **erasable blob** (`_cek` present) → delete the `BlobObject` (the SOLE
466
+ * copy of the wrapped content CEK → chunks permanently undecryptable) and
467
+ * reclaim the chunks. The crypto-shred is EAGER on every path: GDPR erasure
468
+ * must not wait on orphan retention.
469
+ * - **legacy blob** (no `_cek`) → reclaimed only when `reclaimLegacy` (the
470
+ * `forget()` erasure path); otherwise left for deferred GC so the existing
471
+ * `BlobLifecyclePolicy.orphanRetentionDays` semantics are preserved.
472
+ *
473
+ * @returns `'shredded'` (erasable, refCount 0, chunks dead) · `'retainedShared'`
474
+ * (erasable, still referenced) · `'residue'` (legacy — not a crypto-shred).
475
+ */
476
+ private releaseRef;
477
+ /**
478
+ * Crypto-shred this record's blob attachments (#365 slice 2) — called by
479
+ * `vault.forget()`.
480
+ *
481
+ * For each distinct eTag the record references (a record may attach the same
482
+ * content under several slot names → several refCount holds): decrement the
483
+ * blob's refCount by that many. When it reaches 0:
484
+ * - **erasable blob** (`_cek` present) → delete the `BlobObject` (the SOLE
485
+ * recoverable copy of the wrapped content CEK → chunks permanently
486
+ * undecryptable) and reclaim the chunk bytes. This is the crypto-shred.
487
+ * - **legacy blob** (no `_cek`) → chunks are under the shared `_blob` DEK and
488
+ * stay decryptable until byte-deleted; we delete the orphaned chunks +
489
+ * index but report it as residue, not a cryptographic erasure.
490
+ * When refCount stays > 0 the content legitimately persists for its other
491
+ * owner — reported as `retainedShared` (or `residue` if legacy).
492
+ *
493
+ * Finally drops the record's slot map, severing the subject's link.
494
+ */
495
+ shredAllForRecord(): Promise<{
496
+ shredded: string[];
497
+ retainedShared: string[];
498
+ residue: string[];
499
+ }>;
500
+ /** CAS retry loop for an arbitrary BlobObject mutation. */
501
+ private casUpdateBlobObject;
502
+ /**
503
+ * Migrate this record's LEGACY blobs (no `_cek`, chunks under the shared
504
+ * `_blob` DEK) to per-blob content CEKs so they become crypto-shreddable
505
+ * (#365 slice 3). Returns the eTags migrated vs. already-erasable.
506
+ *
507
+ * **Explicit maintenance pass** (mirrors the record-CEK migration posture):
508
+ * re-encrypts the existing compressed chunks IN PLACE under a fresh content
509
+ * CEK — preserving the eTag, chunkCount, chunkSize, and compression — then
510
+ * flips the `_cek` discriminant. Crash-safe + idempotent via `_cekPending`:
511
+ * 1. persist the wrapped content CEK in `_cekPending` (readers ignore it →
512
+ * the blob stays readable under the `_blob` DEK; the key survives a crash);
513
+ * 2. re-encrypt each chunk under the content CEK (a resume reads an
514
+ * already-migrated chunk under the content CEK, else under the `_blob` DEK);
515
+ * 3. promote `_cekPending` → `_cek` (atomic flip). Reads now use the CEK.
516
+ * A re-run after a crash resumes from whichever phase was reached.
517
+ *
518
+ * Dedup-safe: migrating a shared blob (refCount > 1) re-keys it for every
519
+ * referencer at once; a non-erasable collection still reads it (it unwraps
520
+ * `_cek` under the `_blob` DEK it holds).
521
+ */
522
+ migrate(): Promise<{
523
+ migrated: string[];
524
+ alreadyErasable: string[];
525
+ }>;
445
526
  private writeChunk;
446
527
  private readChunk;
447
528
  private versionKey;
@@ -598,6 +679,13 @@ interface BlobStrategyOpenArgs {
598
679
  readonly getDEK: (collectionName: string) => Promise<CryptoKey>;
599
680
  readonly encrypted: boolean;
600
681
  readonly userId: string;
682
+ /**
683
+ * Collection opts into per-record keys (`perRecordKeys`), so its blobs are
684
+ * erasable: new uploads mint a per-blob content CEK (crypto-shreddable at
685
+ * `refCount → 0`). Off → legacy shared-`_blob`-DEK chunks. See the per-blob
686
+ * CEK design spec.
687
+ */
688
+ readonly erasableBlobs?: boolean;
601
689
  }
602
690
  /**
603
691
  * The seam interface. `@internal` — do not build public APIs on this
@@ -807,224 +895,6 @@ interface ConsentStrategy {
807
895
  read(adapter: NoydbStore, vault: string, encrypted: boolean, getDEK: (collectionName: string) => Promise<CryptoKey>, filter?: ConsentAuditFilter): Promise<ConsentAuditEntry[]>;
808
896
  }
809
897
 
810
- /**
811
- * Ledger entry shape + canonical JSON + sha256 helpers.
812
- *
813
- * This file holds the PURE primitives used by the hash-chained ledger:
814
- * the entry type, the deterministic (sort-stable) JSON encoder, and
815
- * the sha256 hasher that produces `prevHash` and `ledger.head()`.
816
- *
817
- * Everything here is validator-free and side-effect free — the only
818
- * runtime dep is Web Crypto's `subtle.digest` for the sha256 call,
819
- * which we already use for every other hashing operation in the core.
820
- *
821
- * The hash chain property works like this:
822
- *
823
- * hash(entry[i]) = sha256(canonicalJSON(entry[i]))
824
- * entry[i+1].prevHash = hash(entry[i])
825
- *
826
- * Any modification to `entry[i]` (field values, field order, whitespace)
827
- * produces a different `hash(entry[i])`, which means `entry[i+1]`'s
828
- * stored `prevHash` no longer matches the recomputed hash, which means
829
- * `verify()` returns `{ ok: false, divergedAt: i + 1 }`. The chain is
830
- * append-only and tamper-evident without external anchoring.
831
- */
832
- /**
833
- * A single ledger entry in its plaintext form — what gets serialized,
834
- * hashed, and then encrypted with the ledger DEK before being written
835
- * to the `_ledger/` adapter collection.
836
- *
837
- * ## Why hash the ciphertext, not the plaintext?
838
- *
839
- * `payloadHash` is the sha256 of the record's ENCRYPTED envelope bytes,
840
- * not its plaintext. This matters:
841
- *
842
- * 1. **Zero-knowledge preserved.** A user (or a third party) can
843
- * verify the ledger against the stored envelopes without any
844
- * decryption keys. The adapter layer already holds only
845
- * ciphertext, so hashing the ciphertext keeps the ledger at the
846
- * same privacy level as the adapter.
847
- *
848
- * 2. **Determinism.** Plaintext → ciphertext is randomized by the
849
- * fresh per-write IV, so `hash(plaintext)` would need extra
850
- * normalization. `hash(ciphertext)` is already deterministic and
851
- * unique per write.
852
- *
853
- * 3. **Detection property.** If an attacker modifies even one byte of
854
- * the stored ciphertext (trying to flip a record), the hash
855
- * changes, the ledger's recorded `payloadHash` no longer matches,
856
- * and a data-integrity check fails. We don't do that check in
857
- * `verify()` today, but the
858
- * hook is there for a future `verifyIntegrity()` follow-up.
859
- *
860
- * Fields marked `op`, `collection`, `id`, `version`, `ts`, `actor` are
861
- * plaintext METADATA about the operation — NOT the record itself. The
862
- * entry is still encrypted at rest via the ledger DEK, but adapters
863
- * could theoretically infer operation patterns from the sizes and
864
- * timestamps. This is an accepted trade-off for the tamper-evidence
865
- * property; full ORAM-level privacy is out of scope for noy-db.
866
- */
867
- interface LedgerEntry {
868
- /**
869
- * Zero-based sequential position of this entry in the chain. The
870
- * canonical adapter key is this number zero-padded to 10 digits
871
- * (`"0000000001"`) so lexicographic ordering matches numeric order.
872
- */
873
- readonly index: number;
874
- /**
875
- * Hex-encoded sha256 of the canonical JSON of the PREVIOUS entry.
876
- * The genesis entry (index 0) has `prevHash === ''` — the first
877
- * entry in a fresh vault has nothing to point back to.
878
- */
879
- readonly prevHash: string;
880
- /**
881
- * Which kind of mutation this entry records. only supports
882
- * data operations (`put`, `delete`, `amendment`). Access-control
883
- * operations (`grant`, `revoke`, `rotate`) will be added in a
884
- * follow-up once the keyring write path is instrumented — that's
885
- * tracked in the epic issue.
886
- *
887
- * `'amendment'` is the multi-record audit entry written by the
888
- * guards subsystem when an admin/owner uses `withTransactions(...)`
889
- * to repair a constraint-violating state. See `amendment` field
890
- * below for the structured payload.
891
- *
892
- * `'lifecycle'` records a non-data audit event (e.g. partition
893
- * handover) — `collection`/`id` are empty and the event detail
894
- * lives in `reason` (e.g. `'partition-handed-over:<sealId>'`). Like
895
- * `amendment`, it carries no data envelope, so `verifyBackupIntegrity`
896
- * skips it in the data cross-check (it still participates in the
897
- * tamper-evident chain).
898
- */
899
- readonly op: 'put' | 'delete' | 'amendment' | 'lifecycle' | 'migration';
900
- /** The collection the mutation targeted. */
901
- readonly collection: string;
902
- /** The record id the mutation targeted. */
903
- readonly id: string;
904
- /**
905
- * The record version AFTER this mutation. For `put` this is the
906
- * newly assigned version; for `delete` this is the version that
907
- * was deleted (the last version visible to reads).
908
- */
909
- readonly version: number;
910
- /** ISO timestamp of the mutation. */
911
- readonly ts: string;
912
- /** User id of the actor who performed the mutation. */
913
- readonly actor: string;
914
- /**
915
- * Hex-encoded sha256 of the encrypted envelope's `_data` field.
916
- * For `put`, this is the hash of the new ciphertext. For `delete`,
917
- * it's the hash of the last visible ciphertext at deletion time,
918
- * or the empty string if nothing was there to delete. Hashing the
919
- * ciphertext (not the plaintext) preserves zero-knowledge — see
920
- * the file docstring.
921
- */
922
- readonly payloadHash: string;
923
- /**
924
- * Optional human-readable tag describing why this mutation happened.
925
- * Threaded through `collection.put(_, _, { reason })`. Common
926
- * values include `'import:csv'`, `'import:json'`, `'import:xlsx'` from
927
- * `as-*` ImportPlan.apply(), but consumers can use any string for
928
- * domain-specific audit filtering. Auto-strip via `canonicalJson` —
929
- * absent on the wire, never serialized as `null`.
930
- *
931
- * Audit consumers filter: `entries.filter(e => e.reason?.startsWith('import:'))`.
932
- */
933
- readonly reason?: string;
934
- /**
935
- * Optional hex-encoded sha256 of the encrypted JSON Patch delta
936
- * blob stored alongside this entry in `_ledger_deltas/`. Present
937
- * only for `put` operations that had a previous version — the
938
- * genesis put of a new record, and every `delete`, leave this
939
- * field undefined.
940
- *
941
- * The delta payload itself lives in a sibling internal collection
942
- * (`_ledger_deltas/<paddedIndex>`) and is encrypted with the
943
- * ledger DEK. Callers use `ledger.loadDelta(index)` to decrypt and
944
- * deserialize it when reconstructing a historical version.
945
- *
946
- * Why optional instead of always-present: the first put of a
947
- * record has no previous version to diff against, so storing an
948
- * empty patch would be noise. For deletes there's no "next" state
949
- * to describe with a delta. Both cases set this field to undefined.
950
- *
951
- * Note: the canonical-JSON hasher treats `undefined` as invalid
952
- * (it's one of the guard rails), so on the wire this field is
953
- * either `{ deltaHash: '<hex>' }` or absent from the JSON
954
- * entirely — never `{ deltaHash: undefined }`.
955
- */
956
- readonly deltaHash?: string;
957
- /**
958
- * Present only when `op === 'amendment'`. Records the human reason,
959
- * the role of the actor, the (collection, id, vBefore, vAfter) tuple
960
- * for every record touched, and which guard invariants passed.
961
- *
962
- * See docs/superpowers/specs/2026-05-18-guards-design.md.
963
- */
964
- readonly amendment?: {
965
- readonly reason: string;
966
- readonly role: 'admin' | 'owner';
967
- readonly changes: ReadonlyArray<{
968
- readonly collection: string;
969
- readonly id: string;
970
- readonly vBefore: number;
971
- readonly vAfter: number;
972
- }>;
973
- readonly invariantsPassed: ReadonlyArray<string>;
974
- };
975
- }
976
- /**
977
- * Canonical (sort-stable) JSON encoder.
978
- *
979
- * This function is the load-bearing primitive of the hash chain:
980
- * `sha256(canonicalJSON(entry))` must produce the same hex string
981
- * every time, on every machine, for the same logical entry — otherwise
982
- * `verify()` would return `{ ok: false }` on cross-platform reads.
983
- *
984
- * JavaScript's `JSON.stringify` is almost canonical, but NOT quite:
985
- * it preserves the insertion order of object keys, which means
986
- * `{a:1,b:2}` and `{b:2,a:1}` serialize differently. We fix this by
987
- * recursively walking objects and sorting their keys before
988
- * concatenation.
989
- *
990
- * Arrays keep their original order (reordering them would change
991
- * semantics). Numbers, strings, booleans, and `null` use the default
992
- * JSON encoding. `undefined` and functions are rejected — ledger
993
- * entries are plain data, and silently dropping `undefined` would
994
- * break the "same input → same hash" property if a caller forgot to
995
- * omit a field.
996
- *
997
- * Performance: one pass per nesting level; O(n log n) for key sorting
998
- * at each object. Entries are small (< 1 KB) so this is negligible
999
- * compared to the sha256 call.
1000
- */
1001
- declare function canonicalJson(value: unknown): string;
1002
- /**
1003
- * Compute a hex-encoded sha256 of a string via Web Crypto's subtle API.
1004
- *
1005
- * We use hex (not base64) for hashes because hex is case-insensitive,
1006
- * fixed-length (64 chars), and easier to compare visually in debug
1007
- * output. Base64 would save a few bytes in storage but every encrypted
1008
- * ledger entry is already much larger than the hash itself.
1009
- */
1010
- declare function sha256Hex(input: string): Promise<string>;
1011
- /**
1012
- * Compute the canonical hash of a ledger entry. Short wrapper around
1013
- * `canonicalJson` + `sha256Hex`; callers use this instead of composing
1014
- * the two functions every time, so any future change to the hashing
1015
- * pipeline (e.g., adding a domain-separation prefix) lives in one place.
1016
- */
1017
- declare function hashEntry(entry: LedgerEntry): Promise<string>;
1018
- /**
1019
- * Pad an index to the canonical 10-digit form used as the adapter key.
1020
- * Ten digits is enough for ~10 billion ledger entries per vault
1021
- * — far beyond any realistic use case, but cheap enough that the extra
1022
- * digits don't hurt storage.
1023
- */
1024
- declare function paddedIndex(index: number): string;
1025
- /** Parse a padded adapter key back into a number. Returns NaN on malformed input. */
1026
- declare function parseIndex(key: string): number;
1027
-
1028
898
  /**
1029
899
  * RFC 6902 JSON Patch — compute + apply.
1030
900
  *
@@ -2572,6 +2442,88 @@ declare function dictKey<Keys extends string>(name: string, keys?: readonly Keys
2572
2442
  }): DictKeyDescriptor<Keys>;
2573
2443
  /** Runtime predicate for detecting a DictKeyDescriptor. */
2574
2444
  declare function isDictKeyDescriptor(x: unknown): x is DictKeyDescriptor;
2445
+ /**
2446
+ * Descriptor returned by `staticDict()`. A sibling to {@link DictKeyDescriptor}
2447
+ * for **closed, defined-in-code, identical-across-vaults** enums (honorific,
2448
+ * civil-status, gender, religion, ContactTitle, status…).
2449
+ *
2450
+ * Unlike `dictKey`, the labels are supplied **at registration in code** and
2451
+ * resolved through the *same* label machinery, but with **no `_dict_*`
2452
+ * per-vault encrypted copy** and **no `rename()`**. The record stores only
2453
+ * the **code**; a static dict has no mutation surface.
2454
+ *
2455
+ * **Hybrid resolution.** Because a static dict is pure code with no
2456
+ * vault-locale dependency, it can — via a configured `displayLocale` — emit a
2457
+ * `<field>Label` even under a **locale-less read** (the property a locale-less
2458
+ * consumer needs and `dictKey` cannot provide). When a locale *is* active it
2459
+ * behaves exactly like `dictKey` (honoring `onMissing`/`substitute`).
2460
+ *
2461
+ * ```ts
2462
+ * const workers = vault.collection<Worker>('workers', {
2463
+ * dictKeyFields: {
2464
+ * civilStatus: staticDict('civilStatus', {
2465
+ * adultMale: { th: 'นาย', en: 'Mr' },
2466
+ * adultFemale: { th: 'นาง', en: 'Mrs' },
2467
+ * }, { displayLocale: 'th' }),
2468
+ * },
2469
+ * })
2470
+ * ```
2471
+ */
2472
+ interface StaticDictDescriptor<Keys extends string = string> {
2473
+ readonly _noydbStaticDict: true;
2474
+ /** Which dictionary this field references (the registry name). */
2475
+ readonly name: string;
2476
+ /** The in-code label table: key → { locale → label }. */
2477
+ readonly table: Readonly<Record<Keys, Readonly<Record<string, string>>>>;
2478
+ /** Declared valid keys — derived from `Object.keys(table)`. */
2479
+ readonly keys: readonly Keys[];
2480
+ /**
2481
+ * Locale used to emit `<field>Label` under a **locale-less** read — the
2482
+ * hybrid hinge. When unset, a static dict behaves like `dictKey` under a
2483
+ * locale-less read (no label); a locale-less consumer almost always wants
2484
+ * it set.
2485
+ */
2486
+ readonly displayLocale?: string;
2487
+ /** Same `onMissing` policy engine as `dictKey`. Default `'null'`. */
2488
+ readonly onMissing?: OnMissingPolicy;
2489
+ /** Ordered preferred-substitute locales for label resolution. */
2490
+ readonly substitute?: readonly string[];
2491
+ /**
2492
+ * Validate the stored code against `keys` on every `put()`. Default `true`
2493
+ * — codes are closed by construction, so an unknown code is a bug. Set
2494
+ * `false` to allow open codes (skips the `UnknownDictCodeError` guard).
2495
+ */
2496
+ readonly validateCodes?: boolean;
2497
+ }
2498
+ /**
2499
+ * Create a `StaticDictDescriptor` for a code-provided enum field — a sibling
2500
+ * to {@link dictKey} for closed, code-defined, identical-across-vaults enums.
2501
+ *
2502
+ * The labels live in `table` (no `_dict_*` collection, no `rename()`); the
2503
+ * record stores only the stable code. Pass `displayLocale` so `<field>Label`
2504
+ * resolves even under a locale-less read.
2505
+ *
2506
+ * @param name The dictionary name (used for the readonly-guard registry and
2507
+ * the query label seam — never creates a `_dict_<name>` key).
2508
+ * @param table `{ key: { locale: label } }` map.
2509
+ * @param opts `displayLocale` (locale-less label), `onMissing`, `substitute`.
2510
+ *
2511
+ * @example
2512
+ * ```ts
2513
+ * staticDict('civilStatus', {
2514
+ * adultMale: { th: 'นาย', en: 'Mr' },
2515
+ * adultFemale: { th: 'นาง', en: 'Mrs' },
2516
+ * }, { displayLocale: 'th' })
2517
+ * ```
2518
+ */
2519
+ declare function staticDict<const T extends Record<string, Record<string, string>>>(name: string, table: T, opts?: {
2520
+ displayLocale?: string;
2521
+ onMissing?: OnMissingPolicy;
2522
+ substitute?: readonly string[];
2523
+ validateCodes?: boolean;
2524
+ }): StaticDictDescriptor<Extract<keyof T, string>>;
2525
+ /** Runtime predicate for detecting a StaticDictDescriptor. */
2526
+ declare function isStaticDictDescriptor(x: unknown): x is StaticDictDescriptor;
2575
2527
  /**
2576
2528
  * One entry in a `_dict_*` collection. The record `id` (adapter-side
2577
2529
  * key) IS the stable dictionary key (e.g. `'paid'`). The `labels`
@@ -3475,6 +3427,12 @@ interface HistoryStrategy {
3475
3427
  * `NO_HISTORY`.
3476
3428
  */
3477
3429
  clearHistory(adapter: NoydbStore, vault: string, collection?: string, recordId?: string): Promise<number>;
3430
+ /**
3431
+ * Crypto-shred (overwrite-to-tombstone) every `_history` version of a
3432
+ * record for GDPR erasure (#304). Returns the number of versions newly
3433
+ * tombstoned, or `0` under `NO_HISTORY` (no history = nothing to shred).
3434
+ */
3435
+ tombstoneHistory(adapter: NoydbStore, vault: string, collection: string, recordId: string, actor: string): Promise<number>;
3478
3436
  /**
3479
3437
  * Compute the SHA-256 hash of an envelope's encrypted payload, used
3480
3438
  * by `LedgerStore.append` to track tamper-evidence. Returns the
@@ -5737,6 +5695,7 @@ declare class Noydb {
5737
5695
  private readonly policyEnforcers;
5738
5696
  private readonly vaultTemplates;
5739
5697
  private readonly txStrategy;
5698
+ private readonly forgetStrategy;
5740
5699
  private readonly sessionStrategy;
5741
5700
  private readonly syncStrategy;
5742
5701
  private readonly snapshotStrategy;
@@ -5761,6 +5720,8 @@ declare class Noydb {
5761
5720
  /** Audit log for all translator invocations in this session. Cleared on `close()`. */
5762
5721
  private readonly _translatorAuditLog;
5763
5722
  constructor(options: NoydbOptions);
5723
+ /** @internal — resolved forget strategy (NO_FORGET when not configured). */
5724
+ get _forgetStrategy(): ForgetStrategy;
5764
5725
  private resetSessionTimer;
5765
5726
  /**
5766
5727
  * Attach a policy enforcer for a vault.
@@ -7761,58 +7722,339 @@ declare class ReadOnlyVaultFacade implements ReadOnlyVaultFacade$1 {
7761
7722
  }
7762
7723
 
7763
7724
  /**
7764
- * `vault.exportBlobs()`bulk blob extraction primitive.
7725
+ * Managed-passphrase mode rubber-hose-resistant vaults.
7765
7726
  *
7766
- * Async-iterable handle over every blob attached to records in a
7767
- * vault, optionally filtered by collection allowlist and per-record
7768
- * predicate. Emits tuples of `{ blobId, recordRef, bytes, meta }` so
7769
- * the consumer can pipe into any sink (zip stream, S3 multipart, USB
7770
- * copy, cold-storage tape) without pulling the whole export into
7771
- * memory.
7727
+ * A vault mode where the passphrase is machine-generated and never
7728
+ * exposed to the user, sealed under a developer-provided
7729
+ * {@link SealingKeyProvider} (macOS Keychain, Windows Credential
7730
+ * Manager, libsecret, AWS KMS, …). The user has no secret to give
7731
+ * up to coercion they can't reveal what they don't know.
7772
7732
  *
7773
- * ## Auth + audit
7733
+ * ## Components in this file
7774
7734
  *
7775
- * - Capability check runs **once** at handle creation via
7776
- * `Vault.assertCanExport('plaintext', 'blob')`. An operator whose
7777
- * keyring lacks that bit fails before a single byte of ciphertext
7778
- * is decrypted.
7779
- * - Audit entry lands in `_export_audit` at handle creation: the
7780
- * actor, start timestamp, target collections, predicate presence,
7781
- * and batch mechanism. **No content hashes** per the spec
7782
- * non-correlation invariant.
7735
+ * - {@link SealingKeyProvider} the interface concrete providers
7736
+ * implement. Provider implementations live OUTSIDE hub (per-
7737
+ * platform packages).
7738
+ * - {@link MemorySealingKeyProvider} — in-memory test provider; uses
7739
+ * a deterministic per-instance "key" so two providers with
7740
+ * different ids cannot unseal each other's outputs.
7741
+ * - {@link RecipientHint} public material a sender uses to seal
7742
+ * plaintext for a specific recipient; published by
7743
+ * {@link RecipientSealer.publishRecipientHint} and transported
7744
+ * out-of-band to the sender before bundle writes.
7745
+ * - {@link RecipientSealer} — interface for asymmetric/granted
7746
+ * providers that support recipient-target sealing (RSA-OAEP,
7747
+ * cloud-KMS asymmetric, etc.); distinct from self-only
7748
+ * {@link SealingKeyProvider} (macOS Keychain, WebAuthn-PRF).
7749
+ * - {@link MemoryRecipientSealer} — in-process reference
7750
+ * implementation of both `RecipientSealer` and
7751
+ * `SealingKeyProvider` using real WebCrypto RSA-OAEP + AES-GCM;
7752
+ * safe for tests and same-process sender/recipient scenarios.
7753
+ * - {@link loadSealedPassphrase} / {@link saveSealedPassphrase} —
7754
+ * plaintext envelope storage at `_meta/sealed-passphrase`.
7755
+ * Mirrors the `_meta/handle` and `_meta/public-envelope` AES-
7756
+ * GCM-bypassed patterns. The sealing layer (provider's job)
7757
+ * is the security boundary; hub doesn't have a key to encrypt
7758
+ * with at this layer — that's the whole point of the design.
7759
+ * - {@link resolveManagedSecret} — orchestrates the "generate +
7760
+ * seal + persist on first open; unseal on reopen" flow.
7761
+ * Returns the plaintext passphrase string that the rest of the
7762
+ * `createNoydb` keyring path consumes.
7783
7763
  *
7784
- * ## Abort + resume
7764
+ * Deferred to follow-ups:
7765
+ * - Block `rotate-passphrase` policy gate under managed mode.
7766
+ * - Mandatory strong-recovery enforcement.
7767
+ * - Recovery flow under managed mode (generates fresh sealed phrase).
7785
7768
  *
7786
- * - `handle.abort()` flips the internal signal; the next iteration
7787
- * boundary throws `AbortError`. Consumers already in `for await`
7788
- * can catch and exit cleanly.
7789
- * - Restart after a partial failure with `{ afterBlobId }` — the
7790
- * iterator skips tuples up to (and including) that blob id before
7791
- * yielding again. Combined with a blob-count ceiling it supports
7792
- * idempotent batch re-runs.
7769
+ * @see docs/subsystems/session-tiers.md Managed-passphrase mode
7793
7770
  *
7794
7771
  * @module
7795
7772
  */
7796
7773
 
7797
- interface ExportBlobsOptions {
7774
+ /**
7775
+ * The contract concrete providers (per-platform key stores) implement
7776
+ * to seal and unseal a hub-generated random passphrase. The plaintext
7777
+ * passphrase NEVER leaves hub-controlled memory in unsealed form —
7778
+ * the provider receives the bytes, returns opaque sealed bytes, and
7779
+ * later reverses the operation. Hub treats the sealed bytes as
7780
+ * fully opaque.
7781
+ *
7782
+ * Implementations live OUTSIDE `@noy-db/hub` (separate packages
7783
+ * per the issue's "Concrete providers (live outside hub)" note):
7784
+ *
7785
+ * | Platform | Package (TBD) | Backing |
7786
+ * |---|---|---|
7787
+ * | macOS | `@noy-db/seal-macos-keychain` | Security.framework |
7788
+ * | Windows | `@noy-db/seal-wincred` | Credential Manager |
7789
+ * | Linux | `@noy-db/seal-libsecret` | libsecret / secret-service |
7790
+ * | Cloud / server | `@noy-db/seal-aws-kms` | AWS KMS Decrypt |
7791
+ */
7792
+ interface SealingKeyProvider {
7798
7793
  /**
7799
- * Collection allowlist. Omit to export blobs from every collection
7800
- * the caller has read access to.
7794
+ * Non-sensitive identifier disclosed in the persisted envelope.
7795
+ * Surfaced to consumers via `loadSealedPassphrase().providerId` so
7796
+ * a vault opened with the wrong provider class can detect the
7797
+ * mismatch and surface a clear error. NOT secret — fine to log.
7798
+ *
7799
+ * Suggested format: `<family>:<scope>` — e.g. `macos-keychain:com.acme.app`,
7800
+ * `aws-kms:arn:aws:kms:us-east-1:123:key/abc`. The hub never
7801
+ * parses this; it's purely audit metadata.
7801
7802
  */
7802
- readonly collections?: readonly string[];
7803
+ readonly id: string;
7804
+ /** Seal raw passphrase bytes. Output bytes are opaque to hub. */
7805
+ seal(passphrase: Uint8Array): Promise<Uint8Array>;
7803
7806
  /**
7804
- * Per-record predicate. Called on the decrypted record BEFORE any
7805
- * blob bytes are read for that record returning false skips the
7806
- * record and all its slots without touching their chunks.
7807
+ * Reverse {@link seal}. MUST throw on tamper, wrong-provider, or
7808
+ * any other failure hub treats a thrown error as "this provider
7809
+ * cannot unlock this vault" and surfaces it to the caller.
7807
7810
  */
7808
- readonly where?: (record: unknown, context: {
7809
- collection: string;
7811
+ unseal(sealed: Uint8Array): Promise<Uint8Array>;
7812
+ }
7813
+ /**
7814
+ * In-memory test provider. NOT secure — uses a deterministic
7815
+ * per-instance "key" (16-byte SHA-256 of `id`) XOR'd over the
7816
+ * passphrase plus a 4-byte provider-id fingerprint prefix. The XOR is
7817
+ * sufficient to make different `id` values produce mutually-unsealable
7818
+ * outputs (the contract tests for that), but offers ZERO real
7819
+ * confidentiality — never use outside tests.
7820
+ *
7821
+ * Replace with a real platform provider in production.
7822
+ */
7823
+ declare class MemorySealingKeyProvider implements SealingKeyProvider {
7824
+ readonly id: string;
7825
+ private readonly fingerprint;
7826
+ private readonly keyBytes;
7827
+ constructor(opts: {
7810
7828
  id: string;
7811
- }) => boolean;
7829
+ });
7830
+ seal(passphrase: Uint8Array): Promise<Uint8Array>;
7831
+ unseal(sealed: Uint8Array): Promise<Uint8Array>;
7832
+ }
7833
+ /**
7834
+ * Public material a sender uses to seal-for-this-recipient. Published by
7835
+ * a recipient's RecipientSealer; transported to the sender out-of-band
7836
+ * (email, S3, in-app message). The sender obtains the hint, supplies it
7837
+ * to writeNoydbBundle's sealedCredentials.perUser[userId].hint, and the
7838
+ * hub seals each user's credential against it. Per foundation §11.4.
7839
+ */
7840
+ type RecipientHint = {
7841
+ readonly v: 1;
7842
+ /** Recipient's provider id; matches the SealedAutoUnlockEntry.pid they'll unseal under. */
7843
+ readonly pid: string;
7844
+ /** Algorithm the sender uses to produce the seal. Slice 1 ships RSA-OAEP-SHA256 only. */
7845
+ readonly alg: 'rsa-oaep-sha256';
7846
+ /** Public material — alg-specific. For 'rsa-oaep-sha256': { publicKeyPem: string }. */
7847
+ readonly material: Readonly<Record<string, unknown>>;
7848
+ };
7849
+ /**
7850
+ * Handover-capable provider. Implemented additionally by asymmetric/granted
7851
+ * providers (cloud-KMS asymmetric, Azure RSA Key Vault, AWS KMS with grant).
7852
+ * Self-only providers (macOS Keychain, env-var, WebAuthn-PRF) do NOT
7853
+ * implement this — the §11.2 capability matrix lives in the type system.
7854
+ *
7855
+ * Per foundation §11.4. A function that requires recipient-target sealing
7856
+ * takes `RecipientSealer`, not `SealingKeyProvider` — the compiler rejects
7857
+ * passing a self-only provider at the spec site.
7858
+ */
7859
+ interface RecipientSealer {
7860
+ readonly id: string;
7861
+ /** Produce hint material a sender uses to seal-for-this-recipient. */
7862
+ publishRecipientHint(): Promise<RecipientHint>;
7812
7863
  /**
7813
- * Resume after a specific blob id. The iterator skips tuples up to
7814
- * and including this id, then yields. Format of the id is the same
7815
- * as `ExportedBlob.blobId` (the HMAC-keyed eTag).
7864
+ * Seal plaintext for the recipient described by `hint`. Returns opaque
7865
+ * bytes same contract as `SealingKeyProvider.seal()`. The bundle
7866
+ * layer base64-encodes the bytes into `SealedAutoUnlockEntry.sealed`
7867
+ * without inspecting them.
7868
+ */
7869
+ sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array>;
7870
+ }
7871
+ /**
7872
+ * Shared RSA-OAEP-SHA256 + AES-GCM seal in the canonical recipient-target
7873
+ * TLV wire format. Mints a fresh 32-byte CEK, AES-GCM-encrypts `plaintext`
7874
+ * under it, RSA-OAEP-SHA256-wraps the CEK to `publicKeyPem`, and packs:
7875
+ *
7876
+ * byte 0 : version (0x01)
7877
+ * bytes 1..256 : RSA-OAEP-wrapped CEK (fixed 256 bytes at RSA-2048)
7878
+ * bytes 257..268: AES-GCM IV (12 bytes)
7879
+ * bytes 269.. : AES-GCM ciphertext ‖ 16-byte tag
7880
+ *
7881
+ * This is the single source of truth for the wire format — both
7882
+ * {@link MemoryRecipientSealer} and external sealers (e.g. `@noy-db/at-aws-kms`'s
7883
+ * asymmetric-KMS recipient sealer) call it so a blob sealed by one unseals
7884
+ * by the other. WebCrypto RSA-OAEP/SHA-256 here is wire-compatible with
7885
+ * AWS KMS `RSAES_OAEP_SHA_256` (both RSAES-OAEP, SHA-256 hash, MGF1-SHA256,
7886
+ * empty label).
7887
+ *
7888
+ * @public — re-exported from the hub barrel for external sealer packages.
7889
+ */
7890
+ declare function sealRsaOaepTlv(plaintext: Uint8Array, publicKeyPem: string): Promise<Uint8Array>;
7891
+ /**
7892
+ * Parse a {@link sealRsaOaepTlv} blob into its three segments without
7893
+ * decrypting. The `wrapped` CEK is RSA-OAEP-SHA256 ciphertext over a
7894
+ * 32-byte CEK — the unwrap step is pluggable: {@link MemoryRecipientSealer}
7895
+ * decrypts it with a local RSA private key; `@noy-db/at-aws-kms` hands it to
7896
+ * KMS `Decrypt`. After unwrapping, pass the CEK + `iv` + `ct` to
7897
+ * {@link aesGcmOpen}.
7898
+ *
7899
+ * @public — re-exported from the hub barrel for external sealer packages.
7900
+ */
7901
+ declare function parseRsaOaepTlv(bytes: Uint8Array): {
7902
+ wrapped: Uint8Array;
7903
+ iv: Uint8Array;
7904
+ ct: Uint8Array;
7905
+ };
7906
+ /**
7907
+ * AES-GCM-decrypt the `ct` segment of a {@link parseRsaOaepTlv} result under
7908
+ * the unwrapped 32-byte CEK and its `iv`. Throws on a bad tag (tamper) — the
7909
+ * same authenticated-decryption guarantee the TLV relies on.
7910
+ *
7911
+ * @public — re-exported from the hub barrel for external sealer packages.
7912
+ */
7913
+ declare function aesGcmOpen(cekBytes: Uint8Array, iv: Uint8Array, ct: Uint8Array): Promise<Uint8Array>;
7914
+ /**
7915
+ * Reference implementation of `RecipientSealer` + `SealingKeyProvider`.
7916
+ * Uses WebCrypto RSA-OAEP-SHA256 (2048-bit) to wrap a fresh 32-byte
7917
+ * AES-GCM CEK, AES-GCM-encrypts plaintext under it, and packs the
7918
+ * result into a self-describing TLV:
7919
+ *
7920
+ * byte 0 : version (0x01)
7921
+ * bytes 1..256 : RSA-OAEP-wrapped CEK (fixed 256 bytes at RSA-2048)
7922
+ * bytes 257..268: AES-GCM IV (12 bytes)
7923
+ * bytes 269.. : AES-GCM ciphertext ‖ 16-byte tag
7924
+ *
7925
+ * Implements BOTH interfaces. `seal(plaintext)` (self-target) is just
7926
+ * `sealForRecipient(plaintext, this own hint)` — same TLV. Convenient
7927
+ * for tests where one provider plays both ends. Real cloud providers
7928
+ * (`at-aws-kms`, etc.) will pick their own internal layouts; the only
7929
+ * contract is round-trip identity.
7930
+ *
7931
+ * SAFE for production within its scope — the cryptography is real
7932
+ * (RSA-OAEP + AES-GCM via WebCrypto), but the keypair lives in-process
7933
+ * and is regenerated on every construction. Not suitable as a managed
7934
+ * keychain; use it for tests and for shipping bundles where the
7935
+ * recipient instance lives in the same process as the sender (rare).
7936
+ */
7937
+ declare class MemoryRecipientSealer implements SealingKeyProvider, RecipientSealer {
7938
+ readonly id: string;
7939
+ private readonly keypair;
7940
+ constructor(opts: {
7941
+ id: string;
7942
+ });
7943
+ publishRecipientHint(): Promise<RecipientHint>;
7944
+ sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array>;
7945
+ seal(plaintext: Uint8Array): Promise<Uint8Array>;
7946
+ unseal(bytes: Uint8Array): Promise<Uint8Array>;
7947
+ }
7948
+ /** Reserved id for the managed-passphrase envelope under `_meta`. */
7949
+ declare const SEALED_PASSPHRASE_RECORD_ID: "sealed-passphrase";
7950
+ /** Plaintext payload stored inside the `_meta/sealed-passphrase` envelope. */
7951
+ interface SealedPassphrase {
7952
+ readonly _noydb_sealed: 1;
7953
+ readonly providerId: string;
7954
+ /** Sealed bytes. Base64-encoded on the wire; decoded on load. */
7955
+ readonly sealed: Uint8Array;
7956
+ }
7957
+ /**
7958
+ * Wire-format envelope persisted at `_meta/sealed-passphrase` for
7959
+ * managed-mode vaults. The provider produces raw sealed bytes via
7960
+ * {@link SealingKeyProvider.seal}; this wrapper carries the dispatch
7961
+ * metadata hub needs to pick the right provider on the unseal path.
7962
+ *
7963
+ * Stability boundary: once shipped, the wire format only grows by
7964
+ * adding optional fields. See the at-* sealing dimension foundation
7965
+ * doc, §11.9.1.
7966
+ *
7967
+ * v1 shape (this release): `{ v: 1, _noydb_sealed: 1, pid, payload }`.
7968
+ *
7969
+ * Legacy shape (earlier releases): `{ _noydb_sealed: 1, providerId, sealed }`
7970
+ * — accepted on read for backwards compatibility; never produced on
7971
+ * write going forward.
7972
+ */
7973
+ interface SealedEnvelope {
7974
+ /** Envelope schema version. v1 is the current shape. */
7975
+ readonly v: 1;
7976
+ /** Magic marker for forensics + legacy-shape detection. */
7977
+ readonly _noydb_sealed: 1;
7978
+ /** Matches the producing provider's `.id`. Dispatch key on unseal. */
7979
+ readonly pid: string;
7980
+ /** Sealed bytes from the provider, base64-encoded on the wire. */
7981
+ readonly payload: string;
7982
+ }
7983
+ /**
7984
+ * Parse a `_meta/sealed-passphrase` `_data` JSON string into the
7985
+ * in-memory {@link SealedPassphrase} representation. Accepts both:
7986
+ *
7987
+ * 1. v1 wire format `{ v: 1, _noydb_sealed: 1, pid, payload }` —
7988
+ * the current shape.
7989
+ * 2. Legacy wire format `{ _noydb_sealed: 1, providerId, sealed }` —
7990
+ * read-only; never written
7991
+ * going forward.
7992
+ *
7993
+ * Returns `undefined` for any input that doesn't match either shape,
7994
+ * so callers can fall back to "no managed-mode envelope present."
7995
+ *
7996
+ * @internal — exported only for the migration safety-net test suite.
7997
+ */
7998
+ declare function parseSealedEnvelope(raw: unknown): SealedPassphrase | undefined;
7999
+ declare function saveSealedPassphrase(store: NoydbStore, vault: string, payload: {
8000
+ readonly providerId: string;
8001
+ readonly sealed: Uint8Array;
8002
+ }): Promise<void>;
8003
+ declare function loadSealedPassphrase(store: NoydbStore, vault: string): Promise<SealedPassphrase | undefined>;
8004
+
8005
+ /**
8006
+ * `vault.exportBlobs()` — bulk blob extraction primitive.
8007
+ *
8008
+ * Async-iterable handle over every blob attached to records in a
8009
+ * vault, optionally filtered by collection allowlist and per-record
8010
+ * predicate. Emits tuples of `{ blobId, recordRef, bytes, meta }` so
8011
+ * the consumer can pipe into any sink (zip stream, S3 multipart, USB
8012
+ * copy, cold-storage tape) without pulling the whole export into
8013
+ * memory.
8014
+ *
8015
+ * ## Auth + audit
8016
+ *
8017
+ * - Capability check runs **once** at handle creation via
8018
+ * `Vault.assertCanExport('plaintext', 'blob')`. An operator whose
8019
+ * keyring lacks that bit fails before a single byte of ciphertext
8020
+ * is decrypted.
8021
+ * - Audit entry lands in `_export_audit` at handle creation: the
8022
+ * actor, start timestamp, target collections, predicate presence,
8023
+ * and batch mechanism. **No content hashes** — per the spec
8024
+ * non-correlation invariant.
8025
+ *
8026
+ * ## Abort + resume
8027
+ *
8028
+ * - `handle.abort()` flips the internal signal; the next iteration
8029
+ * boundary throws `AbortError`. Consumers already in `for await`
8030
+ * can catch and exit cleanly.
8031
+ * - Restart after a partial failure with `{ afterBlobId }` — the
8032
+ * iterator skips tuples up to (and including) that blob id before
8033
+ * yielding again. Combined with a blob-count ceiling it supports
8034
+ * idempotent batch re-runs.
8035
+ *
8036
+ * @module
8037
+ */
8038
+
8039
+ interface ExportBlobsOptions {
8040
+ /**
8041
+ * Collection allowlist. Omit to export blobs from every collection
8042
+ * the caller has read access to.
8043
+ */
8044
+ readonly collections?: readonly string[];
8045
+ /**
8046
+ * Per-record predicate. Called on the decrypted record BEFORE any
8047
+ * blob bytes are read for that record — returning false skips the
8048
+ * record and all its slots without touching their chunks.
8049
+ */
8050
+ readonly where?: (record: unknown, context: {
8051
+ collection: string;
8052
+ id: string;
8053
+ }) => boolean;
8054
+ /**
8055
+ * Resume after a specific blob id. The iterator skips tuples up to
8056
+ * and including this id, then yields. Format of the id is the same
8057
+ * as `ExportedBlob.blobId` (the HMAC-keyed eTag).
7816
8058
  */
7817
8059
  readonly afterBlobId?: string;
7818
8060
  /**
@@ -8638,6 +8880,7 @@ declare class Vault {
8638
8880
  private readonly periodsStrategy;
8639
8881
  private readonly shadowStrategy;
8640
8882
  private readonly historyStrategy;
8883
+ private readonly forgetStrategy;
8641
8884
  private readonly i18nStrategy;
8642
8885
  private readonly syncStrategy;
8643
8886
  /**
@@ -8799,6 +9042,27 @@ declare class Vault {
8799
9042
  * Populated by `collection()` when the `dictKeyFields` option is passed.
8800
9043
  */
8801
9044
  private readonly dictKeyFieldRegistry;
9045
+ /**
9046
+ * Names of dictionaries backed by a `staticDict()` descriptor (#291).
9047
+ * A static dict skips the `dictKeyFieldRegistry` rename machinery, but the
9048
+ * vault must still *know* a name is static so `vault.dictionary(name)` can
9049
+ * refuse mutation (`StaticDictReadonlyError`). Populated at `collection()`
9050
+ * config time whenever a `StaticDictDescriptor` is seen.
9051
+ */
9052
+ private readonly staticDictNames;
9053
+ /**
9054
+ * Static-dict descriptors keyed by dictionary name (#291). Backs the
9055
+ * read-path label resolver (resolve from the in-memory table) and the
9056
+ * query-seam `resolveDictSource` snapshot. Last writer wins when the same
9057
+ * name is registered by multiple collections (identical-across-vaults by
9058
+ * construction, so the tables match).
9059
+ */
9060
+ private readonly staticByName;
9061
+ /**
9062
+ * Per-collection map of field name → StaticDictDescriptor (#291). Used by
9063
+ * `enforceStaticDictOnPut` to validate stored codes against `desc.keys`.
9064
+ */
9065
+ private readonly staticDescriptorByField;
8802
9066
  /**
8803
9067
  * Registry of i18nText fields declared across all collections. Keyed
8804
9068
  * by collection name → field name → I18nTextDescriptor. Used by
@@ -8858,6 +9122,7 @@ declare class Vault {
8858
9122
  syncStrategy?: SyncStrategy | undefined;
8859
9123
  guardStrategies?: ReadonlyArray<GuardStrategyHandleAny> | undefined;
8860
9124
  numberingConfigs?: ReadonlyArray<DeferredNumberingConfig> | undefined;
9125
+ forgetStrategy?: ForgetStrategy | undefined;
8861
9126
  });
8862
9127
  /**
8863
9128
  * Construct (or reconstruct) the lazy DEK resolver. Captures the
@@ -8907,8 +9172,8 @@ declare class Vault {
8907
9172
  refs?: Record<string, RefDescriptor>;
8908
9173
  /** — declare i18nText fields for locale-aware reads. */
8909
9174
  i18nFields?: Record<string, I18nTextDescriptor>;
8910
- /** — declare dictKey fields for label resolution on reads. */
8911
- dictKeyFields?: Record<string, DictKeyDescriptor>;
9175
+ /** — declare dictKey / staticDict fields for label resolution on reads. */
9176
+ dictKeyFields?: Record<string, DictKeyDescriptor | StaticDictDescriptor>;
8912
9177
  /** — declare money() fields for currency-safe decimal storage/formatting. */
8913
9178
  moneyFields?: Record<string, MoneyDescriptor>;
8914
9179
  /** — declare computed scalar fields, evaluated on write (schema-owned). */
@@ -8925,6 +9190,14 @@ declare class Vault {
8925
9190
  deterministicFields?: readonly string[];
8926
9191
  /** — explicit ack that deterministic encryption leaks equality. */
8927
9192
  acknowledgeDeterministicRisk?: boolean;
9193
+ /**
9194
+ * — per-record content-encryption keys. When `true`, every record
9195
+ * body is encrypted under a fresh per-record CEK wrapped under the
9196
+ * collection DEK (`_cek`), stable across versions. Foundation for
9197
+ * per-record erasure (#304) / record-scoped sealing (#306). Off by
9198
+ * default; non-adopting collections take the legacy path unchanged.
9199
+ */
9200
+ perRecordKeys?: boolean;
8928
9201
  /**
8929
9202
  * declarative blob retention / TTL policy per slot
8930
9203
  * name. Values are `{ retainDays?, evictWhen? }`. Evaluated only
@@ -9011,6 +9284,14 @@ declare class Vault {
9011
9284
  * `MissingTranslationError` when a required translation is absent.
9012
9285
  */
9013
9286
  enforceI18nOnPut(collectionName: string, record: unknown): void;
9287
+ /**
9288
+ * Validate staticDict codes on a `put()` (#291). For each `staticDict()`
9289
+ * field, every stored code must be a declared key of the descriptor's
9290
+ * table, else `UnknownDictCodeError`. Opt out per descriptor with
9291
+ * `{ validateCodes: false }`. Supports scalar, dotted, and `[].`-wildcard
9292
+ * field paths via `getAtPath` (same path support as i18n validation).
9293
+ */
9294
+ enforceStaticDictOnPut(collectionName: string, record: unknown): void;
9014
9295
  /**
9015
9296
  * Apply locale resolution to a record for the given collection.
9016
9297
  *
@@ -9351,6 +9632,102 @@ declare class Vault {
9351
9632
  * throws on null; this one stays silent so the off-path no-ops.
9352
9633
  */
9353
9634
  private getLedgerOrNull;
9635
+ /** @internal — add a subject→record ref to the encrypted subject index. */
9636
+ _addSubjectRef(subjectId: string, ref: SubjectRef): Promise<void>;
9637
+ /** @internal — drop a subject→record ref from the encrypted subject index. */
9638
+ _removeSubjectRef(subjectId: string, ref: SubjectRef): Promise<void>;
9639
+ /**
9640
+ * Rebuild the encrypted subject index from canonical records. The recovery
9641
+ * path for the documented read-modify-write race (RISK #3). Returns the
9642
+ * number of distinct subjects re-indexed.
9643
+ */
9644
+ rebuildSubjectIndex(): Promise<number>;
9645
+ /**
9646
+ * GDPR crypto-shred of a data subject (#304). Consults the encrypted subject
9647
+ * index and, per matching record:
9648
+ * - rewrites the LIVE envelope to a tombstone (drops `_iv`/`_data`/`_cek`/`_det`),
9649
+ * - tombstones every `_history` version of the record,
9650
+ * so the body and all prior versions become permanently undecryptable while
9651
+ * the collection DEK and every OTHER record stay intact. Then appends ONE
9652
+ * `op:'forget'` ledger entry whose `payloadHash` is `sha256Hex(subjectId)` —
9653
+ * the chain still `verify()`s, PROVING the subject existed and was erased
9654
+ * without retaining any plaintext.
9655
+ *
9656
+ * Reports — but does not silently swallow — two completeness gaps:
9657
+ * - `unmigratedRecords`: a record whose body was NOT yet migrated to a
9658
+ * per-record CEK (legacy body still under the shared collection DEK). It
9659
+ * is still tombstoned, but its pre-shred ciphertext (if leaked to a
9660
+ * backup before migration) stays decryptable. Migrate, then re-forget.
9661
+ * - `blobResidueCollections`: a shredded record still has blob attachments,
9662
+ * which are keyed off a separate `_blob` DEK and are out of scope here.
9663
+ *
9664
+ * @throws ForgetStrategyNotConfiguredError when no `withForgetCascade` was set.
9665
+ */
9666
+ forget(subjectId: string): Promise<ForgetResult>;
9667
+ /**
9668
+ * Seal ONE record's content-encryption key (CEK) to an `at-*` host so that
9669
+ * host — and only that host — can decrypt exactly that record, with no
9670
+ * access to the vault DEK and no ability to read any other record.
9671
+ *
9672
+ * The grantor (this caller, who holds the collection DEK) reads the record's
9673
+ * live `_cek`, unwraps it under the collection DEK, exports the raw CEK
9674
+ * bytes, builds a {@link SealedCekBinding} `{collection, id, cek, expiresAt}`,
9675
+ * seals that binding for the recipient host via the host's published hint,
9676
+ * and persists a thin {@link SealedCekDeliveryEnvelope} at
9677
+ * `_sealed_cek/<collection>/<id>/<pid>`. The binding (not the delivery
9678
+ * envelope) is the security boundary: the host re-verifies `{collection, id}`
9679
+ * and `expiresAt` from inside the sealed payload.
9680
+ *
9681
+ * Only works on a `perRecordKeys` record — a legacy record has no `_cek` to
9682
+ * seal (its body is under the shared collection DEK, which is never exposed
9683
+ * by sealing) → {@link RecordCekNotFoundError}.
9684
+ *
9685
+ * @param collection Collection holding the record.
9686
+ * @param id Record id.
9687
+ * @param hostSealer The recipient host's {@link RecipientSealer}.
9688
+ * @param opts.expiresAt REQUIRED authoritative expiry (ISO 8601), sealed into
9689
+ * the binding the host verifies.
9690
+ * @returns `{ pid, envelopeKey }` — the host provider id and the
9691
+ * `<collection>/<id>/<pid>` key the delivery envelope was written under.
9692
+ */
9693
+ sealRecordToHost(collection: string, id: string, hostSealer: RecipientSealer, opts: {
9694
+ expiresAt: string;
9695
+ }): Promise<{
9696
+ pid: string;
9697
+ envelopeKey: string;
9698
+ }>;
9699
+ /**
9700
+ * Revoke a single sealed-CEK delivery envelope by deleting it from the store.
9701
+ * A soft revocation: it removes the host's copy of the sealed CEK, but a host
9702
+ * that already fetched the envelope keeps whatever it cached. For a hard
9703
+ * revocation that makes the live record undecryptable to every prior grant,
9704
+ * use {@link rotateRecordCek}.
9705
+ */
9706
+ revokeSealedRecord(collection: string, id: string, pid: string): Promise<void>;
9707
+ /**
9708
+ * HARD-rotate a record's CEK: decrypt the live body under the old CEK,
9709
+ * re-encrypt it under a freshly-minted CEK, write the new live envelope, evict
9710
+ * the in-memory caches, and delete EVERY sealed-CEK delivery envelope for the
9711
+ * record. After this, any host holding a previously-sealed CEK can still
9712
+ * decrypt PRE-rotation history versions (they keep their old `_cek`) but NOT
9713
+ * the rotated live record (its body is under the new CEK → the old CEK fails
9714
+ * the AES-GCM auth tag → `TamperedError`). That asymmetry IS the revocation:
9715
+ * old grants lose the live record.
9716
+ *
9717
+ * Administrative path — bypasses `Collection.put` deliberately (no guards, no
9718
+ * history snapshot, no materialized-view refresh): rotation is a key-rotation
9719
+ * operation, not a business write, and must not version-bump history (which
9720
+ * would re-encrypt the prior version under the NEW CEK and defeat the point).
9721
+ *
9722
+ * @throws {@link RecordCekNotFoundError} if the record is missing or has no `_cek`.
9723
+ */
9724
+ rotateRecordCek(collection: string, id: string): Promise<void>;
9725
+ /**
9726
+ * Build the {@link SealingContext} the record-keys grantor functions need:
9727
+ * the vault-bound adapter, DEK resolver, actor, and the dual-cache eviction
9728
+ * `rotateRecordCek` performs (per-record CEK cache + decrypted-record cache).
9729
+ */
9730
+ private sealingContext;
9354
9731
  /**
9355
9732
  * @internal — called by `Noydb.openVault` after construction.
9356
9733
  * Dynamic-imports `GuardRegistry` + `ReadOnlyVaultFacade` and seeds
@@ -10343,6 +10720,25 @@ declare class Collection<T> {
10343
10720
  * is inactive for this collection; a frozen `Set` otherwise.
10344
10721
  */
10345
10722
  private readonly deterministicFields;
10723
+ /**
10724
+ * Per-record CEK opt-in (`perRecordKeys: true`). When set, writes mint /
10725
+ * reuse a per-record content-encryption key and stamp `_cek` on the
10726
+ * envelope (see {@link EncryptedEnvelope._cek}). OFF by default — a
10727
+ * non-adopting collection takes the byte-identical legacy path. The READ
10728
+ * path does not consult this flag: `_cek` presence on the envelope is the
10729
+ * format discriminant, so a mixed vault (and a recipient that never set the
10730
+ * flag) still decrypts CEK records.
10731
+ */
10732
+ private readonly perRecordCek;
10733
+ /**
10734
+ * Session-scoped `(id) → CEK` cache for this collection. Lets updates
10735
+ * reuse a record's stable CEK and lets repeated reads skip the AES-KW
10736
+ * unwrap. Bounded by LRU; never persisted. Dropped when the owning
10737
+ * collection instance is discarded — `vault.load()` clears the
10738
+ * collectionCache, so a keyring refresh drops every CEK alongside the
10739
+ * DEK cache. `null` unless `perRecordCek` is set.
10740
+ */
10741
+ private readonly cekCache;
10346
10742
  /**
10347
10743
  * declared tiers for this collection. `null` when
10348
10744
  * tier-aware methods are disabled. Tier 0 is implicit and never
@@ -10563,7 +10959,7 @@ declare class Collection<T> {
10563
10959
  /** — i18nText field descriptors for locale-aware reads. */
10564
10960
  i18nFields?: Record<string, I18nTextDescriptor> | undefined;
10565
10961
  /** — dictKey field descriptors for label resolution on reads. */
10566
- dictKeyFields?: Record<string, DictKeyDescriptor> | undefined;
10962
+ dictKeyFields?: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined;
10567
10963
  moneyFields?: Record<string, MoneyDescriptor> | undefined;
10568
10964
  computed?: ComputedFields | undefined;
10569
10965
  /**
@@ -10646,6 +11042,15 @@ declare class Collection<T> {
10646
11042
  * any deterministic field is declared. Any other value throws.
10647
11043
  */
10648
11044
  acknowledgeDeterministicRisk?: boolean | undefined;
11045
+ /**
11046
+ * Per-record content-encryption keys. When `true`, every record body
11047
+ * (and every history version of it) is encrypted under a fresh
11048
+ * per-record CEK, AES-KW-wrapped under the collection DEK and stored
11049
+ * on the envelope's `_cek`. Off by default. Foundation for per-record
11050
+ * erasure (#304) and record-scoped sealing (#306). `_det` slots stay
11051
+ * keyed to the collection DEK regardless.
11052
+ */
11053
+ perRecordKeys?: boolean | undefined;
10649
11054
  /**
10650
11055
  * declared tiers this collection supports. An
10651
11056
  * undefined or empty list disables the hierarchical-tier surface
@@ -10865,6 +11270,37 @@ declare class Collection<T> {
10865
11270
  */
10866
11271
  _internalDelete(id: string, txCtx?: TxContext | null): Promise<void>;
10867
11272
  private _doDelete;
11273
+ /**
11274
+ * @internal — GDPR crypto-shred a LIVE record to a tombstone (#304).
11275
+ *
11276
+ * Rewrites the on-disk envelope to `{ _noydb, _v, _ts, _by, _iv:'', _data:'' }`,
11277
+ * dropping `_iv`/`_data`/`_cek`/`_det`. The wrapped per-record CEK is gone, so
11278
+ * the body — and (via {@link tombstoneHistory}) every history version under
11279
+ * the same CEK — is permanently undecryptable; the collection DEK and every
11280
+ * other record are untouched. `_det` is stripped too, so `findByDet` no
11281
+ * longer matches the shredded record (avoiding a post-shred TamperedError).
11282
+ *
11283
+ * Unlike `delete()`/`_internalDelete`, this:
11284
+ * - does NOT fire onDelete guards / MV / derivation dispatch (a shred is an
11285
+ * erasure, not a domain delete — re-running those would be wrong),
11286
+ * - does NOT append a per-record ledger entry (`vault.forget()` appends a
11287
+ * single `op:'forget'` summary for the whole subject),
11288
+ * - keeps the record KEY present (it's an overwrite, not an adapter delete)
11289
+ * so the version counter + "record existed" survive for audit.
11290
+ *
11291
+ * Idempotent: returns `null` when the record is absent or already a tombstone.
11292
+ * Otherwise returns `{ previousVersion }`. Invalidates the eager cache, the
11293
+ * lazy LRU, and the per-record CEK cache for this id.
11294
+ */
11295
+ /**
11296
+ * @internal — decrypt an envelope to a plain record for subject-index
11297
+ * rebuild (#304). Returns `null` for a tombstone or unreadable envelope.
11298
+ * Skips schema validation — the rebuild only reads the subject field.
11299
+ */
11300
+ _decodeEnvelope(envelope: EncryptedEnvelope, id: string): Promise<Record<string, unknown> | null>;
11301
+ _writeTombstone(id: string, actor: string): Promise<{
11302
+ previousVersion: number;
11303
+ } | null>;
10868
11304
  /**
10869
11305
  * Cascade deletes of array-shape derived rows when a source row is
10870
11306
  * deleted. Reads each registered strategy's fanout sidecar
@@ -11166,6 +11602,16 @@ declare class Collection<T> {
11166
11602
  * the cache entry (record still present) or deletes it (record was
11167
11603
  * gone before the tx and the revert deleted it again).
11168
11604
  */
11605
+ /**
11606
+ * @internal — evict ONLY the per-record CEK cache entry for `id`. Used by
11607
+ * `vault.rotateRecordCek()`: after a hard CEK rotation the cached unwrapped
11608
+ * CEK is stale (it would decrypt the pre-rotation body and fail GCM auth on
11609
+ * the post-rotation body). Eviction must be synchronous with the live-envelope
11610
+ * rewrite so no concurrent read observes the old CEK. Paired with
11611
+ * {@link _invalidateCacheEntry} (which refreshes the decrypted-record cache).
11612
+ * No-op when the collection is not `perRecordKeys`.
11613
+ */
11614
+ _invalidateCekCacheEntry(id: string): void;
11169
11615
  _invalidateCacheEntry(id: string): Promise<void>;
11170
11616
  /**
11171
11617
  * Apply a peer tab's committed write to THIS tab's in-memory view:
@@ -11378,6 +11824,21 @@ declare class Collection<T> {
11378
11824
  * query with no index would need to enumerate the whole collection.
11379
11825
  */
11380
11826
  lazyQuery(): LazyQuery<T>;
11827
+ /**
11828
+ * Resolve the stable CEK for a record on the WRITE path — see
11829
+ * {@link resolveStableCek}. Thin delegate that supplies the collection's
11830
+ * CEK cache, live-envelope reader, and DEK resolver.
11831
+ */
11832
+ private resolveRecordCek;
11833
+ /**
11834
+ * Encrypt a JSON body into an envelope.
11835
+ *
11836
+ * When `cek` is supplied (per-record CEK collections), the body is
11837
+ * encrypted under the CEK and the CEK is AES-KW-wrapped under the
11838
+ * collection DEK and stamped on `_cek`. When `cek` is omitted, the legacy
11839
+ * path encrypts the body directly under the collection DEK — byte-identical
11840
+ * to pre-CEK behaviour, so non-adopting collections pay nothing.
11841
+ */
11381
11842
  private encryptJsonString;
11382
11843
  private encryptRecord;
11383
11844
  /**
@@ -11459,7 +11920,20 @@ declare class Collection<T> {
11459
11920
  demote(id: string, toTier: number): Promise<void>;
11460
11921
  private isElevatorOrOwner;
11461
11922
  private emitCrossTierEvent;
11462
- /** Low-level: decrypt an envelope and return the raw JSON string. */
11923
+ /**
11924
+ * Low-level: decrypt an envelope and return the raw JSON string.
11925
+ *
11926
+ * `_cek` presence is the format discriminant (NOT `this.perRecordCek`),
11927
+ * so a mixed vault — and a recipient that never opted into
11928
+ * `perRecordKeys` — decrypts both legacy and CEK records:
11929
+ * - `_cek` present → unwrap the CEK under the collection DEK, decrypt the
11930
+ * body under the CEK (cache the unwrapped CEK so repeated reads skip it).
11931
+ * - `_cek` absent → legacy path, body decrypts directly under the
11932
+ * collection DEK.
11933
+ *
11934
+ * The optional `id` lets reads populate the CEK cache; it is omitted by
11935
+ * callers (history, conflict merge) that have only the envelope.
11936
+ */
11463
11937
  private decryptJsonString;
11464
11938
  /**
11465
11939
  * Decrypt an envelope into a record of type `T`.
@@ -11736,244 +12210,6 @@ interface SessionStrategy {
11736
12210
  revokeAllSessions(): void;
11737
12211
  }
11738
12212
 
11739
- /**
11740
- * Managed-passphrase mode — rubber-hose-resistant vaults.
11741
- *
11742
- * A vault mode where the passphrase is machine-generated and never
11743
- * exposed to the user, sealed under a developer-provided
11744
- * {@link SealingKeyProvider} (macOS Keychain, Windows Credential
11745
- * Manager, libsecret, AWS KMS, …). The user has no secret to give
11746
- * up to coercion — they can't reveal what they don't know.
11747
- *
11748
- * ## Components in this file
11749
- *
11750
- * - {@link SealingKeyProvider} — the interface concrete providers
11751
- * implement. Provider implementations live OUTSIDE hub (per-
11752
- * platform packages).
11753
- * - {@link MemorySealingKeyProvider} — in-memory test provider; uses
11754
- * a deterministic per-instance "key" so two providers with
11755
- * different ids cannot unseal each other's outputs.
11756
- * - {@link RecipientHint} — public material a sender uses to seal
11757
- * plaintext for a specific recipient; published by
11758
- * {@link RecipientSealer.publishRecipientHint} and transported
11759
- * out-of-band to the sender before bundle writes.
11760
- * - {@link RecipientSealer} — interface for asymmetric/granted
11761
- * providers that support recipient-target sealing (RSA-OAEP,
11762
- * cloud-KMS asymmetric, etc.); distinct from self-only
11763
- * {@link SealingKeyProvider} (macOS Keychain, WebAuthn-PRF).
11764
- * - {@link MemoryRecipientSealer} — in-process reference
11765
- * implementation of both `RecipientSealer` and
11766
- * `SealingKeyProvider` using real WebCrypto RSA-OAEP + AES-GCM;
11767
- * safe for tests and same-process sender/recipient scenarios.
11768
- * - {@link loadSealedPassphrase} / {@link saveSealedPassphrase} —
11769
- * plaintext envelope storage at `_meta/sealed-passphrase`.
11770
- * Mirrors the `_meta/handle` and `_meta/public-envelope` AES-
11771
- * GCM-bypassed patterns. The sealing layer (provider's job)
11772
- * is the security boundary; hub doesn't have a key to encrypt
11773
- * with at this layer — that's the whole point of the design.
11774
- * - {@link resolveManagedSecret} — orchestrates the "generate +
11775
- * seal + persist on first open; unseal on reopen" flow.
11776
- * Returns the plaintext passphrase string that the rest of the
11777
- * `createNoydb` keyring path consumes.
11778
- *
11779
- * Deferred to follow-ups:
11780
- * - Block `rotate-passphrase` policy gate under managed mode.
11781
- * - Mandatory strong-recovery enforcement.
11782
- * - Recovery flow under managed mode (generates fresh sealed phrase).
11783
- *
11784
- * @see docs/subsystems/session-tiers.md → Managed-passphrase mode
11785
- *
11786
- * @module
11787
- */
11788
-
11789
- /**
11790
- * The contract concrete providers (per-platform key stores) implement
11791
- * to seal and unseal a hub-generated random passphrase. The plaintext
11792
- * passphrase NEVER leaves hub-controlled memory in unsealed form —
11793
- * the provider receives the bytes, returns opaque sealed bytes, and
11794
- * later reverses the operation. Hub treats the sealed bytes as
11795
- * fully opaque.
11796
- *
11797
- * Implementations live OUTSIDE `@noy-db/hub` (separate packages
11798
- * per the issue's "Concrete providers (live outside hub)" note):
11799
- *
11800
- * | Platform | Package (TBD) | Backing |
11801
- * |---|---|---|
11802
- * | macOS | `@noy-db/seal-macos-keychain` | Security.framework |
11803
- * | Windows | `@noy-db/seal-wincred` | Credential Manager |
11804
- * | Linux | `@noy-db/seal-libsecret` | libsecret / secret-service |
11805
- * | Cloud / server | `@noy-db/seal-aws-kms` | AWS KMS Decrypt |
11806
- */
11807
- interface SealingKeyProvider {
11808
- /**
11809
- * Non-sensitive identifier disclosed in the persisted envelope.
11810
- * Surfaced to consumers via `loadSealedPassphrase().providerId` so
11811
- * a vault opened with the wrong provider class can detect the
11812
- * mismatch and surface a clear error. NOT secret — fine to log.
11813
- *
11814
- * Suggested format: `<family>:<scope>` — e.g. `macos-keychain:com.acme.app`,
11815
- * `aws-kms:arn:aws:kms:us-east-1:123:key/abc`. The hub never
11816
- * parses this; it's purely audit metadata.
11817
- */
11818
- readonly id: string;
11819
- /** Seal raw passphrase bytes. Output bytes are opaque to hub. */
11820
- seal(passphrase: Uint8Array): Promise<Uint8Array>;
11821
- /**
11822
- * Reverse {@link seal}. MUST throw on tamper, wrong-provider, or
11823
- * any other failure — hub treats a thrown error as "this provider
11824
- * cannot unlock this vault" and surfaces it to the caller.
11825
- */
11826
- unseal(sealed: Uint8Array): Promise<Uint8Array>;
11827
- }
11828
- /**
11829
- * In-memory test provider. NOT secure — uses a deterministic
11830
- * per-instance "key" (16-byte SHA-256 of `id`) XOR'd over the
11831
- * passphrase plus a 4-byte provider-id fingerprint prefix. The XOR is
11832
- * sufficient to make different `id` values produce mutually-unsealable
11833
- * outputs (the contract tests for that), but offers ZERO real
11834
- * confidentiality — never use outside tests.
11835
- *
11836
- * Replace with a real platform provider in production.
11837
- */
11838
- declare class MemorySealingKeyProvider implements SealingKeyProvider {
11839
- readonly id: string;
11840
- private readonly fingerprint;
11841
- private readonly keyBytes;
11842
- constructor(opts: {
11843
- id: string;
11844
- });
11845
- seal(passphrase: Uint8Array): Promise<Uint8Array>;
11846
- unseal(sealed: Uint8Array): Promise<Uint8Array>;
11847
- }
11848
- /**
11849
- * Public material a sender uses to seal-for-this-recipient. Published by
11850
- * a recipient's RecipientSealer; transported to the sender out-of-band
11851
- * (email, S3, in-app message). The sender obtains the hint, supplies it
11852
- * to writeNoydbBundle's sealedCredentials.perUser[userId].hint, and the
11853
- * hub seals each user's credential against it. Per foundation §11.4.
11854
- */
11855
- type RecipientHint = {
11856
- readonly v: 1;
11857
- /** Recipient's provider id; matches the SealedAutoUnlockEntry.pid they'll unseal under. */
11858
- readonly pid: string;
11859
- /** Algorithm the sender uses to produce the seal. Slice 1 ships RSA-OAEP-SHA256 only. */
11860
- readonly alg: 'rsa-oaep-sha256';
11861
- /** Public material — alg-specific. For 'rsa-oaep-sha256': { publicKeyPem: string }. */
11862
- readonly material: Readonly<Record<string, unknown>>;
11863
- };
11864
- /**
11865
- * Handover-capable provider. Implemented additionally by asymmetric/granted
11866
- * providers (cloud-KMS asymmetric, Azure RSA Key Vault, AWS KMS with grant).
11867
- * Self-only providers (macOS Keychain, env-var, WebAuthn-PRF) do NOT
11868
- * implement this — the §11.2 capability matrix lives in the type system.
11869
- *
11870
- * Per foundation §11.4. A function that requires recipient-target sealing
11871
- * takes `RecipientSealer`, not `SealingKeyProvider` — the compiler rejects
11872
- * passing a self-only provider at the spec site.
11873
- */
11874
- interface RecipientSealer {
11875
- readonly id: string;
11876
- /** Produce hint material a sender uses to seal-for-this-recipient. */
11877
- publishRecipientHint(): Promise<RecipientHint>;
11878
- /**
11879
- * Seal plaintext for the recipient described by `hint`. Returns opaque
11880
- * bytes — same contract as `SealingKeyProvider.seal()`. The bundle
11881
- * layer base64-encodes the bytes into `SealedAutoUnlockEntry.sealed`
11882
- * without inspecting them.
11883
- */
11884
- sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array>;
11885
- }
11886
- /**
11887
- * Reference implementation of `RecipientSealer` + `SealingKeyProvider`.
11888
- * Uses WebCrypto RSA-OAEP-SHA256 (2048-bit) to wrap a fresh 32-byte
11889
- * AES-GCM CEK, AES-GCM-encrypts plaintext under it, and packs the
11890
- * result into a self-describing TLV:
11891
- *
11892
- * byte 0 : version (0x01)
11893
- * bytes 1..256 : RSA-OAEP-wrapped CEK (fixed 256 bytes at RSA-2048)
11894
- * bytes 257..268: AES-GCM IV (12 bytes)
11895
- * bytes 269.. : AES-GCM ciphertext ‖ 16-byte tag
11896
- *
11897
- * Implements BOTH interfaces. `seal(plaintext)` (self-target) is just
11898
- * `sealForRecipient(plaintext, this own hint)` — same TLV. Convenient
11899
- * for tests where one provider plays both ends. Real cloud providers
11900
- * (`at-aws-kms`, etc.) will pick their own internal layouts; the only
11901
- * contract is round-trip identity.
11902
- *
11903
- * SAFE for production within its scope — the cryptography is real
11904
- * (RSA-OAEP + AES-GCM via WebCrypto), but the keypair lives in-process
11905
- * and is regenerated on every construction. Not suitable as a managed
11906
- * keychain; use it for tests and for shipping bundles where the
11907
- * recipient instance lives in the same process as the sender (rare).
11908
- */
11909
- declare class MemoryRecipientSealer implements SealingKeyProvider, RecipientSealer {
11910
- readonly id: string;
11911
- private readonly keypair;
11912
- constructor(opts: {
11913
- id: string;
11914
- });
11915
- publishRecipientHint(): Promise<RecipientHint>;
11916
- sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array>;
11917
- seal(plaintext: Uint8Array): Promise<Uint8Array>;
11918
- unseal(bytes: Uint8Array): Promise<Uint8Array>;
11919
- }
11920
- /** Reserved id for the managed-passphrase envelope under `_meta`. */
11921
- declare const SEALED_PASSPHRASE_RECORD_ID: "sealed-passphrase";
11922
- /** Plaintext payload stored inside the `_meta/sealed-passphrase` envelope. */
11923
- interface SealedPassphrase {
11924
- readonly _noydb_sealed: 1;
11925
- readonly providerId: string;
11926
- /** Sealed bytes. Base64-encoded on the wire; decoded on load. */
11927
- readonly sealed: Uint8Array;
11928
- }
11929
- /**
11930
- * Wire-format envelope persisted at `_meta/sealed-passphrase` for
11931
- * managed-mode vaults. The provider produces raw sealed bytes via
11932
- * {@link SealingKeyProvider.seal}; this wrapper carries the dispatch
11933
- * metadata hub needs to pick the right provider on the unseal path.
11934
- *
11935
- * Stability boundary: once shipped, the wire format only grows by
11936
- * adding optional fields. See the at-* sealing dimension foundation
11937
- * doc, §11.9.1.
11938
- *
11939
- * v1 shape (this release): `{ v: 1, _noydb_sealed: 1, pid, payload }`.
11940
- *
11941
- * Legacy shape (earlier releases): `{ _noydb_sealed: 1, providerId, sealed }`
11942
- * — accepted on read for backwards compatibility; never produced on
11943
- * write going forward.
11944
- */
11945
- interface SealedEnvelope {
11946
- /** Envelope schema version. v1 is the current shape. */
11947
- readonly v: 1;
11948
- /** Magic marker for forensics + legacy-shape detection. */
11949
- readonly _noydb_sealed: 1;
11950
- /** Matches the producing provider's `.id`. Dispatch key on unseal. */
11951
- readonly pid: string;
11952
- /** Sealed bytes from the provider, base64-encoded on the wire. */
11953
- readonly payload: string;
11954
- }
11955
- /**
11956
- * Parse a `_meta/sealed-passphrase` `_data` JSON string into the
11957
- * in-memory {@link SealedPassphrase} representation. Accepts both:
11958
- *
11959
- * 1. v1 wire format `{ v: 1, _noydb_sealed: 1, pid, payload }` —
11960
- * the current shape.
11961
- * 2. Legacy wire format `{ _noydb_sealed: 1, providerId, sealed }` —
11962
- * read-only; never written
11963
- * going forward.
11964
- *
11965
- * Returns `undefined` for any input that doesn't match either shape,
11966
- * so callers can fall back to "no managed-mode envelope present."
11967
- *
11968
- * @internal — exported only for the migration safety-net test suite.
11969
- */
11970
- declare function parseSealedEnvelope(raw: unknown): SealedPassphrase | undefined;
11971
- declare function saveSealedPassphrase(store: NoydbStore, vault: string, payload: {
11972
- readonly providerId: string;
11973
- readonly sealed: Uint8Array;
11974
- }): Promise<void>;
11975
- declare function loadSealedPassphrase(store: NoydbStore, vault: string): Promise<SealedPassphrase | undefined>;
11976
-
11977
12213
  /**
11978
12214
  * Core types — the {@link NoydbStore} interface, envelope format, roles, and
11979
12215
  * all configuration shapes consumed by {@link createNoydb}.
@@ -12070,6 +12306,27 @@ interface EncryptedEnvelope {
12070
12306
  * side channel.
12071
12307
  */
12072
12308
  readonly _det?: Record<string, string>;
12309
+ /**
12310
+ * Per-record content-encryption key (CEK), base64 AES-KW-wrapped under
12311
+ * the collection (or tier) DEK. Present only on records written by a
12312
+ * collection opened with `perRecordKeys: true`. When present, the body
12313
+ * (`_iv`/`_data`) is encrypted under the unwrapped CEK rather than the
12314
+ * collection DEK directly.
12315
+ *
12316
+ * Presence is the format discriminant: `_cek` absent → legacy body
12317
+ * keyed off the collection DEK (read unchanged); `_cek` present →
12318
+ * unwrap under the collection DEK, then decrypt the body under the CEK.
12319
+ *
12320
+ * The CEK is stable across every version of a record (insert mints it;
12321
+ * updates and history snapshots reuse it), so all `_history` envelopes
12322
+ * for a record carry the same `_cek`. This is the foundation for
12323
+ * per-record erasure (#304) and record-scoped sealing (#306).
12324
+ *
12325
+ * `_det` slots are deliberately NOT keyed off the CEK — they remain
12326
+ * keyed to the collection DEK so blind-equality search keeps working
12327
+ * across records.
12328
+ */
12329
+ readonly _cek?: string;
12073
12330
  }
12074
12331
  /**
12075
12332
  * Placeholder returned by `getAtTier()` in `'ghost'` mode when a
@@ -13288,6 +13545,25 @@ interface BlobObject {
13288
13545
  readonly createdAt: string;
13289
13546
  /** Live reference count — slots + published versions pointing to this blob. */
13290
13547
  readonly refCount: number;
13548
+ /**
13549
+ * Base64 AES-KW-wrapped per-blob **content CEK** (wrapped under the `_blob`
13550
+ * DEK). Present on erasable-collection blobs (`perRecordKeys`): the chunks
13551
+ * are encrypted under this content CEK rather than directly under the `_blob`
13552
+ * DEK, so deleting this BlobObject at `refCount → 0` crypto-shreds the chunks
13553
+ * (they become permanently undecryptable). Absent → legacy blob, chunks
13554
+ * decrypt directly under the `_blob` DEK (read unchanged). See
13555
+ * docs/superpowers/specs/2026-06-13-per-blob-cek-design.md.
13556
+ */
13557
+ readonly _cek?: string;
13558
+ /**
13559
+ * Transient migration marker (#365 slice 3). Present only while a legacy
13560
+ * blob is being migrated to a content CEK: it holds the wrapped content CEK
13561
+ * BEFORE the chunks have been re-encrypted under it. Readers **ignore**
13562
+ * `_cekPending` (they key off `_cek`), so the blob stays readable under the
13563
+ * `_blob` DEK during migration AND the content CEK survives a crash → a
13564
+ * re-run resumes and promotes `_cekPending` → `_cek`. Never set on a settled blob.
13565
+ */
13566
+ readonly _cekPending?: string;
13291
13567
  /**
13292
13568
  * Hint indicating which store holds the chunk data.
13293
13569
  * Used by `routeStore` size-tiered routing: `'default'` for small blobs
@@ -13519,6 +13795,19 @@ interface NoydbOptions {
13519
13795
  * @internal
13520
13796
  */
13521
13797
  readonly historyStrategy?: HistoryStrategy;
13798
+ /**
13799
+ * GDPR right-to-erasure (#304). Pass `withForgetCascade({ subjects })`
13800
+ * from `@noy-db/hub/forget` to declare which collections carry erasable
13801
+ * subject data and the record field naming the data subject. Enables
13802
+ * `vault.forget(subjectId)` crypto-shred (rewrite-to-tombstone of the live
13803
+ * record + every history version → body permanently undecryptable, single
13804
+ * `op:'forget'` ledger entry, chain still verifies). Each declared
13805
+ * collection is forced to `perRecordKeys: true`. When omitted (the
13806
+ * `NO_FORGET` default), `vault.forget()` throws
13807
+ * `ForgetStrategyNotConfiguredError` and no subject-index write hooks run.
13808
+ * Requires `historyStrategy` (the ledger) for the erasure-proof entry.
13809
+ */
13810
+ readonly forgetStrategy?: ForgetStrategy;
13522
13811
  /**
13523
13812
  * tree-shake seam — optional i18n strategy. Pass `withI18n()`
13524
13813
  * from `@noy-db/hub/i18n` to enable `i18nText`/`dictKey` field
@@ -13874,4 +14163,4 @@ interface DeleteManyResult {
13874
14163
  }>;
13875
14164
  }
13876
14165
 
13877
- export { type ExportBlobsAuditEntry as $, BLOB_COLLECTION as A, type BlobStrategy as B, BLOB_EVICTION_AUDIT_COLLECTION as C, DICT_COLLECTION_PREFIX as D, BLOB_INDEX_COLLECTION as E, BLOB_SLOTS_PREFIX as F, BLOB_VERSIONS_PREFIX as G, type BlobEvictionEntry as H, type I18nStrategy as I, type BlobFieldPolicy as J, type BlobFieldsConfig as K, type Layer as L, type BlobObject as M, type BlobPutOptions as N, type OnMissing as O, PolicyEnforcer as P, type BlobResponseOptions as Q, type ResolveI18nOptions as R, type ScriptWarning as S, BlobSet as T, type BlobStrategyOpenArgs as U, type CompactRunOptions as V, type CompactionContext as W, type CompactionResult as X, DEFAULT_CHUNK_SIZE as Y, EXPORT_AUDIT_COLLECTION as Z, ExportBlobsAbortedError as _, type DictEntry as a, type NoydbStore as a$, type ExportBlobsHandle as a0, type ExportBlobsOptions as a1, type ExportedBlob as a2, type SlotInfo as a3, type SlotRecord as a4, type VersionRecord as a5, createExportBlobsHandle as a6, runCompaction as a7, type ConsentStrategy as a8, CONSENT_AUDIT_COLLECTION as a9, VaultFrame as aA, type NoydbBundleStore as aB, type RetentionPolicy as aC, type SnapshotPolicy as aD, type SnapshotStrategy as aE, type SnapshotMeta as aF, type SnapshotMode as aG, type DerivationStrategy as aH, type DerivationContext as aI, type ArrayOutputSpec as aJ, DerivationRegistry as aK, type DerivationStrategyHandle as aL, type DerivedFromMeta as aM, type OutputSpec as aN, type RecordOutputSpec as aO, type MaterializedViewStrategy as aP, type MaterializedViewStrategyHandle as aQ, type OverlayedViewStrategy as aR, Collection as aS, type OverlayFieldMergeMode as aT, type OverlayFieldMergeRule as aU, OverlayedViewRegistry as aV, type OverlayedViewStrategyHandle as aW, type SyncStrategy as aX, type Role as aY, type UnlockedKeyring as aZ, type HistoryStrategy as a_, type ConsentAuditEntry as aa, type ConsentAuditFilter as ab, type ConsentContext as ac, type ConsentOp as ad, loadConsentEntries as ae, writeConsentEntry as af, type PeriodsStrategy as ag, type CarryForwardContext as ah, type ClosePeriodOptions as ai, type OpenPeriodOptions as aj, PERIODS_COLLECTION as ak, type PeriodRecord as al, type ReadOnlyCollection as am, appendPeriodLedgerEntry as an, assertTsWritable as ao, chainAnchor as ap, loadPeriods as aq, validatePeriodName as ar, type GuardStrategy as as, type GuardChange as at, type GuardContext as au, GuardRegistry as av, type GuardStrategyHandle as aw, ReadOnlyVaultFacade as ax, type ShadowStrategy as ay, CollectionFrame as az, type DictKeyDescriptor as b, type CollectionChangeEvent as b$, type HistoryOptions as b0, type EncryptedEnvelope as b1, type PruneOptions as b2, type AppendInput as b3, type ChangeType as b4, CollectionInstant as b5, type DiffEntry as b6, type JsonPatch as b7, type JsonPatchOp as b8, type LedgerEntry as b9, type MaterializedViewOutput as bA, type UnionArmJoin as bB, type UnionSource as bC, type UserEnvelope as bD, type GateName as bE, type GatePolicy as bF, type VaultPolicy as bG, type ActiveTier as bH, type FactorProof as bI, type SchemaUpdateStrategy as bJ, type TransformFn as bK, type PersistedSchemaEnvelope as bL, type UpdateDecision as bM, type DirectoryConfig as bN, type UserVisibility as bO, type AccessibleVault as bP, type AffectedDocument as bQ, type ArchivePolicy as bR, type ArchiveResult as bS, type ArchiveRunOptions as bT, type ArchiveStrategy as bU, BUNDLE_STORE_POLICY as bV, type BuiltInGateName as bW, type CacheOptions as bX, type CacheStats as bY, type CapturedBlueprint as bZ, type ChangeEvent as b_, LedgerStore as ba, type VaultEngine as bb, VaultInstant as bc, type VerifyResult as bd, applyPatch as be, canonicalJson as bf, computePatch as bg, diff as bh, formatDiff as bi, hashEntry as bj, paddedIndex as bk, parseIndex as bl, sha256Hex as bm, type PublicEnvelope as bn, type SealingKeyProvider as bo, type BundleRecipient as bp, type RecipientSealer as bq, type RecipientHint as br, Vault as bs, type RecoveryEnrollmentInput as bt, type ShamirRecoveryProvider as bu, TxContext as bv, type MVQueryContext as bw, type RegisteredMV as bx, MaterializedViewRegistry as by, type MaterializedFromMeta as bz, DictionaryHandle as c, type ListPageResult as c$, type CollectionConflictResolver as c0, type CollectionDescriptor as c1, type CollectionStats as c2, ComputedFieldError as c3, type ComputedFields as c4, type ComputedFn as c5, type Conflict as c6, type ConflictPolicy as c7, type ConflictStrategy as c8, type CrossTierAccessEvent as c9, type ExportStreamOptions as cA, type FactorKind as cB, type FactorProofBundle as cC, type FactorRequirement as cD, type FanoutQueryOptions as cE, type FanoutResult as cF, type FenceDoc as cG, type FenceState as cH, type FieldChange as cI, type FieldDescriptor as cJ, type FieldSource as cK, type GhostRecord as cL, type GrantOptions as cM, type GuardViolation as cN, type HistoryConfig as cO, type HistoryEntry as cP, INDEXED_STORE_POLICY as cQ, type ImportCapability as cR, type InferOutput as cS, type InternalCollectionStats as cT, type IssueDelegationOptions as cU, type IssueMagicLinkGrantOptions as cV, type KeyringAuthenticator as cW, type KeyringAuthenticatorWrappingDEKs as cX, type KeyringAuthenticatorWrappingKEK as cY, type KeyringFile as cZ, type ListAccessibleVaultsOptions as c_, CrossVaultAggregation as ca, CrossVaultGroupedAggregation as cb, type GroupedRow as cc, type CrossVaultLiveAggregation as cd, type CrossVaultLiveQuery as ce, DEFAULT_PUBLIC_ENVELOPE_SCHEMA as cf, DELEGATIONS_COLLECTION as cg, type DeepPartial as ch, type DeepPartialOrNull as ci, type DeferredNumberingConfig as cj, type DelegationToken as ck, type DeleteManyResult as cl, type DeploymentEvent as cm, type DerivationDescriptor as cn, type DirtyEntry as co, type DryRunResult as cp, type DumpSchemaOptions as cq, ELEVATION_AUDIT_COLLECTION as cr, ElevatedHandle as cs, type EnrollAuthenticatorOptions as ct, type EnrollAuthenticatorWrappingDEKsOptions as cu, type EnrollAuthenticatorWrappingKEKOptions as cv, type EnrollRecoveryResult as cw, type ExportCapability as cx, type ExportChunk as cy, type ExportFormat as cz, type DictionaryOptions as d, type RotatePassphraseInput as d$, type ListUsersOptions as d0, type LiveQueryOptions as d1, type LiveUserEnvelope as d2, type LocaleReadOptions as d3, Lru as d4, type LruOptions as d5, type LruStats as d6, MAGIC_LINK_CONTENT_INFO_PREFIX as d7, MAGIC_LINK_GRANTS_COLLECTION as d8, MAGIC_LINK_KEK_INFO_PREFIX as d9, PresenceHandle as dA, type PresencePeer as dB, type PublicEnvelopeField as dC, type PublicEnvelopeSchema as dD, type PublicEnvelopeText as dE, type PullMode as dF, type PullOptions as dG, type PullPolicy as dH, type PullResult as dI, type PushMode as dJ, type PushOptions as dK, type PushPolicy as dL, type PushResult as dM, type PutManyItemOptions as dN, type PutManyOptions as dO, type PutManyResult as dP, type QueryAcrossOptions as dQ, type QueryAcrossResult as dR, type QuickUnlockState as dS, QuickUnlockStore as dT, type ReAuthOperation as dU, type RecoverPassphraseInput as dV, type RecoverPassphraseResult as dW, type RecoverUserOptions as dX, type RecoveryProof as dY, type ResolvedPublicEnvelopeSchema as dZ, type RevokeOptions as d_, type MagicLinkGrantPayload as da, type MagicLinkGrantRecord as db, type MaterializedViewDescriptor as dc, MemoryRecipientSealer as dd, MemorySealingKeyProvider as de, NOYDB_BACKUP_VERSION as df, NOYDB_FORMAT_VERSION as dg, NOYDB_KEYRING_VERSION as dh, NOYDB_SYNC_VERSION as di, type NextOptions as dj, Noydb as dk, type NoydbEventMap as dl, type NoydbOptions as dm, type Assignment as dn, type OverlayViewDescriptor as dp, PUBLIC_ENVELOPE_FIELDS as dq, type PaperRecoveryDoc as dr, type PaperRecoveryEntry as ds, type PassphrasePolicy as dt, type PassphraseValidationResult as du, type Permission as dv, type Permissions as dw, type PersistedSchemaKind as dx, type PlaintextTranslatorContext as dy, type PlaintextTranslatorFn as dz, type I18nMap as e, VaultGroup as e$, type RotateRecoveryOptions as e0, type RotateRecoveryResult as e1, SEALED_PASSPHRASE_RECORD_ID as e2, type SchemaDelta as e3, type SchemaIntrospection as e4, type SchemaManifestRow as e5, type SealedEnvelope as e6, type SealedPassphrase as e7, type SequenceHandle as e8, type SequenceOptions as e9, type SyncTarget as eA, type SyncTargetRole as eB, SyncTransaction as eC, type SyncTransactionResult as eD, type TabChannel as eE, type TabCoordinationOptions as eF, type TabLockManager as eG, type TabPresence as eH, type TabRole as eI, type TierMode as eJ, type TransactionInvariant as eK, type TranslatorAuditEntry as eL, TxCollection as eM, type TxOp as eN, TxVault as eO, USER_ENVELOPE_COLLECTION as eP, USER_ENVELOPE_MAX_BYTES as eQ, type Unsubscribe as eR, type UpdateAuthenticatorOptions as eS, type UpdateContext as eT, type UpdateUserOptions as eU, UserApi as eV, type UserEnvelopeCheckGate as eW, UserEnvelopeOversizedError as eX, type UserEnvelopePresented as eY, type UserInfo as eZ, type VaultBackup as e_, SequenceStore as ea, type SessionPolicy as eb, type SetPublicEnvelopeInput as ec, type ShamirRecoveryDoc as ed, type ShamirRecoveryEntry as ee, ShardedCollection as ef, ShardedGroupedQuery as eg, ShardedQuery as eh, type ShardingConfig as ei, type SkippedVault as ej, type SlotRewrapCeremony as ek, type SlotRewrapContext as el, type StandardSchemaV1 as em, type StandardSchemaV1Issue as en, type StandardSchemaV1SyncResult as eo, StateManagementVault as ep, type StoreAuth as eq, type StoreAuthKind as er, type StoreCapabilities as es, type StoreTime as et, SyncEngine as eu, type SyncMetadata as ev, type SyncPolicy as ew, SyncScheduler as ex, type SyncSchedulerStatus as ey, type SyncStatus as ez, type I18nTextDescriptor as f, validatePublicEnvelopeInput as f$, type VaultGroupOptions as f0, type VaultPolicyOnDisk as f1, type VaultRegistryRow as f2, type VaultSchemaSnapshot as f3, type VaultSnapshot as f4, type VaultTemplate as f5, type WarningRules as f6, WeakPassphraseError as f7, type WeakPassphraseReason as f8, type WithArchiveOptions as f9, listUsers as fA, listUsersWithEnvelopes as fB, loadActiveDelegations as fC, loadPaperRecoveryEntries as fD, loadSealedPassphrase as fE, loadShamirRecoveryEntries as fF, magicLinkGrantRecordId as fG, mintPaperRecoveryEntry as fH, mintShamirRecoveryEntry as fI, mintWrappedDeksBlob as fJ, parseSealedEnvelope as fK, readMagicLinkGrantRecord as fL, recoverUser as fM, removeAuthenticator as fN, resolveSchema as fO, resolveSequenceKey as fP, revokeDelegation as fQ, revokeMagicLinkGrant as fR, runTransaction as fS, savePaperRecoveryEntries as fT, saveSealedPassphrase as fU, saveShamirRecoveryEntries as fV, unwrapDeksFromBlob as fW, unwrapDeksFromPaperEntry as fX, unwrapDeksFromShamirEntry as fY, unwrapMagicLinkGrant as fZ, validatePassphrase as f_, type WrappedDeksBlob as fa, type WriteConflict as fb, type WriteEvent as fc, type WriteHook as fd, type WriteQueue as fe, assertStrongPassphrase as ff, buildRecipientKeyringFile as fg, burnPaperRecoveryEntry as fh, createNoydb as fi, createStore as fj, deriveMagicLinkContentKey as fk, enrollAuthenticator as fl, estimateEntropy as fm, evalComputedFields as fn, evaluateExportCapability as fo, evaluateImportCapability as fp, findAuthenticator as fq, hasExportCapability as fr, hasImportCapability as fs, hasRecoveryEnrolled as ft, isMagicLinkGrantExpired as fu, isPublicEnvelope as fv, issueDelegation as fw, recoverPassphrase as fx, rotatePassphrase as fy, listMagicLinkGrants as fz, type I18nTextOptions as g, validateSchemaInput as g0, validateSchemaOutput as g1, withArchive as g2, withDeferredNumbering as g3, writeMagicLinkGrant as g4, changeSecret as g5, createOwnerKeyring as g6, ensureCollectionDEK as g7, grant as g8, loadKeyring as g9, persistKeyring as ga, revoke as gb, updateAuthenticator as gc, updateKeyringIdentity as gd, type TxStrategy as ge, type AmendmentTxOptions as gf, type OnMissingPolicy as h, applyI18nLocale as i, dictCollectionName as j, dictKey as k, enforceScript as l, getAtPath as m, i18nText as n, inferScripts as o, isDictCollectionName as p, isDictKeyDescriptor as q, isI18nTextDescriptor as r, resolveI18nText as s, resolvePolicy as t, setAtPathInPlace as u, validateI18nTextValue as v, type SessionStrategy as w, createEnforcer as x, validateSessionPolicy as y, BLOB_CHUNKS_COLLECTION as z };
14166
+ export { DEFAULT_CHUNK_SIZE as $, createEnforcer as A, validateSessionPolicy as B, type BlobStrategy as C, DICT_COLLECTION_PREFIX as D, BLOB_CHUNKS_COLLECTION as E, BLOB_COLLECTION as F, BLOB_EVICTION_AUDIT_COLLECTION as G, BLOB_INDEX_COLLECTION as H, type I18nStrategy as I, BLOB_SLOTS_PREFIX as J, BLOB_VERSIONS_PREFIX as K, type Layer as L, type BlobEvictionEntry as M, type BlobFieldPolicy as N, type OnMissing as O, PolicyEnforcer as P, type BlobFieldsConfig as Q, type ResolveI18nOptions as R, type ScriptWarning as S, type BlobObject as T, type BlobPutOptions as U, type BlobResponseOptions as V, BlobSet as W, type BlobStrategyOpenArgs as X, type CompactRunOptions as Y, type CompactionContext as Z, type CompactionResult as _, type DictEntry as a, type Role as a$, EXPORT_AUDIT_COLLECTION as a0, ExportBlobsAbortedError as a1, type ExportBlobsAuditEntry as a2, type ExportBlobsHandle as a3, type ExportBlobsOptions as a4, type ExportedBlob as a5, type SlotInfo as a6, type SlotRecord as a7, type VersionRecord as a8, createExportBlobsHandle as a9, ReadOnlyVaultFacade as aA, type ShadowStrategy as aB, CollectionFrame as aC, VaultFrame as aD, type NoydbBundleStore as aE, type RetentionPolicy as aF, type SnapshotPolicy as aG, type SnapshotStrategy as aH, type SnapshotMeta as aI, type SnapshotMode as aJ, type DerivationStrategy as aK, type DerivationContext as aL, type ArrayOutputSpec as aM, DerivationRegistry as aN, type DerivationStrategyHandle as aO, type DerivedFromMeta as aP, type OutputSpec as aQ, type RecordOutputSpec as aR, type MaterializedViewStrategy as aS, type MaterializedViewStrategyHandle as aT, type OverlayedViewStrategy as aU, Collection as aV, type OverlayFieldMergeMode as aW, type OverlayFieldMergeRule as aX, OverlayedViewRegistry as aY, type OverlayedViewStrategyHandle as aZ, type SyncStrategy as a_, runCompaction as aa, type ConsentStrategy as ab, CONSENT_AUDIT_COLLECTION as ac, type ConsentAuditEntry as ad, type ConsentAuditFilter as ae, type ConsentContext as af, type ConsentOp as ag, loadConsentEntries as ah, writeConsentEntry as ai, type PeriodsStrategy as aj, type CarryForwardContext as ak, type ClosePeriodOptions as al, type OpenPeriodOptions as am, PERIODS_COLLECTION as an, type PeriodRecord as ao, type ReadOnlyCollection as ap, appendPeriodLedgerEntry as aq, assertTsWritable as ar, chainAnchor as as, loadPeriods as at, validatePeriodName as au, type GuardStrategy as av, type GuardChange as aw, type GuardContext as ax, GuardRegistry as ay, type GuardStrategyHandle as az, type DictKeyDescriptor as b, type CollectionStats as b$, type UnlockedKeyring as b0, type HistoryStrategy as b1, type NoydbStore as b2, type HistoryOptions as b3, type EncryptedEnvelope as b4, type PruneOptions as b5, type AppendInput as b6, type ChangeType as b7, CollectionInstant as b8, type DiffEntry as b9, type UserEnvelope as bA, type GateName as bB, type GatePolicy as bC, type VaultPolicy as bD, type ActiveTier as bE, type FactorProof as bF, type SchemaUpdateStrategy as bG, type TransformFn as bH, type PersistedSchemaEnvelope as bI, type UpdateDecision as bJ, type DirectoryConfig as bK, type UserVisibility as bL, type AccessibleVault as bM, type AffectedDocument as bN, type ArchivePolicy as bO, type ArchiveResult as bP, type ArchiveRunOptions as bQ, type ArchiveStrategy as bR, BUNDLE_STORE_POLICY as bS, type BuiltInGateName as bT, type CacheOptions as bU, type CacheStats as bV, type CapturedBlueprint as bW, type ChangeEvent as bX, type CollectionChangeEvent as bY, type CollectionConflictResolver as bZ, type CollectionDescriptor as b_, type JsonPatch as ba, type JsonPatchOp as bb, LedgerStore as bc, type VaultEngine as bd, VaultInstant as be, type VerifyResult as bf, applyPatch as bg, computePatch as bh, diff as bi, formatDiff as bj, type PublicEnvelope as bk, type SealingKeyProvider as bl, type BundleRecipient as bm, type RecipientSealer as bn, type RecipientHint as bo, Vault as bp, type RecoveryEnrollmentInput as bq, type ShamirRecoveryProvider as br, TxContext as bs, type MVQueryContext as bt, type RegisteredMV as bu, MaterializedViewRegistry as bv, type MaterializedFromMeta as bw, type MaterializedViewOutput as bx, type UnionArmJoin as by, type UnionSource as bz, DictionaryHandle as c, type LiveUserEnvelope as c$, ComputedFieldError as c0, type ComputedFields as c1, type ComputedFn as c2, type Conflict as c3, type ConflictPolicy as c4, type ConflictStrategy as c5, type CrossTierAccessEvent as c6, CrossVaultAggregation as c7, CrossVaultGroupedAggregation as c8, type GroupedRow as c9, type FactorRequirement as cA, type FanoutQueryOptions as cB, type FanoutResult as cC, type FenceDoc as cD, type FenceState as cE, type FieldChange as cF, type FieldDescriptor as cG, type FieldSource as cH, type GhostRecord as cI, type GrantOptions as cJ, type GuardViolation as cK, type HistoryConfig as cL, type HistoryEntry as cM, INDEXED_STORE_POLICY as cN, type ImportCapability as cO, type InferOutput as cP, type InternalCollectionStats as cQ, type IssueDelegationOptions as cR, type IssueMagicLinkGrantOptions as cS, type KeyringAuthenticator as cT, type KeyringAuthenticatorWrappingDEKs as cU, type KeyringAuthenticatorWrappingKEK as cV, type KeyringFile as cW, type ListAccessibleVaultsOptions as cX, type ListPageResult as cY, type ListUsersOptions as cZ, type LiveQueryOptions as c_, type CrossVaultLiveAggregation as ca, type CrossVaultLiveQuery as cb, DEFAULT_PUBLIC_ENVELOPE_SCHEMA as cc, DELEGATIONS_COLLECTION as cd, type DeepPartial as ce, type DeepPartialOrNull as cf, type DeferredNumberingConfig as cg, type DelegationToken as ch, type DeleteManyResult as ci, type DeploymentEvent as cj, type DerivationDescriptor as ck, type DirtyEntry as cl, type DryRunResult as cm, type DumpSchemaOptions as cn, ELEVATION_AUDIT_COLLECTION as co, ElevatedHandle as cp, type EnrollAuthenticatorOptions as cq, type EnrollAuthenticatorWrappingDEKsOptions as cr, type EnrollAuthenticatorWrappingKEKOptions as cs, type EnrollRecoveryResult as ct, type ExportCapability as cu, type ExportChunk as cv, type ExportFormat as cw, type ExportStreamOptions as cx, type FactorKind as cy, type FactorProofBundle as cz, type DictionaryOptions as d, SEALED_PASSPHRASE_RECORD_ID as d$, type LocaleReadOptions as d0, Lru as d1, type LruOptions as d2, type LruStats as d3, MAGIC_LINK_CONTENT_INFO_PREFIX as d4, MAGIC_LINK_GRANTS_COLLECTION as d5, MAGIC_LINK_KEK_INFO_PREFIX as d6, type MagicLinkGrantPayload as d7, type MagicLinkGrantRecord as d8, type MaterializedViewDescriptor as d9, type PublicEnvelopeSchema as dA, type PublicEnvelopeText as dB, type PullMode as dC, type PullOptions as dD, type PullPolicy as dE, type PullResult as dF, type PushMode as dG, type PushOptions as dH, type PushPolicy as dI, type PushResult as dJ, type PutManyItemOptions as dK, type PutManyOptions as dL, type PutManyResult as dM, type QueryAcrossOptions as dN, type QueryAcrossResult as dO, type QuickUnlockState as dP, QuickUnlockStore as dQ, type ReAuthOperation as dR, type RecoverPassphraseInput as dS, type RecoverPassphraseResult as dT, type RecoverUserOptions as dU, type RecoveryProof as dV, type ResolvedPublicEnvelopeSchema as dW, type RevokeOptions as dX, type RotatePassphraseInput as dY, type RotateRecoveryOptions as dZ, type RotateRecoveryResult as d_, MemoryRecipientSealer as da, MemorySealingKeyProvider as db, NOYDB_BACKUP_VERSION as dc, NOYDB_FORMAT_VERSION as dd, NOYDB_KEYRING_VERSION as de, NOYDB_SYNC_VERSION as df, type NextOptions as dg, Noydb as dh, type NoydbEventMap as di, type NoydbOptions as dj, type Assignment as dk, type OverlayViewDescriptor as dl, PUBLIC_ENVELOPE_FIELDS as dm, type PaperRecoveryDoc as dn, type PaperRecoveryEntry as dp, type PassphrasePolicy as dq, type PassphraseValidationResult as dr, type Permission as ds, type Permissions as dt, type PersistedSchemaKind as du, type PlaintextTranslatorContext as dv, type PlaintextTranslatorFn as dw, PresenceHandle as dx, type PresencePeer as dy, type PublicEnvelopeField as dz, type I18nMap as e, type VaultRegistryRow as e$, type SchemaDelta as e0, type SchemaIntrospection as e1, type SchemaManifestRow as e2, type SealedEnvelope as e3, type SealedPassphrase as e4, type SequenceHandle as e5, type SequenceOptions as e6, SequenceStore as e7, type SessionPolicy as e8, type SetPublicEnvelopeInput as e9, type SyncTransactionResult as eA, type TabChannel as eB, type TabCoordinationOptions as eC, type TabLockManager as eD, type TabPresence as eE, type TabRole as eF, type TierMode as eG, type TransactionInvariant as eH, type TranslatorAuditEntry as eI, TxCollection as eJ, type TxOp as eK, TxVault as eL, USER_ENVELOPE_COLLECTION as eM, USER_ENVELOPE_MAX_BYTES as eN, type Unsubscribe as eO, type UpdateAuthenticatorOptions as eP, type UpdateContext as eQ, type UpdateUserOptions as eR, UserApi as eS, type UserEnvelopeCheckGate as eT, UserEnvelopeOversizedError as eU, type UserEnvelopePresented as eV, type UserInfo as eW, type VaultBackup as eX, VaultGroup as eY, type VaultGroupOptions as eZ, type VaultPolicyOnDisk as e_, type ShamirRecoveryDoc as ea, type ShamirRecoveryEntry as eb, ShardedCollection as ec, ShardedGroupedQuery as ed, ShardedQuery as ee, type ShardingConfig as ef, type SkippedVault as eg, type SlotRewrapCeremony as eh, type SlotRewrapContext as ei, type StandardSchemaV1 as ej, type StandardSchemaV1Issue as ek, type StandardSchemaV1SyncResult as el, StateManagementVault as em, type StoreAuth as en, type StoreAuthKind as eo, type StoreCapabilities as ep, type StoreTime as eq, SyncEngine as er, type SyncMetadata as es, type SyncPolicy as et, SyncScheduler as eu, type SyncSchedulerStatus as ev, type SyncStatus as ew, type SyncTarget as ex, type SyncTargetRole as ey, SyncTransaction as ez, type I18nTextDescriptor as f, validatePublicEnvelopeInput as f$, type VaultSchemaSnapshot as f0, type VaultSnapshot as f1, type VaultTemplate as f2, type WarningRules as f3, WeakPassphraseError as f4, type WeakPassphraseReason as f5, type WithArchiveOptions as f6, type WrappedDeksBlob as f7, type WriteConflict as f8, type WriteEvent as f9, loadActiveDelegations as fA, loadPaperRecoveryEntries as fB, loadSealedPassphrase as fC, loadShamirRecoveryEntries as fD, magicLinkGrantRecordId as fE, mintPaperRecoveryEntry as fF, mintShamirRecoveryEntry as fG, mintWrappedDeksBlob as fH, parseRsaOaepTlv as fI, parseSealedEnvelope as fJ, readMagicLinkGrantRecord as fK, recoverUser as fL, removeAuthenticator as fM, resolveSchema as fN, resolveSequenceKey as fO, revokeDelegation as fP, revokeMagicLinkGrant as fQ, runTransaction as fR, savePaperRecoveryEntries as fS, saveSealedPassphrase as fT, saveShamirRecoveryEntries as fU, sealRsaOaepTlv as fV, unwrapDeksFromBlob as fW, unwrapDeksFromPaperEntry as fX, unwrapDeksFromShamirEntry as fY, unwrapMagicLinkGrant as fZ, validatePassphrase as f_, type WriteHook as fa, type WriteQueue as fb, aesGcmOpen as fc, assertStrongPassphrase as fd, buildRecipientKeyringFile as fe, burnPaperRecoveryEntry as ff, createNoydb as fg, createStore as fh, deriveMagicLinkContentKey as fi, enrollAuthenticator as fj, estimateEntropy as fk, evalComputedFields as fl, evaluateExportCapability as fm, evaluateImportCapability as fn, findAuthenticator as fo, hasExportCapability as fp, hasImportCapability as fq, hasRecoveryEnrolled as fr, isMagicLinkGrantExpired as fs, isPublicEnvelope as ft, issueDelegation as fu, recoverPassphrase as fv, rotatePassphrase as fw, listMagicLinkGrants as fx, listUsers as fy, listUsersWithEnvelopes as fz, type I18nTextOptions as g, validateSchemaInput as g0, validateSchemaOutput as g1, withArchive as g2, withDeferredNumbering as g3, writeMagicLinkGrant as g4, changeSecret as g5, createOwnerKeyring as g6, ensureCollectionDEK as g7, grant as g8, loadKeyring as g9, persistKeyring as ga, revoke as gb, updateAuthenticator as gc, updateKeyringIdentity as gd, type TxStrategy as ge, type AmendmentTxOptions as gf, type OnMissingPolicy as h, type StaticDictDescriptor as i, applyI18nLocale as j, dictCollectionName as k, dictKey as l, enforceScript as m, getAtPath as n, i18nText as o, inferScripts as p, isDictCollectionName as q, isDictKeyDescriptor as r, isI18nTextDescriptor as s, isStaticDictDescriptor as t, resolveI18nText as u, resolvePolicy as v, setAtPathInPlace as w, staticDict as x, validateI18nTextValue as y, type SessionStrategy as z };