@noy-db/hub 0.2.0-pre.23 → 0.2.0-pre.25

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 (285) hide show
  1. package/dist/aggregate/index.cjs.map +1 -1
  2. package/dist/aggregate/index.d.cts +3 -3
  3. package/dist/aggregate/index.d.ts +3 -3
  4. package/dist/aggregate/index.js +5 -5
  5. package/dist/attestation/index.cjs.map +1 -1
  6. package/dist/attestation/index.d.cts +4 -4
  7. package/dist/attestation/index.d.ts +4 -4
  8. package/dist/attestation/index.js +6 -6
  9. package/dist/blobs/index.cjs.map +1 -1
  10. package/dist/blobs/index.d.cts +6 -6
  11. package/dist/blobs/index.d.ts +6 -6
  12. package/dist/blobs/index.js +6 -6
  13. package/dist/bundle/index.cjs +421 -1209
  14. package/dist/bundle/index.cjs.map +1 -1
  15. package/dist/bundle/index.d.cts +15 -6
  16. package/dist/bundle/index.d.ts +15 -6
  17. package/dist/bundle/index.js +42 -193
  18. package/dist/bundle/index.js.map +1 -1
  19. package/dist/{chunk-SQOK5UM6.js → chunk-2KA3PDUR.js} +2 -2
  20. package/dist/{chunk-HYJMAV53.js → chunk-2RHBFCWQ.js} +93 -93
  21. package/dist/chunk-2RHBFCWQ.js.map +1 -0
  22. package/dist/{chunk-U2XSUCDF.js → chunk-3BANVNDH.js} +2 -2
  23. package/dist/{chunk-P65YMN5V.js → chunk-56ENKU46.js} +397 -165
  24. package/dist/chunk-56ENKU46.js.map +1 -0
  25. package/dist/{chunk-37VGJM3T.js → chunk-7JSP3E67.js} +2 -2
  26. package/dist/{chunk-F5ILTHMU.js → chunk-ANLOD6IS.js} +5 -5
  27. package/dist/{chunk-JYNH4FIM.js → chunk-C7UIT5XY.js} +4 -4
  28. package/dist/{chunk-OTWT6BAJ.js → chunk-DDOYOMAD.js} +2 -2
  29. package/dist/chunk-DDOYOMAD.js.map +1 -0
  30. package/dist/{chunk-TGIJTNM3.js → chunk-E5TJAQS7.js} +2 -2
  31. package/dist/{chunk-IY24WS2P.js → chunk-EJJTUDNI.js} +4 -4
  32. package/dist/{chunk-IY24WS2P.js.map → chunk-EJJTUDNI.js.map} +1 -1
  33. package/dist/{chunk-GJTKMME7.js → chunk-EW3H5Y7N.js} +2 -2
  34. package/dist/{chunk-JDCPRJVS.js → chunk-EYZJULEN.js} +4 -4
  35. package/dist/{chunk-I3IYTUUI.js → chunk-FCIZXX56.js} +3 -3
  36. package/dist/{chunk-C2RJVZZL.js → chunk-FJ3C3ELF.js} +2 -2
  37. package/dist/{chunk-ZONKSLF2.js → chunk-FO5WEDKF.js} +2 -2
  38. package/dist/{chunk-SQKAECUL.js → chunk-FUDVHE2U.js} +2 -2
  39. package/dist/{chunk-IVZWHIEK.js → chunk-GHXOVGTX.js} +5 -5
  40. package/dist/{chunk-UU6M64HI.js → chunk-GPZHHTJU.js} +4 -4
  41. package/dist/{chunk-3HNKR65T.js → chunk-H4XFA2LM.js} +3 -3
  42. package/dist/{chunk-JOK73NDT.js → chunk-HUXDQIVU.js} +3 -3
  43. package/dist/{chunk-F5GWNSE2.js → chunk-J73KU4AE.js} +3 -3
  44. package/dist/{chunk-F5GWNSE2.js.map → chunk-J73KU4AE.js.map} +1 -1
  45. package/dist/{chunk-O5XKZCUD.js → chunk-JJKXJAH2.js} +5 -5
  46. package/dist/{chunk-TNH5SLCD.js → chunk-KD253AI5.js} +2 -2
  47. package/dist/{chunk-WWVJXBOT.js → chunk-KJ37E3R5.js} +5 -5
  48. package/dist/{chunk-S45MDEEF.js → chunk-KNJ7MK4B.js} +2 -2
  49. package/dist/{chunk-TA6HPKWQ.js → chunk-LR7CODVN.js} +1 -1
  50. package/dist/chunk-LR7CODVN.js.map +1 -0
  51. package/dist/{chunk-J6RGRZOY.js → chunk-LX4CPLU6.js} +2 -2
  52. package/dist/{chunk-WE2BUQD2.js → chunk-N4EXCKWP.js} +3 -3
  53. package/dist/{chunk-EYK72OTL.js → chunk-OCRDV3NU.js} +5 -5
  54. package/dist/chunk-OCRDV3NU.js.map +1 -0
  55. package/dist/{chunk-JBBWALNI.js → chunk-OMBPGXCL.js} +2 -2
  56. package/dist/{chunk-NV4IHBZS.js → chunk-PS6PSEZL.js} +5 -5
  57. package/dist/{chunk-6QE4DUYC.js → chunk-Q7P4WHTL.js} +2 -2
  58. package/dist/{chunk-TAMRU7A2.js → chunk-QYQRAOEF.js} +4 -4
  59. package/dist/{chunk-6QAZ5O6X.js → chunk-RHVYFAVQ.js} +2 -2
  60. package/dist/chunk-RZOGD7IF.js +232 -0
  61. package/dist/chunk-RZOGD7IF.js.map +1 -0
  62. package/dist/{chunk-YPIOFSN3.js → chunk-SKYBEGHB.js} +2 -2
  63. package/dist/{chunk-7MRT7EPB.js → chunk-TESFHBOW.js} +3 -3
  64. package/dist/{chunk-CQYEDODS.js → chunk-TSUICI5N.js} +3 -3
  65. package/dist/{chunk-FRRJIUSI.js → chunk-UNBX2HMA.js} +17 -9
  66. package/dist/chunk-UNBX2HMA.js.map +1 -0
  67. package/dist/{chunk-TYMDCIQM.js → chunk-VGAN5RLD.js} +4 -4
  68. package/dist/{chunk-5YTXYPES.js → chunk-VJNV2GRF.js} +5 -5
  69. package/dist/{chunk-NSXNXLYM.js → chunk-VUUQYWF5.js} +2 -2
  70. package/dist/{chunk-IW4L4X65.js → chunk-WVYL6HM7.js} +2 -2
  71. package/dist/{chunk-BZW5IL43.js → chunk-Y5CTT6K5.js} +4 -4
  72. package/dist/{chunk-C6W5KVDV.js → chunk-YP2AYE5W.js} +35 -35
  73. package/dist/chunk-YP2AYE5W.js.map +1 -0
  74. package/dist/{chunk-KOAJ3TZM.js → chunk-YRQPI67X.js} +2 -2
  75. package/dist/{chunk-MBXKRHSS.js → chunk-YYTM4U4J.js} +2 -2
  76. package/dist/{chunk-2XA2ZML4.js → chunk-ZCBJIDT4.js} +3 -3
  77. package/dist/{chunk-AI4USDRI.js → chunk-ZW2YSN6G.js} +4 -4
  78. package/dist/consent/index.cjs.map +1 -1
  79. package/dist/consent/index.d.cts +5 -5
  80. package/dist/consent/index.d.ts +5 -5
  81. package/dist/consent/index.js +3 -3
  82. package/dist/{crypto-456N7UVX.js → crypto-YBKBNPVM.js} +3 -3
  83. package/dist/{ulid-Dwt3JEcy.d.ts → decrypt-partition-C71vhnND.d.cts} +19 -64
  84. package/dist/{ulid-Bg-IBJyA.d.cts → decrypt-partition-CyyJUWLR.d.ts} +19 -64
  85. package/dist/{delegation-DP4COTXB.js → delegation-4JSMM6BB.js} +5 -5
  86. package/dist/derivations/index.cjs.map +1 -1
  87. package/dist/derivations/index.d.cts +6 -6
  88. package/dist/derivations/index.d.ts +6 -6
  89. package/dist/derivations/index.js +4 -4
  90. package/dist/{dev-unlock-Bw7iBD1D.d.cts → dev-unlock-BdrE0kbS.d.cts} +1 -1
  91. package/dist/{dev-unlock-DzDzLTdZ.d.ts → dev-unlock-ByBkl99-.d.ts} +1 -1
  92. package/dist/{errors-Dkc_fi-S.d.cts → errors-Dwk2k1xY.d.cts} +14 -5
  93. package/dist/{errors-Dkc_fi-S.d.ts → errors-Dwk2k1xY.d.ts} +14 -5
  94. package/dist/executor-3SVNESQ3.js +8 -0
  95. package/dist/executor-BIW4FT5R.js +12 -0
  96. package/dist/executor-VEZUBJNQ.js +8 -0
  97. package/dist/{fanout-sidecar-YXNAEZ33.js → fanout-sidecar-ZQT4Y7PF.js} +2 -2
  98. package/dist/forget/index.js +4 -4
  99. package/dist/guards/index.cjs.map +1 -1
  100. package/dist/guards/index.d.cts +6 -6
  101. package/dist/guards/index.d.ts +6 -6
  102. package/dist/guards/index.js +6 -6
  103. package/dist/{hash-C52X_-m5.d.cts → hash-BUkDp_8Q.d.cts} +1 -1
  104. package/dist/{hash-DepR-xVc.d.ts → hash-CZxVv8RH.d.ts} +1 -1
  105. package/dist/history/index.cjs.map +1 -1
  106. package/dist/history/index.d.cts +6 -6
  107. package/dist/history/index.d.ts +6 -6
  108. package/dist/history/index.js +5 -5
  109. package/dist/i18n/index.cjs.map +1 -1
  110. package/dist/i18n/index.d.cts +5 -5
  111. package/dist/i18n/index.d.ts +5 -5
  112. package/dist/i18n/index.js +6 -6
  113. package/dist/index-CBUhOmrM.d.cts +70 -0
  114. package/dist/index-DFhKV-6A.d.ts +70 -0
  115. package/dist/{index-tZqVB9g5.d.cts → index-DoxKSsMj.d.cts} +2 -2
  116. package/dist/{index-Bm9hIY7t.d.ts → index-LaexBi3v.d.ts} +2 -2
  117. package/dist/index.cjs +25660 -25495
  118. package/dist/index.cjs.map +1 -1
  119. package/dist/index.d.cts +135 -80
  120. package/dist/index.d.ts +135 -80
  121. package/dist/index.js +70 -51
  122. package/dist/index.js.map +1 -1
  123. package/dist/indexing/index.cjs.map +1 -1
  124. package/dist/indexing/index.js +4 -4
  125. package/dist/issue-LEBPVF3Y.js +12 -0
  126. package/dist/kernel/index.cjs +657 -0
  127. package/dist/kernel/index.cjs.map +1 -0
  128. package/dist/kernel/index.d.cts +11 -0
  129. package/dist/kernel/index.d.ts +11 -0
  130. package/dist/kernel/index.js +40 -0
  131. package/dist/{ledger-I7JUYP4L.js → ledger-FLRTSOYH.js} +5 -5
  132. package/dist/materialized-views/index.cjs.map +1 -1
  133. package/dist/materialized-views/index.d.cts +6 -6
  134. package/dist/materialized-views/index.d.ts +6 -6
  135. package/dist/materialized-views/index.js +8 -8
  136. package/dist/{mime-magic-Cxf9B_Dm.d.cts → mime-magic-BAhLjkHw.d.cts} +1 -1
  137. package/dist/{mime-magic-Dejetix_.d.ts → mime-magic-C1UbcBxP.d.ts} +1 -1
  138. package/dist/noydb-6FA46A4M.js +38 -0
  139. package/dist/overlay-views/index.cjs.map +1 -1
  140. package/dist/overlay-views/index.d.cts +6 -6
  141. package/dist/overlay-views/index.d.ts +6 -6
  142. package/dist/overlay-views/index.js +4 -4
  143. package/dist/periods/index.cjs.map +1 -1
  144. package/dist/periods/index.d.cts +5 -5
  145. package/dist/periods/index.d.ts +5 -5
  146. package/dist/periods/index.js +5 -5
  147. package/dist/{public-envelope-5XRTUNKF.js → public-envelope-DBKJEBBF.js} +4 -4
  148. package/dist/query/index.cjs.map +1 -1
  149. package/dist/query/index.d.cts +3 -3
  150. package/dist/query/index.d.ts +3 -3
  151. package/dist/query/index.js +7 -7
  152. package/dist/registry-CMEVTOCN.js +8 -0
  153. package/dist/{registry-NWHOLD5M.js → registry-OUZ3VBZA.js} +3 -3
  154. package/dist/registry-XUBRO5JJ.js +8 -0
  155. package/dist/{revoke-5IEK22KT.js → revoke-P5D3UTRX.js} +6 -6
  156. package/dist/sealed-record/index.cjs.map +1 -1
  157. package/dist/sealed-record/index.d.cts +1 -1
  158. package/dist/sealed-record/index.d.ts +1 -1
  159. package/dist/sealed-record/index.js +2 -2
  160. package/dist/session/index.cjs.map +1 -1
  161. package/dist/session/index.d.cts +6 -6
  162. package/dist/session/index.d.ts +6 -6
  163. package/dist/session/index.js +3 -3
  164. package/dist/shadow/index.cjs.map +1 -1
  165. package/dist/shadow/index.d.cts +5 -5
  166. package/dist/shadow/index.d.ts +5 -5
  167. package/dist/shadow/index.js +2 -2
  168. package/dist/{signer-I6YARZQA.js → signer-NEQPCHMW.js} +5 -5
  169. package/dist/snapshots/index.cjs.map +1 -1
  170. package/dist/snapshots/index.d.cts +5 -5
  171. package/dist/snapshots/index.d.ts +5 -5
  172. package/dist/snapshots/index.js +4 -4
  173. package/dist/{stale-CPESGAPL.js → stale-KKCHF2VB.js} +2 -2
  174. package/dist/store/index.cjs.map +1 -1
  175. package/dist/store/index.d.cts +5 -5
  176. package/dist/store/index.d.ts +5 -5
  177. package/dist/store/index.js +2 -2
  178. package/dist/{strategy-WtB-jXYv.d.cts → strategy-D1zjEV3n.d.cts} +1 -1
  179. package/dist/{strategy-54eIwox5.d.ts → strategy-YQ1qJWyq.d.ts} +1 -1
  180. package/dist/sync/index.cjs.map +1 -1
  181. package/dist/sync/index.d.cts +4 -4
  182. package/dist/sync/index.d.ts +4 -4
  183. package/dist/sync/index.js +4 -4
  184. package/dist/team/index.cjs +10 -3
  185. package/dist/team/index.cjs.map +1 -1
  186. package/dist/team/index.d.cts +5 -5
  187. package/dist/team/index.d.ts +5 -5
  188. package/dist/team/index.js +8 -8
  189. package/dist/{transition-guard-Ctxapq1b.d.ts → transition-guard-BSLdikC_.d.ts} +1 -1
  190. package/dist/{transition-guard-BcLyTGYq.d.cts → transition-guard-DPs6al8h.d.cts} +1 -1
  191. package/dist/tx/index.cjs +1 -1
  192. package/dist/tx/index.cjs.map +1 -1
  193. package/dist/tx/index.d.cts +5 -5
  194. package/dist/tx/index.d.ts +5 -5
  195. package/dist/tx/index.js +3 -3
  196. package/dist/{types-Bhs2i_Ll.d.cts → types-BCYvhKzr.d.cts} +282 -578
  197. package/dist/{types-DONgts0n.d.ts → types-CCq0WHh9.d.ts} +282 -578
  198. package/dist/ulid-DRH25k3y.d.cts +66 -0
  199. package/dist/ulid-DRH25k3y.d.ts +66 -0
  200. package/dist/util/index.cjs.map +1 -1
  201. package/dist/util/index.js +1 -1
  202. package/dist/{with-materialized-view-BYb3p9wT.d.cts → with-materialized-view-CTHe6uh9.d.cts} +1 -1
  203. package/dist/{with-materialized-view-CyVLOr09.d.ts → with-materialized-view-DiD41wQp.d.ts} +1 -1
  204. package/dist/{with-overlayed-view-BhLRxqwI.d.ts → with-overlayed-view-DlbsJMhF.d.ts} +1 -1
  205. package/dist/{with-overlayed-view-LGrQ984e.d.cts → with-overlayed-view-Dlz5hcM8.d.cts} +1 -1
  206. package/dist/{with-rollup-Bj8c7ttB.d.cts → with-rollup-BBWdrCvu.d.cts} +1 -1
  207. package/dist/{with-rollup-CO8ibRcK.d.ts → with-rollup-mT4_CWaU.d.ts} +1 -1
  208. package/package.json +13 -3
  209. package/dist/chunk-C6W5KVDV.js.map +0 -1
  210. package/dist/chunk-EYK72OTL.js.map +0 -1
  211. package/dist/chunk-FRRJIUSI.js.map +0 -1
  212. package/dist/chunk-HYJMAV53.js.map +0 -1
  213. package/dist/chunk-JTI57WRT.js +0 -164
  214. package/dist/chunk-JTI57WRT.js.map +0 -1
  215. package/dist/chunk-OTWT6BAJ.js.map +0 -1
  216. package/dist/chunk-P65YMN5V.js.map +0 -1
  217. package/dist/chunk-TA6HPKWQ.js.map +0 -1
  218. package/dist/chunk-ZC7J6ZYV.js +0 -7
  219. package/dist/chunk-ZC7J6ZYV.js.map +0 -1
  220. package/dist/executor-4IEW4KG5.js +0 -8
  221. package/dist/executor-KYJCJCIN.js +0 -12
  222. package/dist/executor-W7VIBOBZ.js +0 -8
  223. package/dist/issue-JXC6T2QR.js +0 -12
  224. package/dist/noydb-VGR2HLDB.js +0 -39
  225. package/dist/registry-ATRHOG5B.js +0 -8
  226. package/dist/registry-LEHB26TY.js +0 -8
  227. package/dist/state-vault-JR3CFGNP.js +0 -14
  228. package/dist/vault-group-BB246VIM.js +0 -804
  229. package/dist/vault-group-BB246VIM.js.map +0 -1
  230. /package/dist/{chunk-SQOK5UM6.js.map → chunk-2KA3PDUR.js.map} +0 -0
  231. /package/dist/{chunk-U2XSUCDF.js.map → chunk-3BANVNDH.js.map} +0 -0
  232. /package/dist/{chunk-37VGJM3T.js.map → chunk-7JSP3E67.js.map} +0 -0
  233. /package/dist/{chunk-F5ILTHMU.js.map → chunk-ANLOD6IS.js.map} +0 -0
  234. /package/dist/{chunk-JYNH4FIM.js.map → chunk-C7UIT5XY.js.map} +0 -0
  235. /package/dist/{chunk-TGIJTNM3.js.map → chunk-E5TJAQS7.js.map} +0 -0
  236. /package/dist/{chunk-GJTKMME7.js.map → chunk-EW3H5Y7N.js.map} +0 -0
  237. /package/dist/{chunk-JDCPRJVS.js.map → chunk-EYZJULEN.js.map} +0 -0
  238. /package/dist/{chunk-I3IYTUUI.js.map → chunk-FCIZXX56.js.map} +0 -0
  239. /package/dist/{chunk-C2RJVZZL.js.map → chunk-FJ3C3ELF.js.map} +0 -0
  240. /package/dist/{chunk-ZONKSLF2.js.map → chunk-FO5WEDKF.js.map} +0 -0
  241. /package/dist/{chunk-SQKAECUL.js.map → chunk-FUDVHE2U.js.map} +0 -0
  242. /package/dist/{chunk-IVZWHIEK.js.map → chunk-GHXOVGTX.js.map} +0 -0
  243. /package/dist/{chunk-UU6M64HI.js.map → chunk-GPZHHTJU.js.map} +0 -0
  244. /package/dist/{chunk-3HNKR65T.js.map → chunk-H4XFA2LM.js.map} +0 -0
  245. /package/dist/{chunk-JOK73NDT.js.map → chunk-HUXDQIVU.js.map} +0 -0
  246. /package/dist/{chunk-O5XKZCUD.js.map → chunk-JJKXJAH2.js.map} +0 -0
  247. /package/dist/{chunk-TNH5SLCD.js.map → chunk-KD253AI5.js.map} +0 -0
  248. /package/dist/{chunk-WWVJXBOT.js.map → chunk-KJ37E3R5.js.map} +0 -0
  249. /package/dist/{chunk-S45MDEEF.js.map → chunk-KNJ7MK4B.js.map} +0 -0
  250. /package/dist/{chunk-J6RGRZOY.js.map → chunk-LX4CPLU6.js.map} +0 -0
  251. /package/dist/{chunk-WE2BUQD2.js.map → chunk-N4EXCKWP.js.map} +0 -0
  252. /package/dist/{chunk-JBBWALNI.js.map → chunk-OMBPGXCL.js.map} +0 -0
  253. /package/dist/{chunk-NV4IHBZS.js.map → chunk-PS6PSEZL.js.map} +0 -0
  254. /package/dist/{chunk-6QE4DUYC.js.map → chunk-Q7P4WHTL.js.map} +0 -0
  255. /package/dist/{chunk-TAMRU7A2.js.map → chunk-QYQRAOEF.js.map} +0 -0
  256. /package/dist/{chunk-6QAZ5O6X.js.map → chunk-RHVYFAVQ.js.map} +0 -0
  257. /package/dist/{chunk-YPIOFSN3.js.map → chunk-SKYBEGHB.js.map} +0 -0
  258. /package/dist/{chunk-7MRT7EPB.js.map → chunk-TESFHBOW.js.map} +0 -0
  259. /package/dist/{chunk-CQYEDODS.js.map → chunk-TSUICI5N.js.map} +0 -0
  260. /package/dist/{chunk-TYMDCIQM.js.map → chunk-VGAN5RLD.js.map} +0 -0
  261. /package/dist/{chunk-5YTXYPES.js.map → chunk-VJNV2GRF.js.map} +0 -0
  262. /package/dist/{chunk-NSXNXLYM.js.map → chunk-VUUQYWF5.js.map} +0 -0
  263. /package/dist/{chunk-IW4L4X65.js.map → chunk-WVYL6HM7.js.map} +0 -0
  264. /package/dist/{chunk-BZW5IL43.js.map → chunk-Y5CTT6K5.js.map} +0 -0
  265. /package/dist/{chunk-KOAJ3TZM.js.map → chunk-YRQPI67X.js.map} +0 -0
  266. /package/dist/{chunk-MBXKRHSS.js.map → chunk-YYTM4U4J.js.map} +0 -0
  267. /package/dist/{chunk-2XA2ZML4.js.map → chunk-ZCBJIDT4.js.map} +0 -0
  268. /package/dist/{chunk-AI4USDRI.js.map → chunk-ZW2YSN6G.js.map} +0 -0
  269. /package/dist/{crypto-456N7UVX.js.map → crypto-YBKBNPVM.js.map} +0 -0
  270. /package/dist/{delegation-DP4COTXB.js.map → delegation-4JSMM6BB.js.map} +0 -0
  271. /package/dist/{executor-4IEW4KG5.js.map → executor-3SVNESQ3.js.map} +0 -0
  272. /package/dist/{executor-KYJCJCIN.js.map → executor-BIW4FT5R.js.map} +0 -0
  273. /package/dist/{executor-W7VIBOBZ.js.map → executor-VEZUBJNQ.js.map} +0 -0
  274. /package/dist/{fanout-sidecar-YXNAEZ33.js.map → fanout-sidecar-ZQT4Y7PF.js.map} +0 -0
  275. /package/dist/{issue-JXC6T2QR.js.map → issue-LEBPVF3Y.js.map} +0 -0
  276. /package/dist/{ledger-I7JUYP4L.js.map → kernel/index.js.map} +0 -0
  277. /package/dist/{noydb-VGR2HLDB.js.map → ledger-FLRTSOYH.js.map} +0 -0
  278. /package/dist/{public-envelope-5XRTUNKF.js.map → noydb-6FA46A4M.js.map} +0 -0
  279. /package/dist/{registry-ATRHOG5B.js.map → public-envelope-DBKJEBBF.js.map} +0 -0
  280. /package/dist/{registry-LEHB26TY.js.map → registry-CMEVTOCN.js.map} +0 -0
  281. /package/dist/{registry-NWHOLD5M.js.map → registry-OUZ3VBZA.js.map} +0 -0
  282. /package/dist/{revoke-5IEK22KT.js.map → registry-XUBRO5JJ.js.map} +0 -0
  283. /package/dist/{signer-I6YARZQA.js.map → revoke-P5D3UTRX.js.map} +0 -0
  284. /package/dist/{stale-CPESGAPL.js.map → signer-NEQPCHMW.js.map} +0 -0
  285. /package/dist/{state-vault-JR3CFGNP.js.map → stale-KKCHF2VB.js.map} +0 -0
package/dist/index.js CHANGED
@@ -3,10 +3,12 @@ import {
3
3
  issueDelegation,
4
4
  loadActiveDelegations,
5
5
  revokeDelegation
6
- } from "./chunk-AI4USDRI.js";
6
+ } from "./chunk-ZW2YSN6G.js";
7
7
  import {
8
8
  Collection,
9
9
  ComputedFieldError,
10
+ CustodyApi,
11
+ DEED_RECORD_ID,
10
12
  DEFAULT_FRESHNESS_MS,
11
13
  ELEVATION_AUDIT_COLLECTION,
12
14
  ElevatedHandle,
@@ -29,6 +31,7 @@ import {
29
31
  approveWithdrawal,
30
32
  checkGate,
31
33
  compileSequenceFormat,
34
+ createDeedOwner,
32
35
  createNoydb,
33
36
  derivePersistedSchema,
34
37
  describeAllUsersAuth,
@@ -39,10 +42,13 @@ import {
39
42
  estimateRecordBytes,
40
43
  evalComputedFields,
41
44
  exportAccessibleData,
45
+ isDeedVault,
42
46
  isLinkCollectionName,
43
47
  isRefArray,
44
48
  isZodSchema,
49
+ liberateVault,
45
50
  listWithdrawalRequests,
51
+ loadDeedMarker,
46
52
  loadVaultPolicy,
47
53
  mergePolicy,
48
54
  parseBytes,
@@ -58,10 +64,7 @@ import {
58
64
  validateSchemaOutput,
59
65
  withArchive,
60
66
  withdrawAccessibleData
61
- } from "./chunk-P65YMN5V.js";
62
- import {
63
- STATE_VAULT_NAME
64
- } from "./chunk-ZC7J6ZYV.js";
67
+ } from "./chunk-56ENKU46.js";
65
68
  import {
66
69
  isDiscriminant
67
70
  } from "./chunk-STNPB3UM.js";
@@ -74,37 +77,37 @@ import {
74
77
  immutableGuard,
75
78
  transitionGuard,
76
79
  withGuard
77
- } from "./chunk-C2RJVZZL.js";
78
- import "./chunk-ADB7GPM3.js";
80
+ } from "./chunk-FJ3C3ELF.js";
79
81
  import "./chunk-A3JMGXPG.js";
80
- import "./chunk-J6RGRZOY.js";
82
+ import "./chunk-ADB7GPM3.js";
83
+ import "./chunk-LX4CPLU6.js";
81
84
  import {
82
85
  CollectionFrame,
83
86
  VaultFrame
84
- } from "./chunk-TGIJTNM3.js";
87
+ } from "./chunk-E5TJAQS7.js";
85
88
  import {
86
89
  TxCollection,
87
90
  TxContext,
88
91
  TxVault,
89
92
  runTransaction
90
- } from "./chunk-IY24WS2P.js";
93
+ } from "./chunk-EJJTUDNI.js";
91
94
  import {
92
95
  withDerivation,
93
96
  withRollup
94
- } from "./chunk-YPIOFSN3.js";
95
- import "./chunk-S45MDEEF.js";
96
- import "./chunk-6QAZ5O6X.js";
97
+ } from "./chunk-SKYBEGHB.js";
98
+ import "./chunk-KNJ7MK4B.js";
99
+ import "./chunk-RHVYFAVQ.js";
97
100
  import {
98
101
  withMaterializedView
99
- } from "./chunk-6QE4DUYC.js";
100
- import "./chunk-5YTXYPES.js";
101
- import "./chunk-KOAJ3TZM.js";
102
- import "./chunk-IW4L4X65.js";
102
+ } from "./chunk-Q7P4WHTL.js";
103
+ import "./chunk-VJNV2GRF.js";
104
+ import "./chunk-YRQPI67X.js";
105
+ import "./chunk-WVYL6HM7.js";
103
106
  import {
104
107
  withOverlayedView
105
- } from "./chunk-JBBWALNI.js";
106
- import "./chunk-SQOK5UM6.js";
107
- import "./chunk-MBXKRHSS.js";
108
+ } from "./chunk-OMBPGXCL.js";
109
+ import "./chunk-2KA3PDUR.js";
110
+ import "./chunk-YYTM4U4J.js";
108
111
  import {
109
112
  DEFAULT_CROSS_JOIN_MAX_ROWS,
110
113
  DEFAULT_JOIN_MAX_ROWS,
@@ -114,7 +117,7 @@ import {
114
117
  buildLiveQuery,
115
118
  executePlan,
116
119
  resetJoinWarnings
117
- } from "./chunk-NV4IHBZS.js";
120
+ } from "./chunk-PS6PSEZL.js";
118
121
  import {
119
122
  BLOB_CHUNKS_COLLECTION,
120
123
  BLOB_COLLECTION,
@@ -128,19 +131,19 @@ import {
128
131
  importExternalObjects,
129
132
  isPreCompressed,
130
133
  memoryObjectProjection
131
- } from "./chunk-WWVJXBOT.js";
132
- import "./chunk-2XA2ZML4.js";
133
- import "./chunk-3HNKR65T.js";
134
+ } from "./chunk-KJ37E3R5.js";
135
+ import "./chunk-ZCBJIDT4.js";
136
+ import "./chunk-H4XFA2LM.js";
134
137
  import {
135
138
  CollectionIndexes
136
- } from "./chunk-GJTKMME7.js";
139
+ } from "./chunk-EW3H5Y7N.js";
137
140
  import {
138
141
  avg,
139
142
  count,
140
143
  max,
141
144
  min,
142
145
  sum
143
- } from "./chunk-ZONKSLF2.js";
146
+ } from "./chunk-FO5WEDKF.js";
144
147
  import {
145
148
  Aggregation,
146
149
  GROUPBY_MAX_CARDINALITY,
@@ -150,7 +153,7 @@ import {
150
153
  GroupedQueryN,
151
154
  groupAndReduce,
152
155
  reduceRecords
153
- } from "./chunk-JYNH4FIM.js";
156
+ } from "./chunk-C7UIT5XY.js";
154
157
  import {
155
158
  MoneyCurrencyError,
156
159
  MoneyPrecisionError,
@@ -165,11 +168,14 @@ import {
165
168
  readPath,
166
169
  rescaleScaledInt,
167
170
  scaleForCurrency
168
- } from "./chunk-U2XSUCDF.js";
171
+ } from "./chunk-3BANVNDH.js";
169
172
  import {
170
173
  mergeCrdtStates,
171
174
  resolveCrdtSnapshot
172
175
  } from "./chunk-J66GRPNH.js";
176
+ import {
177
+ decryptExtractedPartition
178
+ } from "./chunk-RZOGD7IF.js";
173
179
  import {
174
180
  MemoryRecipientSealer,
175
181
  MemorySealingKeyProvider,
@@ -183,7 +189,7 @@ import {
183
189
  savePersistedSchema,
184
190
  saveSealedPassphrase,
185
191
  sealRsaOaepTlv
186
- } from "./chunk-C6W5KVDV.js";
192
+ } from "./chunk-YP2AYE5W.js";
187
193
  import {
188
194
  NOYDB_BUNDLE_FORMAT_VERSION,
189
195
  NOYDB_BUNDLE_MAGIC,
@@ -194,7 +200,7 @@ import {
194
200
  readNoydbBundlePublicEnvelope,
195
201
  resetBrotliSupportCache,
196
202
  writeNoydbBundle
197
- } from "./chunk-WE2BUQD2.js";
203
+ } from "./chunk-N4EXCKWP.js";
198
204
  import {
199
205
  PUBLIC_ENVELOPE_RECORD_ID,
200
206
  isPublicEnvelope,
@@ -202,14 +208,14 @@ import {
202
208
  readPublicEnvelope,
203
209
  savePublicEnvelope,
204
210
  validatePublicEnvelopeInput
205
- } from "./chunk-JOK73NDT.js";
206
- import "./chunk-BZW5IL43.js";
211
+ } from "./chunk-HUXDQIVU.js";
212
+ import "./chunk-Y5CTT6K5.js";
207
213
  import {
208
214
  CONSENT_AUDIT_COLLECTION
209
- } from "./chunk-SQKAECUL.js";
215
+ } from "./chunk-FUDVHE2U.js";
210
216
  import {
211
217
  PERIODS_COLLECTION
212
- } from "./chunk-I3IYTUUI.js";
218
+ } from "./chunk-FCIZXX56.js";
213
219
  import "./chunk-UF3BUNQZ.js";
214
220
  import {
215
221
  DICT_COLLECTION_PREFIX,
@@ -220,7 +226,7 @@ import {
220
226
  isDictKeyDescriptor,
221
227
  isStaticDictDescriptor,
222
228
  staticDict
223
- } from "./chunk-O5XKZCUD.js";
229
+ } from "./chunk-JJKXJAH2.js";
224
230
  import {
225
231
  applyI18nLocale,
226
232
  enforceScript,
@@ -230,7 +236,7 @@ import {
230
236
  resolveI18nText,
231
237
  resolvePolicy,
232
238
  validateI18nTextValue
233
- } from "./chunk-TNH5SLCD.js";
239
+ } from "./chunk-KD253AI5.js";
234
240
  import {
235
241
  createBundleStore,
236
242
  routeStore,
@@ -242,7 +248,7 @@ import {
242
248
  withRetry,
243
249
  wrapBundleStore,
244
250
  wrapStore
245
- } from "./chunk-NSXNXLYM.js";
251
+ } from "./chunk-VUUQYWF5.js";
246
252
  import {
247
253
  SYNC_CREDENTIALS_COLLECTION,
248
254
  credentialStatus,
@@ -250,7 +256,7 @@ import {
250
256
  getCredential,
251
257
  listCredentials,
252
258
  putCredential
253
- } from "./chunk-EYK72OTL.js";
259
+ } from "./chunk-OCRDV3NU.js";
254
260
  import {
255
261
  MAGIC_LINK_CONTENT_INFO_PREFIX,
256
262
  MAGIC_LINK_GRANTS_COLLECTION,
@@ -285,17 +291,17 @@ import {
285
291
  unwrapDeksFromShamirEntry,
286
292
  unwrapMagicLinkGrant,
287
293
  writeMagicLinkGrant
288
- } from "./chunk-HYJMAV53.js";
294
+ } from "./chunk-2RHBFCWQ.js";
289
295
  import {
290
296
  assertTierAccess,
291
297
  dekKey,
292
298
  effectiveClearance
293
- } from "./chunk-F5GWNSE2.js";
299
+ } from "./chunk-J73KU4AE.js";
294
300
  import {
295
301
  PresenceHandle,
296
302
  SyncEngine,
297
303
  SyncTransaction
298
- } from "./chunk-UU6M64HI.js";
304
+ } from "./chunk-GPZHHTJU.js";
299
305
  import {
300
306
  DIRECTORY_RECORD_ID,
301
307
  USER_ENVELOPE_COLLECTION,
@@ -323,7 +329,7 @@ import {
323
329
  saveUserEnvelope,
324
330
  validatePassphrase,
325
331
  visibilityRecordId
326
- } from "./chunk-FRRJIUSI.js";
332
+ } from "./chunk-UNBX2HMA.js";
327
333
  import {
328
334
  BUNDLE_STORE_POLICY,
329
335
  INDEXED_STORE_POLICY,
@@ -343,7 +349,7 @@ import {
343
349
  revokeAllSessions,
344
350
  revokeSession,
345
351
  validateSessionPolicy
346
- } from "./chunk-7MRT7EPB.js";
352
+ } from "./chunk-TESFHBOW.js";
347
353
  import {
348
354
  generateULID,
349
355
  isULID
@@ -353,14 +359,14 @@ import {
353
359
  VaultInstant,
354
360
  diff,
355
361
  formatDiff
356
- } from "./chunk-TYMDCIQM.js";
362
+ } from "./chunk-VGAN5RLD.js";
357
363
  import {
358
364
  LEDGER_COLLECTION,
359
365
  LEDGER_DELTAS_COLLECTION,
360
366
  LedgerStore,
361
367
  applyPatch,
362
368
  computePatch
363
- } from "./chunk-JDCPRJVS.js";
369
+ } from "./chunk-EYZJULEN.js";
364
370
  import {
365
371
  canonicalJson,
366
372
  envelopePayloadHash,
@@ -369,14 +375,14 @@ import {
369
375
  parseIndex,
370
376
  sha256Hex
371
377
  } from "./chunk-PDVP3C2I.js";
372
- import "./chunk-CQYEDODS.js";
378
+ import "./chunk-TSUICI5N.js";
373
379
  import {
374
380
  NOYDB_BACKUP_VERSION,
375
381
  NOYDB_FORMAT_VERSION,
376
382
  NOYDB_KEYRING_VERSION,
377
383
  NOYDB_SYNC_VERSION,
378
384
  createStore
379
- } from "./chunk-TA6HPKWQ.js";
385
+ } from "./chunk-LR7CODVN.js";
380
386
  import {
381
387
  base64ToBuffer,
382
388
  bufferToBase64,
@@ -385,7 +391,7 @@ import {
385
391
  derivePresenceKey,
386
392
  encryptBytes,
387
393
  encryptDeterministic
388
- } from "./chunk-37VGJM3T.js";
394
+ } from "./chunk-7JSP3E67.js";
389
395
  import {
390
396
  AlreadyElevatedError,
391
397
  AmendmentForbiddenError,
@@ -483,7 +489,7 @@ import {
483
489
  UnsupportedIndexOptionError,
484
490
  ValidationError,
485
491
  VaultTemplateNotFoundError
486
- } from "./chunk-OTWT6BAJ.js";
492
+ } from "./chunk-DDOYOMAD.js";
487
493
 
488
494
  // src/debug.ts
489
495
  function readPlaintextRecord(envelope) {
@@ -564,6 +570,9 @@ function withDeferredNumbering(config) {
564
570
  };
565
571
  }
566
572
 
573
+ // src/constants.ts
574
+ var STATE_VAULT_NAME = "__noydb_state__";
575
+
567
576
  // src/money/arith.ts
568
577
  function parseAmount(label, amount, scale, rounding) {
569
578
  const r = parseToScaledInt(amount, scale, rounding);
@@ -703,11 +712,13 @@ async function diffVault(vault, candidate, options = {}) {
703
712
  if (before === void 0 && after !== void 0) {
704
713
  added.push({ collection, id, record: after });
705
714
  } else if (before !== void 0 && after === void 0) {
706
- deleted.push({ collection, id, record: before });
715
+ const metadata = options.includeMetadata ? await vault.collection(collection).getMetadata(id) ?? void 0 : void 0;
716
+ deleted.push({ collection, id, record: before, ...metadata !== void 0 ? { metadata } : {} });
707
717
  } else if (before !== void 0 && after !== void 0) {
708
718
  if (compareFn(before, after)) {
709
719
  unchanged?.push({ collection, id, record: after });
710
720
  } else {
721
+ const metadata = options.includeMetadata ? await vault.collection(collection).getMetadata(id) ?? void 0 : void 0;
711
722
  const fieldDiffs = diff(before, after);
712
723
  const fieldsChanged = uniqueTopLevelKeys(fieldDiffs);
713
724
  modified.push({
@@ -716,7 +727,8 @@ async function diffVault(vault, candidate, options = {}) {
716
727
  record: after,
717
728
  before,
718
729
  fieldsChanged,
719
- fieldDiffs
730
+ fieldDiffs,
731
+ ...metadata !== void 0 ? { metadata } : {}
720
732
  });
721
733
  }
722
734
  }
@@ -848,6 +860,8 @@ export {
848
860
  ConflictError,
849
861
  CrossJoinSourceUnknownError,
850
862
  CrossJoinTooLargeError,
863
+ CustodyApi,
864
+ DEED_RECORD_ID,
851
865
  DEFAULT_CHUNK_SIZE,
852
866
  DEFAULT_CROSS_JOIN_MAX_ROWS,
853
867
  DEFAULT_FRESHNESS_MS,
@@ -1038,6 +1052,7 @@ export {
1038
1052
  coordinatedCutover,
1039
1053
  count,
1040
1054
  createBundleStore,
1055
+ createDeedOwner,
1041
1056
  createEnforcer,
1042
1057
  createNoydb,
1043
1058
  createSession,
@@ -1045,6 +1060,7 @@ export {
1045
1060
  credentialStatus,
1046
1061
  decryptBytes,
1047
1062
  decryptDeterministic,
1063
+ decryptExtractedPartition,
1048
1064
  dekKey,
1049
1065
  deleteCredential,
1050
1066
  deleteUserEnvelope,
@@ -1093,6 +1109,7 @@ export {
1093
1109
  immutableGuard,
1094
1110
  importExternalObjects,
1095
1111
  inferScripts,
1112
+ isDeedVault,
1096
1113
  isDevUnlockActive,
1097
1114
  isDictCollectionName,
1098
1115
  isDictKeyDescriptor,
@@ -1112,6 +1129,7 @@ export {
1112
1129
  issueDelegation,
1113
1130
  recoverPassphrase as keyringRecoverPassphrase,
1114
1131
  rotatePassphrase as keyringRotatePassphrase,
1132
+ liberateVault,
1115
1133
  listCredentials,
1116
1134
  listMagicLinkGrants,
1117
1135
  listUserEnvelopeIds,
@@ -1119,6 +1137,7 @@ export {
1119
1137
  listUsersWithEnvelopes,
1120
1138
  listWithdrawalRequests,
1121
1139
  loadActiveDelegations,
1140
+ loadDeedMarker,
1122
1141
  loadDevUnlock,
1123
1142
  loadPaperRecoveryEntries,
1124
1143
  loadPersistedSchema,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/debug.ts","../src/schema-update/strategies.ts","../src/schema-update/cutover.ts","../src/numbering/descriptor.ts","../src/money/arith.ts","../src/money/branded.ts","../src/vault-diff.ts"],"sourcesContent":["/**\n * Helpers for reading records out of a *plaintext* store (`encrypt: false`)\n * with native tooling — the programmatic core of a `noydb cat`-style unwrap.\n * See the plaintext/debug-store-mode design.\n */\nimport type { EncryptedEnvelope } from './types.js'\n\n/**\n * Extract the record from a plaintext stored envelope, handling both layouts:\n *\n * - **classic plaintext** (`encrypt: false`): the record is JSON in `_data`.\n * - **debugPlaintext**: the record's fields are inlined beside the\n * `_`-prefixed metadata (marked by `_debug`).\n *\n * Returns `null` for an empty/absent body. Throws if handed an **encrypted**\n * envelope (non-empty `_iv`) — there is no key here; decrypt through the vault\n * instead. Intended for record envelopes, not blob chunks.\n *\n * @example\n * ```ts\n * // node script over a to-file store, no vault needed:\n * const env = JSON.parse(readFileSync('data/acme/invoices/inv-1.json', 'utf8'))\n * console.log(readPlaintextRecord(env)) // → { id: 'inv-1', total: '120.00', … }\n * ```\n */\nexport function readPlaintextRecord<T = Record<string, unknown>>(\n envelope: EncryptedEnvelope,\n): T | null {\n if (envelope._iv !== '') {\n throw new Error(\n 'readPlaintextRecord: envelope is encrypted (non-empty _iv) — decrypt via the vault, not this helper',\n )\n }\n if (envelope._debug !== undefined) {\n const record: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(envelope)) {\n if (!key.startsWith('_')) record[key] = value\n }\n return record as T\n }\n if (!envelope._data) return null\n return JSON.parse(envelope._data) as T\n}\n","/** Bundled light update strategies. */\nimport { NonAdditiveSchemaChangeError, SchemaLockedError } from '../errors.js'\nimport type { SchemaUpdateStrategy, SchemaDelta } from './types.js'\n\n/** Allow any schema change. Explicit blind / back-compat. */\nexport function blindUpdate(): SchemaUpdateStrategy {\n return { name: 'blindUpdate', onSchemaDelta: () => ({ action: 'allow' }) }\n}\n\n/** Allow additive changes; reject non-additive ones. The safety backstop. */\nexport function additiveOnly(): SchemaUpdateStrategy {\n return {\n name: 'additiveOnly',\n onSchemaDelta(delta: SchemaDelta) {\n if (delta.kind === 'non-additive') {\n return {\n action: 'reject' as const,\n error: new NonAdditiveSchemaChangeError(\n `Non-additive schema change to \"${delta.collection}\" ` +\n `(added: [${delta.added.join(', ')}], removed: [${delta.removed.join(', ')}], ` +\n `changed: [${delta.changed.map(c => c.field).join(', ')}]). ` +\n `Register a coordinatedCutover() strategy to migrate, or revert the change.`,\n ),\n }\n }\n return { action: 'allow' as const }\n },\n }\n}\n\n/**\n * Reject schema changes. With `fields`, reject only when one of those\n * fields is added/removed/changed; otherwise reject any non-`none` delta.\n */\nexport function lockSchema(opts?: { readonly fields?: readonly string[] }): SchemaUpdateStrategy {\n const fields = opts?.fields\n return {\n name: 'lockSchema',\n onSchemaDelta(delta: SchemaDelta) {\n if (delta.kind === 'none') return { action: 'allow' as const }\n const touched = fields\n ? [...delta.added, ...delta.removed, ...delta.changed.map(c => c.field)].filter(f => fields.includes(f))\n : ['<any>']\n if (touched.length === 0) return { action: 'allow' as const }\n return {\n action: 'reject' as const,\n error: new SchemaLockedError(\n `Schema for \"${delta.collection}\" is locked` +\n (fields ? ` on fields [${fields.join(', ')}] (touched: [${touched.join(', ')}])` : '') +\n `; the change was refused.`,\n ),\n }\n },\n }\n}\n","/** The coordinatedCutover update strategy (single-step — no from/to). */\nimport type { SchemaUpdateStrategy, SchemaDelta, TransformFn } from './types.js'\n\nexport function coordinatedCutover(opts: { readonly transform: TransformFn }): SchemaUpdateStrategy {\n return {\n name: 'coordinatedCutover',\n onSchemaDelta(delta: SchemaDelta) {\n if (delta.kind === 'non-additive') {\n return { action: 'cutover' as const, transform: opts.transform }\n }\n return { action: 'allow' as const }\n },\n }\n}\n","/**\n * @category capability\n * Deferred-numbering config descriptor. See\n * docs/superpowers/specs/2026-06-08-sealed-numbering-and-store-clock-design.md.\n */\n\n/** A registered deferred-numbering series. */\nexport interface DeferredNumberingConfig {\n /** Series name — the key passed to `vault.sequence(series)`. */\n readonly series: string\n /** Collection holding the records to number. */\n readonly collection: string\n /** Field on each record where the assigned serial is written. */\n readonly field: string\n /**\n * Minimum wall-clock age (ms) before an entry is eligible at a pass, in\n * addition to the interval commit-wait. Default 0 — the store-clock\n * interval (`storeLatest ≤ now.earliest`) is the correctness mechanism.\n */\n readonly settleWindowMs: number\n}\n\n/** Declare a deferred-numbering series. Pass the result in `createNoydb({ numbering: [...] })`. */\nexport function withDeferredNumbering(config: {\n series: string\n collection: string\n field: string\n settleWindowMs?: number\n}): DeferredNumberingConfig {\n return {\n series: config.series,\n collection: config.collection,\n field: config.field,\n settleWindowMs: config.settleWindowMs ?? 0,\n }\n}\n","/**\n * Exact money arithmetic helpers (#337) — `mulRate` and `allocate`.\n *\n * Both operate on the canonical decoded string form that `get()`\n * returns (`'10000.00'`), entirely in scaled-`BigInt` space — no\n * floating-point step anywhere, exact past 2^53. They are pure\n * functions with no vault or descriptor dependency: the working scale\n * is inferred from the amount's fractional digits (a canonical money\n * string always carries exactly the field's scale) or pinned with\n * `opts.scale`.\n *\n * Why these two: app-side invariants of the form\n * `Σ parts === whole` (receipt totals, net-zero WHT pairs, proration)\n * carry ±0.01 tolerances ONLY because the math is major-unit floats +\n * round2. `mulRate` (VAT-style rate application with explicit\n * rounding) and `allocate` (largest-remainder split — parts sum to the\n * input EXACTLY, by construction) make those tolerances zero.\n */\n\nimport {\n parseToScaledInt,\n formatScaledInt,\n rescaleScaledInt,\n decimalScaleOf,\n type RoundingMode,\n} from './fixed-point.js'\nimport { MoneyUnsupportedError } from './descriptor.js'\n\nexport interface MulRateOptions {\n /**\n * Output scale (fraction digits). Defaults to the amount's own\n * fractional digits — for a canonical money string that IS the\n * field's scale.\n */\n readonly scale?: number\n /** Rounding for the final re-scale. Default `'half-up'`. */\n readonly rounding?: RoundingMode\n}\n\nexport interface AllocateOptions {\n /** Working scale. Defaults to the amount's own fractional digits. */\n readonly scale?: number\n}\n\n/** Parse `amount` at `scale` or throw the standard money TypeError. */\nfunction parseAmount(label: string, amount: number | string, scale: number, rounding?: RoundingMode): bigint {\n const r = parseToScaledInt(amount, scale, rounding)\n if (!r.ok) {\n throw new MoneyUnsupportedError(\n r.reason === 'precision'\n ? `${label}: amount ${JSON.stringify(amount)} has more precision than scale ${scale} and no rounding mode is configured`\n : `${label}: amount ${JSON.stringify(amount)} is not a finite decimal`,\n )\n }\n return r.value\n}\n\nfunction resolveScale(label: string, amount: number | string, explicit: number | undefined): number {\n if (explicit !== undefined) {\n if (!Number.isInteger(explicit) || explicit < 0) {\n throw new MoneyUnsupportedError(`${label}: scale must be a non-negative integer`)\n }\n return explicit\n }\n const inferred = decimalScaleOf(amount)\n if (inferred === null) {\n throw new MoneyUnsupportedError(`${label}: amount ${JSON.stringify(amount)} is not a finite decimal`)\n }\n return inferred\n}\n\n/**\n * Multiply a money amount by a decimal rate, exactly.\n *\n * The rate is parsed at its OWN full precision (`0.07` → `7` at scale\n * 2), the product computed in `BigInt` at `amountScale + rateScale`,\n * then re-scaled back to the output scale with the requested rounding —\n * one rounding step, at the very end.\n *\n * ```ts\n * mulRate('10000.00', 0.07) // '700.00' (VAT)\n * mulRate('33.33', '0.07') // '2.33' (half-up)\n * mulRate('33.33', 0.07, { rounding: 'floor' }) // '2.33'\n * mulRate(100, 0.07, { scale: 2 }) // '7.00'\n * ```\n */\nexport function mulRate(\n amount: number | string,\n rate: number | string,\n opts: MulRateOptions = {},\n): string {\n const scale = resolveScale('mulRate', amount, opts.scale)\n const rounding = opts.rounding ?? 'half-up'\n const a = parseAmount('mulRate', amount, scale, rounding)\n\n const rateScale = decimalScaleOf(rate)\n if (rateScale === null) {\n throw new MoneyUnsupportedError(`mulRate: rate ${JSON.stringify(rate)} is not a finite decimal`)\n }\n const r = parseToScaledInt(rate, rateScale)\n if (!r.ok) {\n throw new MoneyUnsupportedError(`mulRate: rate ${JSON.stringify(rate)} is not a finite decimal`)\n }\n\n const product = a * r.value // scaled at scale + rateScale\n return formatScaledInt(rescaleScaledInt(product, scale + rateScale, scale, rounding), scale)\n}\n\n/**\n * Split a money amount across weighted buckets with ZERO drift: the\n * returned parts sum to the input exactly, by construction\n * (largest-remainder method).\n *\n * Each bucket gets `floor(amount × weightᵢ / Σweights)`; the leftover\n * minor units (always fewer than the bucket count) go one each to the\n * buckets with the largest truncated remainders — ties broken by\n * position, earlier bucket first. Weights are parsed as exact decimals\n * (no float division anywhere); they must be non-negative with a\n * positive sum.\n *\n * ```ts\n * allocate('100.00', [1, 1, 1]) // ['33.34', '33.33', '33.33']\n * allocate('0.05', [3, 7]) // ['0.02', '0.03']\n * allocate('-100.00', [1, 1, 1]) // ['-33.34', '-33.33', '-33.33']\n * ```\n */\nexport function allocate(\n amount: number | string,\n weights: ReadonlyArray<number | string>,\n opts: AllocateOptions = {},\n): string[] {\n if (weights.length === 0) {\n throw new MoneyUnsupportedError('allocate: weights must not be empty')\n }\n const scale = resolveScale('allocate', amount, opts.scale)\n const a = parseAmount('allocate', amount, scale)\n\n // Parse every weight as an exact decimal at a common scale, so the\n // proportion arithmetic below is pure BigInt.\n let weightScale = 0\n for (const w of weights) {\n const s = decimalScaleOf(w)\n if (s === null) {\n throw new MoneyUnsupportedError(`allocate: weight ${JSON.stringify(w)} is not a finite decimal`)\n }\n if (s > weightScale) weightScale = s\n }\n const scaledWeights = weights.map(w => {\n const r = parseToScaledInt(w, weightScale)\n if (!r.ok || r.value < 0n) {\n throw new MoneyUnsupportedError(`allocate: weight ${JSON.stringify(w)} must be a non-negative decimal`)\n }\n return r.value\n })\n const sumW = scaledWeights.reduce((acc, w) => acc + w, 0n)\n if (sumW === 0n) {\n throw new MoneyUnsupportedError('allocate: weights must not all be zero')\n }\n\n // Largest-remainder over the MAGNITUDE; a negative amount negates the\n // parts at the end, so Σparts === amount holds for both signs.\n const negative = a < 0n\n const mag = negative ? -a : a\n\n const base: bigint[] = []\n const remainders: Array<{ index: number; rem: bigint }> = []\n let distributed = 0n\n for (let i = 0; i < scaledWeights.length; i++) {\n const product = mag * scaledWeights[i]!\n const share = product / sumW\n base.push(share)\n distributed += share\n remainders.push({ index: i, rem: product % sumW })\n }\n\n // Leftover minor units: strictly fewer than the bucket count.\n let leftover = mag - distributed\n remainders.sort((x, y) => (y.rem > x.rem ? 1 : y.rem < x.rem ? -1 : x.index - y.index))\n for (const { index } of remainders) {\n if (leftover === 0n) break\n base[index] = base[index]! + 1n\n leftover -= 1n\n }\n\n return base.map(p => formatScaledInt(negative && p !== 0n ? -p : p, scale))\n}\n","/**\n * Branded money output type (#338).\n *\n * The decoded read shape of a money field is an exact decimal STRING\n * (`'10000.00'`) — but a hand-written schema types it `string | number`,\n * which is honest about the input side and unhelpful on the output\n * side: every read site hand-coerces, and a missed coercion passes\n * typecheck silently (then surfaces as a runtime template warning, or\n * worse, as `'10000.00' * 100` arithmetic).\n *\n * {@link MoneyString} is the output-side brand: a `string` that has\n * been through noy-db's decode (or {@link asMoney}'s guard). Branding\n * is type-level only — zero runtime cost on the read path.\n *\n * ## Wiring the brand through a validator (the input/output asymmetry)\n *\n * Keep the permissive `string | number` on the INPUT side so write\n * sites are untouched, and brand the OUTPUT side. With Zod:\n *\n * ```ts\n * import type { MoneyString } from '@noy-db/hub'\n *\n * const moneyValue = z.union([z.number(), z.string()]) as unknown as\n * z.ZodType<MoneyString, z.ZodTypeDef, string | number>\n *\n * const Invoice = z.object({ id: z.string(), total: moneyValue })\n * type InvoiceOut = z.output<typeof Invoice> // total: MoneyString\n * type InvoiceIn = z.input<typeof Invoice> // total: string | number\n * ```\n *\n * The cast is sound for fields declared in `moneyFields`: reads pass\n * through `decodeMoneyFields`, which always produces the canonical\n * decimal string.\n */\n\nimport { decimalScaleOf } from './fixed-point.js'\nimport { MoneyUnsupportedError } from './descriptor.js'\n\ndeclare const MONEY_BRAND: unique symbol\n\n/**\n * An exact decimal string produced by noy-db's money decode\n * (`'10000.00'`). The brand exists only at the type level — at runtime\n * a `MoneyString` is a plain string.\n */\nexport type MoneyString = string & { readonly [MONEY_BRAND]: true }\n\n/**\n * Runtime-guarded cast to {@link MoneyString}. Accepts a decimal string\n * or a number, returns the canonical decimal string branded — throws\n * `MoneyUnsupportedError` on anything non-finite / non-decimal. Use at\n * trust boundaries (deserialized JSON, route params); values read\n * through `get()`/`list()` are already canonical.\n */\nexport function asMoney(value: string | number): MoneyString {\n if (!isMoneyLike(value)) {\n throw new MoneyUnsupportedError(`asMoney: ${JSON.stringify(value)} is not a finite decimal`)\n }\n return String(value).trim() as MoneyString\n}\n\n/** Type guard: is `value` a decimal string acceptable as money? */\nexport function isMoneyString(value: unknown): value is MoneyString {\n return typeof value === 'string' && isMoneyLike(value)\n}\n\n/**\n * The ONE sanctioned escape hatch to a JS `number` — explicit because\n * the conversion is lossy past 2^53. For display math and chart axes;\n * never feed the result back into stored amounts (use `mulRate` /\n * `allocate` for exact arithmetic).\n */\nexport function moneyNumber(value: MoneyString | string | number): number {\n if (!isMoneyLike(value)) {\n throw new MoneyUnsupportedError(`moneyNumber: ${JSON.stringify(value)} is not a finite decimal`)\n }\n return Number(value)\n}\n\nfunction isMoneyLike(value: unknown): boolean {\n if (typeof value === 'number') return Number.isFinite(value)\n if (typeof value !== 'string') return false\n return decimalScaleOf(value) !== null\n}\n","/**\n * Vault-level diff orchestrator.\n *\n * Compares a live `Vault`'s plaintext state against a candidate state\n * (another vault, a plain `{ collection: records[] }` map, or a vault\n * dump JSON) and returns a structured `VaultDiff` plan listing the\n * records that would be added, modified, or deleted to bring the live\n * vault into the candidate's shape.\n *\n * Builds on two existing record-level helpers:\n *\n * 1. `diff(a, b)` from `./history/diff.ts` — emits dot-pathed\n * `DiffEntry[]` with `type: 'added' | 'removed' | 'changed'` for\n * each changed field of two records. Used here for the\n * `fieldDiffs` of every `modified` entry, and (with empty result)\n * as the default deep-equal check.\n *\n * 2. `Vault.exportStream()` from `./vault.ts` — the canonical\n * decrypt-and-stream-records iterator. Used to walk both sides\n * when the candidate is itself a `Vault`. ACL-scoped: collections\n * the caller can't read silently drop out, the same way every\n * other plaintext-emitting export pipeline filters them.\n *\n * The new orchestration is the **vault-level** enumeration: bucket\n * each record id into added (only in candidate), deleted (only in\n * vault), or modified (in both with field changes); leave the\n * field-level granularity to the existing `diff()`.\n *\n * Use cases:\n *\n * - Import preview (`@noy-db/as-*` `fromString` returns a plan\n * whose body is a `VaultDiff`).\n * - Backup verification (\"does this `.noydb` bundle from yesterday\n * match the current vault?\").\n * - Two-vault reconciliation (\"what's different between Office A\n * and Office B before we sync?\").\n * - Test assertions (golden-file testing with one-liner\n * `expect(plan.summary).toEqual(...)`).\n *\n * @module\n */\n\nimport type { Vault } from './vault.js'\nimport { diff as fieldDiff, type DiffEntry as FieldDiffEntry } from './history/diff.js'\n\n// ─── Public types ──────────────────────────────────────────────────────\n\n/** Per-record entry shape — added and deleted records carry only the record value. */\nexport interface VaultDiffEntry<T = unknown> {\n readonly collection: string\n readonly id: string\n readonly record: T\n}\n\n/** Modified records carry both halves of the diff plus the field-level breakdown. */\nexport interface VaultDiffModifiedEntry<T = unknown> extends VaultDiffEntry<T> {\n /** The record as it stands in the live vault. */\n readonly before: T\n /** Top-level keys whose values differ between `before` and `record`. */\n readonly fieldsChanged: readonly string[]\n /**\n * Field-level diff entries from `diff(before, record)`. Reuses the\n * existing per-record diff helper so consumers can render git-style\n * `path: from → to` rows without re-walking the records.\n */\n readonly fieldDiffs: readonly FieldDiffEntry[]\n}\n\nexport interface VaultDiff<T = unknown> {\n readonly added: readonly VaultDiffEntry<T>[]\n readonly modified: readonly VaultDiffModifiedEntry<T>[]\n readonly deleted: readonly VaultDiffEntry<T>[]\n /** Only populated when `options.includeUnchanged: true`. */\n readonly unchanged: readonly VaultDiffEntry<T>[] | undefined\n readonly summary: {\n readonly add: number\n readonly modify: number\n readonly delete: number\n readonly total: number\n }\n /**\n * Format the diff as a human-readable string.\n *\n * - `'count'` — one line, just the numbers (`12 added · 3 modified · 0 deleted`)\n * - `'one-line'` — count plus a single overview line\n * - `'full'` — count + one row per added/modified/deleted record (default)\n */\n format(opts?: { detail?: 'count' | 'one-line' | 'full' }): string\n}\n\nexport interface DiffOptions {\n /** Restrict the diff to a subset of collections. */\n readonly collections?: readonly string[]\n /** Field on each record that carries its id. Defaults to `'id'`. */\n readonly idKey?: string\n /** Override the default deep-equal check for \"modified vs unchanged\". */\n readonly compareFn?: (a: unknown, b: unknown) => boolean\n /** If true, include unchanged records in the diff (off by default to save memory). */\n readonly includeUnchanged?: boolean\n}\n\n/**\n * Candidate state to diff the vault against:\n *\n * - A `Vault` instance — both sides are walked via `exportStream()`.\n * - A `Record<collection, records[]>` map — same shape `as-json.toObject()`\n * produces. Useful for diffing parsed file content against the live vault.\n * - A `VaultDump` (output of `vault.dump()`) — a JSON string carrying the\n * full vault state. Parsed and reduced to the map shape above.\n */\nexport type DiffCandidate<T = unknown> =\n | Vault\n | Record<string, readonly T[]>\n | string\n\n// ─── Implementation ────────────────────────────────────────────────────\n\n/**\n * Compute the diff between a live vault and a candidate state.\n *\n * Returns a fully buffered `VaultDiff` — no streaming. Memory cost is\n * O(n + m) in the row count of vault + candidate. For documented\n * 1K-50K-record vaults this is fine; a streaming variant lands as a\n * follow-up if a > 100K-record consumer arrives.\n */\nexport async function diffVault<T = unknown>(\n vault: Vault,\n candidate: DiffCandidate<T>,\n options: DiffOptions = {},\n): Promise<VaultDiff<T>> {\n const idKey = options.idKey ?? 'id'\n const filter = options.collections ? new Set(options.collections) : null\n const compareFn =\n options.compareFn ?? ((a: unknown, b: unknown) => fieldDiff(a, b).length === 0)\n\n // Side A — walk the live vault via exportStream(). Each chunk arrives\n // already decrypted and ACL-scoped, so collections the caller can't\n // read silently drop out. exportStream's records are typed `unknown[]`\n // — diffVault is the type-erasure boundary; the caller asserts the\n // record shape via the function's `<T>` generic.\n const live = new Map<string, Map<string, T>>()\n for await (const chunk of vault.exportStream({ granularity: 'collection' })) {\n if (filter && !filter.has(chunk.collection)) continue\n const collection = live.get(chunk.collection) ?? new Map<string, T>()\n for (const record of chunk.records) {\n const id = readIdField(record, idKey)\n if (!id) continue\n collection.set(id, record as T)\n }\n live.set(chunk.collection, collection)\n }\n\n // Side B — normalise the candidate into the same shape.\n const cand = await normaliseCandidate<T>(candidate, idKey, filter)\n\n // Walk every (collection, id) on either side and bucket.\n const added: VaultDiffEntry<T>[] = []\n const modified: VaultDiffModifiedEntry<T>[] = []\n const deleted: VaultDiffEntry<T>[] = []\n const unchanged: VaultDiffEntry<T>[] | undefined = options.includeUnchanged ? [] : undefined\n\n const collectionNames = new Set([...live.keys(), ...cand.keys()])\n for (const collection of [...collectionNames].sort()) {\n const liveColl = live.get(collection) ?? new Map<string, T>()\n const candColl = cand.get(collection) ?? new Map<string, T>()\n const allIds = new Set([...liveColl.keys(), ...candColl.keys()])\n\n for (const id of [...allIds].sort()) {\n const before = liveColl.get(id)\n const after = candColl.get(id)\n\n if (before === undefined && after !== undefined) {\n added.push({ collection, id, record: after })\n } else if (before !== undefined && after === undefined) {\n deleted.push({ collection, id, record: before })\n } else if (before !== undefined && after !== undefined) {\n if (compareFn(before, after)) {\n unchanged?.push({ collection, id, record: after })\n } else {\n const fieldDiffs = fieldDiff(before, after)\n const fieldsChanged = uniqueTopLevelKeys(fieldDiffs)\n modified.push({\n collection,\n id,\n record: after,\n before,\n fieldsChanged,\n fieldDiffs,\n })\n }\n }\n }\n }\n\n const summary = {\n add: added.length,\n modify: modified.length,\n delete: deleted.length,\n total: added.length + modified.length + deleted.length,\n }\n\n return {\n added,\n modified,\n deleted,\n unchanged,\n summary,\n format(opts) {\n return formatDiff(opts?.detail ?? 'full', { added, modified, deleted, summary })\n },\n }\n}\n\n// ─── Internals ─────────────────────────────────────────────────────────\n\nasync function normaliseCandidate<T>(\n candidate: DiffCandidate<T>,\n idKey: string,\n filter: Set<string> | null,\n): Promise<Map<string, Map<string, T>>> {\n const out = new Map<string, Map<string, T>>()\n\n // Vault instance — duck-type via the exportStream method (matches\n // vault.ts's structural shape without forcing a runtime instanceof check\n // that would import the class and risk circular deps).\n if (\n typeof candidate === 'object' &&\n candidate !== null &&\n 'exportStream' in candidate &&\n typeof (candidate as Vault).exportStream === 'function'\n ) {\n for await (const chunk of (candidate as Vault).exportStream({ granularity: 'collection' })) {\n if (filter && !filter.has(chunk.collection)) continue\n const collection = out.get(chunk.collection) ?? new Map<string, T>()\n for (const record of chunk.records) {\n const id = readIdField(record, idKey)\n if (!id) continue\n collection.set(id, record as T)\n }\n out.set(chunk.collection, collection)\n }\n return out\n }\n\n // String — assume a vault.dump() JSON string. Parse and reduce to the map shape.\n if (typeof candidate === 'string') {\n let parsed: unknown\n try {\n parsed = JSON.parse(candidate)\n } catch (err) {\n throw new Error(\n `diffVault: candidate string is not valid JSON (${(err as Error).message})`,\n )\n }\n return collectionsFromObject<T>(parsed, idKey, filter)\n }\n\n // Plain object — `Record<collection, records[]>` (same shape as-json.toObject() returns).\n return collectionsFromObject<T>(candidate, idKey, filter)\n}\n\nfunction collectionsFromObject<T>(\n raw: unknown,\n idKey: string,\n filter: Set<string> | null,\n): Map<string, Map<string, T>> {\n const out = new Map<string, Map<string, T>>()\n if (raw === null || typeof raw !== 'object') {\n throw new Error('diffVault: candidate must be a Vault, an object, or a JSON string')\n }\n // A vault dump JSON has a top-level shape like { _compartment, _keyring, <coll>: <records[]> }.\n // We accept both: keys starting with `_` are skipped (they're metadata), the rest are collections.\n for (const [key, value] of Object.entries(raw)) {\n if (key.startsWith('_')) continue\n if (filter && !filter.has(key)) continue\n if (!Array.isArray(value)) continue\n const collection = new Map<string, T>()\n for (const record of value as readonly T[]) {\n if (record === null || typeof record !== 'object') continue\n const id = readIdField(record, idKey)\n if (!id) continue\n collection.set(id, record)\n }\n out.set(key, collection)\n }\n return out\n}\n\nfunction uniqueTopLevelKeys(diffs: readonly FieldDiffEntry[]): readonly string[] {\n const keys = new Set<string>()\n for (const d of diffs) {\n // path is dot-separated; the top-level key is everything before the\n // first `.` or `[`. (`a.b.c` → `a`, `tags[0]` → `tags`, `(root)` → `(root)`).\n const m = /^[^.[]+/.exec(d.path)\n if (m) keys.add(m[0])\n }\n return [...keys]\n}\n\n/**\n * Pull the id field off a record without going through `String(obj)`,\n * which would emit `[object Object]` for nested objects and silently\n * collapse rows that share the same parent. Only string and number ids\n * are accepted; anything else returns the empty string and the record\n * is skipped at the call site.\n */\nfunction readIdField(record: unknown, idKey: string): string {\n if (record === null || typeof record !== 'object') return ''\n const v = (record as Record<string, unknown>)[idKey]\n if (typeof v === 'string') return v\n if (typeof v === 'number' && Number.isFinite(v)) return String(v)\n return ''\n}\n\ninterface FormatBuckets<T> {\n readonly added: readonly VaultDiffEntry<T>[]\n readonly modified: readonly VaultDiffModifiedEntry<T>[]\n readonly deleted: readonly VaultDiffEntry<T>[]\n readonly summary: VaultDiff<T>['summary']\n}\n\nfunction formatDiff<T>(\n detail: 'count' | 'one-line' | 'full',\n b: FormatBuckets<T>,\n): string {\n const head = `${b.summary.add} added · ${b.summary.modify} modified · ${b.summary.delete} deleted`\n if (detail === 'count') return head\n if (b.summary.total === 0) return head + '\\n(no changes)'\n if (detail === 'one-line') return head\n\n const rows: string[] = [head, '']\n for (const e of b.added) rows.push(`${e.collection}/${e.id}\\tadded`)\n for (const e of b.modified) {\n const fields = e.fieldDiffs\n .map((f) => `${f.path}: ${shortJSON(f.from)} → ${shortJSON(f.to)}`)\n .join(', ')\n rows.push(`${e.collection}/${e.id}\\tmodified\\t${fields}`)\n }\n for (const e of b.deleted) rows.push(`${e.collection}/${e.id}\\tdeleted`)\n return rows.join('\\n')\n}\n\nfunction shortJSON(value: unknown): string {\n if (value === undefined) return 'undefined'\n const s = JSON.stringify(value)\n // JSON.stringify returns string for any JSON value except `undefined`\n // (handled above), `function`, and `symbol`. Fall back to a static\n // tag for those — never let an arbitrary object hit the default\n // stringifier (which the lint rule explicitly bans).\n if (typeof s !== 'string') return '<unrepresentable>'\n return s.length > 60 ? s.slice(0, 57) + '...' : s\n}\n"],"mappings":"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","names":["formatDiff"]}
1
+ {"version":3,"sources":["../src/debug.ts","../src/schema-update/strategies.ts","../src/schema-update/cutover.ts","../src/numbering/descriptor.ts","../src/constants.ts","../src/money/arith.ts","../src/money/branded.ts","../src/vault-diff.ts"],"sourcesContent":["/**\n * Helpers for reading records out of a *plaintext* store (`encrypt: false`)\n * with native tooling — the programmatic core of a `noydb cat`-style unwrap.\n * See the plaintext/debug-store-mode design.\n */\nimport type { EncryptedEnvelope } from './types.js'\n\n/**\n * Extract the record from a plaintext stored envelope, handling both layouts:\n *\n * - **classic plaintext** (`encrypt: false`): the record is JSON in `_data`.\n * - **debugPlaintext**: the record's fields are inlined beside the\n * `_`-prefixed metadata (marked by `_debug`).\n *\n * Returns `null` for an empty/absent body. Throws if handed an **encrypted**\n * envelope (non-empty `_iv`) — there is no key here; decrypt through the vault\n * instead. Intended for record envelopes, not blob chunks.\n *\n * @example\n * ```ts\n * // node script over a to-file store, no vault needed:\n * const env = JSON.parse(readFileSync('data/acme/invoices/inv-1.json', 'utf8'))\n * console.log(readPlaintextRecord(env)) // → { id: 'inv-1', total: '120.00', … }\n * ```\n */\nexport function readPlaintextRecord<T = Record<string, unknown>>(\n envelope: EncryptedEnvelope,\n): T | null {\n if (envelope._iv !== '') {\n throw new Error(\n 'readPlaintextRecord: envelope is encrypted (non-empty _iv) — decrypt via the vault, not this helper',\n )\n }\n if (envelope._debug !== undefined) {\n const record: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(envelope)) {\n if (!key.startsWith('_')) record[key] = value\n }\n return record as T\n }\n if (!envelope._data) return null\n return JSON.parse(envelope._data) as T\n}\n","/** Bundled light update strategies. */\nimport { NonAdditiveSchemaChangeError, SchemaLockedError } from '../errors.js'\nimport type { SchemaUpdateStrategy, SchemaDelta } from './types.js'\n\n/** Allow any schema change. Explicit blind / back-compat. */\nexport function blindUpdate(): SchemaUpdateStrategy {\n return { name: 'blindUpdate', onSchemaDelta: () => ({ action: 'allow' }) }\n}\n\n/** Allow additive changes; reject non-additive ones. The safety backstop. */\nexport function additiveOnly(): SchemaUpdateStrategy {\n return {\n name: 'additiveOnly',\n onSchemaDelta(delta: SchemaDelta) {\n if (delta.kind === 'non-additive') {\n return {\n action: 'reject' as const,\n error: new NonAdditiveSchemaChangeError(\n `Non-additive schema change to \"${delta.collection}\" ` +\n `(added: [${delta.added.join(', ')}], removed: [${delta.removed.join(', ')}], ` +\n `changed: [${delta.changed.map(c => c.field).join(', ')}]). ` +\n `Register a coordinatedCutover() strategy to migrate, or revert the change.`,\n ),\n }\n }\n return { action: 'allow' as const }\n },\n }\n}\n\n/**\n * Reject schema changes. With `fields`, reject only when one of those\n * fields is added/removed/changed; otherwise reject any non-`none` delta.\n */\nexport function lockSchema(opts?: { readonly fields?: readonly string[] }): SchemaUpdateStrategy {\n const fields = opts?.fields\n return {\n name: 'lockSchema',\n onSchemaDelta(delta: SchemaDelta) {\n if (delta.kind === 'none') return { action: 'allow' as const }\n const touched = fields\n ? [...delta.added, ...delta.removed, ...delta.changed.map(c => c.field)].filter(f => fields.includes(f))\n : ['<any>']\n if (touched.length === 0) return { action: 'allow' as const }\n return {\n action: 'reject' as const,\n error: new SchemaLockedError(\n `Schema for \"${delta.collection}\" is locked` +\n (fields ? ` on fields [${fields.join(', ')}] (touched: [${touched.join(', ')}])` : '') +\n `; the change was refused.`,\n ),\n }\n },\n }\n}\n","/** The coordinatedCutover update strategy (single-step — no from/to). */\nimport type { SchemaUpdateStrategy, SchemaDelta, TransformFn } from './types.js'\n\nexport function coordinatedCutover(opts: { readonly transform: TransformFn }): SchemaUpdateStrategy {\n return {\n name: 'coordinatedCutover',\n onSchemaDelta(delta: SchemaDelta) {\n if (delta.kind === 'non-additive') {\n return { action: 'cutover' as const, transform: opts.transform }\n }\n return { action: 'allow' as const }\n },\n }\n}\n","/**\n * @category capability\n * Deferred-numbering config descriptor. See\n * docs/superpowers/specs/2026-06-08-sealed-numbering-and-store-clock-design.md.\n */\n\n/** A registered deferred-numbering series. */\nexport interface DeferredNumberingConfig {\n /** Series name — the key passed to `vault.sequence(series)`. */\n readonly series: string\n /** Collection holding the records to number. */\n readonly collection: string\n /** Field on each record where the assigned serial is written. */\n readonly field: string\n /**\n * Minimum wall-clock age (ms) before an entry is eligible at a pass, in\n * addition to the interval commit-wait. Default 0 — the store-clock\n * interval (`storeLatest ≤ now.earliest`) is the correctness mechanism.\n */\n readonly settleWindowMs: number\n}\n\n/** Declare a deferred-numbering series. Pass the result in `createNoydb({ numbering: [...] })`. */\nexport function withDeferredNumbering(config: {\n series: string\n collection: string\n field: string\n settleWindowMs?: number\n}): DeferredNumberingConfig {\n return {\n series: config.series,\n collection: config.collection,\n field: config.field,\n settleWindowMs: config.settleWindowMs ?? 0,\n }\n}\n","/**\n * Hub-core constants that must be referenceable without pulling any\n * subsystem chunk. Kept import-free.\n */\n\n/** Reserved fleet-wide control-plane vault name. Hub reserves it for an outward orchestration framework's state/control-plane vault. */\nexport const STATE_VAULT_NAME = '__noydb_state__'\n","/**\n * Exact money arithmetic helpers (#337) — `mulRate` and `allocate`.\n *\n * Both operate on the canonical decoded string form that `get()`\n * returns (`'10000.00'`), entirely in scaled-`BigInt` space — no\n * floating-point step anywhere, exact past 2^53. They are pure\n * functions with no vault or descriptor dependency: the working scale\n * is inferred from the amount's fractional digits (a canonical money\n * string always carries exactly the field's scale) or pinned with\n * `opts.scale`.\n *\n * Why these two: app-side invariants of the form\n * `Σ parts === whole` (receipt totals, net-zero WHT pairs, proration)\n * carry ±0.01 tolerances ONLY because the math is major-unit floats +\n * round2. `mulRate` (VAT-style rate application with explicit\n * rounding) and `allocate` (largest-remainder split — parts sum to the\n * input EXACTLY, by construction) make those tolerances zero.\n */\n\nimport {\n parseToScaledInt,\n formatScaledInt,\n rescaleScaledInt,\n decimalScaleOf,\n type RoundingMode,\n} from './fixed-point.js'\nimport { MoneyUnsupportedError } from './descriptor.js'\n\nexport interface MulRateOptions {\n /**\n * Output scale (fraction digits). Defaults to the amount's own\n * fractional digits — for a canonical money string that IS the\n * field's scale.\n */\n readonly scale?: number\n /** Rounding for the final re-scale. Default `'half-up'`. */\n readonly rounding?: RoundingMode\n}\n\nexport interface AllocateOptions {\n /** Working scale. Defaults to the amount's own fractional digits. */\n readonly scale?: number\n}\n\n/** Parse `amount` at `scale` or throw the standard money TypeError. */\nfunction parseAmount(label: string, amount: number | string, scale: number, rounding?: RoundingMode): bigint {\n const r = parseToScaledInt(amount, scale, rounding)\n if (!r.ok) {\n throw new MoneyUnsupportedError(\n r.reason === 'precision'\n ? `${label}: amount ${JSON.stringify(amount)} has more precision than scale ${scale} and no rounding mode is configured`\n : `${label}: amount ${JSON.stringify(amount)} is not a finite decimal`,\n )\n }\n return r.value\n}\n\nfunction resolveScale(label: string, amount: number | string, explicit: number | undefined): number {\n if (explicit !== undefined) {\n if (!Number.isInteger(explicit) || explicit < 0) {\n throw new MoneyUnsupportedError(`${label}: scale must be a non-negative integer`)\n }\n return explicit\n }\n const inferred = decimalScaleOf(amount)\n if (inferred === null) {\n throw new MoneyUnsupportedError(`${label}: amount ${JSON.stringify(amount)} is not a finite decimal`)\n }\n return inferred\n}\n\n/**\n * Multiply a money amount by a decimal rate, exactly.\n *\n * The rate is parsed at its OWN full precision (`0.07` → `7` at scale\n * 2), the product computed in `BigInt` at `amountScale + rateScale`,\n * then re-scaled back to the output scale with the requested rounding —\n * one rounding step, at the very end.\n *\n * ```ts\n * mulRate('10000.00', 0.07) // '700.00' (VAT)\n * mulRate('33.33', '0.07') // '2.33' (half-up)\n * mulRate('33.33', 0.07, { rounding: 'floor' }) // '2.33'\n * mulRate(100, 0.07, { scale: 2 }) // '7.00'\n * ```\n */\nexport function mulRate(\n amount: number | string,\n rate: number | string,\n opts: MulRateOptions = {},\n): string {\n const scale = resolveScale('mulRate', amount, opts.scale)\n const rounding = opts.rounding ?? 'half-up'\n const a = parseAmount('mulRate', amount, scale, rounding)\n\n const rateScale = decimalScaleOf(rate)\n if (rateScale === null) {\n throw new MoneyUnsupportedError(`mulRate: rate ${JSON.stringify(rate)} is not a finite decimal`)\n }\n const r = parseToScaledInt(rate, rateScale)\n if (!r.ok) {\n throw new MoneyUnsupportedError(`mulRate: rate ${JSON.stringify(rate)} is not a finite decimal`)\n }\n\n const product = a * r.value // scaled at scale + rateScale\n return formatScaledInt(rescaleScaledInt(product, scale + rateScale, scale, rounding), scale)\n}\n\n/**\n * Split a money amount across weighted buckets with ZERO drift: the\n * returned parts sum to the input exactly, by construction\n * (largest-remainder method).\n *\n * Each bucket gets `floor(amount × weightᵢ / Σweights)`; the leftover\n * minor units (always fewer than the bucket count) go one each to the\n * buckets with the largest truncated remainders — ties broken by\n * position, earlier bucket first. Weights are parsed as exact decimals\n * (no float division anywhere); they must be non-negative with a\n * positive sum.\n *\n * ```ts\n * allocate('100.00', [1, 1, 1]) // ['33.34', '33.33', '33.33']\n * allocate('0.05', [3, 7]) // ['0.02', '0.03']\n * allocate('-100.00', [1, 1, 1]) // ['-33.34', '-33.33', '-33.33']\n * ```\n */\nexport function allocate(\n amount: number | string,\n weights: ReadonlyArray<number | string>,\n opts: AllocateOptions = {},\n): string[] {\n if (weights.length === 0) {\n throw new MoneyUnsupportedError('allocate: weights must not be empty')\n }\n const scale = resolveScale('allocate', amount, opts.scale)\n const a = parseAmount('allocate', amount, scale)\n\n // Parse every weight as an exact decimal at a common scale, so the\n // proportion arithmetic below is pure BigInt.\n let weightScale = 0\n for (const w of weights) {\n const s = decimalScaleOf(w)\n if (s === null) {\n throw new MoneyUnsupportedError(`allocate: weight ${JSON.stringify(w)} is not a finite decimal`)\n }\n if (s > weightScale) weightScale = s\n }\n const scaledWeights = weights.map(w => {\n const r = parseToScaledInt(w, weightScale)\n if (!r.ok || r.value < 0n) {\n throw new MoneyUnsupportedError(`allocate: weight ${JSON.stringify(w)} must be a non-negative decimal`)\n }\n return r.value\n })\n const sumW = scaledWeights.reduce((acc, w) => acc + w, 0n)\n if (sumW === 0n) {\n throw new MoneyUnsupportedError('allocate: weights must not all be zero')\n }\n\n // Largest-remainder over the MAGNITUDE; a negative amount negates the\n // parts at the end, so Σparts === amount holds for both signs.\n const negative = a < 0n\n const mag = negative ? -a : a\n\n const base: bigint[] = []\n const remainders: Array<{ index: number; rem: bigint }> = []\n let distributed = 0n\n for (let i = 0; i < scaledWeights.length; i++) {\n const product = mag * scaledWeights[i]!\n const share = product / sumW\n base.push(share)\n distributed += share\n remainders.push({ index: i, rem: product % sumW })\n }\n\n // Leftover minor units: strictly fewer than the bucket count.\n let leftover = mag - distributed\n remainders.sort((x, y) => (y.rem > x.rem ? 1 : y.rem < x.rem ? -1 : x.index - y.index))\n for (const { index } of remainders) {\n if (leftover === 0n) break\n base[index] = base[index]! + 1n\n leftover -= 1n\n }\n\n return base.map(p => formatScaledInt(negative && p !== 0n ? -p : p, scale))\n}\n","/**\n * Branded money output type (#338).\n *\n * The decoded read shape of a money field is an exact decimal STRING\n * (`'10000.00'`) — but a hand-written schema types it `string | number`,\n * which is honest about the input side and unhelpful on the output\n * side: every read site hand-coerces, and a missed coercion passes\n * typecheck silently (then surfaces as a runtime template warning, or\n * worse, as `'10000.00' * 100` arithmetic).\n *\n * {@link MoneyString} is the output-side brand: a `string` that has\n * been through noy-db's decode (or {@link asMoney}'s guard). Branding\n * is type-level only — zero runtime cost on the read path.\n *\n * ## Wiring the brand through a validator (the input/output asymmetry)\n *\n * Keep the permissive `string | number` on the INPUT side so write\n * sites are untouched, and brand the OUTPUT side. With Zod:\n *\n * ```ts\n * import type { MoneyString } from '@noy-db/hub'\n *\n * const moneyValue = z.union([z.number(), z.string()]) as unknown as\n * z.ZodType<MoneyString, z.ZodTypeDef, string | number>\n *\n * const Invoice = z.object({ id: z.string(), total: moneyValue })\n * type InvoiceOut = z.output<typeof Invoice> // total: MoneyString\n * type InvoiceIn = z.input<typeof Invoice> // total: string | number\n * ```\n *\n * The cast is sound for fields declared in `moneyFields`: reads pass\n * through `decodeMoneyFields`, which always produces the canonical\n * decimal string.\n */\n\nimport { decimalScaleOf } from './fixed-point.js'\nimport { MoneyUnsupportedError } from './descriptor.js'\n\ndeclare const MONEY_BRAND: unique symbol\n\n/**\n * An exact decimal string produced by noy-db's money decode\n * (`'10000.00'`). The brand exists only at the type level — at runtime\n * a `MoneyString` is a plain string.\n */\nexport type MoneyString = string & { readonly [MONEY_BRAND]: true }\n\n/**\n * Runtime-guarded cast to {@link MoneyString}. Accepts a decimal string\n * or a number, returns the canonical decimal string branded — throws\n * `MoneyUnsupportedError` on anything non-finite / non-decimal. Use at\n * trust boundaries (deserialized JSON, route params); values read\n * through `get()`/`list()` are already canonical.\n */\nexport function asMoney(value: string | number): MoneyString {\n if (!isMoneyLike(value)) {\n throw new MoneyUnsupportedError(`asMoney: ${JSON.stringify(value)} is not a finite decimal`)\n }\n return String(value).trim() as MoneyString\n}\n\n/** Type guard: is `value` a decimal string acceptable as money? */\nexport function isMoneyString(value: unknown): value is MoneyString {\n return typeof value === 'string' && isMoneyLike(value)\n}\n\n/**\n * The ONE sanctioned escape hatch to a JS `number` — explicit because\n * the conversion is lossy past 2^53. For display math and chart axes;\n * never feed the result back into stored amounts (use `mulRate` /\n * `allocate` for exact arithmetic).\n */\nexport function moneyNumber(value: MoneyString | string | number): number {\n if (!isMoneyLike(value)) {\n throw new MoneyUnsupportedError(`moneyNumber: ${JSON.stringify(value)} is not a finite decimal`)\n }\n return Number(value)\n}\n\nfunction isMoneyLike(value: unknown): boolean {\n if (typeof value === 'number') return Number.isFinite(value)\n if (typeof value !== 'string') return false\n return decimalScaleOf(value) !== null\n}\n","/**\n * Vault-level diff orchestrator.\n *\n * Compares a live `Vault`'s plaintext state against a candidate state\n * (another vault, a plain `{ collection: records[] }` map, or a vault\n * dump JSON) and returns a structured `VaultDiff` plan listing the\n * records that would be added, modified, or deleted to bring the live\n * vault into the candidate's shape.\n *\n * Builds on two existing record-level helpers:\n *\n * 1. `diff(a, b)` from `./history/diff.ts` — emits dot-pathed\n * `DiffEntry[]` with `type: 'added' | 'removed' | 'changed'` for\n * each changed field of two records. Used here for the\n * `fieldDiffs` of every `modified` entry, and (with empty result)\n * as the default deep-equal check.\n *\n * 2. `Vault.exportStream()` from `./vault.ts` — the canonical\n * decrypt-and-stream-records iterator. Used to walk both sides\n * when the candidate is itself a `Vault`. ACL-scoped: collections\n * the caller can't read silently drop out, the same way every\n * other plaintext-emitting export pipeline filters them.\n *\n * The new orchestration is the **vault-level** enumeration: bucket\n * each record id into added (only in candidate), deleted (only in\n * vault), or modified (in both with field changes); leave the\n * field-level granularity to the existing `diff()`.\n *\n * Use cases:\n *\n * - Import preview (`@noy-db/as-*` `fromString` returns a plan\n * whose body is a `VaultDiff`).\n * - Backup verification (\"does this `.noydb` bundle from yesterday\n * match the current vault?\").\n * - Two-vault reconciliation (\"what's different between Office A\n * and Office B before we sync?\").\n * - Test assertions (golden-file testing with one-liner\n * `expect(plan.summary).toEqual(...)`).\n *\n * @module\n */\n\nimport type { Vault } from './vault.js'\nimport { diff as fieldDiff, type DiffEntry as FieldDiffEntry } from './history/diff.js'\n\n// ─── Public types ──────────────────────────────────────────────────────\n\n/** Per-record entry shape — added and deleted records carry only the record value. */\nexport interface VaultDiffEntry<T = unknown> {\n readonly collection: string\n readonly id: string\n readonly record: T\n /**\n * Unencrypted envelope metadata for the RECEIVER-side record.\n * Populated only when `diffVault` is called with `{includeMetadata: true}`.\n * Default: `undefined` (zero extra reads, no behavior change).\n *\n * Populated for `modified` (the CURRENT receiver state, before the candidate\n * is applied) and `deleted` (the receiver envelope of the record being\n * removed). `added` entries have no receiver envelope at diff time, so their\n * `metadata` is always absent.\n */\n readonly metadata?: {\n readonly version: number\n readonly timestamp: string\n readonly by?: string\n readonly source?: string\n readonly sourceTs?: string\n }\n}\n\n/** Modified records carry both halves of the diff plus the field-level breakdown. */\nexport interface VaultDiffModifiedEntry<T = unknown> extends VaultDiffEntry<T> {\n /** The record as it stands in the live vault. */\n readonly before: T\n /** Top-level keys whose values differ between `before` and `record`. */\n readonly fieldsChanged: readonly string[]\n /**\n * Field-level diff entries from `diff(before, record)`. Reuses the\n * existing per-record diff helper so consumers can render git-style\n * `path: from → to` rows without re-walking the records.\n */\n readonly fieldDiffs: readonly FieldDiffEntry[]\n}\n\nexport interface VaultDiff<T = unknown> {\n readonly added: readonly VaultDiffEntry<T>[]\n readonly modified: readonly VaultDiffModifiedEntry<T>[]\n readonly deleted: readonly VaultDiffEntry<T>[]\n /** Only populated when `options.includeUnchanged: true`. */\n readonly unchanged: readonly VaultDiffEntry<T>[] | undefined\n readonly summary: {\n readonly add: number\n readonly modify: number\n readonly delete: number\n readonly total: number\n }\n /**\n * Format the diff as a human-readable string.\n *\n * - `'count'` — one line, just the numbers (`12 added · 3 modified · 0 deleted`)\n * - `'one-line'` — count plus a single overview line\n * - `'full'` — count + one row per added/modified/deleted record (default)\n */\n format(opts?: { detail?: 'count' | 'one-line' | 'full' }): string\n}\n\nexport interface DiffOptions {\n /** Restrict the diff to a subset of collections. */\n readonly collections?: readonly string[]\n /** Field on each record that carries its id. Defaults to `'id'`. */\n readonly idKey?: string\n /** Override the default deep-equal check for \"modified vs unchanged\". */\n readonly compareFn?: (a: unknown, b: unknown) => boolean\n /** If true, include unchanged records in the diff (off by default to save memory). */\n readonly includeUnchanged?: boolean\n /**\n * When `true`, each entry in `added`, `modified`, and `deleted` will carry a\n * `metadata` field with the RECEIVER-side envelope metadata\n * (`version`, `timestamp`, `by?`, `source?`, `sourceTs?`).\n *\n * Off by default — no extra adapter reads, no behavior change for existing callers.\n * (FR-5 read surface, #445)\n */\n readonly includeMetadata?: boolean\n}\n\n/**\n * Candidate state to diff the vault against:\n *\n * - A `Vault` instance — both sides are walked via `exportStream()`.\n * - A `Record<collection, records[]>` map — same shape `as-json.toObject()`\n * produces. Useful for diffing parsed file content against the live vault.\n * - A `VaultDump` (output of `vault.dump()`) — a JSON string carrying the\n * full vault state. Parsed and reduced to the map shape above.\n */\nexport type DiffCandidate<T = unknown> =\n | Vault\n | Record<string, readonly T[]>\n | string\n\n// ─── Implementation ────────────────────────────────────────────────────\n\n/**\n * Compute the diff between a live vault and a candidate state.\n *\n * Returns a fully buffered `VaultDiff` — no streaming. Memory cost is\n * O(n + m) in the row count of vault + candidate. For documented\n * 1K-50K-record vaults this is fine; a streaming variant lands as a\n * follow-up if a > 100K-record consumer arrives.\n */\nexport async function diffVault<T = unknown>(\n vault: Vault,\n candidate: DiffCandidate<T>,\n options: DiffOptions = {},\n): Promise<VaultDiff<T>> {\n const idKey = options.idKey ?? 'id'\n const filter = options.collections ? new Set(options.collections) : null\n const compareFn =\n options.compareFn ?? ((a: unknown, b: unknown) => fieldDiff(a, b).length === 0)\n\n // Side A — walk the live vault via exportStream(). Each chunk arrives\n // already decrypted and ACL-scoped, so collections the caller can't\n // read silently drop out. exportStream's records are typed `unknown[]`\n // — diffVault is the type-erasure boundary; the caller asserts the\n // record shape via the function's `<T>` generic.\n const live = new Map<string, Map<string, T>>()\n for await (const chunk of vault.exportStream({ granularity: 'collection' })) {\n if (filter && !filter.has(chunk.collection)) continue\n const collection = live.get(chunk.collection) ?? new Map<string, T>()\n for (const record of chunk.records) {\n const id = readIdField(record, idKey)\n if (!id) continue\n collection.set(id, record as T)\n }\n live.set(chunk.collection, collection)\n }\n\n // Side B — normalise the candidate into the same shape.\n const cand = await normaliseCandidate<T>(candidate, idKey, filter)\n\n // Walk every (collection, id) on either side and bucket.\n const added: VaultDiffEntry<T>[] = []\n const modified: VaultDiffModifiedEntry<T>[] = []\n const deleted: VaultDiffEntry<T>[] = []\n const unchanged: VaultDiffEntry<T>[] | undefined = options.includeUnchanged ? [] : undefined\n\n const collectionNames = new Set([...live.keys(), ...cand.keys()])\n for (const collection of [...collectionNames].sort()) {\n const liveColl = live.get(collection) ?? new Map<string, T>()\n const candColl = cand.get(collection) ?? new Map<string, T>()\n const allIds = new Set([...liveColl.keys(), ...candColl.keys()])\n\n for (const id of [...allIds].sort()) {\n const before = liveColl.get(id)\n const after = candColl.get(id)\n\n if (before === undefined && after !== undefined) {\n // added: record only in candidate — no receiver envelope\n added.push({ collection, id, record: after })\n } else if (before !== undefined && after === undefined) {\n // deleted: record only in receiver — attach metadata if requested\n const metadata = options.includeMetadata\n ? (await vault.collection(collection).getMetadata(id)) ?? undefined\n : undefined\n deleted.push({ collection, id, record: before, ...(metadata !== undefined ? { metadata } : {}) })\n } else if (before !== undefined && after !== undefined) {\n if (compareFn(before, after)) {\n unchanged?.push({ collection, id, record: after })\n } else {\n // modified: record in both — attach receiver-side metadata if requested\n const metadata = options.includeMetadata\n ? (await vault.collection(collection).getMetadata(id)) ?? undefined\n : undefined\n const fieldDiffs = fieldDiff(before, after)\n const fieldsChanged = uniqueTopLevelKeys(fieldDiffs)\n modified.push({\n collection,\n id,\n record: after,\n before,\n fieldsChanged,\n fieldDiffs,\n ...(metadata !== undefined ? { metadata } : {}),\n })\n }\n }\n }\n }\n\n const summary = {\n add: added.length,\n modify: modified.length,\n delete: deleted.length,\n total: added.length + modified.length + deleted.length,\n }\n\n return {\n added,\n modified,\n deleted,\n unchanged,\n summary,\n format(opts) {\n return formatDiff(opts?.detail ?? 'full', { added, modified, deleted, summary })\n },\n }\n}\n\n// ─── Internals ─────────────────────────────────────────────────────────\n\nasync function normaliseCandidate<T>(\n candidate: DiffCandidate<T>,\n idKey: string,\n filter: Set<string> | null,\n): Promise<Map<string, Map<string, T>>> {\n const out = new Map<string, Map<string, T>>()\n\n // Vault instance — duck-type via the exportStream method (matches\n // vault.ts's structural shape without forcing a runtime instanceof check\n // that would import the class and risk circular deps).\n if (\n typeof candidate === 'object' &&\n candidate !== null &&\n 'exportStream' in candidate &&\n typeof (candidate as Vault).exportStream === 'function'\n ) {\n for await (const chunk of (candidate as Vault).exportStream({ granularity: 'collection' })) {\n if (filter && !filter.has(chunk.collection)) continue\n const collection = out.get(chunk.collection) ?? new Map<string, T>()\n for (const record of chunk.records) {\n const id = readIdField(record, idKey)\n if (!id) continue\n collection.set(id, record as T)\n }\n out.set(chunk.collection, collection)\n }\n return out\n }\n\n // String — assume a vault.dump() JSON string. Parse and reduce to the map shape.\n if (typeof candidate === 'string') {\n let parsed: unknown\n try {\n parsed = JSON.parse(candidate)\n } catch (err) {\n throw new Error(\n `diffVault: candidate string is not valid JSON (${(err as Error).message})`,\n )\n }\n return collectionsFromObject<T>(parsed, idKey, filter)\n }\n\n // Plain object — `Record<collection, records[]>` (same shape as-json.toObject() returns).\n return collectionsFromObject<T>(candidate, idKey, filter)\n}\n\nfunction collectionsFromObject<T>(\n raw: unknown,\n idKey: string,\n filter: Set<string> | null,\n): Map<string, Map<string, T>> {\n const out = new Map<string, Map<string, T>>()\n if (raw === null || typeof raw !== 'object') {\n throw new Error('diffVault: candidate must be a Vault, an object, or a JSON string')\n }\n // A vault dump JSON has a top-level shape like { _compartment, _keyring, <coll>: <records[]> }.\n // We accept both: keys starting with `_` are skipped (they're metadata), the rest are collections.\n for (const [key, value] of Object.entries(raw)) {\n if (key.startsWith('_')) continue\n if (filter && !filter.has(key)) continue\n if (!Array.isArray(value)) continue\n const collection = new Map<string, T>()\n for (const record of value as readonly T[]) {\n if (record === null || typeof record !== 'object') continue\n const id = readIdField(record, idKey)\n if (!id) continue\n collection.set(id, record)\n }\n out.set(key, collection)\n }\n return out\n}\n\nfunction uniqueTopLevelKeys(diffs: readonly FieldDiffEntry[]): readonly string[] {\n const keys = new Set<string>()\n for (const d of diffs) {\n // path is dot-separated; the top-level key is everything before the\n // first `.` or `[`. (`a.b.c` → `a`, `tags[0]` → `tags`, `(root)` → `(root)`).\n const m = /^[^.[]+/.exec(d.path)\n if (m) keys.add(m[0])\n }\n return [...keys]\n}\n\n/**\n * Pull the id field off a record without going through `String(obj)`,\n * which would emit `[object Object]` for nested objects and silently\n * collapse rows that share the same parent. Only string and number ids\n * are accepted; anything else returns the empty string and the record\n * is skipped at the call site.\n */\nfunction readIdField(record: unknown, idKey: string): string {\n if (record === null || typeof record !== 'object') return ''\n const v = (record as Record<string, unknown>)[idKey]\n if (typeof v === 'string') return v\n if (typeof v === 'number' && Number.isFinite(v)) return String(v)\n return ''\n}\n\ninterface FormatBuckets<T> {\n readonly added: readonly VaultDiffEntry<T>[]\n readonly modified: readonly VaultDiffModifiedEntry<T>[]\n readonly deleted: readonly VaultDiffEntry<T>[]\n readonly summary: VaultDiff<T>['summary']\n}\n\nfunction formatDiff<T>(\n detail: 'count' | 'one-line' | 'full',\n b: FormatBuckets<T>,\n): string {\n const head = `${b.summary.add} added · ${b.summary.modify} modified · ${b.summary.delete} deleted`\n if (detail === 'count') return head\n if (b.summary.total === 0) return head + '\\n(no changes)'\n if (detail === 'one-line') return head\n\n const rows: string[] = [head, '']\n for (const e of b.added) rows.push(`${e.collection}/${e.id}\\tadded`)\n for (const e of b.modified) {\n const fields = e.fieldDiffs\n .map((f) => `${f.path}: ${shortJSON(f.from)} → ${shortJSON(f.to)}`)\n .join(', ')\n rows.push(`${e.collection}/${e.id}\\tmodified\\t${fields}`)\n }\n for (const e of b.deleted) rows.push(`${e.collection}/${e.id}\\tdeleted`)\n return rows.join('\\n')\n}\n\nfunction shortJSON(value: unknown): string {\n if (value === undefined) return 'undefined'\n const s = JSON.stringify(value)\n // JSON.stringify returns string for any JSON value except `undefined`\n // (handled above), `function`, and `symbol`. Fall back to a static\n // tag for those — never let an arbitrary object hit the default\n // stringifier (which the lint rule explicitly bans).\n if (typeof s !== 'string') return '<unrepresentable>'\n return s.length > 60 ? s.slice(0, 57) + '...' : s\n}\n"],"mappings":"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","names":["formatDiff"]}