@noy-db/hub 0.2.0-pre.15 → 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 (301) hide show
  1. package/dist/aggregate/index.cjs +106 -10
  2. package/dist/aggregate/index.cjs.map +1 -1
  3. package/dist/aggregate/index.d.cts +3 -2
  4. package/dist/aggregate/index.d.ts +3 -2
  5. package/dist/aggregate/index.js +4 -4
  6. package/dist/attestation/index.cjs.map +1 -1
  7. package/dist/attestation/index.d.cts +5 -3
  8. package/dist/attestation/index.d.ts +5 -3
  9. package/dist/attestation/index.js +6 -6
  10. package/dist/blobs/index.cjs +226 -11
  11. package/dist/blobs/index.cjs.map +1 -1
  12. package/dist/blobs/index.d.cts +6 -4
  13. package/dist/blobs/index.d.ts +6 -4
  14. package/dist/blobs/index.js +6 -5
  15. package/dist/blobs/index.js.map +1 -1
  16. package/dist/bundle/index.cjs +1268 -141
  17. package/dist/bundle/index.cjs.map +1 -1
  18. package/dist/bundle/index.d.cts +7 -5
  19. package/dist/bundle/index.d.ts +7 -5
  20. package/dist/bundle/index.js +21 -10
  21. package/dist/bundle/index.js.map +1 -1
  22. package/dist/{chunk-5LQG6ZO2.js → chunk-2FU2FTXD.js} +9 -4
  23. package/dist/chunk-2FU2FTXD.js.map +1 -0
  24. package/dist/{chunk-JD3OZAI4.js → chunk-3G3W65EQ.js} +2 -2
  25. package/dist/{chunk-XWH4MXIU.js → chunk-5AXTH4QZ.js} +2 -2
  26. package/dist/{chunk-4TBBMHVC.js → chunk-5LIROIDM.js} +2 -2
  27. package/dist/{chunk-3EWXMOK3.js → chunk-7H2GEJ3O.js} +28 -13
  28. package/dist/chunk-7H2GEJ3O.js.map +1 -0
  29. package/dist/{chunk-WGHU7BLI.js → chunk-AEIKD3PP.js} +52 -38
  30. package/dist/chunk-AEIKD3PP.js.map +1 -0
  31. package/dist/{chunk-KI6HAJWL.js → chunk-BH3X5L6A.js} +4 -4
  32. package/dist/{chunk-BQ65SS5A.js → chunk-BJSLBUJ7.js} +2 -2
  33. package/dist/{chunk-L2FE64BU.js → chunk-BL5GYANC.js} +3 -3
  34. package/dist/{chunk-A5ZOOZFB.js → chunk-BSZOCSDZ.js} +4 -4
  35. package/dist/{chunk-ZNQYHJXX.js → chunk-C3HYQPV4.js} +2 -2
  36. package/dist/{chunk-PE4AQGFH.js → chunk-CD2AVTEM.js} +5 -5
  37. package/dist/{chunk-7EFFHEN5.js → chunk-D77ZQSQQ.js} +852 -143
  38. package/dist/chunk-D77ZQSQQ.js.map +1 -0
  39. package/dist/{chunk-56DJ7JVK.js → chunk-DWEBTE2W.js} +5 -5
  40. package/dist/{chunk-Z4DO7YSI.js → chunk-DYYYUW5D.js} +2 -2
  41. package/dist/{chunk-NSCVNK5K.js → chunk-E77UKJYL.js} +5 -5
  42. package/dist/{chunk-KIP6JLTF.js → chunk-F4G63NTZ.js} +2 -2
  43. package/dist/{chunk-NU6Q3FOR.js → chunk-FEJDVE3Z.js} +12 -2
  44. package/dist/{chunk-NU6Q3FOR.js.map → chunk-FEJDVE3Z.js.map} +1 -1
  45. package/dist/{chunk-DQU36Q7I.js → chunk-GP3SDSH2.js} +14 -5
  46. package/dist/chunk-GP3SDSH2.js.map +1 -0
  47. package/dist/{chunk-IQLVUT37.js → chunk-H2MRGONI.js} +2 -2
  48. package/dist/{chunk-EYVQHAGH.js → chunk-HGVSHKZW.js} +8 -5
  49. package/dist/chunk-HGVSHKZW.js.map +1 -0
  50. package/dist/chunk-I5IUYN7B.js +125 -0
  51. package/dist/chunk-I5IUYN7B.js.map +1 -0
  52. package/dist/{chunk-CJORTUJ2.js → chunk-J7RWBXFY.js} +2 -2
  53. package/dist/{chunk-AAVWKNZW.js → chunk-JDWE6JMX.js} +2 -2
  54. package/dist/{chunk-6AJBSQU4.js → chunk-KCEHMDZF.js} +3 -3
  55. package/dist/{chunk-TS26M2SB.js → chunk-M476FOQ7.js} +2 -2
  56. package/dist/{chunk-F4OJZIWQ.js → chunk-NBBMMJ2H.js} +4 -4
  57. package/dist/{chunk-CZI2A4MQ.js → chunk-NYSYPFXJ.js} +3 -3
  58. package/dist/{chunk-EGD5DXFT.js → chunk-PDULVIBY.js} +14 -2
  59. package/dist/chunk-PDULVIBY.js.map +1 -0
  60. package/dist/{chunk-Z6FNBOTC.js → chunk-PDVP3C2I.js} +1 -1
  61. package/dist/{chunk-Z6FNBOTC.js.map → chunk-PDVP3C2I.js.map} +1 -1
  62. package/dist/{chunk-COFPAMX6.js → chunk-QHM6XEAH.js} +6 -6
  63. package/dist/{chunk-C5T5AFWN.js → chunk-QO6RGLLD.js} +12 -6
  64. package/dist/chunk-QO6RGLLD.js.map +1 -0
  65. package/dist/{chunk-7HT2MEZ5.js → chunk-ROPJVUG3.js} +23 -6
  66. package/dist/chunk-ROPJVUG3.js.map +1 -0
  67. package/dist/{chunk-VU7SWWT5.js → chunk-ROVO6NPJ.js} +11 -7
  68. package/dist/chunk-ROVO6NPJ.js.map +1 -0
  69. package/dist/{chunk-6RR3MNMG.js → chunk-SHX5QBCI.js} +3 -3
  70. package/dist/{chunk-GC4V7RU7.js → chunk-SISBMAPO.js} +1 -1
  71. package/dist/chunk-SISBMAPO.js.map +1 -0
  72. package/dist/{chunk-BIYRQQV6.js → chunk-SNMJ7SB3.js} +5 -5
  73. package/dist/{chunk-7PS7EOCF.js → chunk-TIDXB5DF.js} +4 -4
  74. package/dist/chunk-U5QCMH3W.js +151 -0
  75. package/dist/chunk-U5QCMH3W.js.map +1 -0
  76. package/dist/{chunk-YULZKK4F.js → chunk-UNTGHX5A.js} +37 -2
  77. package/dist/chunk-UNTGHX5A.js.map +1 -0
  78. package/dist/{chunk-FWPKCXTN.js → chunk-WIAOUFFB.js} +2 -2
  79. package/dist/{chunk-LX3CB26H.js → chunk-WV7WV6JO.js} +195 -17
  80. package/dist/chunk-WV7WV6JO.js.map +1 -0
  81. package/dist/{chunk-X73VS74Y.js → chunk-XJV6OB4D.js} +2 -2
  82. package/dist/{chunk-OHVFWCJP.js → chunk-XMHUK5PN.js} +49 -19
  83. package/dist/chunk-XMHUK5PN.js.map +1 -0
  84. package/dist/{chunk-WBAYSNUQ.js → chunk-XMVHEWF6.js} +4 -4
  85. package/dist/{chunk-HOR4R722.js → chunk-XPIHJ34I.js} +30 -4
  86. package/dist/chunk-XPIHJ34I.js.map +1 -0
  87. package/dist/{chunk-DKO2QFSA.js → chunk-YYVZYTWW.js} +3 -3
  88. package/dist/{chunk-535SSHBS.js → chunk-ZEGSDPB7.js} +81 -2
  89. package/dist/chunk-ZEGSDPB7.js.map +1 -0
  90. package/dist/{chunk-YHPM5D7Y.js → chunk-ZNGPEV5J.js} +63 -4
  91. package/dist/chunk-ZNGPEV5J.js.map +1 -0
  92. package/dist/consent/index.cjs.map +1 -1
  93. package/dist/consent/index.d.cts +6 -4
  94. package/dist/consent/index.d.ts +6 -4
  95. package/dist/consent/index.js +3 -3
  96. package/dist/{crypto-QXQOHMHF.js → crypto-7BN2HDWG.js} +7 -3
  97. package/dist/{delegation-NIQ43IPU.js → delegation-MGH5SODX.js} +5 -5
  98. package/dist/derivations/index.cjs +24 -3
  99. package/dist/derivations/index.cjs.map +1 -1
  100. package/dist/derivations/index.d.cts +7 -5
  101. package/dist/derivations/index.d.ts +7 -5
  102. package/dist/derivations/index.js +4 -4
  103. package/dist/{dev-unlock-iAS8z9jc.d.ts → dev-unlock-CI1ijTML.d.ts} +1 -1
  104. package/dist/{dev-unlock-nVkuRLLe.d.cts → dev-unlock-iXbYFAWl.d.cts} +1 -1
  105. package/dist/{strategy-CbneC7bS.d.ts → errors-Dz64FA65.d.cts} +98 -727
  106. package/dist/{strategy-CbneC7bS.d.cts → errors-Dz64FA65.d.ts} +98 -727
  107. package/dist/executor-3W63Y44O.js +11 -0
  108. package/dist/executor-CFFWPWBJ.js +8 -0
  109. package/dist/executor-VDQQOR4F.js +8 -0
  110. package/dist/{fanout-sidecar-N6OJX6QR.js → fanout-sidecar-FIJJ46YG.js} +2 -2
  111. package/dist/forget/index.cjs +43 -0
  112. package/dist/forget/index.cjs.map +1 -0
  113. package/dist/forget/index.d.cts +1 -0
  114. package/dist/forget/index.d.ts +1 -0
  115. package/dist/forget/index.js +14 -0
  116. package/dist/guards/index.cjs +9 -5
  117. package/dist/guards/index.cjs.map +1 -1
  118. package/dist/guards/index.d.cts +7 -5
  119. package/dist/guards/index.d.ts +7 -5
  120. package/dist/guards/index.js +6 -6
  121. package/dist/{hash-DHOnRarj.d.ts → hash-blk7Bkes.d.ts} +1 -1
  122. package/dist/{hash-Cv6byZs7.d.cts → hash-tEcM5fnv.d.cts} +1 -1
  123. package/dist/history/index.cjs +27 -4
  124. package/dist/history/index.cjs.map +1 -1
  125. package/dist/history/index.d.cts +7 -5
  126. package/dist/history/index.d.ts +7 -5
  127. package/dist/history/index.js +9 -7
  128. package/dist/history/index.js.map +1 -1
  129. package/dist/i18n/index.cjs +53 -0
  130. package/dist/i18n/index.cjs.map +1 -1
  131. package/dist/i18n/index.d.cts +6 -4
  132. package/dist/i18n/index.d.ts +6 -4
  133. package/dist/i18n/index.js +16 -8
  134. package/dist/i18n/index.js.map +1 -1
  135. package/dist/{immutable-guard-BehB1YGB.d.ts → immutable-guard-B5M95nbq.d.ts} +16 -1
  136. package/dist/{immutable-guard-yBEOYmif.d.cts → immutable-guard-qN3zF8o1.d.cts} +16 -1
  137. package/dist/index-C-SSRIxP.d.cts +348 -0
  138. package/dist/index-C-SSRIxP.d.ts +348 -0
  139. package/dist/{index-XNB2r6bX.d.ts → index-DpU6KWof.d.ts} +9 -1
  140. package/dist/{index-D95VK1Qy.d.cts → index-u-kWzSrL.d.cts} +9 -1
  141. package/dist/index.cjs +2715 -1302
  142. package/dist/index.cjs.map +1 -1
  143. package/dist/index.d.cts +16 -12
  144. package/dist/index.d.ts +16 -12
  145. package/dist/index.js +132 -106
  146. package/dist/index.js.map +1 -1
  147. package/dist/indexing/index.cjs.map +1 -1
  148. package/dist/indexing/index.js +4 -4
  149. package/dist/issue-TTMGHQ2J.js +12 -0
  150. package/dist/{ledger-CWSE3BLF.js → ledger-LFVLHE5H.js} +6 -6
  151. package/dist/materialized-views/index.cjs +407 -5
  152. package/dist/materialized-views/index.cjs.map +1 -1
  153. package/dist/materialized-views/index.d.cts +7 -5
  154. package/dist/materialized-views/index.d.ts +7 -5
  155. package/dist/materialized-views/index.js +12 -12
  156. package/dist/noydb-36S6GQNC.js +37 -0
  157. package/dist/overlay-views/index.cjs +47 -17
  158. package/dist/overlay-views/index.cjs.map +1 -1
  159. package/dist/overlay-views/index.d.cts +28 -8
  160. package/dist/overlay-views/index.d.ts +28 -8
  161. package/dist/overlay-views/index.js +4 -4
  162. package/dist/periods/index.cjs.map +1 -1
  163. package/dist/periods/index.d.cts +6 -4
  164. package/dist/periods/index.d.ts +6 -4
  165. package/dist/periods/index.js +6 -6
  166. package/dist/{public-envelope-SYHEYQ3X.js → public-envelope-RXZNP3V6.js} +4 -4
  167. package/dist/query/index.cjs +28 -11
  168. package/dist/query/index.cjs.map +1 -1
  169. package/dist/query/index.d.cts +3 -2
  170. package/dist/query/index.d.ts +3 -2
  171. package/dist/query/index.js +6 -6
  172. package/dist/registry-3YFLZ7WD.js +8 -0
  173. package/dist/{registry-DK5YWAAA.js → registry-SECUWSGY.js} +3 -3
  174. package/dist/registry-TGZISEWC.js +8 -0
  175. package/dist/{revoke-ZDFKMR5E.js → revoke-B54H2S2W.js} +6 -6
  176. package/dist/sealed-record/index.cjs +139 -0
  177. package/dist/sealed-record/index.cjs.map +1 -0
  178. package/dist/sealed-record/index.d.cts +123 -0
  179. package/dist/sealed-record/index.d.ts +123 -0
  180. package/dist/sealed-record/index.js +42 -0
  181. package/dist/sealed-record/index.js.map +1 -0
  182. package/dist/session/index.cjs.map +1 -1
  183. package/dist/session/index.d.cts +7 -5
  184. package/dist/session/index.d.ts +7 -5
  185. package/dist/session/index.js +3 -3
  186. package/dist/shadow/index.cjs.map +1 -1
  187. package/dist/shadow/index.d.cts +6 -4
  188. package/dist/shadow/index.d.ts +6 -4
  189. package/dist/shadow/index.js +2 -2
  190. package/dist/{signer-P5D7Y72U.js → signer-YSXZT574.js} +5 -5
  191. package/dist/snapshots/index.cjs.map +1 -1
  192. package/dist/snapshots/index.d.cts +6 -4
  193. package/dist/snapshots/index.d.ts +6 -4
  194. package/dist/snapshots/index.js +4 -4
  195. package/dist/{stale-JH67FU57.js → stale-TOA36SRK.js} +2 -2
  196. package/dist/stale-TOA36SRK.js.map +1 -0
  197. package/dist/{state-vault-TMXZRTY5.js → state-vault-W2OEABNO.js} +3 -3
  198. package/dist/store/index.cjs.map +1 -1
  199. package/dist/store/index.d.cts +6 -4
  200. package/dist/store/index.d.ts +6 -4
  201. package/dist/store/index.js +2 -2
  202. package/dist/strategy-4M9jo172.d.ts +739 -0
  203. package/dist/strategy-CLC1j79g.d.cts +739 -0
  204. package/dist/sync/index.cjs.map +1 -1
  205. package/dist/sync/index.d.cts +5 -3
  206. package/dist/sync/index.d.ts +5 -3
  207. package/dist/sync/index.js +4 -4
  208. package/dist/team/index.cjs.map +1 -1
  209. package/dist/team/index.d.cts +6 -4
  210. package/dist/team/index.d.ts +6 -4
  211. package/dist/team/index.js +8 -8
  212. package/dist/tx/index.cjs +66 -3
  213. package/dist/tx/index.cjs.map +1 -1
  214. package/dist/tx/index.d.cts +24 -6
  215. package/dist/tx/index.d.ts +24 -6
  216. package/dist/tx/index.js +9 -5
  217. package/dist/tx/index.js.map +1 -1
  218. package/dist/{types-4t1-tWS4.d.ts → types-CljIHm_J.d.ts} +1127 -606
  219. package/dist/{types-BpPV5uyy.d.cts → types-CrSpRDuG.d.cts} +1127 -606
  220. package/dist/{ulid-DAfenvFd.d.ts → ulid-CWfL2Vfv.d.ts} +1 -1
  221. package/dist/{ulid-CiPrpGqm.d.cts → ulid-CrI7PPbA.d.cts} +1 -1
  222. package/dist/util/index.cjs.map +1 -1
  223. package/dist/util/index.js +1 -1
  224. package/dist/{vault-group-KOM7QRJG.js → vault-group-DHAHFX2A.js} +4 -4
  225. package/dist/{with-derivation-OK9M2sJE.d.ts → with-derivation-BZ2y4bzF.d.ts} +1 -1
  226. package/dist/{with-derivation-DBqJB3dQ.d.cts → with-derivation-Bozs8DmD.d.cts} +1 -1
  227. package/dist/{with-materialized-view-Dt-ufPWQ.d.ts → with-materialized-view-B892zYZV.d.ts} +1 -1
  228. package/dist/{with-materialized-view-NzuxYPDF.d.cts → with-materialized-view-NzF71cG_.d.cts} +1 -1
  229. package/dist/{with-overlayed-view-eDvMs6LO.d.ts → with-overlayed-view-CR6m7CHe.d.ts} +1 -1
  230. package/dist/{with-overlayed-view-CC0_ocy-.d.cts → with-overlayed-view-UI8qSGL4.d.cts} +1 -1
  231. package/package.json +23 -3
  232. package/dist/chunk-3EWXMOK3.js.map +0 -1
  233. package/dist/chunk-535SSHBS.js.map +0 -1
  234. package/dist/chunk-5LQG6ZO2.js.map +0 -1
  235. package/dist/chunk-7EFFHEN5.js.map +0 -1
  236. package/dist/chunk-7HT2MEZ5.js.map +0 -1
  237. package/dist/chunk-C5T5AFWN.js.map +0 -1
  238. package/dist/chunk-DQU36Q7I.js.map +0 -1
  239. package/dist/chunk-EGD5DXFT.js.map +0 -1
  240. package/dist/chunk-EYVQHAGH.js.map +0 -1
  241. package/dist/chunk-GC4V7RU7.js.map +0 -1
  242. package/dist/chunk-HOR4R722.js.map +0 -1
  243. package/dist/chunk-LX3CB26H.js.map +0 -1
  244. package/dist/chunk-OHVFWCJP.js.map +0 -1
  245. package/dist/chunk-VU7SWWT5.js.map +0 -1
  246. package/dist/chunk-WGHU7BLI.js.map +0 -1
  247. package/dist/chunk-YHPM5D7Y.js.map +0 -1
  248. package/dist/chunk-YULZKK4F.js.map +0 -1
  249. package/dist/executor-6ZDSDZ6V.js +0 -8
  250. package/dist/executor-HSSRXDOB.js +0 -11
  251. package/dist/executor-IDZDAFNH.js +0 -8
  252. package/dist/issue-ADVS4OVP.js +0 -12
  253. package/dist/noydb-GZGFBA4E.js +0 -35
  254. package/dist/registry-IUZQVVBB.js +0 -8
  255. package/dist/registry-XGLNADIE.js +0 -8
  256. /package/dist/{chunk-JD3OZAI4.js.map → chunk-3G3W65EQ.js.map} +0 -0
  257. /package/dist/{chunk-XWH4MXIU.js.map → chunk-5AXTH4QZ.js.map} +0 -0
  258. /package/dist/{chunk-4TBBMHVC.js.map → chunk-5LIROIDM.js.map} +0 -0
  259. /package/dist/{chunk-KI6HAJWL.js.map → chunk-BH3X5L6A.js.map} +0 -0
  260. /package/dist/{chunk-BQ65SS5A.js.map → chunk-BJSLBUJ7.js.map} +0 -0
  261. /package/dist/{chunk-L2FE64BU.js.map → chunk-BL5GYANC.js.map} +0 -0
  262. /package/dist/{chunk-A5ZOOZFB.js.map → chunk-BSZOCSDZ.js.map} +0 -0
  263. /package/dist/{chunk-ZNQYHJXX.js.map → chunk-C3HYQPV4.js.map} +0 -0
  264. /package/dist/{chunk-PE4AQGFH.js.map → chunk-CD2AVTEM.js.map} +0 -0
  265. /package/dist/{chunk-56DJ7JVK.js.map → chunk-DWEBTE2W.js.map} +0 -0
  266. /package/dist/{chunk-Z4DO7YSI.js.map → chunk-DYYYUW5D.js.map} +0 -0
  267. /package/dist/{chunk-NSCVNK5K.js.map → chunk-E77UKJYL.js.map} +0 -0
  268. /package/dist/{chunk-KIP6JLTF.js.map → chunk-F4G63NTZ.js.map} +0 -0
  269. /package/dist/{chunk-IQLVUT37.js.map → chunk-H2MRGONI.js.map} +0 -0
  270. /package/dist/{chunk-CJORTUJ2.js.map → chunk-J7RWBXFY.js.map} +0 -0
  271. /package/dist/{chunk-AAVWKNZW.js.map → chunk-JDWE6JMX.js.map} +0 -0
  272. /package/dist/{chunk-6AJBSQU4.js.map → chunk-KCEHMDZF.js.map} +0 -0
  273. /package/dist/{chunk-TS26M2SB.js.map → chunk-M476FOQ7.js.map} +0 -0
  274. /package/dist/{chunk-F4OJZIWQ.js.map → chunk-NBBMMJ2H.js.map} +0 -0
  275. /package/dist/{chunk-CZI2A4MQ.js.map → chunk-NYSYPFXJ.js.map} +0 -0
  276. /package/dist/{chunk-COFPAMX6.js.map → chunk-QHM6XEAH.js.map} +0 -0
  277. /package/dist/{chunk-6RR3MNMG.js.map → chunk-SHX5QBCI.js.map} +0 -0
  278. /package/dist/{chunk-BIYRQQV6.js.map → chunk-SNMJ7SB3.js.map} +0 -0
  279. /package/dist/{chunk-7PS7EOCF.js.map → chunk-TIDXB5DF.js.map} +0 -0
  280. /package/dist/{chunk-FWPKCXTN.js.map → chunk-WIAOUFFB.js.map} +0 -0
  281. /package/dist/{chunk-X73VS74Y.js.map → chunk-XJV6OB4D.js.map} +0 -0
  282. /package/dist/{chunk-WBAYSNUQ.js.map → chunk-XMVHEWF6.js.map} +0 -0
  283. /package/dist/{chunk-DKO2QFSA.js.map → chunk-YYVZYTWW.js.map} +0 -0
  284. /package/dist/{crypto-QXQOHMHF.js.map → crypto-7BN2HDWG.js.map} +0 -0
  285. /package/dist/{delegation-NIQ43IPU.js.map → delegation-MGH5SODX.js.map} +0 -0
  286. /package/dist/{executor-6ZDSDZ6V.js.map → executor-3W63Y44O.js.map} +0 -0
  287. /package/dist/{executor-HSSRXDOB.js.map → executor-CFFWPWBJ.js.map} +0 -0
  288. /package/dist/{executor-IDZDAFNH.js.map → executor-VDQQOR4F.js.map} +0 -0
  289. /package/dist/{fanout-sidecar-N6OJX6QR.js.map → fanout-sidecar-FIJJ46YG.js.map} +0 -0
  290. /package/dist/{issue-ADVS4OVP.js.map → forget/index.js.map} +0 -0
  291. /package/dist/{ledger-CWSE3BLF.js.map → issue-TTMGHQ2J.js.map} +0 -0
  292. /package/dist/{noydb-GZGFBA4E.js.map → ledger-LFVLHE5H.js.map} +0 -0
  293. /package/dist/{public-envelope-SYHEYQ3X.js.map → noydb-36S6GQNC.js.map} +0 -0
  294. /package/dist/{registry-DK5YWAAA.js.map → public-envelope-RXZNP3V6.js.map} +0 -0
  295. /package/dist/{registry-IUZQVVBB.js.map → registry-3YFLZ7WD.js.map} +0 -0
  296. /package/dist/{registry-XGLNADIE.js.map → registry-SECUWSGY.js.map} +0 -0
  297. /package/dist/{revoke-ZDFKMR5E.js.map → registry-TGZISEWC.js.map} +0 -0
  298. /package/dist/{signer-P5D7Y72U.js.map → revoke-B54H2S2W.js.map} +0 -0
  299. /package/dist/{stale-JH67FU57.js.map → signer-YSXZT574.js.map} +0 -0
  300. /package/dist/{state-vault-TMXZRTY5.js.map → state-vault-W2OEABNO.js.map} +0 -0
  301. /package/dist/{vault-group-KOM7QRJG.js.map → vault-group-DHAHFX2A.js.map} +0 -0
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  MoneyUnsupportedError,
3
3
  formatScaledInt,
4
+ parseToScaledInt,
4
5
  readPath,
5
6
  scaleForCurrency
6
- } from "./chunk-CJORTUJ2.js";
7
+ } from "./chunk-J7RWBXFY.js";
7
8
  import {
8
9
  GroupCardinalityError
9
- } from "./chunk-535SSHBS.js";
10
+ } from "./chunk-ZEGSDPB7.js";
10
11
 
11
12
  // src/aggregate/aggregation.ts
12
13
  function reduceRecords(records, spec) {
@@ -144,13 +145,22 @@ function canonicalGroupKey(fields, row) {
144
145
  }
145
146
 
146
147
  // src/money/money-reducer.ts
147
- function toScaledInt(v) {
148
- if (typeof v === "string" || typeof v === "number" || typeof v === "bigint") {
149
- try {
150
- return BigInt(v);
151
- } catch {
152
- return null;
148
+ function toScaledIntFromAny(v, scale) {
149
+ if (typeof v === "bigint") return v;
150
+ if (typeof v === "number") {
151
+ const r = parseToScaledInt(v, scale);
152
+ return r.ok ? r.value : null;
153
+ }
154
+ if (typeof v === "string") {
155
+ if (!v.includes(".")) {
156
+ try {
157
+ return BigInt(v);
158
+ } catch {
159
+ return null;
160
+ }
153
161
  }
162
+ const r = parseToScaledInt(v, scale);
163
+ return r.ok ? r.value : null;
154
164
  }
155
165
  return null;
156
166
  }
@@ -158,13 +168,15 @@ function readMoney(record, field, desc) {
158
168
  const raw = readPath(record, field);
159
169
  if (raw === null || raw === void 0) return null;
160
170
  if (desc.mode === "fixed") {
161
- const value2 = toScaledInt(raw);
162
- return value2 === null ? null : { currency: desc.fixedCurrency, value: value2 };
171
+ const cur = desc.fixedCurrency;
172
+ const value2 = toScaledIntFromAny(raw, desc.scaleFor(cur));
173
+ return value2 === null ? null : { currency: cur, value: value2 };
163
174
  }
164
175
  if (typeof raw !== "object") return null;
165
176
  const o = raw;
166
177
  if (typeof o.currency !== "string") return null;
167
- const value = toScaledInt(o.amount);
178
+ const scale = desc.allows(o.currency) ? desc.scaleFor(o.currency) : 0;
179
+ const value = toScaledIntFromAny(o.amount, scale);
168
180
  return value === null ? null : { currency: o.currency, value };
169
181
  }
170
182
  function targetScaleFor(desc, currency) {
@@ -385,11 +397,14 @@ var GroupedQueryN = class extends GroupedQueryBase {
385
397
  );
386
398
  }
387
399
  };
388
- function groupAndReduce(records, fieldOrFields, spec) {
400
+ function groupAndReduce(records, fieldOrFields, spec, moneyFields) {
389
401
  const fields = typeof fieldOrFields === "string" ? [fieldOrFields] : fieldOrFields;
390
402
  if (fields.length === 0) {
391
403
  throw new Error(".groupBy() requires at least one field");
392
404
  }
405
+ if (moneyFields) {
406
+ spec = wrapMoneyReducers(spec, moneyFields);
407
+ }
393
408
  const buckets = /* @__PURE__ */ new Map();
394
409
  const fieldLabel = fields.length === 1 ? fields[0] : `[${fields.join(", ")}]`;
395
410
  for (const record of records) {
@@ -521,4 +536,4 @@ export {
521
536
  groupAndReduce,
522
537
  GroupedAggregation
523
538
  };
524
- //# sourceMappingURL=chunk-3EWXMOK3.js.map
539
+ //# sourceMappingURL=chunk-7H2GEJ3O.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/aggregate/aggregation.ts","../src/aggregate/canonical-key.ts","../src/money/money-reducer.ts","../src/aggregate/groupby.ts"],"sourcesContent":["/**\n * Aggregate execution — the runtime behind `Query.aggregate()`.\n *\n * takes an `AggregateSpec` (a record of named reducers\n * built from `reducers.ts`) and runs every reducer over the records\n * produced by the underlying query. Two terminal surfaces:\n *\n * - `.run(): R` — synchronous one-shot reduction. Matches the\n * existing `Query.toArray()` / `.first()` / `.count()` style.\n * - `.live(): LiveAggregation<R>` — reactive primitive that\n * re-runs the reduction whenever the query's source notifies of\n * a change. uses naive full re-run; incremental delta\n * maintenance is admitted by the reducer protocol (`remove()`)\n * but not wired to the executor yet — a follow-up optimization\n * can switch from full re-run to delta-based without breaking\n * the public API. Consumers get correct, reactive values today.\n *\n * The `Aggregation<R>` wrapper is deliberately tiny — it exists so\n * `.aggregate(spec)` can be chained with either `.run()` or `.live()`\n * without the builder needing two separate terminal methods. It\n * holds the closure over the query execution (produces the current\n * matching record set) and the spec, and stitches them together in\n * either mode.\n *\n * This file depends ONLY on `reducers.ts` — it has no knowledge of\n * the `Query` class. Tests can therefore exercise the reduction\n * surface with plain record arrays, without spinning up a Collection.\n */\n\nimport type { Reducer } from './reducers.js'\n\n/**\n * A named set of reducers, keyed by output field name. Each key\n * becomes a field on the aggregated result.\n *\n * ```ts\n * const spec = {\n * total: sum('amount'),\n * n: count(),\n * avgAmount: avg('amount'),\n * }\n * ```\n */\nexport type AggregateSpec = Readonly<Record<string, Reducer<unknown, unknown>>>\n\n/**\n * Map an `AggregateSpec` to its reduced result shape — each key\n * carries the finalized result type from its reducer. A spec built\n * from `{ total: sum('amount'), n: count() }` yields a result of\n * `{ total: number, n: number }`.\n *\n * This uses a mapped type with a conditional to extract `R` from\n * each `Reducer<R, _>`. The `infer` captures the user-visible result\n * type, discarding the internal state type `S`.\n */\nexport type AggregateResult<Spec extends AggregateSpec> = {\n [K in keyof Spec]: Spec[K] extends Reducer<infer R, unknown> ? R : never\n}\n\n/**\n * Pure reduction over a record array. Runs every reducer's\n * `init → step* → finalize` pipeline exactly once over the records.\n *\n * Called by `Aggregation.run()` and by the live-mode refresh path.\n * Exported for tests and for future `scan().aggregate()` reuse\n * — the streaming path will call the same reducer protocol with a\n * per-page loop instead of a single array.\n */\nexport function reduceRecords<Spec extends AggregateSpec>(\n records: readonly unknown[],\n spec: Spec,\n): AggregateResult<Spec> {\n // Per-slot state, keyed by the spec's output field name.\n const state: Record<string, unknown> = {}\n for (const key of Object.keys(spec)) {\n state[key] = spec[key]!.init()\n }\n for (const record of records) {\n for (const key of Object.keys(spec)) {\n state[key] = spec[key]!.step(state[key], record)\n }\n }\n const result: Record<string, unknown> = {}\n for (const key of Object.keys(spec)) {\n result[key] = spec[key]!.finalize(state[key])\n }\n return result as AggregateResult<Spec>\n}\n\n/**\n * A minimal reactive primitive for aggregation results.\n *\n * Same spirit as the `LiveQuery` in : frame-agnostic, a plain\n * object with `value` / `error` fields and a `subscribe(cb)`\n * notification channel that Vue / React / Solid adapters wrap in\n * their own primitive. Intentionally NOT a Promise — aggregations\n * have a well-defined \"current value\" at every instant, and the\n * reactive consumer wants to read that value synchronously.\n *\n * Error semantics mirror `LiveQuery`: if a re-run throws, the\n * previous successful `value` is preserved and the error is stored\n * in `error` so consumers can render an error state without losing\n * the last-known-good result. The throw does NOT propagate out of\n * the source's change handler (which would tear down the upstream\n * emitter).\n *\n * `stop()` tears down the upstream subscription. It is idempotent —\n * calling it multiple times is safe — and subscribe calls after\n * stop are no-ops (they immediately return a no-op unsubscribe).\n * Always call `stop()` when done; Vue's `onUnmounted` is the\n * canonical place. Raw consumers must do it themselves.\n */\nexport interface LiveAggregation<R> {\n /** Current reduced value. Undefined only if the first compute threw. */\n readonly value: R | undefined\n /** Last execution error, if any. Cleared on the next successful run. */\n readonly error: unknown\n /** Notify on every recomputation (success or error). Returns unsubscribe. */\n subscribe(cb: () => void): () => void\n /** Tear down the upstream subscription. Idempotent. */\n stop(): void\n}\n\n/**\n * Upstream change-notification hook for live aggregation.\n *\n * Matches the shape that `QuerySource.subscribe` already uses — a\n * single method that accepts a callback and returns an unsubscribe\n * function. The `Aggregation` wrapper collects upstreams from the\n * query's source and wires them into a single re-run trigger.\n */\nexport interface AggregationUpstream {\n subscribe(cb: () => void): () => void\n}\n\n/**\n * Internal implementation of `LiveAggregation`. Not exported —\n * consumers get the interface only. The class wraps a `recompute`\n * closure (which runs the full reduction and returns the new value)\n * and a list of upstreams (sources whose changes should trigger a\n * re-run).\n *\n * Error isolation: if an individual listener callback throws, the\n * other listeners still fire and the error is logged to the warn\n * channel. This matches `LiveQuery` from and keeps one misbehaving\n * consumer from tearing down the whole live aggregation.\n */\nclass LiveAggregationImpl<R> implements LiveAggregation<R> {\n public value: R | undefined\n public error: unknown\n private readonly listeners = new Set<() => void>()\n private readonly unsubscribes: Array<() => void> = []\n private stopped = false\n\n constructor(\n private readonly recompute: () => R,\n upstreams: readonly AggregationUpstream[],\n ) {\n // Initial computation — surface any error through the `error`\n // field rather than letting the constructor throw, so consumers\n // can always construct a LiveAggregation and check its state\n // afterwards. Throwing from a constructor would force every\n // caller to wrap in try/catch, which is the opposite of the\n // \"reactive value with error state\" ergonomics we want.\n try {\n this.value = recompute()\n this.error = undefined\n } catch (err) {\n this.value = undefined\n this.error = err\n }\n\n // Wire up upstream subscriptions. Each one triggers a full\n // recomputation; we don't attempt incremental updates in.\n for (const upstream of upstreams) {\n const unsub = upstream.subscribe(() => this.refresh())\n this.unsubscribes.push(unsub)\n }\n }\n\n private refresh(): void {\n if (this.stopped) return\n try {\n this.value = this.recompute()\n this.error = undefined\n } catch (err) {\n // Preserve the previous successful value — consumers render an\n // error state using `error` without losing the last-known-good\n // number. This matches LiveQuery's error-preservation contract.\n this.error = err\n }\n for (const listener of this.listeners) {\n try {\n listener()\n } catch (err) {\n // Isolate listener errors so one bad consumer can't tear\n // down every other subscriber on the same aggregation.\n console.warn('[noy-db] LiveAggregation listener threw:', err)\n }\n }\n }\n\n subscribe(cb: () => void): () => void {\n if (this.stopped) {\n // No-op after stop. Returning a harmless unsubscribe lets\n // consumers use the same teardown pattern unconditionally.\n return () => {}\n }\n this.listeners.add(cb)\n return () => {\n this.listeners.delete(cb)\n }\n }\n\n stop(): void {\n if (this.stopped) return\n this.stopped = true\n for (const unsub of this.unsubscribes) {\n try {\n unsub()\n } catch (err) {\n console.warn('[noy-db] LiveAggregation upstream unsubscribe threw:', err)\n }\n }\n this.unsubscribes.length = 0\n this.listeners.clear()\n }\n}\n\n/**\n * Chainable wrapper returned by `Query.aggregate(spec)`. Holds the\n * execute-records closure and the spec; terminal methods (`run`,\n * `live`) stitch them together in either mode.\n *\n * Why a wrapper instead of two terminal methods on `Query` directly?\n *\n * The `.aggregate(spec)` call is where the spec is bound — both\n * `.run()` and `.live()` need the same spec, and the consumer's\n * fluent style is `query.where(...).aggregate(spec).run()` or\n * `.aggregate(spec).live()`. Wrapping lets the spec be named once\n * and reused for either terminal, and keeps the `Query` class\n * from growing a pair of near-duplicate method overloads\n * (`aggregateRun` / `aggregateLive`) that would be harder to\n * discover.\n */\nexport class Aggregation<R> {\n constructor(\n private readonly executeRecords: () => readonly unknown[],\n private readonly spec: AggregateSpec,\n private readonly upstreams: readonly AggregationUpstream[],\n ) {}\n\n /**\n * Execute the query and reduce the results synchronously.\n * Returns the reduced shape matching the spec — e.g. a spec of\n * `{ total: sum('amount'), n: count() }` returns\n * `{ total: number, n: number }`.\n */\n run(): R {\n return reduceRecords(this.executeRecords(), this.spec) as unknown as R\n }\n\n /**\n * Build a reactive `LiveAggregation<R>` that re-runs the reduction\n * whenever any upstream source notifies of a change. The initial\n * value is computed eagerly in the constructor, so consumers can\n * read `live.value` immediately after calling `.live()`.\n *\n * Always call `live.stop()` when finished — it tears down the\n * upstream subscriptions. Vue's `onUnmounted` is the canonical\n * place.\n *\n * **Implementation note:** every upstream change triggers a full\n * re-reduction. Incremental maintenance (O(1) per delta for\n * sum/count/avg via the reducer protocol's `remove()` method) is a\n * planned follow-up optimization — the protocol already supports\n * it, but the executor doesn't drive it yet. Consumers get\n * correct, reactive values today; future PRs can switch to\n * delta-based maintenance without changing this API.\n */\n live(): LiveAggregation<R> {\n const recompute = (): R =>\n reduceRecords(this.executeRecords(), this.spec) as unknown as R\n return new LiveAggregationImpl<R>(recompute, this.upstreams)\n }\n}\n\n/**\n * Build a `LiveAggregation<V>` from a recompute closure and a list\n * of upstreams. Exposed so sibling files in the query DSL\n * (currently `groupby.ts`) can reuse the reactive primitive\n * without reaching into `LiveAggregationImpl` directly. This keeps\n * the implementation class private while still allowing planned\n * composition with `.groupBy().aggregate().live()`.\n */\nexport function buildLiveAggregation<V>(\n recompute: () => V,\n upstreams: readonly AggregationUpstream[],\n): LiveAggregation<V> {\n return new LiveAggregationImpl<V>(recompute, upstreams)\n}\n","/**\n * Canonicalise a group-key tuple to a stable string for dedup hashing.\n *\n * Sorts field names lexicographically before serialising, so that\n * `.groupBy('a', 'b')` and `.groupBy('b', 'a')` produce identical\n * keys for the same logical group. Values are JSON-stringified;\n * `undefined` and `null` are distinguished (matching the Map-key\n * semantics in `groupAndReduce`).\n *\n * NOT part of the public API. Used by:\n * - `groupAndReduce` for the dedup Map's key\n * - `materialized-views/query-hash` for UNION MV cross-arm row-key dedup (PR 2)\n *\n * Pure: same input → same output, no side effects.\n */\nexport function canonicalGroupKey(\n fields: readonly string[],\n row: Record<string, unknown>,\n): string {\n const sorted = [...fields].sort()\n const parts: string[] = []\n for (const name of sorted) {\n const v = row[name]\n const serialised =\n v === undefined ? 'undefined' : JSON.stringify(v)\n parts.push(`${name}=${serialised}`)\n }\n return parts.join('|')\n}\n","/**\n * Money-aware aggregation: exact `sum` / `min` / `max` over money\n * fields.\n *\n * The generic reducers (`aggregate/reducers.ts`) read a field via\n * `readNumber`, which coerces a string (the stored scaled-integer form\n * of money, e.g. `'12345'`) to `0` — so an un-wrapped money `sum` would\n * silently return zero. {@link wrapMoneyReducers} rewrites any `sum` /\n * `min` / `max` over a declared money field into a reducer that\n * accumulates per-currency `BigInt` totals of the stored integers, so\n * the result is exact for any magnitude (past `Number.MAX_SAFE_INTEGER`\n * included).\n *\n * Results are currency-aware and never silently mix currencies:\n * - **fixed** mode → a single exact decimal string.\n * - **multi** mode → an exact `Record<currency, string>` map.\n * - **`sum` with `convertTo` + `fx`** → a single exact string, with\n * each currency converted via BigInt arithmetic (no float).\n *\n * `remove()` is implemented for every money reducer so they participate\n * in incremental live-aggregation and materialized-view maintenance\n * exactly like the generic reducers they replace.\n */\n\nimport { readPath } from '../query/predicate.js'\nimport { formatScaledInt, parseToScaledInt } from './fixed-point.js'\nimport { scaleForCurrency } from './iso4217.js'\nimport { MoneyUnsupportedError } from './descriptor.js'\nimport type { MoneyDescriptor } from './descriptor.js'\nimport type { Reducer } from '../aggregate/reducers.js'\nimport type { AggregateSpec } from '../aggregate/aggregation.js'\n\nexport type FxRates = Record<string, number | string>\n\ninterface ReadMoney {\n currency: string\n value: bigint\n}\n\n/**\n * Coerce an arbitrary money-field value into its scaled `BigInt` at the\n * given `scale`. Handles the two shapes a money field can arrive in by\n * the time it reaches a reducer:\n *\n * - **stored form** — a bare scaled-integer string (`'12345'`) or a\n * `bigint`. No decimal point, so `BigInt(v)` is the fast path.\n * - **decoded form** — a canonical decimal string (`'123.45'`), which\n * is what `query().toArray()` / `decodeMoneyFields` produce (UNION\n * arms map over decoded rows). `BigInt('123.45')` throws, so these\n * route through `parseToScaledInt(v, scale)`.\n *\n * A `number` is treated as a decimal magnitude (parsed at `scale`).\n * Anything unparseable → `null`.\n */\nfunction toScaledIntFromAny(v: unknown, scale: number): bigint | null {\n if (typeof v === 'bigint') return v\n if (typeof v === 'number') {\n const r = parseToScaledInt(v, scale)\n return r.ok ? r.value : null\n }\n if (typeof v === 'string') {\n if (!v.includes('.')) {\n // Stored scaled-integer form (e.g. '12345') — no decimal point.\n try {\n return BigInt(v)\n } catch {\n return null\n }\n }\n // Decoded canonical-decimal form (e.g. '123.45').\n const r = parseToScaledInt(v, scale)\n return r.ok ? r.value : null\n }\n return null\n}\n\n/** Read the raw stored money value (scaled integer) from a record. */\nfunction readMoney(record: unknown, field: string, desc: MoneyDescriptor): ReadMoney | null {\n const raw = readPath(record, field)\n if (raw === null || raw === undefined) return null\n if (desc.mode === 'fixed') {\n const cur = desc.fixedCurrency!\n const value = toScaledIntFromAny(raw, desc.scaleFor(cur))\n return value === null ? null : { currency: cur, value }\n }\n // multi mode: stored as { amount, currency }\n if (typeof raw !== 'object') return null\n const o = raw as { amount?: unknown; currency?: unknown }\n if (typeof o.currency !== 'string') return null\n const scale = desc.allows(o.currency) ? desc.scaleFor(o.currency) : 0\n const value = toScaledIntFromAny(o.amount, scale)\n return value === null ? null : { currency: o.currency, value }\n}\n\n/** Resolve the scale to use for a target currency (may be outside the allow-list). */\nfunction targetScaleFor(desc: MoneyDescriptor, currency: string): number {\n if (desc.allows(currency)) return desc.scaleFor(currency)\n const s = scaleForCurrency(currency)\n if (s === null) {\n throw new Error(`money: cannot determine scale for conversion target \"${currency}\"`)\n }\n return s\n}\n\n/** Parse a rate (number | string) into a scaled BigInt + its scale. */\nfunction parseRate(rate: number | string): { int: bigint; scale: number } {\n const s = String(rate).trim()\n const neg = s.startsWith('-')\n const body = neg ? s.slice(1) : s\n const dot = body.indexOf('.')\n const intPart = dot === -1 ? body : body.slice(0, dot)\n const fracPart = dot === -1 ? '' : body.slice(dot + 1)\n const int = BigInt((intPart === '' ? '0' : intPart) + fracPart)\n return { int: neg ? -int : int, scale: fracPart.length }\n}\n\n/** BigInt division of `n / d` with half-even (banker's) rounding. */\nfunction divRoundHalfEven(n: bigint, d: bigint): bigint {\n const q = n / d\n const r = n % d\n const twiceR = (r < 0n ? -r : r) * 2n\n if (twiceR < d) return q\n if (twiceR > d) return q + (n < 0n ? -1n : 1n)\n return q % 2n === 0n ? q : q + (n < 0n ? -1n : 1n)\n}\n\n/** Convert a scaled integer from `srcScale` to `targetScale` applying `rate`. */\nfunction convertScaled(value: bigint, srcScale: number, rate: number | string, targetScale: number): bigint {\n const { int: rateInt, scale: rateScale } = parseRate(rate)\n const product = value * rateInt\n const curScale = srcScale + rateScale\n if (curScale === targetScale) return product\n if (curScale < targetScale) return product * 10n ** BigInt(targetScale - curScale)\n return divRoundHalfEven(product, 10n ** BigInt(curScale - targetScale))\n}\n\nfunction finalizeSum(\n state: Map<string, bigint>,\n desc: MoneyDescriptor,\n convertTo: string | undefined,\n fx: FxRates | undefined,\n): string | Record<string, string> {\n if (convertTo !== undefined) {\n if (fx === undefined) {\n throw new Error(`money: sum convertTo \"${convertTo}\" requires an fx rate map`)\n }\n const targetScale = targetScaleFor(desc, convertTo)\n let total = 0n\n for (const [cur, v] of state) {\n if (cur === convertTo) {\n total += convertScaled(v, desc.scaleFor(cur), 1, targetScale)\n continue\n }\n const rate = fx[`${cur}->${convertTo}`]\n if (rate === undefined) {\n throw new Error(`money: no fx rate for \"${cur}->${convertTo}\"`)\n }\n total += convertScaled(v, desc.scaleFor(cur), rate, targetScale)\n }\n return formatScaledInt(total, targetScale)\n }\n\n if (desc.mode === 'fixed') {\n const cur = desc.fixedCurrency!\n return formatScaledInt(state.get(cur) ?? 0n, desc.scaleFor(cur))\n }\n\n const out: Record<string, string> = {}\n for (const [cur, v] of state) out[cur] = formatScaledInt(v, desc.scaleFor(cur))\n return out\n}\n\nfunction moneySumReducer(\n field: string,\n desc: MoneyDescriptor,\n convertTo: string | undefined,\n fx: FxRates | undefined,\n): Reducer<unknown, Map<string, bigint>> {\n return {\n op: 'sum',\n field,\n init: () => new Map<string, bigint>(),\n step: (state, record) => {\n const m = readMoney(record, field, desc)\n if (m) state.set(m.currency, (state.get(m.currency) ?? 0n) + m.value)\n return state\n },\n remove: (state, record) => {\n const m = readMoney(record, field, desc)\n if (m) state.set(m.currency, (state.get(m.currency) ?? 0n) - m.value)\n return state\n },\n finalize: (state) => finalizeSum(state, desc, convertTo, fx),\n }\n}\n\nfunction extremum(values: readonly bigint[], op: 'min' | 'max'): bigint {\n let out = values[0]!\n for (let i = 1; i < values.length; i++) {\n const v = values[i]!\n if (op === 'min' ? v < out : v > out) out = v\n }\n return out\n}\n\nfunction moneyMinMaxReducer(\n op: 'min' | 'max',\n field: string,\n desc: MoneyDescriptor,\n): Reducer<unknown, Map<string, bigint[]>> {\n return {\n op,\n field,\n init: () => new Map<string, bigint[]>(),\n step: (state, record) => {\n const m = readMoney(record, field, desc)\n if (m) {\n const arr = state.get(m.currency)\n if (arr) arr.push(m.value)\n else state.set(m.currency, [m.value])\n }\n return state\n },\n remove: (state, record) => {\n const m = readMoney(record, field, desc)\n if (m) {\n const arr = state.get(m.currency)\n if (arr) {\n const idx = arr.indexOf(m.value)\n if (idx >= 0) arr.splice(idx, 1)\n }\n }\n return state\n },\n finalize: (state) => {\n if (desc.mode === 'fixed') {\n const cur = desc.fixedCurrency!\n const arr = state.get(cur)\n if (!arr || arr.length === 0) return null\n return formatScaledInt(extremum(arr, op), desc.scaleFor(cur))\n }\n const out: Record<string, string> = {}\n for (const [cur, arr] of state) {\n if (arr.length > 0) out[cur] = formatScaledInt(extremum(arr, op), desc.scaleFor(cur))\n }\n return out\n },\n }\n}\n\n/**\n * Rewrite any `sum` / `min` / `max` reducer over a declared money field\n * into its exact BigInt money-aware equivalent. Other reducers (and\n * reducers over non-money fields) pass through unchanged. Returns a new\n * spec; the input is not mutated.\n */\nexport function wrapMoneyReducers(\n spec: AggregateSpec,\n moneyFields: Record<string, MoneyDescriptor>,\n): AggregateSpec {\n let changed = false\n const out: Record<string, Reducer<unknown, unknown>> = {}\n for (const [key, reducer] of Object.entries(spec)) {\n const field = reducer.field\n const desc = field ? moneyFields[field] : undefined\n if (desc && reducer.op === 'avg') {\n throw new MoneyUnsupportedError(\n field!,\n `avg() is not supported on money field \"${field}\" in v1 — use sum() and count() and divide at the boundary.`,\n )\n }\n if (desc && (reducer.op === 'sum' || reducer.op === 'min' || reducer.op === 'max')) {\n changed = true\n out[key] =\n reducer.op === 'sum'\n ? moneySumReducer(field!, desc, reducer.convertTo, reducer.fx as FxRates | undefined)\n : (moneyMinMaxReducer(reducer.op, field!, desc) as Reducer<unknown, unknown>)\n } else {\n out[key] = reducer\n }\n }\n return changed ? out : spec\n}\n","/**\n * Query DSL `.groupBy()` —.\n *\n * Chains after `.where()` / `.filter()` / `.or()` / `.and()` on a\n * Query and before a reducer spec, so consumers can compute\n * per-bucket aggregates without folding in userland:\n *\n * ```ts\n * const byClient = invoices.query()\n * .where('status', '==', 'open')\n * .groupBy('clientId')\n * .aggregate({ total: sum('amount'), n: count() })\n * .run()\n * // → [ { clientId: 'c1', total: 5250, n: 3 }, … ]\n * ```\n *\n * Execution pipeline:\n *\n * 1. Run the query's where/filter clauses (same candidate /\n * filter pipeline as `.aggregate()` directly on Query).\n * 2. Partition the matching records into buckets keyed by\n * `readPath(record, field)`. JS `Map` preserves insertion\n * order, so the first-seen key for a bucket determines its\n * position in the result array — consumers who want a\n * specific ordering should `.sort()` downstream.\n * 3. Enforce cardinality: warn once per field at 10% of the cap\n * (10_000 buckets), throw `GroupCardinalityError` at 100% of\n * the cap (100_000 buckets).\n * 4. For each bucket, build a per-group reducer state and\n * step every record in the bucket through it.\n * 5. Emit one result row per bucket, shaped as\n * `{ [field]: key, ...reduced }`.\n *\n * **Null / undefined keys:** `Map` distinguishes `null` from\n * `undefined`, so records with a missing group field get their own\n * bucket, and records with an explicit `null` value get a separate\n * bucket from that. Consumers who want them merged can coalesce\n * upstream with `.filter()`.\n *\n * **Live mode:** `.groupBy().aggregate().live()` re-runs the full\n * grouping pipeline on every source change. Per-bucket incremental\n * delta maintenance is a future optimization — the reducer\n * protocol's `remove()` hook admits it, but ships naive\n * re-grouping for simplicity.\n *\n * **Type-level stable-key narrowing:** when\n * `dictKey` lands, `groupBy<DictField>()` will narrow the group key\n * type to the stable dictionary key rather than the resolved locale\n * label. That prevents grouping by the locale-resolved label,\n * which would produce different buckets per reader. types the\n * key as `unknown` at the result shape; the dictKey narrowing\n * layers on top without an API break.\n *\n * Partition-awareness seam: when partitioned collections land,\n * per-partition grouping will need to merge sub-results across\n * partitions. The reducer protocol's `{ seed }` parameter\n * (already plumbed through in `reducers.ts`) is the mechanism —\n * groupBy doesn't need its own seam for the moment, because it\n * delegates to the reducer protocol for all per-bucket state.\n */\n\nimport { readPath } from '../query/predicate.js'\nimport type {\n AggregateSpec,\n AggregateResult,\n AggregationUpstream,\n LiveAggregation,\n} from './aggregation.js'\nimport { buildLiveAggregation } from './aggregation.js'\nimport { canonicalGroupKey } from './canonical-key.js'\nimport { GroupCardinalityError } from '../errors.js'\nimport type { MoneyDescriptor } from '../money/descriptor.js'\nimport { wrapMoneyReducers } from '../money/money-reducer.js'\n\n/**\n * Cardinality thresholds for `.groupBy()`. The warn threshold gives\n * consumers a heads-up before the hard error; the cap is a fixed\n * constant in (not overridable). A `{ maxGroups }` override\n * can be added later without a break if a real consumer asks.\n */\nexport const GROUPBY_WARN_CARDINALITY = 10_000\nexport const GROUPBY_MAX_CARDINALITY = 100_000\n\n/**\n * One-shot warning dedup per-field-set — reactive dashboards\n * re-executing the same grouped query should produce the warning\n * once, not once per re-fire. Keyed on the sorted JSON of grouping\n * field names so `.groupBy('a', 'b')` and `.groupBy('b', 'a')`\n * share the same dedup slot (their result tuples are isomorphic).\n */\nconst warnedCardinalityFields = new Set<string>()\nfunction warnCardinalityApproaching(\n fields: readonly string[],\n observed: number,\n): void {\n const key = JSON.stringify([...fields].sort())\n if (warnedCardinalityFields.has(key)) return\n warnedCardinalityFields.add(key)\n const label = `[${fields.join(', ')}]`\n console.warn(\n `[noy-db] .groupBy(${label}) produced ${observed} distinct groups, ` +\n `${Math.round((observed / GROUPBY_MAX_CARDINALITY) * 100)}% of the ` +\n `${GROUPBY_MAX_CARDINALITY}-group ceiling. Narrow the query with ` +\n `.where() before grouping, or switch to a lower-cardinality field.`,\n )\n}\n\n/**\n * Test-only: clear the per-field cardinality warning dedup between\n * tests. Production code never calls this — matching the\n * `resetJoinWarnings` pattern in `join.ts`.\n */\nexport function resetGroupByWarnings(): void {\n warnedCardinalityFields.clear()\n}\n\n/**\n * Result row shape for a grouped aggregation. Each row carries the\n * group key value under the grouping field name plus every reducer\n * output from the spec.\n *\n * types the group key as `unknown` at the result shape — the\n * runtime read via `readPath` can return any value, and narrowing\n * to a specific type would require the caller to assert at the\n * call site. `dictKey` narrowing layers on top of this by\n * adding an overload that constrains `F` when the grouping field\n * is a `dictKey`.\n */\nexport type GroupedRow<F extends string, R> = { [K in F]: unknown } & R\n\n/**\n * Multi-key variant — result-row shape for variadic\n * `.groupBy(...fields)`. Every grouped field name appears on the row\n * (typed as `unknown` for the same reason as `GroupedRow`), plus the\n * reducer outputs from the spec.\n */\nexport type GroupedRowN<F extends readonly string[], R> =\n { [K in F[number]]: unknown } & R\n\n/**\n * Shared base class for the chainable grouped-query wrappers. Holds\n * the constructor + protected fields that both single-key\n * `GroupedQuery<T, F>` and variadic `GroupedQueryN<T, F>` need; each\n * subclass only overrides `aggregate()` with its own result-row\n * generic.\n *\n * Not exported — implementation detail. Adding `.having()` /\n * `.live()` / `.orderByGroup()` etc. in the future lands here once\n * and both subclasses pick it up automatically.\n *\n * @internal\n */\nabstract class GroupedQueryBase {\n /**\n * Field set this grouped query buckets on. Stored in declaration\n * order — the same order is preserved on every result row by\n * `groupAndReduce`. For the single-field constructor, this is\n * `[field]`.\n */\n protected readonly fields: readonly string[]\n\n constructor(\n protected readonly executeRecords: () => readonly unknown[],\n fieldOrFields: string | readonly string[],\n protected readonly upstreams: readonly AggregationUpstream[],\n /**\n * Optional dict label resolver attached by the query builder when\n * the grouping field is a dictKey. Variadic groupings always pass\n * `undefined` — `<field>Label` projection has no meaningful shape\n * for composite keys.\n */\n protected readonly dictLabelResolver?: (\n key: string,\n locale: string,\n fallback?: string | readonly string[],\n ) => Promise<string | undefined>,\n /**\n * Money field descriptors for the backing collection — used to\n * rewrite `sum`/`min`/`max` over money fields into exact BigInt\n * reducers when `.aggregate(spec)` is terminated.\n */\n protected readonly moneyFields?: Record<string, MoneyDescriptor>,\n ) {\n this.fields =\n typeof fieldOrFields === 'string' ? [fieldOrFields] : [...fieldOrFields]\n }\n\n /** Apply money-aware reducer rewriting when money fields are declared. */\n protected wrapSpec<Spec extends AggregateSpec>(spec: Spec): Spec {\n return this.moneyFields ? (wrapMoneyReducers(spec, this.moneyFields) as Spec) : spec\n }\n}\n\n/**\n * Chainable wrapper returned by `Query.groupBy(field)`. Terminates\n * with `.aggregate(spec)` which returns a `GroupedAggregation`.\n *\n * Kept minimal — the only operation on a grouped query is\n * aggregation. Ordering, limiting, and further filtering belong on\n * the underlying `Query` before `.groupBy()` is called; applying\n * them post-group would be a different operation (`having` /\n * `groupOrderBy`), out of scope for.\n */\nexport class GroupedQuery<T, F extends string> extends GroupedQueryBase {\n /**\n * Build a grouped aggregation. Returns a `GroupedAggregation`\n * with `.run()`, `.runAsync()`, and `.live()` terminals — same shape\n * as the non-grouped `.aggregate()` wrapper, just with an array\n * result (one row per bucket) instead of a single reduced object.\n */\n aggregate<Spec extends AggregateSpec>(\n spec: Spec,\n ): GroupedAggregation<GroupedRow<F, AggregateResult<Spec>>> {\n // T is phantom on the wrapper so consumers can still see the\n // source row type on hover. Reference it to keep lint quiet.\n void undefined as T | undefined\n return new GroupedAggregation<GroupedRow<F, AggregateResult<Spec>>>(\n this.executeRecords,\n this.fields,\n this.wrapSpec(spec),\n this.upstreams,\n this.dictLabelResolver,\n )\n }\n}\n\n/**\n * Variadic-keyed sibling of `GroupedQuery<T, F>`. Constructed by the\n * multi-arg `Query.groupBy(...fields)` overload. The runtime shape is\n * identical — only the type-level result-row narrowing differs.\n */\nexport class GroupedQueryN<T, F extends readonly string[]> extends GroupedQueryBase {\n aggregate<Spec extends AggregateSpec>(\n spec: Spec,\n ): GroupedAggregation<GroupedRowN<F, AggregateResult<Spec>>> {\n void undefined as T | undefined\n return new GroupedAggregation<GroupedRowN<F, AggregateResult<Spec>>>(\n this.executeRecords,\n this.fields,\n this.wrapSpec(spec),\n this.upstreams,\n this.dictLabelResolver,\n )\n }\n}\n\n/**\n * Execute the group-and-reduce pipeline. Pure function over a\n * record array and a spec — shared by `GroupedAggregation.run()`\n * and the live-mode refresh path. Exported for tests and for any\n * future `scan().groupBy().aggregate()` reuse.\n *\n * Enforces the cardinality cap incrementally during the partition\n * loop, so a runaway grouping throws at the moment the 100_001st\n * bucket would be created — the consumer doesn't have to wait for\n * the full partition to materialize before the error fires.\n */\nexport function groupAndReduce<R>(\n records: readonly unknown[],\n fieldOrFields: string | readonly string[],\n spec: AggregateSpec,\n moneyFields?: Record<string, MoneyDescriptor>,\n): R[] {\n const fields: readonly string[] =\n typeof fieldOrFields === 'string' ? [fieldOrFields] : fieldOrFields\n if (fields.length === 0) {\n throw new Error('.groupBy() requires at least one field')\n }\n\n // Money-aware aggregation: when the caller declares money descriptors\n // for output/intermediate fields, rewrite any `sum`/`min`/`max` over\n // them into exact BigInt reducers before bucketing. Omitted → spec\n // passes through unchanged (backward compatible). The chainable\n // `GroupedQuery` path already wraps upstream via `wrapSpec`; this\n // covers direct `groupAndReduce` callers (UNION-form MVs) that have\n // no Query wrapper to do it.\n if (moneyFields) {\n spec = wrapMoneyReducers(spec, moneyFields)\n }\n\n // Bucket value is { keyValues, records } so the output row can stamp\n // every grouped field in DECLARATION ORDER. Map preserves insertion\n // order natively (ES2015), so first-seen keys determine ordering.\n interface Bucket {\n keyValues: Record<string, unknown>\n records: unknown[]\n }\n const buckets = new Map<string, Bucket>()\n // Field-label string for error messages — matches the variadic\n // surface (`[a, b]` for multi-key, `\"k\"` for single-key back-compat).\n const fieldLabel = fields.length === 1 ? fields[0]! : `[${fields.join(', ')}]`\n\n for (const record of records) {\n // Read each field's value into a row object, then canonicalise.\n const keyValues: Record<string, unknown> = {}\n for (const f of fields) {\n keyValues[f] = readPath(record, f)\n }\n const dedupKey = canonicalGroupKey(fields, keyValues)\n let bucket = buckets.get(dedupKey)\n if (bucket === undefined) {\n if (buckets.size >= GROUPBY_MAX_CARDINALITY) {\n throw new GroupCardinalityError(\n fieldLabel,\n buckets.size + 1,\n GROUPBY_MAX_CARDINALITY,\n )\n }\n bucket = { keyValues, records: [] }\n buckets.set(dedupKey, bucket)\n }\n bucket.records.push(record)\n }\n\n if (buckets.size >= GROUPBY_WARN_CARDINALITY) {\n warnCardinalityApproaching(fields, buckets.size)\n }\n\n // Reduce each bucket through the spec. Same init/step/finalize\n // pipeline as `reduceRecords` in aggregate.ts, but one state per\n // bucket. Inlining the loop here keeps the per-bucket path tight\n // — calling `reduceRecords` per bucket would recompute\n // `Object.keys(spec)` once per bucket unnecessarily.\n const reducerKeys = Object.keys(spec)\n const out: R[] = []\n for (const bucket of buckets.values()) {\n const state: Record<string, unknown> = {}\n for (const rk of reducerKeys) {\n state[rk] = spec[rk]!.init()\n }\n for (const record of bucket.records) {\n for (const rk of reducerKeys) {\n state[rk] = spec[rk]!.step(state[rk], record)\n }\n }\n // Stamp grouped fields FIRST, in declaration order — this is\n // tested via `Object.keys(row).slice(0, fields.length)`.\n const row: Record<string, unknown> = {}\n for (const f of fields) {\n row[f] = bucket.keyValues[f]\n }\n for (const rk of reducerKeys) {\n row[rk] = spec[rk]!.finalize(state[rk])\n }\n out.push(row as unknown as R)\n }\n return out\n}\n\n/**\n * Grouped aggregation wrapper — the `.groupBy(field).aggregate(spec)`\n * terminal. Shape mirrors `Aggregation<R>` from aggregate.ts: two\n * terminals (`.run()` and `.live()`), spec bound at construction\n * time, upstreams collected for live mode.\n *\n * The generic `R` is the per-row result shape (i.e. a single\n * grouped row), and the terminals return `R[]` — one row per\n * bucket.\n */\nexport class GroupedAggregation<R> {\n private readonly fields: readonly string[]\n\n constructor(\n private readonly executeRecords: () => readonly unknown[],\n fields: string | readonly string[],\n private readonly spec: AggregateSpec,\n private readonly upstreams: readonly AggregationUpstream[],\n /**\n * Optional dict label resolver for `<field>Label` projection\n *. Present when the grouping field is a dictKey.\n */\n private readonly dictLabelResolver?: (\n key: string,\n locale: string,\n fallback?: string | readonly string[],\n ) => Promise<string | undefined>,\n ) {\n this.fields = typeof fields === 'string' ? [fields] : [...fields]\n }\n\n /** Execute the query, group, reduce, and return an array of rows. */\n run(): R[] {\n return groupAndReduce<R>(this.executeRecords(), this.fields, this.spec)\n }\n\n /**\n * Execute the query, group, reduce, and resolve `<field>Label` for\n * each result row when the grouping field is a `dictKey` and a\n * `locale` is provided. Returns `R[]` synchronously when\n * no locale is specified (identical to `.run()`).\n *\n * The `<field>Label` field is appended to each row. Rows whose group\n * key has no dictionary entry get `<field>Label: undefined`.\n *\n * Dict-label resolution is single-field only — multi-key groupings\n * do not produce a `<field>Label`. The resolver is only attached\n * by the builder when `fields.length === 1`.\n */\n async runAsync(opts?: {\n locale?: string\n fallback?: string | readonly string[]\n }): Promise<R[]> {\n const rows = groupAndReduce<R>(this.executeRecords(), this.fields, this.spec)\n if (!opts?.locale || !this.dictLabelResolver || this.fields.length !== 1) return rows\n\n const resolve = this.dictLabelResolver\n const locale = opts.locale\n const fallback = opts.fallback\n const field = this.fields[0]!\n const labelKey = `${field}Label`\n\n return Promise.all(\n rows.map(async (row) => {\n const key = (row as Record<string, unknown>)[field]\n if (typeof key !== 'string') return row\n const label = await resolve(key, locale, fallback)\n return { ...(row as Record<string, unknown>), [labelKey]: label } as unknown as R\n }),\n )\n }\n\n /**\n * Build a reactive `LiveAggregation<R[]>` that re-runs the full\n * group-and-reduce pipeline whenever any upstream source notifies\n * of a change. Same error-isolation and idempotent-stop contract\n * as `Aggregation.live()` — the implementation delegates to the\n * same `LiveAggregationImpl` class by threading a fresh\n * recompute closure through the existing constructor.\n *\n * uses naive full re-run on every change. Incremental\n * per-bucket maintenance (apply `step` on inserted records,\n * `remove` on deleted records, route by bucket key) is a future\n * optimization — the reducer protocol admits it, but wiring\n * delta-aware source subscriptions is a separate PR.\n *\n * Always call `live.stop()` when finished.\n */\n live(): LiveAggregation<R[]> {\n const recompute = (): R[] =>\n groupAndReduce<R>(this.executeRecords(), this.fields, this.spec)\n return buildLiveAggregation<R[]>(recompute, this.upstreams)\n }\n}\n"],"mappings":"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","names":["value"]}
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  NOYDB_FORMAT_VERSION
3
- } from "./chunk-GC4V7RU7.js";
3
+ } from "./chunk-SISBMAPO.js";
4
4
  import {
5
5
  decrypt,
6
6
  encrypt
7
- } from "./chunk-YULZKK4F.js";
7
+ } from "./chunk-UNTGHX5A.js";
8
8
 
9
9
  // src/persisted-schemas/storage.ts
10
10
  var SCHEMAS_COLLECTION = "_schemas";
@@ -84,6 +84,49 @@ var MemorySealingKeyProvider = class {
84
84
  return out;
85
85
  }
86
86
  };
87
+ async function sealRsaOaepTlv(plaintext, publicKeyPem) {
88
+ const b64 = publicKeyPem.replace(/-----BEGIN PUBLIC KEY-----/, "").replace(/-----END PUBLIC KEY-----/, "").replace(/\s+/g, "");
89
+ const spki = base64ToBytes(b64);
90
+ const recipientPub = await crypto.subtle.importKey(
91
+ "spki",
92
+ spki,
93
+ { name: "RSA-OAEP", hash: "SHA-256" },
94
+ false,
95
+ ["encrypt"]
96
+ );
97
+ const cekBytes = crypto.getRandomValues(new Uint8Array(32));
98
+ const cek = await crypto.subtle.importKey("raw", cekBytes, "AES-GCM", false, ["encrypt"]);
99
+ const iv = crypto.getRandomValues(new Uint8Array(12));
100
+ const ct = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv }, cek, plaintext));
101
+ const wrapped = new Uint8Array(await crypto.subtle.encrypt({ name: "RSA-OAEP" }, recipientPub, cekBytes));
102
+ cekBytes.fill(0);
103
+ if (wrapped.length !== 256) {
104
+ throw new Error(`sealRsaOaepTlv: expected 256-byte RSA-OAEP wrap, got ${wrapped.length}`);
105
+ }
106
+ const out = new Uint8Array(1 + 256 + 12 + ct.length);
107
+ out[0] = 1;
108
+ out.set(wrapped, 1);
109
+ out.set(iv, 1 + 256);
110
+ out.set(ct, 1 + 256 + 12);
111
+ return out;
112
+ }
113
+ function parseRsaOaepTlv(bytes) {
114
+ if (bytes.length < 1 + 256 + 12 + 16) {
115
+ throw new Error("parseRsaOaepTlv: sealed input too short");
116
+ }
117
+ if (bytes[0] !== 1) {
118
+ throw new Error(`parseRsaOaepTlv: unknown TLV version ${bytes[0]}`);
119
+ }
120
+ return {
121
+ wrapped: bytes.subarray(1, 1 + 256),
122
+ iv: bytes.subarray(1 + 256, 1 + 256 + 12),
123
+ ct: bytes.subarray(1 + 256 + 12)
124
+ };
125
+ }
126
+ async function aesGcmOpen(cekBytes, iv, ct) {
127
+ const cek = await crypto.subtle.importKey("raw", cekBytes, "AES-GCM", false, ["decrypt"]);
128
+ return new Uint8Array(await crypto.subtle.decrypt({ name: "AES-GCM", iv }, cek, ct));
129
+ }
87
130
  var MemoryRecipientSealer = class {
88
131
  id;
89
132
  keypair;
@@ -112,49 +155,17 @@ var MemoryRecipientSealer = class {
112
155
  if (typeof pem !== "string") {
113
156
  throw new Error("MemoryRecipientSealer.sealForRecipient: hint.material.publicKeyPem missing or not a string");
114
157
  }
115
- const b64 = pem.replace(/-----BEGIN PUBLIC KEY-----/, "").replace(/-----END PUBLIC KEY-----/, "").replace(/\s+/g, "");
116
- const spki = base64ToBytes(b64);
117
- const recipientPub = await crypto.subtle.importKey(
118
- "spki",
119
- spki,
120
- { name: "RSA-OAEP", hash: "SHA-256" },
121
- false,
122
- ["encrypt"]
123
- );
124
- const cekBytes = crypto.getRandomValues(new Uint8Array(32));
125
- const cek = await crypto.subtle.importKey("raw", cekBytes, "AES-GCM", false, ["encrypt"]);
126
- const iv = crypto.getRandomValues(new Uint8Array(12));
127
- const ct = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv }, cek, plaintext));
128
- const wrapped = new Uint8Array(await crypto.subtle.encrypt({ name: "RSA-OAEP" }, recipientPub, cekBytes));
129
- cekBytes.fill(0);
130
- if (wrapped.length !== 256) {
131
- throw new Error(`MemoryRecipientSealer.sealForRecipient: expected 256-byte RSA-OAEP wrap, got ${wrapped.length}`);
132
- }
133
- const out = new Uint8Array(1 + 256 + 12 + ct.length);
134
- out[0] = 1;
135
- out.set(wrapped, 1);
136
- out.set(iv, 1 + 256);
137
- out.set(ct, 1 + 256 + 12);
138
- return out;
158
+ return sealRsaOaepTlv(plaintext, pem);
139
159
  }
140
160
  async seal(plaintext) {
141
161
  const hint = await this.publishRecipientHint();
142
162
  return this.sealForRecipient(plaintext, hint);
143
163
  }
144
164
  async unseal(bytes) {
145
- if (bytes.length < 1 + 256 + 12 + 16) {
146
- throw new Error("MemoryRecipientSealer.unseal: sealed input too short");
147
- }
148
- if (bytes[0] !== 1) {
149
- throw new Error(`MemoryRecipientSealer.unseal: unknown TLV version ${bytes[0]}`);
150
- }
151
- const wrapped = bytes.subarray(1, 1 + 256);
152
- const iv = bytes.subarray(1 + 256, 1 + 256 + 12);
153
- const ct = bytes.subarray(1 + 256 + 12);
165
+ const { wrapped, iv, ct } = parseRsaOaepTlv(bytes);
154
166
  const { privateKey } = await this.keypair;
155
167
  const cekBytes = new Uint8Array(await crypto.subtle.decrypt({ name: "RSA-OAEP" }, privateKey, wrapped));
156
- const cek = await crypto.subtle.importKey("raw", cekBytes, "AES-GCM", false, ["decrypt"]);
157
- const pt = new Uint8Array(await crypto.subtle.decrypt({ name: "AES-GCM", iv }, cek, ct));
168
+ const pt = await aesGcmOpen(cekBytes, iv, ct);
158
169
  cekBytes.fill(0);
159
170
  return pt;
160
171
  }
@@ -241,6 +252,9 @@ export {
241
252
  loadPersistedSchema,
242
253
  savePersistedSchema,
243
254
  MemorySealingKeyProvider,
255
+ sealRsaOaepTlv,
256
+ parseRsaOaepTlv,
257
+ aesGcmOpen,
244
258
  MemoryRecipientSealer,
245
259
  SEALED_PASSPHRASE_RECORD_ID,
246
260
  parseSealedEnvelope,
@@ -248,4 +262,4 @@ export {
248
262
  loadSealedPassphrase,
249
263
  resolveManagedSecret
250
264
  };
251
- //# sourceMappingURL=chunk-WGHU7BLI.js.map
265
+ //# sourceMappingURL=chunk-AEIKD3PP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/persisted-schemas/storage.ts","../src/team/managed-passphrase.ts"],"sourcesContent":["/**\n * Read / write the per-collection persisted-schema envelope. Mirrors the\n * standard noy-db record envelope shape and is **AES-GCM encrypted with\n * the collection's DEK** — the schema body (field names, enum values,\n * constraints) is sensitive metadata, so it gets the same encryption\n * envelope as the records it describes.\n *\n * Storage layout:\n *\n * <vault>/_schemas/<collection> → EncryptedEnvelope\n *\n * The DEK passed to {@link savePersistedSchema} / {@link loadPersistedSchema}\n * is the same key the collection uses for its records.\n *\n * @module\n */\n\nimport { encrypt, decrypt } from '../crypto.js'\nimport { NOYDB_FORMAT_VERSION } from '../types.js'\nimport type { NoydbStore, EncryptedEnvelope } from '../types.js'\nimport type { PersistedSchemaEnvelope } from './types.js'\n\n/** Reserved collection name where persisted schemas live. */\nexport const SCHEMAS_COLLECTION = '_schemas' as const\n\n/**\n * Read and decrypt the persisted-schema envelope for one collection.\n * Returns `undefined` when no envelope has been written or when decryption\n * fails (e.g. wrong DEK passed). Tolerates corrupted records — JSON parse\n * failures surface as `undefined`, mirroring `_meta/handle`'s contract.\n */\nexport async function loadPersistedSchema(\n store: NoydbStore,\n vault: string,\n collection: string,\n dek: CryptoKey,\n): Promise<PersistedSchemaEnvelope | undefined> {\n const envelope = await store.get(vault, SCHEMAS_COLLECTION, collection)\n if (!envelope) return undefined\n try {\n const plaintext = await decrypt(envelope._iv, envelope._data, dek)\n const parsed = JSON.parse(plaintext) as PersistedSchemaEnvelope\n if (parsed._noydb_schema !== 1) return undefined\n return parsed\n } catch {\n return undefined\n }\n}\n\n/**\n * Encrypt and persist a schema envelope for one collection. Always\n * overwrites any prior write (callers gate on hash equality before calling\n * to avoid no-op writes).\n */\nexport async function savePersistedSchema(\n store: NoydbStore,\n vault: string,\n collection: string,\n dek: CryptoKey,\n payload: PersistedSchemaEnvelope,\n): Promise<void> {\n const json = JSON.stringify(payload)\n const { iv, data } = await encrypt(json, dek)\n const prior = await store.get(vault, SCHEMAS_COLLECTION, collection)\n const env: EncryptedEnvelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: (prior?._v ?? 0) + 1,\n _ts: new Date().toISOString(),\n _iv: iv,\n _data: data,\n }\n await store.put(vault, SCHEMAS_COLLECTION, collection, env)\n}\n","/**\n * Managed-passphrase mode — rubber-hose-resistant vaults.\n *\n * A vault mode where the passphrase is machine-generated and never\n * exposed to the user, sealed under a developer-provided\n * {@link SealingKeyProvider} (macOS Keychain, Windows Credential\n * Manager, libsecret, AWS KMS, …). The user has no secret to give\n * up to coercion — they can't reveal what they don't know.\n *\n * ## Components in this file\n *\n * - {@link SealingKeyProvider} — the interface concrete providers\n * implement. Provider implementations live OUTSIDE hub (per-\n * platform packages).\n * - {@link MemorySealingKeyProvider} — in-memory test provider; uses\n * a deterministic per-instance \"key\" so two providers with\n * different ids cannot unseal each other's outputs.\n * - {@link RecipientHint} — public material a sender uses to seal\n * plaintext for a specific recipient; published by\n * {@link RecipientSealer.publishRecipientHint} and transported\n * out-of-band to the sender before bundle writes.\n * - {@link RecipientSealer} — interface for asymmetric/granted\n * providers that support recipient-target sealing (RSA-OAEP,\n * cloud-KMS asymmetric, etc.); distinct from self-only\n * {@link SealingKeyProvider} (macOS Keychain, WebAuthn-PRF).\n * - {@link MemoryRecipientSealer} — in-process reference\n * implementation of both `RecipientSealer` and\n * `SealingKeyProvider` using real WebCrypto RSA-OAEP + AES-GCM;\n * safe for tests and same-process sender/recipient scenarios.\n * - {@link loadSealedPassphrase} / {@link saveSealedPassphrase} —\n * plaintext envelope storage at `_meta/sealed-passphrase`.\n * Mirrors the `_meta/handle` and `_meta/public-envelope` AES-\n * GCM-bypassed patterns. The sealing layer (provider's job)\n * is the security boundary; hub doesn't have a key to encrypt\n * with at this layer — that's the whole point of the design.\n * - {@link resolveManagedSecret} — orchestrates the \"generate +\n * seal + persist on first open; unseal on reopen\" flow.\n * Returns the plaintext passphrase string that the rest of the\n * `createNoydb` keyring path consumes.\n *\n * Deferred to follow-ups:\n * - Block `rotate-passphrase` policy gate under managed mode.\n * - Mandatory strong-recovery enforcement.\n * - Recovery flow under managed mode (generates fresh sealed phrase).\n *\n * @see docs/subsystems/session-tiers.md → Managed-passphrase mode\n *\n * @module\n */\n\nimport type { NoydbStore, EncryptedEnvelope } from '../types.js'\nimport { NOYDB_FORMAT_VERSION } from '../types.js'\n\n/**\n * The contract concrete providers (per-platform key stores) implement\n * to seal and unseal a hub-generated random passphrase. The plaintext\n * passphrase NEVER leaves hub-controlled memory in unsealed form —\n * the provider receives the bytes, returns opaque sealed bytes, and\n * later reverses the operation. Hub treats the sealed bytes as\n * fully opaque.\n *\n * Implementations live OUTSIDE `@noy-db/hub` (separate packages\n * per the issue's \"Concrete providers (live outside hub)\" note):\n *\n * | Platform | Package (TBD) | Backing |\n * |---|---|---|\n * | macOS | `@noy-db/seal-macos-keychain` | Security.framework |\n * | Windows | `@noy-db/seal-wincred` | Credential Manager |\n * | Linux | `@noy-db/seal-libsecret` | libsecret / secret-service |\n * | Cloud / server | `@noy-db/seal-aws-kms` | AWS KMS Decrypt |\n */\nexport interface SealingKeyProvider {\n /**\n * Non-sensitive identifier disclosed in the persisted envelope.\n * Surfaced to consumers via `loadSealedPassphrase().providerId` so\n * a vault opened with the wrong provider class can detect the\n * mismatch and surface a clear error. NOT secret — fine to log.\n *\n * Suggested format: `<family>:<scope>` — e.g. `macos-keychain:com.acme.app`,\n * `aws-kms:arn:aws:kms:us-east-1:123:key/abc`. The hub never\n * parses this; it's purely audit metadata.\n */\n readonly id: string\n\n /** Seal raw passphrase bytes. Output bytes are opaque to hub. */\n seal(passphrase: Uint8Array): Promise<Uint8Array>\n\n /**\n * Reverse {@link seal}. MUST throw on tamper, wrong-provider, or\n * any other failure — hub treats a thrown error as \"this provider\n * cannot unlock this vault\" and surfaces it to the caller.\n */\n unseal(sealed: Uint8Array): Promise<Uint8Array>\n}\n\n/**\n * In-memory test provider. NOT secure — uses a deterministic\n * per-instance \"key\" (16-byte SHA-256 of `id`) XOR'd over the\n * passphrase plus a 4-byte provider-id fingerprint prefix. The XOR is\n * sufficient to make different `id` values produce mutually-unsealable\n * outputs (the contract tests for that), but offers ZERO real\n * confidentiality — never use outside tests.\n *\n * Replace with a real platform provider in production.\n */\nexport class MemorySealingKeyProvider implements SealingKeyProvider {\n readonly id: string\n private readonly fingerprint: Uint8Array\n private readonly keyBytes: Uint8Array\n\n constructor(opts: { id: string }) {\n this.id = opts.id\n // Deterministic 4-byte fingerprint of the provider id, prepended\n // to every sealed output so we can detect \"wrong provider\" at\n // unseal time without leaking anything sensitive about either\n // provider's actual key material.\n const encoded = new TextEncoder().encode(opts.id)\n let h = 0\n for (let i = 0; i < encoded.length; i++) {\n h = (h * 31 + encoded[i]!) >>> 0\n }\n this.fingerprint = new Uint8Array([\n (h >>> 24) & 0xff, (h >>> 16) & 0xff, (h >>> 8) & 0xff, h & 0xff,\n ])\n // Deterministic 16-byte \"key\" derived from the id by repeating\n // the fingerprint with offsets. Good enough for the XOR-stream\n // test cipher; never confuse this with real key derivation.\n this.keyBytes = new Uint8Array(16)\n for (let i = 0; i < 16; i++) {\n this.keyBytes[i] = this.fingerprint[i % 4]! ^ (i * 17)\n }\n }\n\n async seal(passphrase: Uint8Array): Promise<Uint8Array> {\n const out = new Uint8Array(4 + passphrase.length)\n out.set(this.fingerprint, 0)\n for (let i = 0; i < passphrase.length; i++) {\n out[4 + i] = passphrase[i]! ^ this.keyBytes[i % 16]!\n }\n return out\n }\n\n async unseal(sealed: Uint8Array): Promise<Uint8Array> {\n if (sealed.length < 4) {\n throw new Error('MemorySealingKeyProvider: sealed input too short')\n }\n for (let i = 0; i < 4; i++) {\n if (sealed[i] !== this.fingerprint[i]) {\n throw new Error(\n `MemorySealingKeyProvider(\"${this.id}\"): provider-id mismatch on unseal `\n + '(sealed bytes were produced by a different provider)',\n )\n }\n }\n const body = sealed.subarray(4)\n const out = new Uint8Array(body.length)\n for (let i = 0; i < body.length; i++) {\n out[i] = body[i]! ^ this.keyBytes[i % 16]!\n }\n return out\n }\n}\n\n/**\n * Public material a sender uses to seal-for-this-recipient. Published by\n * a recipient's RecipientSealer; transported to the sender out-of-band\n * (email, S3, in-app message). The sender obtains the hint, supplies it\n * to writeNoydbBundle's sealedCredentials.perUser[userId].hint, and the\n * hub seals each user's credential against it. Per foundation §11.4.\n */\nexport type RecipientHint = {\n readonly v: 1\n /** Recipient's provider id; matches the SealedAutoUnlockEntry.pid they'll unseal under. */\n readonly pid: string\n /** Algorithm the sender uses to produce the seal. Slice 1 ships RSA-OAEP-SHA256 only. */\n readonly alg: 'rsa-oaep-sha256'\n /** Public material — alg-specific. For 'rsa-oaep-sha256': { publicKeyPem: string }. */\n readonly material: Readonly<Record<string, unknown>>\n}\n\n/**\n * Handover-capable provider. Implemented additionally by asymmetric/granted\n * providers (cloud-KMS asymmetric, Azure RSA Key Vault, AWS KMS with grant).\n * Self-only providers (macOS Keychain, env-var, WebAuthn-PRF) do NOT\n * implement this — the §11.2 capability matrix lives in the type system.\n *\n * Per foundation §11.4. A function that requires recipient-target sealing\n * takes `RecipientSealer`, not `SealingKeyProvider` — the compiler rejects\n * passing a self-only provider at the spec site.\n */\nexport interface RecipientSealer {\n readonly id: string\n /** Produce hint material a sender uses to seal-for-this-recipient. */\n publishRecipientHint(): Promise<RecipientHint>\n /**\n * Seal plaintext for the recipient described by `hint`. Returns opaque\n * bytes — same contract as `SealingKeyProvider.seal()`. The bundle\n * layer base64-encodes the bytes into `SealedAutoUnlockEntry.sealed`\n * without inspecting them.\n */\n sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array>\n}\n\n/**\n * Shared RSA-OAEP-SHA256 + AES-GCM seal in the canonical recipient-target\n * TLV wire format. Mints a fresh 32-byte CEK, AES-GCM-encrypts `plaintext`\n * under it, RSA-OAEP-SHA256-wraps the CEK to `publicKeyPem`, and packs:\n *\n * byte 0 : version (0x01)\n * bytes 1..256 : RSA-OAEP-wrapped CEK (fixed 256 bytes at RSA-2048)\n * bytes 257..268: AES-GCM IV (12 bytes)\n * bytes 269.. : AES-GCM ciphertext ‖ 16-byte tag\n *\n * This is the single source of truth for the wire format — both\n * {@link MemoryRecipientSealer} and external sealers (e.g. `@noy-db/at-aws-kms`'s\n * asymmetric-KMS recipient sealer) call it so a blob sealed by one unseals\n * by the other. WebCrypto RSA-OAEP/SHA-256 here is wire-compatible with\n * AWS KMS `RSAES_OAEP_SHA_256` (both RSAES-OAEP, SHA-256 hash, MGF1-SHA256,\n * empty label).\n *\n * @public — re-exported from the hub barrel for external sealer packages.\n */\nexport async function sealRsaOaepTlv(plaintext: Uint8Array, publicKeyPem: string): Promise<Uint8Array> {\n // Parse PEM → SPKI bytes.\n const b64 = publicKeyPem.replace(/-----BEGIN PUBLIC KEY-----/, '').replace(/-----END PUBLIC KEY-----/, '').replace(/\\s+/g, '')\n const spki = base64ToBytes(b64)\n const recipientPub = await crypto.subtle.importKey(\n 'spki', spki as BufferSource,\n { name: 'RSA-OAEP', hash: 'SHA-256' },\n false, ['encrypt'],\n )\n // Mint fresh CEK + IV, AES-GCM encrypt plaintext.\n const cekBytes = crypto.getRandomValues(new Uint8Array(32))\n const cek = await crypto.subtle.importKey('raw', cekBytes as BufferSource, 'AES-GCM', false, ['encrypt'])\n const iv = crypto.getRandomValues(new Uint8Array(12))\n const ct = new Uint8Array(await crypto.subtle.encrypt({ name: 'AES-GCM', iv: iv as BufferSource }, cek, plaintext as BufferSource))\n // RSA-OAEP-wrap the CEK bytes.\n const wrapped = new Uint8Array(await crypto.subtle.encrypt({ name: 'RSA-OAEP' }, recipientPub, cekBytes as BufferSource))\n cekBytes.fill(0)\n if (wrapped.length !== 256) {\n throw new Error(`sealRsaOaepTlv: expected 256-byte RSA-OAEP wrap, got ${wrapped.length}`)\n }\n // TLV layout.\n const out = new Uint8Array(1 + 256 + 12 + ct.length)\n out[0] = 0x01\n out.set(wrapped, 1)\n out.set(iv, 1 + 256)\n out.set(ct, 1 + 256 + 12)\n return out\n}\n\n/**\n * Parse a {@link sealRsaOaepTlv} blob into its three segments without\n * decrypting. The `wrapped` CEK is RSA-OAEP-SHA256 ciphertext over a\n * 32-byte CEK — the unwrap step is pluggable: {@link MemoryRecipientSealer}\n * decrypts it with a local RSA private key; `@noy-db/at-aws-kms` hands it to\n * KMS `Decrypt`. After unwrapping, pass the CEK + `iv` + `ct` to\n * {@link aesGcmOpen}.\n *\n * @public — re-exported from the hub barrel for external sealer packages.\n */\nexport function parseRsaOaepTlv(bytes: Uint8Array): { wrapped: Uint8Array; iv: Uint8Array; ct: Uint8Array } {\n if (bytes.length < 1 + 256 + 12 + 16) {\n throw new Error('parseRsaOaepTlv: sealed input too short')\n }\n if (bytes[0] !== 0x01) {\n throw new Error(`parseRsaOaepTlv: unknown TLV version ${bytes[0]}`)\n }\n return {\n wrapped: bytes.subarray(1, 1 + 256),\n iv: bytes.subarray(1 + 256, 1 + 256 + 12),\n ct: bytes.subarray(1 + 256 + 12),\n }\n}\n\n/**\n * AES-GCM-decrypt the `ct` segment of a {@link parseRsaOaepTlv} result under\n * the unwrapped 32-byte CEK and its `iv`. Throws on a bad tag (tamper) — the\n * same authenticated-decryption guarantee the TLV relies on.\n *\n * @public — re-exported from the hub barrel for external sealer packages.\n */\nexport async function aesGcmOpen(cekBytes: Uint8Array, iv: Uint8Array, ct: Uint8Array): Promise<Uint8Array> {\n const cek = await crypto.subtle.importKey('raw', cekBytes as BufferSource, 'AES-GCM', false, ['decrypt'])\n return new Uint8Array(await crypto.subtle.decrypt({ name: 'AES-GCM', iv: iv as BufferSource }, cek, ct as BufferSource))\n}\n\n/**\n * Reference implementation of `RecipientSealer` + `SealingKeyProvider`.\n * Uses WebCrypto RSA-OAEP-SHA256 (2048-bit) to wrap a fresh 32-byte\n * AES-GCM CEK, AES-GCM-encrypts plaintext under it, and packs the\n * result into a self-describing TLV:\n *\n * byte 0 : version (0x01)\n * bytes 1..256 : RSA-OAEP-wrapped CEK (fixed 256 bytes at RSA-2048)\n * bytes 257..268: AES-GCM IV (12 bytes)\n * bytes 269.. : AES-GCM ciphertext ‖ 16-byte tag\n *\n * Implements BOTH interfaces. `seal(plaintext)` (self-target) is just\n * `sealForRecipient(plaintext, this own hint)` — same TLV. Convenient\n * for tests where one provider plays both ends. Real cloud providers\n * (`at-aws-kms`, etc.) will pick their own internal layouts; the only\n * contract is round-trip identity.\n *\n * SAFE for production within its scope — the cryptography is real\n * (RSA-OAEP + AES-GCM via WebCrypto), but the keypair lives in-process\n * and is regenerated on every construction. Not suitable as a managed\n * keychain; use it for tests and for shipping bundles where the\n * recipient instance lives in the same process as the sender (rare).\n */\nexport class MemoryRecipientSealer implements SealingKeyProvider, RecipientSealer {\n readonly id: string\n private readonly keypair: Promise<CryptoKeyPair>\n\n constructor(opts: { id: string }) {\n this.id = opts.id\n this.keypair = crypto.subtle.generateKey(\n { name: 'RSA-OAEP', modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: 'SHA-256' },\n true,\n ['encrypt', 'decrypt'],\n )\n }\n\n async publishRecipientHint(): Promise<RecipientHint> {\n const { publicKey } = await this.keypair\n const spki = await crypto.subtle.exportKey('spki', publicKey)\n const pem = '-----BEGIN PUBLIC KEY-----\\n'\n + bytesToBase64(new Uint8Array(spki)).match(/.{1,64}/g)!.join('\\n')\n + '\\n-----END PUBLIC KEY-----\\n'\n return { v: 1, pid: this.id, alg: 'rsa-oaep-sha256', material: { publicKeyPem: pem } }\n }\n\n async sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array> {\n if (hint.v !== 1) {\n throw new Error(`MemoryRecipientSealer.sealForRecipient: unsupported hint.v ${String(hint.v)} (expected 1)`)\n }\n if (hint.alg !== 'rsa-oaep-sha256') {\n throw new Error(`MemoryRecipientSealer.sealForRecipient: unsupported hint.alg '${String(hint.alg)}' (expected 'rsa-oaep-sha256')`)\n }\n const pem = hint.material['publicKeyPem']\n if (typeof pem !== 'string') {\n throw new Error('MemoryRecipientSealer.sealForRecipient: hint.material.publicKeyPem missing or not a string')\n }\n return sealRsaOaepTlv(plaintext, pem)\n }\n\n async seal(plaintext: Uint8Array): Promise<Uint8Array> {\n const hint = await this.publishRecipientHint()\n return this.sealForRecipient(plaintext, hint)\n }\n\n async unseal(bytes: Uint8Array): Promise<Uint8Array> {\n const { wrapped, iv, ct } = parseRsaOaepTlv(bytes)\n const { privateKey } = await this.keypair\n // Local RSA-OAEP-SHA256 unwrap of the CEK — the pluggable step external\n // sealers replace with KMS Decrypt.\n const cekBytes = new Uint8Array(await crypto.subtle.decrypt({ name: 'RSA-OAEP' }, privateKey, wrapped as BufferSource))\n const pt = await aesGcmOpen(cekBytes, iv, ct)\n cekBytes.fill(0)\n return pt\n }\n}\n\n// ─── Persisted envelope ────────────────────────────────────────────────\n\n/** Reserved id for the managed-passphrase envelope under `_meta`. */\nexport const SEALED_PASSPHRASE_RECORD_ID = 'sealed-passphrase' as const\n\n/** Plaintext payload stored inside the `_meta/sealed-passphrase` envelope. */\nexport interface SealedPassphrase {\n readonly _noydb_sealed: 1\n readonly providerId: string\n /** Sealed bytes. Base64-encoded on the wire; decoded on load. */\n readonly sealed: Uint8Array\n}\n\n/**\n * Wire-format envelope persisted at `_meta/sealed-passphrase` for\n * managed-mode vaults. The provider produces raw sealed bytes via\n * {@link SealingKeyProvider.seal}; this wrapper carries the dispatch\n * metadata hub needs to pick the right provider on the unseal path.\n *\n * Stability boundary: once shipped, the wire format only grows by\n * adding optional fields. See the at-* sealing dimension foundation\n * doc, §11.9.1.\n *\n * v1 shape (this release): `{ v: 1, _noydb_sealed: 1, pid, payload }`.\n *\n * Legacy shape (earlier releases): `{ _noydb_sealed: 1, providerId, sealed }`\n * — accepted on read for backwards compatibility; never produced on\n * write going forward.\n */\nexport interface SealedEnvelope {\n /** Envelope schema version. v1 is the current shape. */\n readonly v: 1\n /** Magic marker for forensics + legacy-shape detection. */\n readonly _noydb_sealed: 1\n /** Matches the producing provider's `.id`. Dispatch key on unseal. */\n readonly pid: string\n /** Sealed bytes from the provider, base64-encoded on the wire. */\n readonly payload: string\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n let binary = ''\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]!)\n return btoa(binary)\n}\n\nfunction base64ToBytes(b64: string): Uint8Array {\n const binary = atob(b64)\n const out = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i)\n return out\n}\n\n/**\n * Parse a `_meta/sealed-passphrase` `_data` JSON string into the\n * in-memory {@link SealedPassphrase} representation. Accepts both:\n *\n * 1. v1 wire format `{ v: 1, _noydb_sealed: 1, pid, payload }` —\n * the current shape.\n * 2. Legacy wire format `{ _noydb_sealed: 1, providerId, sealed }` —\n * read-only; never written\n * going forward.\n *\n * Returns `undefined` for any input that doesn't match either shape,\n * so callers can fall back to \"no managed-mode envelope present.\"\n *\n * @internal — exported only for the migration safety-net test suite.\n */\nexport function parseSealedEnvelope(raw: unknown): SealedPassphrase | undefined {\n if (typeof raw !== 'object' || raw === null) return undefined\n const r = raw as Record<string, unknown>\n if (r._noydb_sealed !== 1) return undefined\n\n // v1 shape — preferred.\n if (\n r.v === 1\n && typeof r.pid === 'string'\n && typeof r.payload === 'string'\n ) {\n return {\n _noydb_sealed: 1,\n providerId: r.pid,\n sealed: base64ToBytes(r.payload),\n }\n }\n\n // Legacy shape — earlier releases. Accept on read for compat.\n if (\n typeof r.providerId === 'string'\n && typeof r.sealed === 'string'\n ) {\n return {\n _noydb_sealed: 1,\n providerId: r.providerId,\n sealed: base64ToBytes(r.sealed),\n }\n }\n\n return undefined\n}\n\nexport async function saveSealedPassphrase(\n store: NoydbStore,\n vault: string,\n payload: { readonly providerId: string; readonly sealed: Uint8Array },\n): Promise<void> {\n const persisted: SealedEnvelope = {\n v: 1,\n _noydb_sealed: 1,\n pid: payload.providerId,\n payload: bytesToBase64(payload.sealed),\n }\n const prior = await store.get(vault, '_meta', SEALED_PASSPHRASE_RECORD_ID)\n const env: EncryptedEnvelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: (prior?._v ?? 0) + 1,\n _ts: new Date().toISOString(),\n // AES-GCM bypassed — the sealing layer is the security boundary.\n _iv: '',\n _data: JSON.stringify(persisted),\n }\n await store.put(vault, '_meta', SEALED_PASSPHRASE_RECORD_ID, env)\n}\n\nexport async function loadSealedPassphrase(\n store: NoydbStore,\n vault: string,\n): Promise<SealedPassphrase | undefined> {\n const envelope = await store.get(vault, '_meta', SEALED_PASSPHRASE_RECORD_ID)\n if (!envelope) return undefined\n try {\n return parseSealedEnvelope(JSON.parse(envelope._data))\n } catch {\n return undefined\n }\n}\n\n// ─── createNoydb orchestration ─────────────────────────────────────────\n\n/**\n * Resolve the effective plaintext passphrase string for a managed-mode\n * vault. Two paths:\n *\n * 1. **First open (no envelope persisted):** generate a 256-bit random\n * via `crypto.getRandomValues`, base64-encode for use as a\n * passphrase string, seal the underlying bytes under the\n * provider, persist `_meta/sealed-passphrase`, return the\n * base64 string.\n *\n * 2. **Reopen (envelope exists):** read + unseal + decode → return.\n * A different provider whose `seal` output disagrees on the\n * stored bytes throws here, surfaced as a clear error.\n *\n * The returned string is the same shape that `secret:` would take in\n * standard mode — the rest of the keyring path consumes it\n * unchanged.\n *\n * @internal — called from `createNoydb` / `getKeyringInternal`.\n */\nexport async function resolveManagedSecret(\n store: NoydbStore,\n vault: string,\n provider: SealingKeyProvider,\n): Promise<string> {\n const existing = await loadSealedPassphrase(store, vault)\n if (existing) {\n if (existing.providerId !== provider.id) {\n throw new Error(\n `Managed-mode vault \"${vault}\" was sealed under provider id `\n + `\"${existing.providerId}\" but the current SealingKeyProvider is `\n + `\"${provider.id}\". Pass the same provider that originally enrolled `\n + 'the vault, or treat this as a fresh enrollment and clear '\n + '`_meta/sealed-passphrase` first.',\n )\n }\n const plaintext = await provider.unseal(existing.sealed)\n return bytesToBase64(plaintext)\n }\n\n // First open: mint a 256-bit random, seal, persist.\n const random = new Uint8Array(32)\n globalThis.crypto.getRandomValues(random)\n const sealed = await provider.seal(random)\n await saveSealedPassphrase(store, vault, { providerId: provider.id, sealed })\n return bytesToBase64(random)\n}\n"],"mappings":"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","names":[]}
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  canonicalJson,
3
3
  sha256Hex
4
- } from "./chunk-Z6FNBOTC.js";
4
+ } from "./chunk-PDVP3C2I.js";
5
5
  import {
6
6
  PeriodClosedError,
7
7
  ValidationError
8
- } from "./chunk-535SSHBS.js";
8
+ } from "./chunk-ZEGSDPB7.js";
9
9
 
10
10
  // src/periods/periods.ts
11
11
  var PERIODS_COLLECTION = "_periods";
@@ -56,7 +56,7 @@ function validatePeriodName(name, existing) {
56
56
  }
57
57
  async function appendPeriodLedgerEntry(ledger, actor, envelope, name) {
58
58
  if (!ledger) return;
59
- const { envelopePayloadHash } = await import("./ledger-CWSE3BLF.js");
59
+ const { envelopePayloadHash } = await import("./ledger-LFVLHE5H.js");
60
60
  await ledger.append({
61
61
  op: "put",
62
62
  collection: PERIODS_COLLECTION,
@@ -87,4 +87,4 @@ export {
87
87
  appendPeriodLedgerEntry,
88
88
  withPeriods
89
89
  };
90
- //# sourceMappingURL=chunk-KI6HAJWL.js.map
90
+ //# sourceMappingURL=chunk-BH3X5L6A.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ReadOnlyFrameError
3
- } from "./chunk-535SSHBS.js";
3
+ } from "./chunk-ZEGSDPB7.js";
4
4
 
5
5
  // src/shadow/vault-frame.ts
6
6
  var VaultFrame = class {
@@ -76,4 +76,4 @@ export {
76
76
  VaultFrame,
77
77
  CollectionFrame
78
78
  };
79
- //# sourceMappingURL=chunk-BQ65SS5A.js.map
79
+ //# sourceMappingURL=chunk-BJSLBUJ7.js.map
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  pickLocale
3
- } from "./chunk-DKO2QFSA.js";
3
+ } from "./chunk-YYVZYTWW.js";
4
4
  import {
5
5
  BundleIntegrityError,
6
6
  BundleSealMismatchError,
7
7
  ValidationError
8
- } from "./chunk-535SSHBS.js";
8
+ } from "./chunk-ZEGSDPB7.js";
9
9
 
10
10
  // src/bundle/format.ts
11
11
  var NOYDB_BUNDLE_MAGIC = new Uint8Array([78, 68, 66, 49]);
@@ -792,4 +792,4 @@ export {
792
792
  readNoydbBundlePublicEnvelope,
793
793
  readNoydbBundle
794
794
  };
795
- //# sourceMappingURL=chunk-L2FE64BU.js.map
795
+ //# sourceMappingURL=chunk-BL5GYANC.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  NOYDB_FORMAT_VERSION,
3
3
  NOYDB_KEYRING_VERSION
4
- } from "./chunk-GC4V7RU7.js";
4
+ } from "./chunk-SISBMAPO.js";
5
5
  import {
6
6
  base64ToBuffer,
7
7
  bufferToBase64,
@@ -12,7 +12,7 @@ import {
12
12
  generateSalt,
13
13
  unwrapKey,
14
14
  wrapKey
15
- } from "./chunk-YULZKK4F.js";
15
+ } from "./chunk-UNTGHX5A.js";
16
16
  import {
17
17
  ConflictError,
18
18
  DirectoryDisabledError,
@@ -24,7 +24,7 @@ import {
24
24
  PermissionDeniedError,
25
25
  PrivilegeEscalationError,
26
26
  ValidationError
27
- } from "./chunk-535SSHBS.js";
27
+ } from "./chunk-ZEGSDPB7.js";
28
28
 
29
29
  // src/directory/storage.ts
30
30
  var META_COLLECTION = "_meta";
@@ -894,4 +894,4 @@ export {
894
894
  hasImportCapability,
895
895
  evaluateImportCapability
896
896
  };
897
- //# sourceMappingURL=chunk-A5ZOOZFB.js.map
897
+ //# sourceMappingURL=chunk-BSZOCSDZ.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  FieldFrozenError,
3
3
  InvariantError
4
- } from "./chunk-535SSHBS.js";
4
+ } from "./chunk-ZEGSDPB7.js";
5
5
 
6
6
  // src/guards/executor.ts
7
7
  var GuardExecutor = {
@@ -77,4 +77,4 @@ function deepEqual(a, b) {
77
77
  export {
78
78
  GuardExecutor
79
79
  };
80
- //# sourceMappingURL=chunk-ZNQYHJXX.js.map
80
+ //# sourceMappingURL=chunk-C3HYQPV4.js.map
@@ -2,18 +2,18 @@ import {
2
2
  ATTESTATIONS_COLLECTION,
3
3
  REVOKED_RECORD_ID,
4
4
  loadOrCreateSigner
5
- } from "./chunk-7PS7EOCF.js";
5
+ } from "./chunk-TIDXB5DF.js";
6
6
  import {
7
7
  NOYDB_FORMAT_VERSION
8
- } from "./chunk-GC4V7RU7.js";
8
+ } from "./chunk-SISBMAPO.js";
9
9
  import {
10
10
  decrypt,
11
11
  encrypt
12
- } from "./chunk-YULZKK4F.js";
12
+ } from "./chunk-UNTGHX5A.js";
13
13
  import {
14
14
  AttestationError,
15
15
  ConflictError
16
- } from "./chunk-535SSHBS.js";
16
+ } from "./chunk-ZEGSDPB7.js";
17
17
 
18
18
  // src/attestation/revoke.ts
19
19
  import { signRevocationList } from "@noy-db/attestation";
@@ -80,4 +80,4 @@ export {
80
80
  getRevokedDocIdsCore,
81
81
  publishRevocationListCore
82
82
  };
83
- //# sourceMappingURL=chunk-PE4AQGFH.js.map
83
+ //# sourceMappingURL=chunk-CD2AVTEM.js.map