@noy-db/hub 0.7.0-pre.9 → 0.7.0

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 (441) hide show
  1. package/CHANGELOG.md +1319 -0
  2. package/README.md +7 -6
  3. package/dist/api-TXFOVOXX.js +19 -0
  4. package/dist/as/index.js +14 -14
  5. package/dist/at/index.js +9 -10
  6. package/dist/attestation/index.js +18 -19
  7. package/dist/attestation/index.js.map +1 -1
  8. package/dist/{backup-QZQEP5RO.js → backup-IJTB4S4M.js} +14 -15
  9. package/dist/{backup-QZQEP5RO.js.map → backup-IJTB4S4M.js.map} +1 -1
  10. package/dist/blobs/index.js +13 -14
  11. package/dist/blobs/index.js.map +1 -1
  12. package/dist/broker/index.js +12 -13
  13. package/dist/broker/index.js.map +1 -1
  14. package/dist/by/index.js +2 -3
  15. package/dist/cargo/index.js +33 -34
  16. package/dist/{chunk-5UKIZIO3.js → chunk-2577DKXB.js} +2 -2
  17. package/dist/chunk-2C3AQB46.js +1652 -0
  18. package/dist/chunk-2C3AQB46.js.map +1 -0
  19. package/dist/{chunk-LUVGSKXE.js → chunk-2N4GY74U.js} +6 -6
  20. package/dist/{chunk-I5LSKXT6.js → chunk-2Y4IMKA6.js} +4 -4
  21. package/dist/{chunk-7XT7KZTN.js → chunk-3RCJJBNR.js} +10 -10
  22. package/dist/{chunk-GM4IM7TC.js → chunk-453F654R.js} +2 -2
  23. package/dist/{chunk-JUBWUJY5.js → chunk-4GVM6QZA.js} +2 -2
  24. package/dist/{chunk-2DGBRE4K.js → chunk-4OZNXTO4.js} +2 -2
  25. package/dist/{chunk-P2RJAVMR.js → chunk-5VCRVKOZ.js} +4 -4
  26. package/dist/{chunk-RCONOOVF.js → chunk-5WDXHNSW.js} +5 -5
  27. package/dist/chunk-66TQOPFM.js +37 -0
  28. package/dist/chunk-66TQOPFM.js.map +1 -0
  29. package/dist/{chunk-Q2OAAREU.js → chunk-6GMZ7HEE.js} +6 -6
  30. package/dist/{chunk-6L5IMNJX.js → chunk-6GOE5PGN.js} +168 -1328
  31. package/dist/chunk-6GOE5PGN.js.map +1 -0
  32. package/dist/{chunk-TQGT5BZE.js → chunk-6I2RQCET.js} +4 -4
  33. package/dist/{chunk-UL7TLJ54.js → chunk-6X6SEMEE.js} +6 -4
  34. package/dist/{chunk-UL7TLJ54.js.map → chunk-6X6SEMEE.js.map} +1 -1
  35. package/dist/{chunk-P7KJME6C.js → chunk-6YXCPL4T.js} +2 -2
  36. package/dist/{chunk-DOPZWTMJ.js → chunk-77K4PG6P.js} +8 -8
  37. package/dist/{chunk-LAI7ENPW.js → chunk-7MG2LHO5.js} +3 -3
  38. package/dist/{chunk-N4CHCXDL.js → chunk-7MG7SJT7.js} +1 -1
  39. package/dist/{chunk-N4CHCXDL.js.map → chunk-7MG7SJT7.js.map} +1 -1
  40. package/dist/{chunk-SW4TOSJL.js → chunk-7O3Y4PPD.js} +1 -1
  41. package/dist/chunk-7O3Y4PPD.js.map +1 -0
  42. package/dist/{chunk-HOIWW2LV.js → chunk-7V4TP3AF.js} +4 -4
  43. package/dist/{chunk-GKOJR53Y.js → chunk-ANATMFIO.js} +5 -5
  44. package/dist/{chunk-MU74BYOD.js → chunk-ANSIZYEG.js} +3 -3
  45. package/dist/{chunk-IS5LFHV2.js → chunk-AO42KJO6.js} +7 -7
  46. package/dist/{chunk-RPX2H2OL.js → chunk-BLN54W3L.js} +3 -3
  47. package/dist/{chunk-HS3LEVT4.js → chunk-BM5TWITZ.js} +7 -7
  48. package/dist/{chunk-JRWLUWDM.js → chunk-BOET4NA4.js} +3 -3
  49. package/dist/{chunk-XGXVPCYW.js → chunk-BOWNCWZT.js} +3 -3
  50. package/dist/{chunk-5EC7X5QA.js → chunk-BSFNRLK2.js} +5 -5
  51. package/dist/{chunk-65ZYRK7O.js → chunk-BUE2D7PX.js} +26 -3
  52. package/dist/chunk-BUE2D7PX.js.map +1 -0
  53. package/dist/{chunk-UTFY6W6X.js → chunk-BZ3534YM.js} +2 -2
  54. package/dist/chunk-CARABLSQ.js +176 -0
  55. package/dist/chunk-CARABLSQ.js.map +1 -0
  56. package/dist/{chunk-HLFLJCDX.js → chunk-CHJBLCOG.js} +7 -7
  57. package/dist/{chunk-OLUTCM23.js → chunk-CPWQB3N5.js} +7 -7
  58. package/dist/{chunk-3GIA3HJ2.js → chunk-DGOZ4UZD.js} +2 -2
  59. package/dist/{chunk-FPN5D4JX.js → chunk-ELNXJMGB.js} +6 -6
  60. package/dist/{chunk-NMDMSHBF.js → chunk-EQEYOJBM.js} +3 -3
  61. package/dist/{chunk-RHTPGS56.js → chunk-EYBQEIUY.js} +3 -3
  62. package/dist/{chunk-Q2ZN5DWZ.js → chunk-FAHMLERK.js} +2 -2
  63. package/dist/chunk-FFWI7UH7.js +53 -0
  64. package/dist/chunk-FFWI7UH7.js.map +1 -0
  65. package/dist/{chunk-MENI33ZV.js → chunk-FMZY5Q6L.js} +3 -3
  66. package/dist/{chunk-FZWAGG5T.js → chunk-FXBIP2WD.js} +6 -6
  67. package/dist/{chunk-OHGCRKWA.js → chunk-G56KBWFY.js} +18 -8
  68. package/dist/{chunk-OHGCRKWA.js.map → chunk-G56KBWFY.js.map} +1 -1
  69. package/dist/{chunk-K432FT7T.js → chunk-GPEQUXHL.js} +4 -4
  70. package/dist/{chunk-DNMTN46H.js → chunk-GY4WYNNG.js} +2 -2
  71. package/dist/{chunk-OQDHIAR2.js → chunk-HDOU6I2Y.js} +80 -8
  72. package/dist/chunk-HDOU6I2Y.js.map +1 -0
  73. package/dist/{chunk-MQPHKJ74.js → chunk-J6FXAEUG.js} +12 -12
  74. package/dist/{chunk-PV7XXAXK.js → chunk-JBDFMYKQ.js} +2 -2
  75. package/dist/{chunk-IZTU6RKH.js → chunk-JMGDHKQF.js} +2 -2
  76. package/dist/{chunk-AHIIBDNH.js → chunk-K6LHRFBL.js} +7 -7
  77. package/dist/{chunk-FN26SFGH.js → chunk-K7NTTA6P.js} +2 -2
  78. package/dist/{chunk-MV2OEK3K.js → chunk-KG7TZKZG.js} +5 -5
  79. package/dist/{chunk-5NKHCJU5.js → chunk-KJIMGIWO.js} +8 -8
  80. package/dist/{chunk-ZB2K3FV7.js → chunk-KTFRCC5C.js} +2 -2
  81. package/dist/{chunk-X6YRP5EC.js → chunk-KUJDV5QH.js} +5 -5
  82. package/dist/{chunk-PCIBCL26.js → chunk-KUX3OB6D.js} +7 -5
  83. package/dist/{chunk-PCIBCL26.js.map → chunk-KUX3OB6D.js.map} +1 -1
  84. package/dist/{chunk-OKCQNMO6.js → chunk-L742JPKZ.js} +6 -6
  85. package/dist/{chunk-P22XPNFW.js → chunk-L7CIOOBW.js} +2 -2
  86. package/dist/{chunk-QOHGWFAW.js → chunk-LWBCUYZW.js} +2 -2
  87. package/dist/{chunk-357ECVLE.js → chunk-MUM7IANK.js} +3 -3
  88. package/dist/{chunk-JFSUYGNE.js → chunk-MVMXZYXT.js} +2 -2
  89. package/dist/{chunk-3SWP2FYA.js → chunk-NA2NIJZI.js} +8 -8
  90. package/dist/{chunk-MOQ6OGKS.js → chunk-NKHRDYOR.js} +4 -4
  91. package/dist/{chunk-FKQCC4C5.js → chunk-NQKIUNW5.js} +2 -2
  92. package/dist/{chunk-SWFIXQF5.js → chunk-PT43Y56J.js} +6 -6
  93. package/dist/{chunk-MTTPHBIE.js → chunk-Q2PU57HC.js} +2 -2
  94. package/dist/{chunk-FLRLZ4XZ.js → chunk-Q7HZX3IF.js} +2 -2
  95. package/dist/{chunk-75WNTBZL.js → chunk-QIBVIOXO.js} +3 -3
  96. package/dist/{chunk-KQIDBIZL.js → chunk-QIZPZMUI.js} +2 -2
  97. package/dist/{chunk-VT4DTCK5.js → chunk-REDOOY2Q.js} +3 -3
  98. package/dist/chunk-REDOOY2Q.js.map +1 -0
  99. package/dist/{chunk-KZTPL7NL.js → chunk-RMF67KCG.js} +2 -2
  100. package/dist/{chunk-OEJ4R52I.js → chunk-RMS3NEA3.js} +2 -2
  101. package/dist/{chunk-VTTDPGEK.js → chunk-RRNRNANG.js} +9 -9
  102. package/dist/chunk-RTBJ5IOO.js +87 -0
  103. package/dist/chunk-RTBJ5IOO.js.map +1 -0
  104. package/dist/chunk-RXLYKVTF.js +17 -0
  105. package/dist/chunk-RXLYKVTF.js.map +1 -0
  106. package/dist/{chunk-XKA6UH5V.js → chunk-SFAWCTEM.js} +2 -2
  107. package/dist/{chunk-FYT3DXPN.js → chunk-SKGMN35F.js} +2 -2
  108. package/dist/{chunk-USKHHOIV.js → chunk-SL3JAAKN.js} +2 -2
  109. package/dist/chunk-SMH6SRX7.js +87 -0
  110. package/dist/chunk-SMH6SRX7.js.map +1 -0
  111. package/dist/{chunk-QJLOWGOU.js → chunk-SPXXX5E4.js} +12 -82
  112. package/dist/chunk-SPXXX5E4.js.map +1 -0
  113. package/dist/{chunk-JILOSL4O.js → chunk-SPYWXKJN.js} +3 -3
  114. package/dist/{chunk-4RUFYGWG.js → chunk-SZJ3DLZA.js} +2 -2
  115. package/dist/chunk-TFMM5DBB.js +20 -0
  116. package/dist/chunk-TFMM5DBB.js.map +1 -0
  117. package/dist/{chunk-O3SNM66K.js → chunk-TFR7DSOV.js} +2 -2
  118. package/dist/{chunk-DIVY2CJZ.js → chunk-TRGTKX5E.js} +3 -3
  119. package/dist/{chunk-JY4U6CYV.js → chunk-TUFM4UZP.js} +2 -2
  120. package/dist/{chunk-FRIVOR5N.js → chunk-U4FOQDY4.js} +5 -172
  121. package/dist/chunk-U4FOQDY4.js.map +1 -0
  122. package/dist/{chunk-DZPMKY3J.js → chunk-UGTBXF5U.js} +3 -3
  123. package/dist/{chunk-THNJ3IKU.js → chunk-ULUMAZ5S.js} +2 -2
  124. package/dist/{chunk-YHIAWECL.js → chunk-UXVWEX5L.js} +2 -2
  125. package/dist/{chunk-IAHDSFFA.js → chunk-UXWB3FPF.js} +10 -10
  126. package/dist/{chunk-NO272T7Q.js → chunk-V4PXLYWM.js} +2 -31
  127. package/dist/chunk-V4PXLYWM.js.map +1 -0
  128. package/dist/{chunk-GHADG5QZ.js → chunk-VTFVLCUH.js} +2 -2
  129. package/dist/{chunk-U3RMWOXY.js → chunk-VXANTWBJ.js} +3 -3
  130. package/dist/{chunk-5W5CEHLA.js → chunk-VXGSWL6L.js} +6 -6
  131. package/dist/{chunk-KHKKD62N.js → chunk-VYYM3MEN.js} +2 -16
  132. package/dist/chunk-VYYM3MEN.js.map +1 -0
  133. package/dist/{chunk-7YVSWPZB.js → chunk-WEQEYLCS.js} +7 -7
  134. package/dist/{chunk-TAJZ7GXO.js → chunk-X2DLENDQ.js} +3 -3
  135. package/dist/{chunk-2E2LT37H.js → chunk-XLMEZIAJ.js} +2 -2
  136. package/dist/{chunk-2MQ2D5OZ.js → chunk-XTXOCYOJ.js} +5 -5
  137. package/dist/{chunk-CWFH36SI.js → chunk-YSRUYAVU.js} +2 -2
  138. package/dist/{chunk-ZQGRZN5L.js → chunk-YYP7WSEB.js} +2 -2
  139. package/dist/{chunk-4U52PMEL.js → chunk-ZN4FD4PE.js} +4 -4
  140. package/dist/{chunk-AW4KTQA4.js → chunk-ZORTV6NH.js} +2 -2
  141. package/dist/{chunk-H5GVPOB4.js → chunk-ZVO4QVPD.js} +5 -5
  142. package/dist/classified/index.js +5 -6
  143. package/dist/{classified-marker-R37XW5PC.js → classified-marker-LI2SF2E4.js} +3 -5
  144. package/dist/{classified-marker-R37XW5PC.js.map → classified-marker-LI2SF2E4.js.map} +1 -1
  145. package/dist/collection-facade-4GRREZ6C.js +45 -0
  146. package/dist/computed-VPOKQK4N.js +10 -0
  147. package/dist/consent/index.js +9 -10
  148. package/dist/consent/index.js.map +1 -1
  149. package/dist/cover/index.js +9 -10
  150. package/dist/crdt/index.js +0 -1
  151. package/dist/crdt/index.js.map +1 -1
  152. package/dist/custody/index.js +12 -13
  153. package/dist/{dead-filter-GRT6RAML.js → dead-filter-TSWZQRR5.js} +2 -3
  154. package/dist/{dead-filter-GRT6RAML.js.map → dead-filter-TSWZQRR5.js.map} +1 -1
  155. package/dist/debug/index.js +1 -2
  156. package/dist/debug/index.js.map +1 -1
  157. package/dist/{delegation-6QRAYSK6.js → delegation-OVIFFPG4.js} +11 -12
  158. package/dist/{delegation-6QRAYSK6.js.map → delegation-OVIFFPG4.js.map} +1 -1
  159. package/dist/derivations/index.js +30 -16
  160. package/dist/derive-6O5SWQKN.js +21 -0
  161. package/dist/directory/index.js +10 -11
  162. package/dist/dispatch-S73TK3IY.js +302 -0
  163. package/dist/dispatch-S73TK3IY.js.map +1 -0
  164. package/dist/{dispatch-QCF7KPIP.js → dispatch-WC6X2M6C.js} +5 -7
  165. package/dist/{dispatch-QCF7KPIP.js.map → dispatch-WC6X2M6C.js.map} +1 -1
  166. package/dist/{enclave-OXZY3NOP.js → enclave-KJOTOH7X.js} +9 -10
  167. package/dist/executor-5NIMLSKZ.js +8 -0
  168. package/dist/executor-AQVXV5GZ.js +8 -0
  169. package/dist/executor-PUAO6AKJ.js +29 -0
  170. package/dist/export-accessible-72EQNBMR.js +22 -0
  171. package/dist/extract-partition-PUYNU3UF.js +37 -0
  172. package/dist/{fanout-sidecar-KGQCUJ7P.js → fanout-sidecar-WUFXNYP4.js} +9 -10
  173. package/dist/{fanout-sidecar-KGQCUJ7P.js.map → fanout-sidecar-WUFXNYP4.js.map} +1 -1
  174. package/dist/{fence-watcher-ZVSMLKQD.js → fence-watcher-U2PW6JU5.js} +1 -3
  175. package/dist/{fence-watcher-ZVSMLKQD.js.map → fence-watcher-U2PW6JU5.js.map} +1 -1
  176. package/dist/find-2ABFCZX4.js +10 -0
  177. package/dist/forget/index.js +9 -10
  178. package/dist/forget/index.js.map +1 -1
  179. package/dist/guards/index.js +4 -5
  180. package/dist/history/index.js +13 -14
  181. package/dist/history/index.js.map +1 -1
  182. package/dist/i18n/index.js +14 -15
  183. package/dist/i18n/index.js.map +1 -1
  184. package/dist/index.d.ts +20 -4
  185. package/dist/index.js +122 -115
  186. package/dist/index.js.map +1 -1
  187. package/dist/indexing/index.js +2 -3
  188. package/dist/indexing/index.js.map +1 -1
  189. package/dist/introspection/index.js +13 -13
  190. package/dist/issue-SIDORTSZ.js +18 -0
  191. package/dist/{json-schema-I22JCYCG.js → json-schema-V3M5MUCM.js} +1 -3
  192. package/dist/{json-schema-I22JCYCG.js.map → json-schema-V3M5MUCM.js.map} +1 -1
  193. package/dist/kernel/collection-config.d.ts +34 -0
  194. package/dist/kernel/collection.d.ts +11 -6
  195. package/dist/kernel/errors.d.ts +28 -0
  196. package/dist/kernel/match-pairs.d.ts +30 -0
  197. package/dist/kernel/types.d.ts +39 -0
  198. package/dist/lazy/index.js +3 -3
  199. package/dist/{ledger-ZAFULLAF.js → ledger-F33ZVMTK.js} +11 -12
  200. package/dist/liberate-LCDPNAG2.js +24 -0
  201. package/dist/link-set-FKNWAYKS.js +30 -0
  202. package/dist/{managed-secret-7OH7HKXV.js → managed-secret-PQYKSR6T.js} +10 -11
  203. package/dist/materialized-views/index.js +21 -21
  204. package/dist/{migrate-cek-QHZ75E6E.js → migrate-cek-5ENH64AA.js} +2 -3
  205. package/dist/{migrate-cek-QHZ75E6E.js.map → migrate-cek-5ENH64AA.js.map} +1 -1
  206. package/dist/money/index.js +4 -5
  207. package/dist/noydb-DUXZPKSN.js +90 -0
  208. package/dist/overlay-views/index.js +4 -5
  209. package/dist/periods/index.js +12 -13
  210. package/dist/pod/index.js +64 -60
  211. package/dist/{pod-handle-BLOI4IFY.js → pod-handle-Q736KYON.js} +10 -11
  212. package/dist/{pod-handle-BLOI4IFY.js.map → pod-handle-Q736KYON.js.map} +1 -1
  213. package/dist/policy/index.js +10 -11
  214. package/dist/port/to/index.d.ts +40 -0
  215. package/dist/portability/index.js +8 -9
  216. package/dist/portability/index.js.map +1 -1
  217. package/dist/{post-register-R33EKJQR.js → post-register-LNE2FE2A.js} +6 -7
  218. package/dist/{post-register-R33EKJQR.js.map → post-register-LNE2FE2A.js.map} +1 -1
  219. package/dist/{purge-scope-FGNNLWHD.js → purge-scope-4HEFPDOW.js} +1 -3
  220. package/dist/{purge-scope-FGNNLWHD.js.map → purge-scope-4HEFPDOW.js.map} +1 -1
  221. package/dist/query/index.js +3 -4
  222. package/dist/{read-only-facade-CHCKSEPD.js → read-only-facade-BIGO37U3.js} +1 -2
  223. package/dist/reduce/index.js +4 -5
  224. package/dist/reduce/index.js.map +1 -1
  225. package/dist/register-I2DZXGAR.js +31 -0
  226. package/dist/registry-23WF3TGH.js +8 -0
  227. package/dist/registry-4AYVUNXK.js +8 -0
  228. package/dist/registry-VSSQPIGF.js +18 -0
  229. package/dist/registry-YLEWMGAC.js +32 -0
  230. package/dist/request-withdrawal-KFQHEZ25.js +30 -0
  231. package/dist/{reveal-PI6ADRQU.js → reveal-67RDQRIN.js} +6 -7
  232. package/dist/{reveal-PI6ADRQU.js.map → reveal-67RDQRIN.js.map} +1 -1
  233. package/dist/revoke-DQDZAZZM.js +23 -0
  234. package/dist/satellites/index.js +1 -2
  235. package/dist/schema-update/index.js +2 -3
  236. package/dist/sealed-record/index.js +12 -13
  237. package/dist/sealed-record/index.js.map +1 -1
  238. package/dist/search/index.js +4 -5
  239. package/dist/{seed-CG7JMJNY.js → seed-G42JYN56.js} +12 -13
  240. package/dist/{seed-CG7JMJNY.js.map → seed-G42JYN56.js.map} +1 -1
  241. package/dist/sequence/index.js +9 -10
  242. package/dist/session/index.js +9 -10
  243. package/dist/session/index.js.map +1 -1
  244. package/dist/shadow/index.js +2 -3
  245. package/dist/shadow/index.js.map +1 -1
  246. package/dist/share-link/index.js +0 -1
  247. package/dist/share-link/index.js.map +1 -1
  248. package/dist/signer-WAMDZHEN.js +24 -0
  249. package/dist/snapshots/index.js +10 -11
  250. package/dist/snapshots/index.js.map +1 -1
  251. package/dist/{stale-HZR7745Y.js → stale-DDL7WQEZ.js} +10 -11
  252. package/dist/storage-FLR73HHF.js +22 -0
  253. package/dist/store/index.js +0 -1
  254. package/dist/{store-coordination-provider-MYIHSZXT.js → store-coordination-provider-MEQ2MJQG.js} +10 -11
  255. package/dist/{store-coordination-provider-MYIHSZXT.js.map → store-coordination-provider-MEQ2MJQG.js.map} +1 -1
  256. package/dist/sync/index.js +10 -11
  257. package/dist/sync/index.js.map +1 -1
  258. package/dist/team/index.js +15 -16
  259. package/dist/tiers/index.js +11 -12
  260. package/dist/to/index.js +2 -3
  261. package/dist/to/index.js.map +1 -1
  262. package/dist/transactions/index.js +3 -4
  263. package/dist/transactions/index.js.map +1 -1
  264. package/dist/{ulid-VQW6ERQN.js → ulid-4MKXG325.js} +1 -2
  265. package/dist/util/index.js +1 -2
  266. package/dist/util/index.js.map +1 -1
  267. package/dist/{vault-diff-FE5J35NJ.js → vault-diff-C6WUJFNP.js} +1 -2
  268. package/dist/vault-head/index.js +8 -9
  269. package/dist/vault-head/index.js.map +1 -1
  270. package/dist/{verify-R6CCBUA3.js → verify-KOV2G5D6.js} +5 -6
  271. package/dist/{verify-R6CCBUA3.js.map → verify-KOV2G5D6.js.map} +1 -1
  272. package/dist/walk-3UQBRMDV.js +21 -0
  273. package/dist/with-formula/derivations/dispatch.d.ts +16 -1
  274. package/dist/with-formula/derivations/registry.d.ts +20 -0
  275. package/dist/with-formula/derivations/trigger-match.d.ts +104 -0
  276. package/dist/with-formula/derivations/types.d.ts +61 -0
  277. package/dist/with-shape/introspection/behaviors.d.ts +7 -0
  278. package/dist/with-shape/introspection/describe.d.ts +10 -1
  279. package/dist/with-shape/introspection/field-meta.d.ts +86 -0
  280. package/dist/withdraw-accessible-EL5GXZBS.js +27 -0
  281. package/package.json +8 -3
  282. package/dist/api-GJQF7OAJ.js +0 -20
  283. package/dist/chunk-65ZYRK7O.js.map +0 -1
  284. package/dist/chunk-6L5IMNJX.js.map +0 -1
  285. package/dist/chunk-FRIVOR5N.js.map +0 -1
  286. package/dist/chunk-J6FXVDKC.js +0 -81
  287. package/dist/chunk-J6FXVDKC.js.map +0 -1
  288. package/dist/chunk-KHKKD62N.js.map +0 -1
  289. package/dist/chunk-NO272T7Q.js.map +0 -1
  290. package/dist/chunk-OQDHIAR2.js.map +0 -1
  291. package/dist/chunk-PZ5AY32C.js +0 -10
  292. package/dist/chunk-QJLOWGOU.js.map +0 -1
  293. package/dist/chunk-SW4TOSJL.js.map +0 -1
  294. package/dist/chunk-VT4DTCK5.js.map +0 -1
  295. package/dist/chunk-XJP66QEN.js +0 -344
  296. package/dist/chunk-XJP66QEN.js.map +0 -1
  297. package/dist/collection-facade-OPJ3EC4L.js +0 -45
  298. package/dist/computed-HW6IG5UH.js +0 -11
  299. package/dist/derive-AAIXSQIE.js +0 -22
  300. package/dist/dispatch-DR3XITEC.js +0 -194
  301. package/dist/dispatch-DR3XITEC.js.map +0 -1
  302. package/dist/executor-67NA4KPO.js +0 -29
  303. package/dist/executor-7JDP7UBK.js +0 -9
  304. package/dist/executor-CRH5OB4V.js +0 -9
  305. package/dist/export-accessible-K4GJAU7U.js +0 -23
  306. package/dist/extract-partition-YJFL5OKK.js +0 -38
  307. package/dist/find-SVZHMEQI.js +0 -11
  308. package/dist/issue-64N6OG7U.js +0 -19
  309. package/dist/liberate-XL6NSGOL.js +0 -25
  310. package/dist/link-set-LQI2IJX6.js +0 -31
  311. package/dist/noydb-SWUGPFBK.js +0 -86
  312. package/dist/register-AYBQNTM3.js +0 -32
  313. package/dist/registry-CQWWOBO4.js +0 -9
  314. package/dist/registry-JCZ4BNLV.js +0 -18
  315. package/dist/registry-JFFENZ44.js +0 -9
  316. package/dist/registry-ZA4HACYR.js +0 -19
  317. package/dist/request-withdrawal-7IKUIAEB.js +0 -31
  318. package/dist/revoke-PUJKRYJF.js +0 -24
  319. package/dist/signer-5TA7FUC3.js +0 -25
  320. package/dist/storage-J2QHNJCB.js +0 -23
  321. package/dist/walk-3PA4ZOKS.js +0 -21
  322. package/dist/withdraw-accessible-62VI4W7D.js +0 -28
  323. package/dist/withdraw-accessible-62VI4W7D.js.map +0 -1
  324. package/dist/zod-HAJM7LMS.js +0 -14763
  325. package/dist/zod-HAJM7LMS.js.map +0 -1
  326. /package/dist/{api-GJQF7OAJ.js.map → api-TXFOVOXX.js.map} +0 -0
  327. /package/dist/{chunk-5UKIZIO3.js.map → chunk-2577DKXB.js.map} +0 -0
  328. /package/dist/{chunk-LUVGSKXE.js.map → chunk-2N4GY74U.js.map} +0 -0
  329. /package/dist/{chunk-I5LSKXT6.js.map → chunk-2Y4IMKA6.js.map} +0 -0
  330. /package/dist/{chunk-7XT7KZTN.js.map → chunk-3RCJJBNR.js.map} +0 -0
  331. /package/dist/{chunk-GM4IM7TC.js.map → chunk-453F654R.js.map} +0 -0
  332. /package/dist/{chunk-JUBWUJY5.js.map → chunk-4GVM6QZA.js.map} +0 -0
  333. /package/dist/{chunk-2DGBRE4K.js.map → chunk-4OZNXTO4.js.map} +0 -0
  334. /package/dist/{chunk-P2RJAVMR.js.map → chunk-5VCRVKOZ.js.map} +0 -0
  335. /package/dist/{chunk-RCONOOVF.js.map → chunk-5WDXHNSW.js.map} +0 -0
  336. /package/dist/{chunk-Q2OAAREU.js.map → chunk-6GMZ7HEE.js.map} +0 -0
  337. /package/dist/{chunk-TQGT5BZE.js.map → chunk-6I2RQCET.js.map} +0 -0
  338. /package/dist/{chunk-P7KJME6C.js.map → chunk-6YXCPL4T.js.map} +0 -0
  339. /package/dist/{chunk-DOPZWTMJ.js.map → chunk-77K4PG6P.js.map} +0 -0
  340. /package/dist/{chunk-LAI7ENPW.js.map → chunk-7MG2LHO5.js.map} +0 -0
  341. /package/dist/{chunk-HOIWW2LV.js.map → chunk-7V4TP3AF.js.map} +0 -0
  342. /package/dist/{chunk-GKOJR53Y.js.map → chunk-ANATMFIO.js.map} +0 -0
  343. /package/dist/{chunk-MU74BYOD.js.map → chunk-ANSIZYEG.js.map} +0 -0
  344. /package/dist/{chunk-IS5LFHV2.js.map → chunk-AO42KJO6.js.map} +0 -0
  345. /package/dist/{chunk-RPX2H2OL.js.map → chunk-BLN54W3L.js.map} +0 -0
  346. /package/dist/{chunk-HS3LEVT4.js.map → chunk-BM5TWITZ.js.map} +0 -0
  347. /package/dist/{chunk-JRWLUWDM.js.map → chunk-BOET4NA4.js.map} +0 -0
  348. /package/dist/{chunk-XGXVPCYW.js.map → chunk-BOWNCWZT.js.map} +0 -0
  349. /package/dist/{chunk-5EC7X5QA.js.map → chunk-BSFNRLK2.js.map} +0 -0
  350. /package/dist/{chunk-UTFY6W6X.js.map → chunk-BZ3534YM.js.map} +0 -0
  351. /package/dist/{chunk-HLFLJCDX.js.map → chunk-CHJBLCOG.js.map} +0 -0
  352. /package/dist/{chunk-OLUTCM23.js.map → chunk-CPWQB3N5.js.map} +0 -0
  353. /package/dist/{chunk-3GIA3HJ2.js.map → chunk-DGOZ4UZD.js.map} +0 -0
  354. /package/dist/{chunk-FPN5D4JX.js.map → chunk-ELNXJMGB.js.map} +0 -0
  355. /package/dist/{chunk-NMDMSHBF.js.map → chunk-EQEYOJBM.js.map} +0 -0
  356. /package/dist/{chunk-RHTPGS56.js.map → chunk-EYBQEIUY.js.map} +0 -0
  357. /package/dist/{chunk-Q2ZN5DWZ.js.map → chunk-FAHMLERK.js.map} +0 -0
  358. /package/dist/{chunk-MENI33ZV.js.map → chunk-FMZY5Q6L.js.map} +0 -0
  359. /package/dist/{chunk-FZWAGG5T.js.map → chunk-FXBIP2WD.js.map} +0 -0
  360. /package/dist/{chunk-K432FT7T.js.map → chunk-GPEQUXHL.js.map} +0 -0
  361. /package/dist/{chunk-DNMTN46H.js.map → chunk-GY4WYNNG.js.map} +0 -0
  362. /package/dist/{chunk-MQPHKJ74.js.map → chunk-J6FXAEUG.js.map} +0 -0
  363. /package/dist/{chunk-PV7XXAXK.js.map → chunk-JBDFMYKQ.js.map} +0 -0
  364. /package/dist/{chunk-IZTU6RKH.js.map → chunk-JMGDHKQF.js.map} +0 -0
  365. /package/dist/{chunk-AHIIBDNH.js.map → chunk-K6LHRFBL.js.map} +0 -0
  366. /package/dist/{chunk-FN26SFGH.js.map → chunk-K7NTTA6P.js.map} +0 -0
  367. /package/dist/{chunk-MV2OEK3K.js.map → chunk-KG7TZKZG.js.map} +0 -0
  368. /package/dist/{chunk-5NKHCJU5.js.map → chunk-KJIMGIWO.js.map} +0 -0
  369. /package/dist/{chunk-ZB2K3FV7.js.map → chunk-KTFRCC5C.js.map} +0 -0
  370. /package/dist/{chunk-X6YRP5EC.js.map → chunk-KUJDV5QH.js.map} +0 -0
  371. /package/dist/{chunk-OKCQNMO6.js.map → chunk-L742JPKZ.js.map} +0 -0
  372. /package/dist/{chunk-P22XPNFW.js.map → chunk-L7CIOOBW.js.map} +0 -0
  373. /package/dist/{chunk-QOHGWFAW.js.map → chunk-LWBCUYZW.js.map} +0 -0
  374. /package/dist/{chunk-357ECVLE.js.map → chunk-MUM7IANK.js.map} +0 -0
  375. /package/dist/{chunk-JFSUYGNE.js.map → chunk-MVMXZYXT.js.map} +0 -0
  376. /package/dist/{chunk-3SWP2FYA.js.map → chunk-NA2NIJZI.js.map} +0 -0
  377. /package/dist/{chunk-MOQ6OGKS.js.map → chunk-NKHRDYOR.js.map} +0 -0
  378. /package/dist/{chunk-FKQCC4C5.js.map → chunk-NQKIUNW5.js.map} +0 -0
  379. /package/dist/{chunk-SWFIXQF5.js.map → chunk-PT43Y56J.js.map} +0 -0
  380. /package/dist/{chunk-MTTPHBIE.js.map → chunk-Q2PU57HC.js.map} +0 -0
  381. /package/dist/{chunk-FLRLZ4XZ.js.map → chunk-Q7HZX3IF.js.map} +0 -0
  382. /package/dist/{chunk-75WNTBZL.js.map → chunk-QIBVIOXO.js.map} +0 -0
  383. /package/dist/{chunk-KQIDBIZL.js.map → chunk-QIZPZMUI.js.map} +0 -0
  384. /package/dist/{chunk-KZTPL7NL.js.map → chunk-RMF67KCG.js.map} +0 -0
  385. /package/dist/{chunk-OEJ4R52I.js.map → chunk-RMS3NEA3.js.map} +0 -0
  386. /package/dist/{chunk-VTTDPGEK.js.map → chunk-RRNRNANG.js.map} +0 -0
  387. /package/dist/{chunk-XKA6UH5V.js.map → chunk-SFAWCTEM.js.map} +0 -0
  388. /package/dist/{chunk-FYT3DXPN.js.map → chunk-SKGMN35F.js.map} +0 -0
  389. /package/dist/{chunk-USKHHOIV.js.map → chunk-SL3JAAKN.js.map} +0 -0
  390. /package/dist/{chunk-JILOSL4O.js.map → chunk-SPYWXKJN.js.map} +0 -0
  391. /package/dist/{chunk-4RUFYGWG.js.map → chunk-SZJ3DLZA.js.map} +0 -0
  392. /package/dist/{chunk-O3SNM66K.js.map → chunk-TFR7DSOV.js.map} +0 -0
  393. /package/dist/{chunk-DIVY2CJZ.js.map → chunk-TRGTKX5E.js.map} +0 -0
  394. /package/dist/{chunk-JY4U6CYV.js.map → chunk-TUFM4UZP.js.map} +0 -0
  395. /package/dist/{chunk-DZPMKY3J.js.map → chunk-UGTBXF5U.js.map} +0 -0
  396. /package/dist/{chunk-THNJ3IKU.js.map → chunk-ULUMAZ5S.js.map} +0 -0
  397. /package/dist/{chunk-YHIAWECL.js.map → chunk-UXVWEX5L.js.map} +0 -0
  398. /package/dist/{chunk-IAHDSFFA.js.map → chunk-UXWB3FPF.js.map} +0 -0
  399. /package/dist/{chunk-GHADG5QZ.js.map → chunk-VTFVLCUH.js.map} +0 -0
  400. /package/dist/{chunk-U3RMWOXY.js.map → chunk-VXANTWBJ.js.map} +0 -0
  401. /package/dist/{chunk-5W5CEHLA.js.map → chunk-VXGSWL6L.js.map} +0 -0
  402. /package/dist/{chunk-7YVSWPZB.js.map → chunk-WEQEYLCS.js.map} +0 -0
  403. /package/dist/{chunk-TAJZ7GXO.js.map → chunk-X2DLENDQ.js.map} +0 -0
  404. /package/dist/{chunk-2E2LT37H.js.map → chunk-XLMEZIAJ.js.map} +0 -0
  405. /package/dist/{chunk-2MQ2D5OZ.js.map → chunk-XTXOCYOJ.js.map} +0 -0
  406. /package/dist/{chunk-CWFH36SI.js.map → chunk-YSRUYAVU.js.map} +0 -0
  407. /package/dist/{chunk-ZQGRZN5L.js.map → chunk-YYP7WSEB.js.map} +0 -0
  408. /package/dist/{chunk-4U52PMEL.js.map → chunk-ZN4FD4PE.js.map} +0 -0
  409. /package/dist/{chunk-AW4KTQA4.js.map → chunk-ZORTV6NH.js.map} +0 -0
  410. /package/dist/{chunk-H5GVPOB4.js.map → chunk-ZVO4QVPD.js.map} +0 -0
  411. /package/dist/{chunk-PZ5AY32C.js.map → collection-facade-4GRREZ6C.js.map} +0 -0
  412. /package/dist/{collection-facade-OPJ3EC4L.js.map → computed-VPOKQK4N.js.map} +0 -0
  413. /package/dist/{computed-HW6IG5UH.js.map → derive-6O5SWQKN.js.map} +0 -0
  414. /package/dist/{derive-AAIXSQIE.js.map → enclave-KJOTOH7X.js.map} +0 -0
  415. /package/dist/{enclave-OXZY3NOP.js.map → executor-5NIMLSKZ.js.map} +0 -0
  416. /package/dist/{executor-67NA4KPO.js.map → executor-AQVXV5GZ.js.map} +0 -0
  417. /package/dist/{executor-7JDP7UBK.js.map → executor-PUAO6AKJ.js.map} +0 -0
  418. /package/dist/{executor-CRH5OB4V.js.map → export-accessible-72EQNBMR.js.map} +0 -0
  419. /package/dist/{export-accessible-K4GJAU7U.js.map → extract-partition-PUYNU3UF.js.map} +0 -0
  420. /package/dist/{extract-partition-YJFL5OKK.js.map → find-2ABFCZX4.js.map} +0 -0
  421. /package/dist/{find-SVZHMEQI.js.map → issue-SIDORTSZ.js.map} +0 -0
  422. /package/dist/{issue-64N6OG7U.js.map → ledger-F33ZVMTK.js.map} +0 -0
  423. /package/dist/{ledger-ZAFULLAF.js.map → liberate-LCDPNAG2.js.map} +0 -0
  424. /package/dist/{liberate-XL6NSGOL.js.map → link-set-FKNWAYKS.js.map} +0 -0
  425. /package/dist/{link-set-LQI2IJX6.js.map → managed-secret-PQYKSR6T.js.map} +0 -0
  426. /package/dist/{managed-secret-7OH7HKXV.js.map → noydb-DUXZPKSN.js.map} +0 -0
  427. /package/dist/{noydb-SWUGPFBK.js.map → read-only-facade-BIGO37U3.js.map} +0 -0
  428. /package/dist/{read-only-facade-CHCKSEPD.js.map → register-I2DZXGAR.js.map} +0 -0
  429. /package/dist/{register-AYBQNTM3.js.map → registry-23WF3TGH.js.map} +0 -0
  430. /package/dist/{registry-CQWWOBO4.js.map → registry-4AYVUNXK.js.map} +0 -0
  431. /package/dist/{registry-JCZ4BNLV.js.map → registry-VSSQPIGF.js.map} +0 -0
  432. /package/dist/{registry-JFFENZ44.js.map → registry-YLEWMGAC.js.map} +0 -0
  433. /package/dist/{registry-ZA4HACYR.js.map → request-withdrawal-KFQHEZ25.js.map} +0 -0
  434. /package/dist/{request-withdrawal-7IKUIAEB.js.map → revoke-DQDZAZZM.js.map} +0 -0
  435. /package/dist/{revoke-PUJKRYJF.js.map → signer-WAMDZHEN.js.map} +0 -0
  436. /package/dist/{signer-5TA7FUC3.js.map → stale-DDL7WQEZ.js.map} +0 -0
  437. /package/dist/{stale-HZR7745Y.js.map → storage-FLR73HHF.js.map} +0 -0
  438. /package/dist/{storage-J2QHNJCB.js.map → ulid-4MKXG325.js.map} +0 -0
  439. /package/dist/{ulid-VQW6ERQN.js.map → vault-diff-C6WUJFNP.js.map} +0 -0
  440. /package/dist/{vault-diff-FE5J35NJ.js.map → walk-3UQBRMDV.js.map} +0 -0
  441. /package/dist/{walk-3PA4ZOKS.js.map → withdraw-accessible-EL5GXZBS.js.map} +0 -0
package/README.md CHANGED
@@ -52,13 +52,13 @@ pnpm add @noy-db/hub @noy-db/to-memory
52
52
 
53
53
  ```ts
54
54
  import { createNoydb } from '@noy-db/hub'
55
- import { memory } from '@noy-db/to-memory'
55
+ import { toMemory } from '@noy-db/to-memory'
56
56
 
57
57
  type Invoice = { id: string; amount: number; customer: string }
58
58
 
59
59
  const db = await createNoydb({
60
60
  store: toMemory(),
61
- userId: 'alice',
61
+ user: 'alice',
62
62
  secret: 'correct horse battery staple',
63
63
  })
64
64
 
@@ -77,9 +77,10 @@ const all = await invoices.list()
77
77
  - **Offline-first sync** — push/pull with optimistic concurrency on encrypted envelopes
78
78
  - **Audit history** — full-copy snapshots with `history()`, `diff()`, `revert()`, `pruneHistory()`
79
79
  - **No third-party runtime dependencies to install** — the only runtime dependency is
80
- `@noy-db/attestation`, on the same version line. (`zod` is vendored into the bundle for the
81
- optional persisted-schema converter and loaded lazily; it never executes unless you use that
82
- path, and it does not appear in your lockfile.)
80
+ `@noy-db/attestation`, on the same version line. `zod` (v3 or v4) and `zod-to-json-schema` are
81
+ OPTIONAL peers used by the persisted-schema converter: nothing is installed on your behalf, nothing is
82
+ vendored into the bundle, and if you do use Zod schemas the converter reads YOUR copy rather
83
+ than a second one frozen at hub's build time.
83
84
 
84
85
  ## Cross-vault queries
85
86
 
@@ -281,7 +282,7 @@ const { evicted, held } = await vault.compact() // held = retained-by-hold count
281
282
  ```ts
282
283
  import { createNoydb, withArchive } from '@noy-db/hub'
283
284
 
284
- const db = await createNoydb({ store: primary, archiveStrategy: withArchive({ store: coldStore }) })
285
+ const db = await createNoydb({ store: primary, user, secret, archiveStrategy: withArchive({ store: coldStore }) })
285
286
  vault.collection('invoices', {
286
287
  archive: { archiveWhen: (r) => r.fiscalYear <= thisYear - 1, legalHold: (r) => r.underHold },
287
288
  })
@@ -0,0 +1,19 @@
1
+ import {
2
+ UserApi,
3
+ createUserApi
4
+ } from "./chunk-MUM7IANK.js";
5
+ import "./chunk-KG7TZKZG.js";
6
+ import "./chunk-77K4PG6P.js";
7
+ import "./chunk-SZJ3DLZA.js";
8
+ import "./chunk-BOWNCWZT.js";
9
+ import "./chunk-YSRUYAVU.js";
10
+ import "./chunk-RMF67KCG.js";
11
+ import "./chunk-LP7BEXCT.js";
12
+ import "./chunk-SL3JAAKN.js";
13
+ import "./chunk-7MG7SJT7.js";
14
+ import "./chunk-7O3Y4PPD.js";
15
+ export {
16
+ UserApi,
17
+ createUserApi
18
+ };
19
+ //# sourceMappingURL=api-TXFOVOXX.js.map
package/dist/as/index.js CHANGED
@@ -1,24 +1,24 @@
1
1
  import "../chunk-UBSFPGVJ.js";
2
- import "../chunk-PCIBCL26.js";
2
+ import "../chunk-KUX3OB6D.js";
3
3
  import {
4
4
  applyListProjection
5
5
  } from "../chunk-VG2ZSFYD.js";
6
- import "../chunk-KHKKD62N.js";
7
- import "../chunk-VT4DTCK5.js";
6
+ import "../chunk-RXLYKVTF.js";
7
+ import "../chunk-VYYM3MEN.js";
8
+ import "../chunk-REDOOY2Q.js";
8
9
  import "../chunk-Y2NBBT6K.js";
9
- import "../chunk-I5LSKXT6.js";
10
- import "../chunk-DOPZWTMJ.js";
11
- import "../chunk-4RUFYGWG.js";
12
- import "../chunk-XGXVPCYW.js";
13
- import "../chunk-CWFH36SI.js";
14
- import "../chunk-KZTPL7NL.js";
10
+ import "../chunk-2Y4IMKA6.js";
11
+ import "../chunk-77K4PG6P.js";
12
+ import "../chunk-SZJ3DLZA.js";
13
+ import "../chunk-BOWNCWZT.js";
14
+ import "../chunk-YSRUYAVU.js";
15
+ import "../chunk-RMF67KCG.js";
15
16
  import "../chunk-LP7BEXCT.js";
16
- import "../chunk-USKHHOIV.js";
17
- import "../chunk-N4CHCXDL.js";
17
+ import "../chunk-SL3JAAKN.js";
18
+ import "../chunk-7MG7SJT7.js";
18
19
  import {
19
20
  ValidationError
20
- } from "../chunk-SW4TOSJL.js";
21
- import "../chunk-PZ5AY32C.js";
21
+ } from "../chunk-7O3Y4PPD.js";
22
22
 
23
23
  // src/port/as/active.ts
24
24
  function redactChunk(chunk, ctx, redact) {
@@ -74,7 +74,7 @@ function contextFor(vault) {
74
74
  // export fails instead.
75
75
  describe: (collection) => vault.collection(collection).describe(),
76
76
  plan: async (records, policy, formatId, idKey) => {
77
- const { diffVault } = await import("../vault-diff-FE5J35NJ.js");
77
+ const { diffVault } = await import("../vault-diff-C6WUJFNP.js");
78
78
  const plan = await diffVault(vault, records, idKey ? { idKey } : {});
79
79
  return {
80
80
  plan,
package/dist/at/index.js CHANGED
@@ -3,17 +3,16 @@ import {
3
3
  MemorySealer,
4
4
  SEALED_SECRET_RECORD_ID,
5
5
  parseSealedEnvelope
6
- } from "../chunk-JUBWUJY5.js";
7
- import "../chunk-DOPZWTMJ.js";
8
- import "../chunk-4RUFYGWG.js";
9
- import "../chunk-XGXVPCYW.js";
10
- import "../chunk-CWFH36SI.js";
11
- import "../chunk-KZTPL7NL.js";
6
+ } from "../chunk-4GVM6QZA.js";
7
+ import "../chunk-77K4PG6P.js";
8
+ import "../chunk-SZJ3DLZA.js";
9
+ import "../chunk-BOWNCWZT.js";
10
+ import "../chunk-YSRUYAVU.js";
11
+ import "../chunk-RMF67KCG.js";
12
12
  import "../chunk-LP7BEXCT.js";
13
- import "../chunk-USKHHOIV.js";
14
- import "../chunk-N4CHCXDL.js";
15
- import "../chunk-SW4TOSJL.js";
16
- import "../chunk-PZ5AY32C.js";
13
+ import "../chunk-SL3JAAKN.js";
14
+ import "../chunk-7MG7SJT7.js";
15
+ import "../chunk-7O3Y4PPD.js";
17
16
  export {
18
17
  MemoryRecipientSealer,
19
18
  MemorySealer,
@@ -1,42 +1,41 @@
1
1
  import {
2
2
  issueAttestationCore
3
- } from "../chunk-LUVGSKXE.js";
3
+ } from "../chunk-2N4GY74U.js";
4
4
  import {
5
5
  getRevokedDocIdsCore,
6
6
  publishRevocationListCore,
7
7
  revokeDocCore,
8
8
  unrevokeDocCore
9
- } from "../chunk-FPN5D4JX.js";
9
+ } from "../chunk-ELNXJMGB.js";
10
10
  import {
11
11
  ATTESTATIONS_COLLECTION
12
- } from "../chunk-GKOJR53Y.js";
12
+ } from "../chunk-ANATMFIO.js";
13
13
  import {
14
14
  NO_ATTESTATION
15
- } from "../chunk-FLRLZ4XZ.js";
15
+ } from "../chunk-Q7HZX3IF.js";
16
16
  import "../chunk-4AOERLTV.js";
17
- import "../chunk-DOPZWTMJ.js";
18
- import "../chunk-4RUFYGWG.js";
19
- import "../chunk-XGXVPCYW.js";
20
- import "../chunk-CWFH36SI.js";
21
- import "../chunk-KZTPL7NL.js";
17
+ import "../chunk-77K4PG6P.js";
18
+ import "../chunk-SZJ3DLZA.js";
19
+ import "../chunk-BOWNCWZT.js";
20
+ import "../chunk-YSRUYAVU.js";
21
+ import "../chunk-RMF67KCG.js";
22
22
  import "../chunk-LP7BEXCT.js";
23
- import "../chunk-USKHHOIV.js";
24
- import "../chunk-N4CHCXDL.js";
23
+ import "../chunk-SL3JAAKN.js";
24
+ import "../chunk-7MG7SJT7.js";
25
25
  import {
26
26
  AttestationError,
27
27
  AttestationNotEnabledError
28
- } from "../chunk-SW4TOSJL.js";
29
- import "../chunk-PZ5AY32C.js";
28
+ } from "../chunk-7O3Y4PPD.js";
30
29
 
31
30
  // src/with-audit/attestation/active.ts
32
31
  function withAttestation() {
33
32
  return {
34
33
  async issueAttestation(ctx, args) {
35
- const { issueAttestationCore: issueAttestationCore2 } = await import("../issue-64N6OG7U.js");
34
+ const { issueAttestationCore: issueAttestationCore2 } = await import("../issue-SIDORTSZ.js");
36
35
  return issueAttestationCore2(ctx, args);
37
36
  },
38
37
  async getDocumentSigningPublicKey(deps) {
39
- const { loadSigner, loadOrCreateSigner } = await import("../signer-5TA7FUC3.js");
38
+ const { loadSigner, loadOrCreateSigner } = await import("../signer-WAMDZHEN.js");
40
39
  const existing = await loadSigner(deps.adapter, deps.vault, deps.getDEK);
41
40
  if (existing) return { keyId: existing.keyId, publicKeyB64: existing.publicKeyB64 };
42
41
  if (deps.role !== "owner") {
@@ -46,19 +45,19 @@ function withAttestation() {
46
45
  return { keyId: signer.keyId, publicKeyB64: signer.publicKeyB64 };
47
46
  },
48
47
  async revokeAttestation(ctx, docId) {
49
- const { revokeDocCore: revokeDocCore2 } = await import("../revoke-PUJKRYJF.js");
48
+ const { revokeDocCore: revokeDocCore2 } = await import("../revoke-DQDZAZZM.js");
50
49
  return revokeDocCore2(ctx, docId);
51
50
  },
52
51
  async unrevokeAttestation(ctx, docId) {
53
- const { unrevokeDocCore: unrevokeDocCore2 } = await import("../revoke-PUJKRYJF.js");
52
+ const { unrevokeDocCore: unrevokeDocCore2 } = await import("../revoke-DQDZAZZM.js");
54
53
  return unrevokeDocCore2(ctx, docId);
55
54
  },
56
55
  async getRevokedDocIds(ctx) {
57
- const { getRevokedDocIdsCore: getRevokedDocIdsCore2 } = await import("../revoke-PUJKRYJF.js");
56
+ const { getRevokedDocIdsCore: getRevokedDocIdsCore2 } = await import("../revoke-DQDZAZZM.js");
58
57
  return getRevokedDocIdsCore2(ctx);
59
58
  },
60
59
  async publishRevocationList(ctx) {
61
- const { publishRevocationListCore: publishRevocationListCore2 } = await import("../revoke-PUJKRYJF.js");
60
+ const { publishRevocationListCore: publishRevocationListCore2 } = await import("../revoke-DQDZAZZM.js");
62
61
  return publishRevocationListCore2(ctx);
63
62
  }
64
63
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/with-audit/attestation/active.ts","../../src/with-audit/attestation/index.ts"],"sourcesContent":["import { AttestationError } from '../../kernel/errors.js'\nimport type { AttestationStrategy } from './strategy.js'\n\n/**\n * Enable the attestation capability.\n * Pass to `createNoydb({ attestationStrategy: withAttestation() })` to make the\n * vault's `issueAttestation` / `getDocumentSigningPublicKey` / `revokeAttestation`\n * / `unrevokeAttestation` / `getRevokedDocIds` / `publishRevocationList` methods\n * live. The issue/revoke/signer engines are dynamically imported here, so they\n * stay out of the floor bundle until opted in.\n */\nexport function withAttestation(): AttestationStrategy {\n return {\n async issueAttestation(ctx, args) {\n const { issueAttestationCore } = await import('./issue.js')\n return issueAttestationCore(ctx, args)\n },\n async getDocumentSigningPublicKey(deps) {\n const { loadSigner, loadOrCreateSigner } = await import('./signer.js')\n // Reading an existing public key is open to any role that holds the\n // _attestations DEK — the public key is not secret. But MINTING the\n // signer is the firm's identity operation (same rule as issueAttestation):\n // a non-owner read must not silently create it.\n const existing = await loadSigner(deps.adapter, deps.vault, deps.getDEK)\n if (existing) return { keyId: existing.keyId, publicKeyB64: existing.publicKeyB64 }\n if (deps.role !== 'owner') {\n throw new AttestationError(`getDocumentSigningPublicKey: no document-signing key exists yet; only the 'owner' may mint it. Caller is '${deps.role}'. Have the owner issue an attestation (or call this) first.`)\n }\n const signer = await loadOrCreateSigner(deps.adapter, deps.vault, deps.getDEK)\n return { keyId: signer.keyId, publicKeyB64: signer.publicKeyB64 }\n },\n async revokeAttestation(ctx, docId) {\n const { revokeDocCore } = await import('./revoke.js')\n return revokeDocCore(ctx, docId)\n },\n async unrevokeAttestation(ctx, docId) {\n const { unrevokeDocCore } = await import('./revoke.js')\n return unrevokeDocCore(ctx, docId)\n },\n async getRevokedDocIds(ctx) {\n const { getRevokedDocIdsCore } = await import('./revoke.js')\n return getRevokedDocIdsCore(ctx)\n },\n async publishRevocationList(ctx) {\n const { publishRevocationListCore } = await import('./revoke.js')\n return publishRevocationListCore(ctx)\n },\n }\n}\n","/**\n * @category capability\n * Document attestation — issue side. Mint a signed, per-field commitment\n * for a record and emit a QR credential verifiable offline via\n * `@noy-db/attestation`. See design-history/2026-05-29-attestation-core-and-issue-design.md.\n */\nexport { withAttestation } from './active.js'\nexport { NO_ATTESTATION, type AttestationStrategy } from './strategy.js'\nexport { AttestationNotEnabledError } from '../../kernel/errors.js'\nexport { issueAttestationCore } from './issue.js'\nexport type { IssueContext, IssueArgs, IssueResult } from './issue.js'\nexport { ATTESTATIONS_COLLECTION } from './signer.js'\nexport { revokeDocCore, unrevokeDocCore, getRevokedDocIdsCore, publishRevocationListCore } from './revoke.js'\nexport type { RevokeContext } from './revoke.js'\nexport { AttestationError } from '../../kernel/errors.js'\n// Re-export the pure verifier surface so consumers can verify from one import:\nexport { verifyAttestation, decodeQr, verifyRevocationList, isRevoked, signRevocationList, type QrPayload, type AttestationFieldSchema, type VerifyResult, type VerifyInput, type RevocationList } from '@noy-db/attestation'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWO,SAAS,kBAAuC;AACrD,SAAO;AAAA,IACL,MAAM,iBAAiB,KAAK,MAAM;AAChC,YAAM,EAAE,sBAAAA,sBAAqB,IAAI,MAAM,OAAO,sBAAY;AAC1D,aAAOA,sBAAqB,KAAK,IAAI;AAAA,IACvC;AAAA,IACA,MAAM,4BAA4B,MAAM;AACtC,YAAM,EAAE,YAAY,mBAAmB,IAAI,MAAM,OAAO,uBAAa;AAKrE,YAAM,WAAW,MAAM,WAAW,KAAK,SAAS,KAAK,OAAO,KAAK,MAAM;AACvE,UAAI,SAAU,QAAO,EAAE,OAAO,SAAS,OAAO,cAAc,SAAS,aAAa;AAClF,UAAI,KAAK,SAAS,SAAS;AACzB,cAAM,IAAI,iBAAiB,6GAA6G,KAAK,IAAI,8DAA8D;AAAA,MACjN;AACA,YAAM,SAAS,MAAM,mBAAmB,KAAK,SAAS,KAAK,OAAO,KAAK,MAAM;AAC7E,aAAO,EAAE,OAAO,OAAO,OAAO,cAAc,OAAO,aAAa;AAAA,IAClE;AAAA,IACA,MAAM,kBAAkB,KAAK,OAAO;AAClC,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,uBAAa;AACpD,aAAOA,eAAc,KAAK,KAAK;AAAA,IACjC;AAAA,IACA,MAAM,oBAAoB,KAAK,OAAO;AACpC,YAAM,EAAE,iBAAAC,iBAAgB,IAAI,MAAM,OAAO,uBAAa;AACtD,aAAOA,iBAAgB,KAAK,KAAK;AAAA,IACnC;AAAA,IACA,MAAM,iBAAiB,KAAK;AAC1B,YAAM,EAAE,sBAAAC,sBAAqB,IAAI,MAAM,OAAO,uBAAa;AAC3D,aAAOA,sBAAqB,GAAG;AAAA,IACjC;AAAA,IACA,MAAM,sBAAsB,KAAK;AAC/B,YAAM,EAAE,2BAAAC,2BAA0B,IAAI,MAAM,OAAO,uBAAa;AAChE,aAAOA,2BAA0B,GAAG;AAAA,IACtC;AAAA,EACF;AACF;;;AChCA,SAAS,mBAAmB,UAAU,sBAAsB,WAAW,0BAAiI;","names":["issueAttestationCore","revokeDocCore","unrevokeDocCore","getRevokedDocIdsCore","publishRevocationListCore"]}
1
+ {"version":3,"sources":["../../src/with-audit/attestation/active.ts","../../src/with-audit/attestation/index.ts"],"sourcesContent":["import { AttestationError } from '../../kernel/errors.js'\nimport type { AttestationStrategy } from './strategy.js'\n\n/**\n * Enable the attestation capability.\n * Pass to `createNoydb({ attestationStrategy: withAttestation() })` to make the\n * vault's `issueAttestation` / `getDocumentSigningPublicKey` / `revokeAttestation`\n * / `unrevokeAttestation` / `getRevokedDocIds` / `publishRevocationList` methods\n * live. The issue/revoke/signer engines are dynamically imported here, so they\n * stay out of the floor bundle until opted in.\n */\nexport function withAttestation(): AttestationStrategy {\n return {\n async issueAttestation(ctx, args) {\n const { issueAttestationCore } = await import('./issue.js')\n return issueAttestationCore(ctx, args)\n },\n async getDocumentSigningPublicKey(deps) {\n const { loadSigner, loadOrCreateSigner } = await import('./signer.js')\n // Reading an existing public key is open to any role that holds the\n // _attestations DEK — the public key is not secret. But MINTING the\n // signer is the firm's identity operation (same rule as issueAttestation):\n // a non-owner read must not silently create it.\n const existing = await loadSigner(deps.adapter, deps.vault, deps.getDEK)\n if (existing) return { keyId: existing.keyId, publicKeyB64: existing.publicKeyB64 }\n if (deps.role !== 'owner') {\n throw new AttestationError(`getDocumentSigningPublicKey: no document-signing key exists yet; only the 'owner' may mint it. Caller is '${deps.role}'. Have the owner issue an attestation (or call this) first.`)\n }\n const signer = await loadOrCreateSigner(deps.adapter, deps.vault, deps.getDEK)\n return { keyId: signer.keyId, publicKeyB64: signer.publicKeyB64 }\n },\n async revokeAttestation(ctx, docId) {\n const { revokeDocCore } = await import('./revoke.js')\n return revokeDocCore(ctx, docId)\n },\n async unrevokeAttestation(ctx, docId) {\n const { unrevokeDocCore } = await import('./revoke.js')\n return unrevokeDocCore(ctx, docId)\n },\n async getRevokedDocIds(ctx) {\n const { getRevokedDocIdsCore } = await import('./revoke.js')\n return getRevokedDocIdsCore(ctx)\n },\n async publishRevocationList(ctx) {\n const { publishRevocationListCore } = await import('./revoke.js')\n return publishRevocationListCore(ctx)\n },\n }\n}\n","/**\n * @category capability\n * Document attestation — issue side. Mint a signed, per-field commitment\n * for a record and emit a QR credential verifiable offline via\n * `@noy-db/attestation`. See design-history/2026-05-29-attestation-core-and-issue-design.md.\n */\nexport { withAttestation } from './active.js'\nexport { NO_ATTESTATION, type AttestationStrategy } from './strategy.js'\nexport { AttestationNotEnabledError } from '../../kernel/errors.js'\nexport { issueAttestationCore } from './issue.js'\nexport type { IssueContext, IssueArgs, IssueResult } from './issue.js'\nexport { ATTESTATIONS_COLLECTION } from './signer.js'\nexport { revokeDocCore, unrevokeDocCore, getRevokedDocIdsCore, publishRevocationListCore } from './revoke.js'\nexport type { RevokeContext } from './revoke.js'\nexport { AttestationError } from '../../kernel/errors.js'\n// Re-export the pure verifier surface so consumers can verify from one import:\nexport { verifyAttestation, decodeQr, verifyRevocationList, isRevoked, signRevocationList, type QrPayload, type AttestationFieldSchema, type VerifyResult, type VerifyInput, type RevocationList } from '@noy-db/attestation'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWO,SAAS,kBAAuC;AACrD,SAAO;AAAA,IACL,MAAM,iBAAiB,KAAK,MAAM;AAChC,YAAM,EAAE,sBAAAA,sBAAqB,IAAI,MAAM,OAAO,sBAAY;AAC1D,aAAOA,sBAAqB,KAAK,IAAI;AAAA,IACvC;AAAA,IACA,MAAM,4BAA4B,MAAM;AACtC,YAAM,EAAE,YAAY,mBAAmB,IAAI,MAAM,OAAO,uBAAa;AAKrE,YAAM,WAAW,MAAM,WAAW,KAAK,SAAS,KAAK,OAAO,KAAK,MAAM;AACvE,UAAI,SAAU,QAAO,EAAE,OAAO,SAAS,OAAO,cAAc,SAAS,aAAa;AAClF,UAAI,KAAK,SAAS,SAAS;AACzB,cAAM,IAAI,iBAAiB,6GAA6G,KAAK,IAAI,8DAA8D;AAAA,MACjN;AACA,YAAM,SAAS,MAAM,mBAAmB,KAAK,SAAS,KAAK,OAAO,KAAK,MAAM;AAC7E,aAAO,EAAE,OAAO,OAAO,OAAO,cAAc,OAAO,aAAa;AAAA,IAClE;AAAA,IACA,MAAM,kBAAkB,KAAK,OAAO;AAClC,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,uBAAa;AACpD,aAAOA,eAAc,KAAK,KAAK;AAAA,IACjC;AAAA,IACA,MAAM,oBAAoB,KAAK,OAAO;AACpC,YAAM,EAAE,iBAAAC,iBAAgB,IAAI,MAAM,OAAO,uBAAa;AACtD,aAAOA,iBAAgB,KAAK,KAAK;AAAA,IACnC;AAAA,IACA,MAAM,iBAAiB,KAAK;AAC1B,YAAM,EAAE,sBAAAC,sBAAqB,IAAI,MAAM,OAAO,uBAAa;AAC3D,aAAOA,sBAAqB,GAAG;AAAA,IACjC;AAAA,IACA,MAAM,sBAAsB,KAAK;AAC/B,YAAM,EAAE,2BAAAC,2BAA0B,IAAI,MAAM,OAAO,uBAAa;AAChE,aAAOA,2BAA0B,GAAG;AAAA,IACtC;AAAA,EACF;AACF;;;AChCA,SAAS,mBAAmB,UAAU,sBAAsB,WAAW,0BAAiI;","names":["issueAttestationCore","revokeDocCore","unrevokeDocCore","getRevokedDocIdsCore","publishRevocationListCore"]}
@@ -1,40 +1,39 @@
1
1
  import {
2
2
  MANIFEST_COLLECTION
3
3
  } from "./chunk-EPFF7LOX.js";
4
- import {
5
- SCHEMAS_COLLECTION
6
- } from "./chunk-I5LSKXT6.js";
7
4
  import {
8
5
  SEQUENCE_COLLECTION
9
- } from "./chunk-H5GVPOB4.js";
6
+ } from "./chunk-ZVO4QVPD.js";
7
+ import {
8
+ SCHEMAS_COLLECTION
9
+ } from "./chunk-2Y4IMKA6.js";
10
10
  import {
11
11
  PERIODS_COLLECTION,
12
12
  PERIOD_ARCHIVES_COLLECTION,
13
13
  PERIOD_FREEZES_COLLECTION,
14
14
  PERIOD_REOPENS_COLLECTION,
15
15
  PERIOD_TARGET_PURGES_COLLECTION
16
- } from "./chunk-Q2ZN5DWZ.js";
16
+ } from "./chunk-FAHMLERK.js";
17
17
  import {
18
18
  LEDGER_COLLECTION,
19
19
  LEDGER_DELTAS_COLLECTION
20
20
  } from "./chunk-I7FD46FF.js";
21
- import "./chunk-DOPZWTMJ.js";
21
+ import "./chunk-77K4PG6P.js";
22
22
  import {
23
23
  buildRecordEnvelope
24
- } from "./chunk-4RUFYGWG.js";
25
- import "./chunk-XGXVPCYW.js";
26
- import "./chunk-CWFH36SI.js";
27
- import "./chunk-KZTPL7NL.js";
24
+ } from "./chunk-SZJ3DLZA.js";
25
+ import "./chunk-BOWNCWZT.js";
26
+ import "./chunk-YSRUYAVU.js";
27
+ import "./chunk-RMF67KCG.js";
28
28
  import "./chunk-LP7BEXCT.js";
29
- import "./chunk-USKHHOIV.js";
29
+ import "./chunk-SL3JAAKN.js";
30
30
  import {
31
31
  NOYDB_BACKUP_VERSION
32
- } from "./chunk-N4CHCXDL.js";
32
+ } from "./chunk-7MG7SJT7.js";
33
33
  import {
34
34
  BackupCorruptedError,
35
35
  BackupLedgerError
36
- } from "./chunk-SW4TOSJL.js";
37
- import "./chunk-PZ5AY32C.js";
36
+ } from "./chunk-7O3Y4PPD.js";
38
37
 
39
38
  // src/with-pod/backup.ts
40
39
  async function dumpVault(ctx) {
@@ -262,4 +261,4 @@ export {
262
261
  loadVault,
263
262
  verifyBackupIntegrity
264
263
  };
265
- //# sourceMappingURL=backup-QZQEP5RO.js.map
264
+ //# sourceMappingURL=backup-IJTB4S4M.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/with-pod/backup.ts"],"sourcesContent":["/**\n * Vault backup / restore / integrity.\n *\n * Holds `dump()` (verifiable encrypted JSON backup, including the blob\n * collections so blob \"covers\" travel in the bundle), `load()` (restore +\n * post-load integrity gate), `verifyBackupIntegrity()` (chain + data-envelope\n * cross-check), and `exportJSON()` (plaintext per-collection export, built on\n * the vault's `exportStream`). Behaviour is byte-identical to the inline\n * `Vault` methods these functions replaced — every dependency the moving code\n * touched on `this.*` arrives via {@link BackupContext}. `Vault` keeps the\n * public methods as thin delegators.\n *\n * Internal — reached through `vault.dump()` / `vault.load()` / etc.\n */\nimport { NOYDB_BACKUP_VERSION } from '../kernel/types.js'\nimport { BackupLedgerError, BackupCorruptedError } from '../kernel/errors.js'\nimport { LEDGER_COLLECTION, LEDGER_DELTAS_COLLECTION } from '../with-commit/history/ledger/constants.js'\nimport { SCHEMAS_COLLECTION } from '../with-shape/persisted-schemas/storage.js'\nimport { SEQUENCE_COLLECTION } from '../with-commit/sequence/index.js'\nimport { MANIFEST_COLLECTION } from '../with-shape/manifest/reserved-collections.js'\n// #1025 — imported from the dependency-light `window.ts`, not `periods.ts`: that\n// module exists precisely so a consumer can name the period collections without\n// dragging the ledger hash-chain machinery (`sha256Hex`/`canonicalJson`) into a\n// bundle that opted out of the periods service. Same reason the sync engine's\n// period-scoped pull imports it.\nimport {\n PERIODS_COLLECTION,\n PERIOD_FREEZES_COLLECTION,\n PERIOD_ARCHIVES_COLLECTION,\n PERIOD_TARGET_PURGES_COLLECTION,\n PERIOD_REOPENS_COLLECTION,\n} from '../with-audit/periods/window.js'\nimport type {\n NoydbStore,\n EncryptedEnvelope,\n VaultBackup,\n VaultSnapshot,\n ExportStreamOptions,\n ExportChunk,\n} from '../kernel/types.js'\nimport type { LedgerStore } from '../with-commit/history/ledger/store.js'\nimport { buildRecordEnvelope } from '../kernel/enclave/index.js'\n\n/** Everything the moving backup methods touched on the vault's `this.*`. */\nexport interface BackupContext {\n /** The ciphertext store. */\n readonly adapter: NoydbStore\n /** Vault namespace name. */\n readonly vault: string\n /** The invoking keyring's user id (read fresh per call). */\n userId(): string\n /** The vault's ledger store, or null when history is off. */\n getLedgerOrNull(): LedgerStore | null\n /** Recompute an envelope's `payloadHash` (bound `historyStrategy.envelopePayloadHash`). */\n envelopePayloadHash(envelope: EncryptedEnvelope): Promise<string>\n /**\n * Refresh the in-memory keyring from the freshly-loaded keyring file and\n * rebuild the DEK resolver. No-op when the vault has no `reloadKeyring`\n * callback (plaintext vaults / test constructions).\n */\n reloadKeyringAndRebuildDEK(): Promise<void>\n /** Clear the vault's collection cache (post-load). */\n clearCollectionCache(): void\n /** Reset the ledger store so the next `ledger()` rebuilds its head cache. */\n resetLedgerStore(): void\n /** The vault's decrypt+ACL export stream (used by `exportJSON`). */\n exportStream(opts: ExportStreamOptions): AsyncIterableIterator<ExportChunk>\n}\n\n/** Result of {@link verifyBackupIntegrity}. */\nexport type VerifyBackupResult =\n | { readonly ok: true; readonly head: string; readonly length: number }\n | {\n readonly ok: false\n readonly kind: 'chain'\n readonly divergedAt: number\n readonly message: string\n }\n | {\n readonly ok: false\n readonly kind: 'data'\n readonly collection: string\n readonly id: string\n readonly message: string\n }\n\n/**\n * Dump vault as a verifiable encrypted JSON backup string.\n *\n * backups embed the current ledger head and the full `_ledger` +\n * `_ledger_deltas` internal collections so the receiver can run\n * `verifyBackupIntegrity()` after `load()` and detect any tampering between\n * dump and restore. Backups produced without a ledger skip the integrity check\n * with a warning — both modes round-trip cleanly.\n */\nexport async function dumpVault(ctx: BackupContext): Promise<string> {\n const snapshot = await ctx.adapter.loadAll(ctx.vault)\n\n // Load keyrings (separate path because loadAll filters them out\n // along with all other underscore-prefixed internal collections).\n const keyringIds = await ctx.adapter.list(ctx.vault, '_keyring')\n const keyrings: Record<string, unknown> = {}\n for (const keyringId of keyringIds) {\n const envelope = await ctx.adapter.get(ctx.vault, '_keyring', keyringId)\n if (envelope) {\n keyrings[keyringId] = JSON.parse(envelope._data)\n }\n }\n\n // Load the ledger entries + deltas so the receiver can replay\n // the chain after restore. Without this, `load()` would have an\n // empty ledger and `verifyBackupIntegrity()` would have nothing\n // to compare against.\n //\n // Also enumerate the blob collections so blob content (\"covers\")\n // travels in the bundle (the blob DEK already travels in `_keyring`).\n // Literals are inlined (not imported from blobs/blob-set.ts) to keep\n // the blob runtime out of this kernel hot path — they mirror\n // BLOB_INDEX/CHUNKS/EVICTION_AUDIT_COLLECTION and SLOTS/VERSIONS_PREFIX.\n // The collect-loop skips empty ids, so this no-ops without blobs.\n const internalSnapshot: VaultSnapshot = {}\n const internalNames = [\n LEDGER_COLLECTION, LEDGER_DELTAS_COLLECTION, SCHEMAS_COLLECTION, SEQUENCE_COLLECTION,\n MANIFEST_COLLECTION, // #941: the pod's manifest-set record(s) travel in the bundle too\n // #1025: the accounting-period close state + its companions. The bundle is\n // the backup/restore path, so without these a restore discarded the\n // hash-chained evidence that a month was ever closed — the artifact\n // `closePeriod` exists to produce — and dropped the write gate with it, so\n // the restored vault silently accepted back-dated writes into a sealed\n // month. The companions matter as much as the close: a bounded reopen\n // window (`reopenPeriod({ until })`) is state a restore must not lose.\n PERIODS_COLLECTION,\n PERIOD_REOPENS_COLLECTION,\n PERIOD_FREEZES_COLLECTION,\n PERIOD_ARCHIVES_COLLECTION,\n PERIOD_TARGET_PURGES_COLLECTION,\n '_history', // full-snapshot version history — so history()/getVersion()/diff() survive the bundle\n '_blob_index', '_blob_chunks', '_blob_eviction_audit',\n // #753 spec §7 Q3: `_blob_intent` markers travel too — restoring mid-op\n // state (a blob row without its marker) would reproduce the ambiguity\n // the journal exists to prevent. Note: `_mv_stale` does NOT travel\n // today (a pre-existing, separate gap) — observed here, tracked on\n // #761, not fixed in this pass.\n '_blob_intent',\n // #769: `_blob_slots_<c>` envelopes travel verbatim (raw ciphertext,\n // same DEK, same vault) — including any `SlotRecord.pendingRelease`\n // resume breadcrumb they carry. This is INTENTIONALLY the opposite of\n // `extract-partition`'s `reKeyBlobs`, which STRIPS `pendingRelease`:\n // a full-vault backup restores into the SAME vault it was taken from,\n // so a breadcrumb taken mid-rehome (together with its `_blob_intent`\n // marker, carried above) is resumable on restore — carry-and-resume is\n // correct here. A partition extraction crosses vaults: the breadcrumb's\n // old eTag may not exist in the destination, so it must be stripped\n // there instead. Asymmetry: backup = same-vault-resumable = carry;\n // partition = cross-vault = strip-breadcrumb-carry-marker.\n ...Object.keys(snapshot).flatMap((c) => [`_blob_slots_${c}`, `_blob_versions_${c}`]),\n ]\n for (const internalName of internalNames) {\n const ids = await ctx.adapter.list(ctx.vault, internalName)\n if (ids.length === 0) continue\n const records: Record<string, EncryptedEnvelope> = {}\n for (const id of ids) {\n const envelope = await ctx.adapter.get(ctx.vault, internalName, id)\n if (envelope) records[id] = envelope\n }\n internalSnapshot[internalName] = records\n }\n\n // Embed the ledger head if there's a chain. An empty ledger\n // (fresh vault) leaves `ledgerHead` undefined, which\n // load() treats the same as a legacy backup (no integrity\n // check, console warning). If history is not opted in,\n // `getLedgerOrNull` returns null and we skip embedding entirely\n // — the backup is still valid, just without the integrity head.\n const ledgerForHead = ctx.getLedgerOrNull()\n const head = ledgerForHead ? await ledgerForHead.head() : null\n const backup: VaultBackup = {\n _noydb_backup: NOYDB_BACKUP_VERSION,\n _compartment: ctx.vault,\n _exported_at: new Date().toISOString(),\n _exported_by: ctx.userId(),\n keyrings: keyrings as VaultBackup['keyrings'],\n collections: snapshot,\n ...(Object.keys(internalSnapshot).length > 0\n ? { _internal: internalSnapshot }\n : {}),\n ...(head\n ? {\n ledgerHead: {\n hash: head.hash,\n index: head.entry.index,\n ts: head.entry.ts,\n },\n }\n : {}),\n }\n\n return JSON.stringify(backup)\n}\n\n/**\n * Restore a vault from a verifiable backup. After loading, runs\n * `verifyBackupIntegrity()` to confirm the hash chain, the embedded head, and\n * every data envelope's payload hash. Legacy backups (no `ledgerHead`) load\n * with a console warning and skip the integrity check.\n */\nexport async function loadVault(ctx: BackupContext, backupJson: string): Promise<void> {\n const backup = JSON.parse(backupJson) as VaultBackup\n\n // 1. Restore data collections.\n await ctx.adapter.saveAll(ctx.vault, backup.collections)\n\n // 2. Restore keyrings.\n for (const [userId, keyringFile] of Object.entries(backup.keyrings)) {\n const envelope = buildRecordEnvelope({ collection: '_keyring', id: userId, version: 1 },\n { iv: '', data: JSON.stringify(keyringFile) })\n await ctx.adapter.put(ctx.vault, '_keyring', userId, envelope)\n }\n\n // 3. Restore internal collections (`_ledger`, `_ledger_deltas`).\n // Required so verifyBackupIntegrity has the chain to walk.\n if (backup._internal) {\n for (const [internalName, records] of Object.entries(backup._internal)) {\n for (const [id, envelope] of Object.entries(records)) {\n await ctx.adapter.put(ctx.vault, internalName, id, envelope)\n }\n }\n }\n\n // 4. Refresh the in-memory keyring from the freshly-loaded\n // keyring file. Without this, the Vault's getDEK\n // closure still holds the OLD session's DEKs, and every\n // decrypt of a loaded ledger entry / data envelope fails\n // with TamperedError because the DEK doesn't match the\n // ciphertext that was encrypted with the SOURCE user's DEK.\n // Skipped for plaintext vaults and for tests that\n // construct Vault without a reloadKeyring callback.\n await ctx.reloadKeyringAndRebuildDEK()\n\n // 5. Clear collection cache + reset the ledger store so the\n // next ledger() call rebuilds its head cache from the\n // freshly-loaded entries.\n ctx.clearCollectionCache()\n ctx.resetLedgerStore()\n\n // 5. Run the verification gate. Legacy backups (no ledgerHead)\n // skip this with a one-line warning so existing consumers can\n // still read them while migrating.\n if (!backup.ledgerHead) {\n console.warn(\n `[noy-db] Loaded a legacy backup with no ledgerHead — ` +\n `verifiable-backup integrity check skipped. ` +\n `Re-export with a ledger-aware build to get tamper detection.`,\n )\n return\n }\n\n const result = await verifyBackupIntegrity(ctx)\n if (!result.ok) {\n // Surface the most specific error class we can. The result\n // shape carries enough info for callers to inspect.\n if (result.kind === 'data') {\n throw new BackupCorruptedError(\n result.collection,\n result.id,\n result.message,\n )\n }\n throw new BackupLedgerError(result.message, result.divergedAt)\n }\n\n // 6. Cross-check: the freshly-verified head must match the\n // value embedded at dump time. A mismatch means someone\n // truncated or extended the chain after dump.\n if (result.head !== backup.ledgerHead.hash) {\n throw new BackupLedgerError(\n `Backup ledger head mismatch: embedded \"${backup.ledgerHead.hash}\" ` +\n `but reconstructed \"${result.head}\".`,\n )\n }\n}\n\n/**\n * End-to-end backup integrity check: `ledger.verify()` (hash chain) plus a data\n * envelope cross-check (every current record's `_data` hash must match the\n * latest `put` entry's `payloadHash`). Returns a discriminated union so callers\n * can distinguish chain vs data failures.\n */\nexport async function verifyBackupIntegrity(ctx: BackupContext): Promise<VerifyBackupResult> {\n // Step 1: chain verification. Without the history strategy there\n // is no ledger; an unaudited backup verifies trivially as `ok`\n // because there's nothing to diverge from.\n const ledgerForVerify = ctx.getLedgerOrNull()\n if (!ledgerForVerify) {\n return { ok: true, head: '', length: 0 }\n }\n const chainResult = await ledgerForVerify.verify()\n if (!chainResult.ok) {\n return {\n ok: false,\n kind: 'chain',\n divergedAt: chainResult.divergedAt,\n message:\n `Ledger chain diverged at index ${chainResult.divergedAt}: ` +\n `expected prevHash \"${chainResult.expected}\" but found \"${chainResult.actual}\".`,\n }\n }\n\n // Step 2: data envelope cross-check. Walk every entry in the\n // ledger and, for the LATEST `put` per (collection, id), recompute\n // the data envelope's payloadHash and compare. Earlier puts of the\n // same id are skipped because the data collection only holds the\n // current version — historical envelopes live in the deltas\n // collection (which is itself protected by the chain).\n // Reuse the ledger we already resolved in step 1.\n const allEntries = await ledgerForVerify.loadAllEntries()\n\n // Find the latest non-delete entry per (collection, id). Walk\n // the entries in reverse so we hit the latest first; mark each\n // (collection, id) as seen and skip subsequent entries.\n const seen = new Set<string>()\n const latest = new Map<\n string,\n { collection: string; id: string; expectedHash: string }\n >()\n for (let i = allEntries.length - 1; i >= 0; i--) {\n const entry = allEntries[i]\n if (!entry) continue\n // Amendment entries are multi-record audit entries whose\n // `collection` and `id` are empty strings — building a `\"/\"`\n // key here would mark that synthetic slot as seen and falsely\n // trip the data check on a record that never existed. Skip\n // them BEFORE the key/seen bookkeeping so they neither\n // tombstone real entries nor enter the latest map.\n if (entry.op === 'amendment' || entry.op === 'lifecycle') continue\n const key = `${entry.collection}/${entry.id}`\n if (seen.has(key)) continue\n seen.add(key)\n // For deletes the data collection should NOT have the record,\n // so we skip — there's nothing to cross-check. Marking the key\n // as seen above ensures any earlier `put` of the same id is\n // also skipped (the record was subsequently deleted).\n if (entry.op === 'delete') continue\n latest.set(key, {\n collection: entry.collection,\n id: entry.id,\n expectedHash: entry.payloadHash,\n })\n }\n\n for (const { collection, id, expectedHash } of latest.values()) {\n const envelope = await ctx.adapter.get(ctx.vault, collection, id)\n if (!envelope) {\n return {\n ok: false,\n kind: 'data',\n collection,\n id,\n message:\n `Ledger expects data record \"${collection}/${id}\" to exist, ` +\n `but the adapter has no envelope for it.`,\n }\n }\n const actualHash = await ctx.envelopePayloadHash(envelope)\n if (actualHash !== expectedHash) {\n return {\n ok: false,\n kind: 'data',\n collection,\n id,\n message:\n `Data envelope \"${collection}/${id}\" has been tampered with: ` +\n `expected payloadHash \"${expectedHash}\", got \"${actualHash}\".`,\n }\n }\n }\n\n return {\n ok: true,\n head: chainResult.head,\n length: chainResult.length,\n }\n}\n\n/**\n * Plaintext per-collection export, built on the vault's `exportStream`. Forces\n * collection granularity (record-by-record output makes no sense in a single\n * string) and merges dictionary snapshots across collections.\n */\nexport async function exportVaultJSON(ctx: BackupContext, opts: ExportStreamOptions = {}): Promise<string> {\n // Force per-collection granularity regardless of caller setting:\n // record-by-record output doesn't make sense in a single string.\n const collections: Record<\n string,\n {\n schema: null\n refs: Record<string, { target: string; mode: 'strict' | 'warn' | 'cascade' }>\n records: unknown[]\n }\n > = {}\n let ledgerHead: ExportChunk['ledgerHead'] | undefined\n // Merged dictionary snapshot across all collections.\n // Only populated when `resolveLabels` is not set.\n const allDictionaries: Record<\n string, // collection name\n Record<string, Record<string, Record<string, string>>>\n > = {}\n\n for await (const chunk of ctx.exportStream({\n granularity: 'collection',\n withLedgerHead: opts.withLedgerHead === true,\n // Thread the export locale so records are read at the\n // `export` layer (i18nText collapsed + dictKey/staticDict labels resolved).\n ...(opts.resolveLabels !== undefined ? { resolveLabels: opts.resolveLabels } : {}),\n })) {\n collections[chunk.collection] = {\n schema: null, // Standard Schema validators are not JSON-serializable\n refs: chunk.refs,\n records: chunk.records,\n }\n if (chunk.ledgerHead) ledgerHead = chunk.ledgerHead\n // Collect dictionary snapshots unless resolveLabels is set\n if (!opts.resolveLabels && chunk.dictionaries) {\n allDictionaries[chunk.collection] = chunk.dictionaries\n }\n }\n\n const hasDictionaries = Object.keys(allDictionaries).length > 0\n return JSON.stringify({\n _noydb_export: 1,\n _compartment: ctx.vault,\n _exported_at: new Date().toISOString(),\n _exported_by: ctx.userId(),\n collections,\n ...(hasDictionaries ? { _dictionaries: allDictionaries } : {}),\n ...(ledgerHead ? { ledgerHead } : {}),\n })\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/with-pod/backup.ts"],"sourcesContent":["/**\n * Vault backup / restore / integrity.\n *\n * Holds `dump()` (verifiable encrypted JSON backup, including the blob\n * collections so blob \"covers\" travel in the bundle), `load()` (restore +\n * post-load integrity gate), `verifyBackupIntegrity()` (chain + data-envelope\n * cross-check), and `exportJSON()` (plaintext per-collection export, built on\n * the vault's `exportStream`). Behaviour is byte-identical to the inline\n * `Vault` methods these functions replaced — every dependency the moving code\n * touched on `this.*` arrives via {@link BackupContext}. `Vault` keeps the\n * public methods as thin delegators.\n *\n * Internal — reached through `vault.dump()` / `vault.load()` / etc.\n */\nimport { NOYDB_BACKUP_VERSION } from '../kernel/types.js'\nimport { BackupLedgerError, BackupCorruptedError } from '../kernel/errors.js'\nimport { LEDGER_COLLECTION, LEDGER_DELTAS_COLLECTION } from '../with-commit/history/ledger/constants.js'\nimport { SCHEMAS_COLLECTION } from '../with-shape/persisted-schemas/storage.js'\nimport { SEQUENCE_COLLECTION } from '../with-commit/sequence/index.js'\nimport { MANIFEST_COLLECTION } from '../with-shape/manifest/reserved-collections.js'\n// #1025 — imported from the dependency-light `window.ts`, not `periods.ts`: that\n// module exists precisely so a consumer can name the period collections without\n// dragging the ledger hash-chain machinery (`sha256Hex`/`canonicalJson`) into a\n// bundle that opted out of the periods service. Same reason the sync engine's\n// period-scoped pull imports it.\nimport {\n PERIODS_COLLECTION,\n PERIOD_FREEZES_COLLECTION,\n PERIOD_ARCHIVES_COLLECTION,\n PERIOD_TARGET_PURGES_COLLECTION,\n PERIOD_REOPENS_COLLECTION,\n} from '../with-audit/periods/window.js'\nimport type {\n NoydbStore,\n EncryptedEnvelope,\n VaultBackup,\n VaultSnapshot,\n ExportStreamOptions,\n ExportChunk,\n} from '../kernel/types.js'\nimport type { LedgerStore } from '../with-commit/history/ledger/store.js'\nimport { buildRecordEnvelope } from '../kernel/enclave/index.js'\n\n/** Everything the moving backup methods touched on the vault's `this.*`. */\nexport interface BackupContext {\n /** The ciphertext store. */\n readonly adapter: NoydbStore\n /** Vault namespace name. */\n readonly vault: string\n /** The invoking keyring's user id (read fresh per call). */\n userId(): string\n /** The vault's ledger store, or null when history is off. */\n getLedgerOrNull(): LedgerStore | null\n /** Recompute an envelope's `payloadHash` (bound `historyStrategy.envelopePayloadHash`). */\n envelopePayloadHash(envelope: EncryptedEnvelope): Promise<string>\n /**\n * Refresh the in-memory keyring from the freshly-loaded keyring file and\n * rebuild the DEK resolver. No-op when the vault has no `reloadKeyring`\n * callback (plaintext vaults / test constructions).\n */\n reloadKeyringAndRebuildDEK(): Promise<void>\n /** Clear the vault's collection cache (post-load). */\n clearCollectionCache(): void\n /** Reset the ledger store so the next `ledger()` rebuilds its head cache. */\n resetLedgerStore(): void\n /** The vault's decrypt+ACL export stream (used by `exportJSON`). */\n exportStream(opts: ExportStreamOptions): AsyncIterableIterator<ExportChunk>\n}\n\n/** Result of {@link verifyBackupIntegrity}. */\nexport type VerifyBackupResult =\n | { readonly ok: true; readonly head: string; readonly length: number }\n | {\n readonly ok: false\n readonly kind: 'chain'\n readonly divergedAt: number\n readonly message: string\n }\n | {\n readonly ok: false\n readonly kind: 'data'\n readonly collection: string\n readonly id: string\n readonly message: string\n }\n\n/**\n * Dump vault as a verifiable encrypted JSON backup string.\n *\n * backups embed the current ledger head and the full `_ledger` +\n * `_ledger_deltas` internal collections so the receiver can run\n * `verifyBackupIntegrity()` after `load()` and detect any tampering between\n * dump and restore. Backups produced without a ledger skip the integrity check\n * with a warning — both modes round-trip cleanly.\n */\nexport async function dumpVault(ctx: BackupContext): Promise<string> {\n const snapshot = await ctx.adapter.loadAll(ctx.vault)\n\n // Load keyrings (separate path because loadAll filters them out\n // along with all other underscore-prefixed internal collections).\n const keyringIds = await ctx.adapter.list(ctx.vault, '_keyring')\n const keyrings: Record<string, unknown> = {}\n for (const keyringId of keyringIds) {\n const envelope = await ctx.adapter.get(ctx.vault, '_keyring', keyringId)\n if (envelope) {\n keyrings[keyringId] = JSON.parse(envelope._data)\n }\n }\n\n // Load the ledger entries + deltas so the receiver can replay\n // the chain after restore. Without this, `load()` would have an\n // empty ledger and `verifyBackupIntegrity()` would have nothing\n // to compare against.\n //\n // Also enumerate the blob collections so blob content (\"covers\")\n // travels in the bundle (the blob DEK already travels in `_keyring`).\n // Literals are inlined (not imported from blobs/blob-set.ts) to keep\n // the blob runtime out of this kernel hot path — they mirror\n // BLOB_INDEX/CHUNKS/EVICTION_AUDIT_COLLECTION and SLOTS/VERSIONS_PREFIX.\n // The collect-loop skips empty ids, so this no-ops without blobs.\n const internalSnapshot: VaultSnapshot = {}\n const internalNames = [\n LEDGER_COLLECTION, LEDGER_DELTAS_COLLECTION, SCHEMAS_COLLECTION, SEQUENCE_COLLECTION,\n MANIFEST_COLLECTION, // #941: the pod's manifest-set record(s) travel in the bundle too\n // #1025: the accounting-period close state + its companions. The bundle is\n // the backup/restore path, so without these a restore discarded the\n // hash-chained evidence that a month was ever closed — the artifact\n // `closePeriod` exists to produce — and dropped the write gate with it, so\n // the restored vault silently accepted back-dated writes into a sealed\n // month. The companions matter as much as the close: a bounded reopen\n // window (`reopenPeriod({ until })`) is state a restore must not lose.\n PERIODS_COLLECTION,\n PERIOD_REOPENS_COLLECTION,\n PERIOD_FREEZES_COLLECTION,\n PERIOD_ARCHIVES_COLLECTION,\n PERIOD_TARGET_PURGES_COLLECTION,\n '_history', // full-snapshot version history — so history()/getVersion()/diff() survive the bundle\n '_blob_index', '_blob_chunks', '_blob_eviction_audit',\n // #753 spec §7 Q3: `_blob_intent` markers travel too — restoring mid-op\n // state (a blob row without its marker) would reproduce the ambiguity\n // the journal exists to prevent. Note: `_mv_stale` does NOT travel\n // today (a pre-existing, separate gap) — observed here, tracked on\n // #761, not fixed in this pass.\n '_blob_intent',\n // #769: `_blob_slots_<c>` envelopes travel verbatim (raw ciphertext,\n // same DEK, same vault) — including any `SlotRecord.pendingRelease`\n // resume breadcrumb they carry. This is INTENTIONALLY the opposite of\n // `extract-partition`'s `reKeyBlobs`, which STRIPS `pendingRelease`:\n // a full-vault backup restores into the SAME vault it was taken from,\n // so a breadcrumb taken mid-rehome (together with its `_blob_intent`\n // marker, carried above) is resumable on restore — carry-and-resume is\n // correct here. A partition extraction crosses vaults: the breadcrumb's\n // old eTag may not exist in the destination, so it must be stripped\n // there instead. Asymmetry: backup = same-vault-resumable = carry;\n // partition = cross-vault = strip-breadcrumb-carry-marker.\n ...Object.keys(snapshot).flatMap((c) => [`_blob_slots_${c}`, `_blob_versions_${c}`]),\n ]\n for (const internalName of internalNames) {\n const ids = await ctx.adapter.list(ctx.vault, internalName)\n if (ids.length === 0) continue\n const records: Record<string, EncryptedEnvelope> = {}\n for (const id of ids) {\n const envelope = await ctx.adapter.get(ctx.vault, internalName, id)\n if (envelope) records[id] = envelope\n }\n internalSnapshot[internalName] = records\n }\n\n // Embed the ledger head if there's a chain. An empty ledger\n // (fresh vault) leaves `ledgerHead` undefined, which\n // load() treats the same as a legacy backup (no integrity\n // check, console warning). If history is not opted in,\n // `getLedgerOrNull` returns null and we skip embedding entirely\n // — the backup is still valid, just without the integrity head.\n const ledgerForHead = ctx.getLedgerOrNull()\n const head = ledgerForHead ? await ledgerForHead.head() : null\n const backup: VaultBackup = {\n _noydb_backup: NOYDB_BACKUP_VERSION,\n _compartment: ctx.vault,\n _exported_at: new Date().toISOString(),\n _exported_by: ctx.userId(),\n keyrings: keyrings as VaultBackup['keyrings'],\n collections: snapshot,\n ...(Object.keys(internalSnapshot).length > 0\n ? { _internal: internalSnapshot }\n : {}),\n ...(head\n ? {\n ledgerHead: {\n hash: head.hash,\n index: head.entry.index,\n ts: head.entry.ts,\n },\n }\n : {}),\n }\n\n return JSON.stringify(backup)\n}\n\n/**\n * Restore a vault from a verifiable backup. After loading, runs\n * `verifyBackupIntegrity()` to confirm the hash chain, the embedded head, and\n * every data envelope's payload hash. Legacy backups (no `ledgerHead`) load\n * with a console warning and skip the integrity check.\n */\nexport async function loadVault(ctx: BackupContext, backupJson: string): Promise<void> {\n const backup = JSON.parse(backupJson) as VaultBackup\n\n // 1. Restore data collections.\n await ctx.adapter.saveAll(ctx.vault, backup.collections)\n\n // 2. Restore keyrings.\n for (const [userId, keyringFile] of Object.entries(backup.keyrings)) {\n const envelope = buildRecordEnvelope({ collection: '_keyring', id: userId, version: 1 },\n { iv: '', data: JSON.stringify(keyringFile) })\n await ctx.adapter.put(ctx.vault, '_keyring', userId, envelope)\n }\n\n // 3. Restore internal collections (`_ledger`, `_ledger_deltas`).\n // Required so verifyBackupIntegrity has the chain to walk.\n if (backup._internal) {\n for (const [internalName, records] of Object.entries(backup._internal)) {\n for (const [id, envelope] of Object.entries(records)) {\n await ctx.adapter.put(ctx.vault, internalName, id, envelope)\n }\n }\n }\n\n // 4. Refresh the in-memory keyring from the freshly-loaded\n // keyring file. Without this, the Vault's getDEK\n // closure still holds the OLD session's DEKs, and every\n // decrypt of a loaded ledger entry / data envelope fails\n // with TamperedError because the DEK doesn't match the\n // ciphertext that was encrypted with the SOURCE user's DEK.\n // Skipped for plaintext vaults and for tests that\n // construct Vault without a reloadKeyring callback.\n await ctx.reloadKeyringAndRebuildDEK()\n\n // 5. Clear collection cache + reset the ledger store so the\n // next ledger() call rebuilds its head cache from the\n // freshly-loaded entries.\n ctx.clearCollectionCache()\n ctx.resetLedgerStore()\n\n // 5. Run the verification gate. Legacy backups (no ledgerHead)\n // skip this with a one-line warning so existing consumers can\n // still read them while migrating.\n if (!backup.ledgerHead) {\n console.warn(\n `[noy-db] Loaded a legacy backup with no ledgerHead — ` +\n `verifiable-backup integrity check skipped. ` +\n `Re-export with a ledger-aware build to get tamper detection.`,\n )\n return\n }\n\n const result = await verifyBackupIntegrity(ctx)\n if (!result.ok) {\n // Surface the most specific error class we can. The result\n // shape carries enough info for callers to inspect.\n if (result.kind === 'data') {\n throw new BackupCorruptedError(\n result.collection,\n result.id,\n result.message,\n )\n }\n throw new BackupLedgerError(result.message, result.divergedAt)\n }\n\n // 6. Cross-check: the freshly-verified head must match the\n // value embedded at dump time. A mismatch means someone\n // truncated or extended the chain after dump.\n if (result.head !== backup.ledgerHead.hash) {\n throw new BackupLedgerError(\n `Backup ledger head mismatch: embedded \"${backup.ledgerHead.hash}\" ` +\n `but reconstructed \"${result.head}\".`,\n )\n }\n}\n\n/**\n * End-to-end backup integrity check: `ledger.verify()` (hash chain) plus a data\n * envelope cross-check (every current record's `_data` hash must match the\n * latest `put` entry's `payloadHash`). Returns a discriminated union so callers\n * can distinguish chain vs data failures.\n */\nexport async function verifyBackupIntegrity(ctx: BackupContext): Promise<VerifyBackupResult> {\n // Step 1: chain verification. Without the history strategy there\n // is no ledger; an unaudited backup verifies trivially as `ok`\n // because there's nothing to diverge from.\n const ledgerForVerify = ctx.getLedgerOrNull()\n if (!ledgerForVerify) {\n return { ok: true, head: '', length: 0 }\n }\n const chainResult = await ledgerForVerify.verify()\n if (!chainResult.ok) {\n return {\n ok: false,\n kind: 'chain',\n divergedAt: chainResult.divergedAt,\n message:\n `Ledger chain diverged at index ${chainResult.divergedAt}: ` +\n `expected prevHash \"${chainResult.expected}\" but found \"${chainResult.actual}\".`,\n }\n }\n\n // Step 2: data envelope cross-check. Walk every entry in the\n // ledger and, for the LATEST `put` per (collection, id), recompute\n // the data envelope's payloadHash and compare. Earlier puts of the\n // same id are skipped because the data collection only holds the\n // current version — historical envelopes live in the deltas\n // collection (which is itself protected by the chain).\n // Reuse the ledger we already resolved in step 1.\n const allEntries = await ledgerForVerify.loadAllEntries()\n\n // Find the latest non-delete entry per (collection, id). Walk\n // the entries in reverse so we hit the latest first; mark each\n // (collection, id) as seen and skip subsequent entries.\n const seen = new Set<string>()\n const latest = new Map<\n string,\n { collection: string; id: string; expectedHash: string }\n >()\n for (let i = allEntries.length - 1; i >= 0; i--) {\n const entry = allEntries[i]\n if (!entry) continue\n // Amendment entries are multi-record audit entries whose\n // `collection` and `id` are empty strings — building a `\"/\"`\n // key here would mark that synthetic slot as seen and falsely\n // trip the data check on a record that never existed. Skip\n // them BEFORE the key/seen bookkeeping so they neither\n // tombstone real entries nor enter the latest map.\n if (entry.op === 'amendment' || entry.op === 'lifecycle') continue\n const key = `${entry.collection}/${entry.id}`\n if (seen.has(key)) continue\n seen.add(key)\n // For deletes the data collection should NOT have the record,\n // so we skip — there's nothing to cross-check. Marking the key\n // as seen above ensures any earlier `put` of the same id is\n // also skipped (the record was subsequently deleted).\n if (entry.op === 'delete') continue\n latest.set(key, {\n collection: entry.collection,\n id: entry.id,\n expectedHash: entry.payloadHash,\n })\n }\n\n for (const { collection, id, expectedHash } of latest.values()) {\n const envelope = await ctx.adapter.get(ctx.vault, collection, id)\n if (!envelope) {\n return {\n ok: false,\n kind: 'data',\n collection,\n id,\n message:\n `Ledger expects data record \"${collection}/${id}\" to exist, ` +\n `but the adapter has no envelope for it.`,\n }\n }\n const actualHash = await ctx.envelopePayloadHash(envelope)\n if (actualHash !== expectedHash) {\n return {\n ok: false,\n kind: 'data',\n collection,\n id,\n message:\n `Data envelope \"${collection}/${id}\" has been tampered with: ` +\n `expected payloadHash \"${expectedHash}\", got \"${actualHash}\".`,\n }\n }\n }\n\n return {\n ok: true,\n head: chainResult.head,\n length: chainResult.length,\n }\n}\n\n/**\n * Plaintext per-collection export, built on the vault's `exportStream`. Forces\n * collection granularity (record-by-record output makes no sense in a single\n * string) and merges dictionary snapshots across collections.\n */\nexport async function exportVaultJSON(ctx: BackupContext, opts: ExportStreamOptions = {}): Promise<string> {\n // Force per-collection granularity regardless of caller setting:\n // record-by-record output doesn't make sense in a single string.\n const collections: Record<\n string,\n {\n schema: null\n refs: Record<string, { target: string; mode: 'strict' | 'warn' | 'cascade' }>\n records: unknown[]\n }\n > = {}\n let ledgerHead: ExportChunk['ledgerHead'] | undefined\n // Merged dictionary snapshot across all collections.\n // Only populated when `resolveLabels` is not set.\n const allDictionaries: Record<\n string, // collection name\n Record<string, Record<string, Record<string, string>>>\n > = {}\n\n for await (const chunk of ctx.exportStream({\n granularity: 'collection',\n withLedgerHead: opts.withLedgerHead === true,\n // Thread the export locale so records are read at the\n // `export` layer (i18nText collapsed + dictKey/staticDict labels resolved).\n ...(opts.resolveLabels !== undefined ? { resolveLabels: opts.resolveLabels } : {}),\n })) {\n collections[chunk.collection] = {\n schema: null, // Standard Schema validators are not JSON-serializable\n refs: chunk.refs,\n records: chunk.records,\n }\n if (chunk.ledgerHead) ledgerHead = chunk.ledgerHead\n // Collect dictionary snapshots unless resolveLabels is set\n if (!opts.resolveLabels && chunk.dictionaries) {\n allDictionaries[chunk.collection] = chunk.dictionaries\n }\n }\n\n const hasDictionaries = Object.keys(allDictionaries).length > 0\n return JSON.stringify({\n _noydb_export: 1,\n _compartment: ctx.vault,\n _exported_at: new Date().toISOString(),\n _exported_by: ctx.userId(),\n collections,\n ...(hasDictionaries ? { _dictionaries: allDictionaries } : {}),\n ...(ledgerHead ? { ledgerHead } : {}),\n })\n}\n"],"mappings":"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","names":[]}
@@ -10,7 +10,7 @@ import {
10
10
  createExportBlobsHandle,
11
11
  reportOrphanBlobChunks,
12
12
  runCompaction
13
- } from "../chunk-IS5LFHV2.js";
13
+ } from "../chunk-AO42KJO6.js";
14
14
  import {
15
15
  BLOB_CHUNKS_COLLECTION,
16
16
  BLOB_COLLECTION,
@@ -25,22 +25,21 @@ import {
25
25
  detectMimeType,
26
26
  isPreCompressed,
27
27
  memoryBlobPinStore
28
- } from "../chunk-HS3LEVT4.js";
29
- import "../chunk-YHIAWECL.js";
30
- import "../chunk-DZPMKY3J.js";
31
- import "../chunk-IZTU6RKH.js";
32
- import "../chunk-DOPZWTMJ.js";
33
- import "../chunk-4RUFYGWG.js";
34
- import "../chunk-XGXVPCYW.js";
35
- import "../chunk-CWFH36SI.js";
36
- import "../chunk-KZTPL7NL.js";
28
+ } from "../chunk-BM5TWITZ.js";
29
+ import "../chunk-UXVWEX5L.js";
30
+ import "../chunk-UGTBXF5U.js";
31
+ import "../chunk-JMGDHKQF.js";
32
+ import "../chunk-77K4PG6P.js";
33
+ import "../chunk-SZJ3DLZA.js";
34
+ import "../chunk-BOWNCWZT.js";
35
+ import "../chunk-YSRUYAVU.js";
36
+ import "../chunk-RMF67KCG.js";
37
37
  import "../chunk-LP7BEXCT.js";
38
- import "../chunk-USKHHOIV.js";
39
- import "../chunk-N4CHCXDL.js";
38
+ import "../chunk-SL3JAAKN.js";
39
+ import "../chunk-7MG7SJT7.js";
40
40
  import {
41
41
  BlobOfflineError
42
- } from "../chunk-SW4TOSJL.js";
43
- import "../chunk-PZ5AY32C.js";
42
+ } from "../chunk-7O3Y4PPD.js";
44
43
 
45
44
  // src/via/blob/active.ts
46
45
  function withBlobs(options = {}) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/via/blob/active.ts"],"sourcesContent":["/**\n * Active blob strategy factory. Calling `blobs()` returns a\n * `BlobsStrategy` whose `openSlot` constructs a real `BlobSet` bound\n * to the caller's record. The returned strategy is passed into\n * `createNoydb({ blobsStrategy: blobs() })` to light up the\n * `collection.blob(id)` path.\n *\n * This module is only reachable through the `@noy-db/hub/blobs`\n * subpath — a consumer that never imports the subpath ships none of\n * this (ESM tree-shaking + hub's `\"sideEffects\": false`).\n */\n\nimport { BlobSet } from '../../with-shape/blobs/blob-set.js'\nimport type { BlobsStrategy } from '../../port/with/blob-strategy.js'\nimport { createBlobPinCache } from '../../with-shape/blobs/blob-pinning.js'\nimport type { BlobPinStore } from '../../with-shape/blobs/blob-pinning.js'\n\n/** Options for {@link withBlobs} (#808). */\nexport interface WithBlobsOptions {\n /**\n * Device-local backend for the offline-pin registry + external side-cache\n * (`collection.blob(id).pin()`, the `cacheBudget` LRU stamps). Default:\n * in-memory — pins then last one app session. Supply a durable,\n * DEVICE-LOCAL store (IndexedDB-backed on the web; it must never sync) to\n * keep pins across restarts. See `BlobPinStore`'s doc for the posture.\n */\n readonly pinStore?: BlobPinStore\n}\n\n/**\n * Build a default `BlobsStrategy` ready to pass into `createNoydb`.\n *\n * Named `withBlobs` (plugin-pattern canonical) rather than `blobs` to\n * avoid shadowing the very common local idiom\n * `const blobs = invoices.blob(id)` in user code.\n *\n * One `withBlobs()` instance owns one device-local pin registry + KPI\n * counter set (#808) — treat it as \"this device's\" blob service.\n *\n * @example\n * ```ts\n * import { createNoydb } from '@noy-db/hub'\n * import { withBlobs } from '@noy-db/hub/blobs'\n *\n * const db = await createNoydb({\n * store, user, secret,\n * blobsStrategy: withBlobs(),\n * })\n *\n * // Now live — delegates to BlobSet.\n * const vault = await db.openVault('acme')\n * await vault.collection('invoices').blob('inv-1').put('receipt.pdf', bytes)\n * ```\n */\nexport function withBlobs(options: WithBlobsOptions = {}): BlobsStrategy {\n const pinCache = createBlobPinCache(options.pinStore)\n return {\n openSlot(args) {\n return new BlobSet({ ...args, pinCache })\n },\n cacheStats() {\n return { ...pinCache.stats }\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDO,SAAS,UAAU,UAA4B,CAAC,GAAkB;AACvE,QAAM,WAAW,mBAAmB,QAAQ,QAAQ;AACpD,SAAO;AAAA,IACL,SAAS,MAAM;AACb,aAAO,IAAI,QAAQ,EAAE,GAAG,MAAM,SAAS,CAAC;AAAA,IAC1C;AAAA,IACA,aAAa;AACX,aAAO,EAAE,GAAG,SAAS,MAAM;AAAA,IAC7B;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/via/blob/active.ts"],"sourcesContent":["/**\n * Active blob strategy factory. Calling `blobs()` returns a\n * `BlobsStrategy` whose `openSlot` constructs a real `BlobSet` bound\n * to the caller's record. The returned strategy is passed into\n * `createNoydb({ blobsStrategy: blobs() })` to light up the\n * `collection.blob(id)` path.\n *\n * This module is only reachable through the `@noy-db/hub/blobs`\n * subpath — a consumer that never imports the subpath ships none of\n * this (ESM tree-shaking + hub's `\"sideEffects\": false`).\n */\n\nimport { BlobSet } from '../../with-shape/blobs/blob-set.js'\nimport type { BlobsStrategy } from '../../port/with/blob-strategy.js'\nimport { createBlobPinCache } from '../../with-shape/blobs/blob-pinning.js'\nimport type { BlobPinStore } from '../../with-shape/blobs/blob-pinning.js'\n\n/** Options for {@link withBlobs} (#808). */\nexport interface WithBlobsOptions {\n /**\n * Device-local backend for the offline-pin registry + external side-cache\n * (`collection.blob(id).pin()`, the `cacheBudget` LRU stamps). Default:\n * in-memory — pins then last one app session. Supply a durable,\n * DEVICE-LOCAL store (IndexedDB-backed on the web; it must never sync) to\n * keep pins across restarts. See `BlobPinStore`'s doc for the posture.\n */\n readonly pinStore?: BlobPinStore\n}\n\n/**\n * Build a default `BlobsStrategy` ready to pass into `createNoydb`.\n *\n * Named `withBlobs` (plugin-pattern canonical) rather than `blobs` to\n * avoid shadowing the very common local idiom\n * `const blobs = invoices.blob(id)` in user code.\n *\n * One `withBlobs()` instance owns one device-local pin registry + KPI\n * counter set (#808) — treat it as \"this device's\" blob service.\n *\n * @example\n * ```ts\n * import { createNoydb } from '@noy-db/hub'\n * import { withBlobs } from '@noy-db/hub/blobs'\n *\n * const db = await createNoydb({\n * store, user, secret,\n * blobsStrategy: withBlobs(),\n * })\n *\n * // Now live — delegates to BlobSet.\n * const vault = await db.openVault('acme')\n * await vault.collection('invoices').blob('inv-1').put('receipt.pdf', bytes)\n * ```\n */\nexport function withBlobs(options: WithBlobsOptions = {}): BlobsStrategy {\n const pinCache = createBlobPinCache(options.pinStore)\n return {\n openSlot(args) {\n return new BlobSet({ ...args, pinCache })\n },\n cacheStats() {\n return { ...pinCache.stats }\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDO,SAAS,UAAU,UAA4B,CAAC,GAAkB;AACvE,QAAM,WAAW,mBAAmB,QAAQ,QAAQ;AACpD,SAAO;AAAA,IACL,SAAS,MAAM;AACb,aAAO,IAAI,QAAQ,EAAE,GAAG,MAAM,SAAS,CAAC;AAAA,IAC1C;AAAA,IACA,aAAa;AACX,aAAO,EAAE,GAAG,SAAS,MAAM;AAAA,IAC7B;AAAA,EACF;AACF;","names":[]}
@@ -1,23 +1,22 @@
1
1
  import {
2
2
  NO_BROKER
3
- } from "../chunk-PV7XXAXK.js";
3
+ } from "../chunk-JBDFMYKQ.js";
4
4
  import {
5
5
  issueChallenge,
6
6
  verifyBrokerProof
7
- } from "../chunk-DOPZWTMJ.js";
8
- import "../chunk-4RUFYGWG.js";
9
- import "../chunk-XGXVPCYW.js";
10
- import "../chunk-CWFH36SI.js";
11
- import "../chunk-KZTPL7NL.js";
7
+ } from "../chunk-77K4PG6P.js";
8
+ import "../chunk-SZJ3DLZA.js";
9
+ import "../chunk-BOWNCWZT.js";
10
+ import "../chunk-YSRUYAVU.js";
11
+ import "../chunk-RMF67KCG.js";
12
12
  import "../chunk-LP7BEXCT.js";
13
- import "../chunk-USKHHOIV.js";
14
- import "../chunk-N4CHCXDL.js";
13
+ import "../chunk-SL3JAAKN.js";
14
+ import "../chunk-7MG7SJT7.js";
15
15
  import {
16
16
  BrokerEnrolmentError,
17
17
  BrokerNotEnabledError,
18
18
  BrokerProofError
19
- } from "../chunk-SW4TOSJL.js";
20
- import "../chunk-PZ5AY32C.js";
19
+ } from "../chunk-7O3Y4PPD.js";
21
20
 
22
21
  // src/with-party/broker/active.ts
23
22
  var DEFAULT_SKEW_MS = 6e4;
@@ -30,7 +29,7 @@ function withBroker(config) {
30
29
  const cache = /* @__PURE__ */ new Map();
31
30
  return {
32
31
  async enroll(ctx) {
33
- const { enrollSeed } = await import("../seed-CG7JMJNY.js");
32
+ const { enrollSeed } = await import("../seed-G42JYN56.js");
34
33
  return enrollSeed({ ...ctx, config });
35
34
  },
36
35
  async rotate(ctx) {
@@ -39,7 +38,7 @@ function withBroker(config) {
39
38
  const inFlight = scoped.map(([, e]) => e.inFlight).filter((p) => p !== void 0);
40
39
  await Promise.allSettled(inFlight);
41
40
  for (const [key] of scoped) cache.delete(key);
42
- const { rotateSeed } = await import("../seed-CG7JMJNY.js");
41
+ const { rotateSeed } = await import("../seed-G42JYN56.js");
43
42
  return rotateSeed({ ...ctx, config });
44
43
  },
45
44
  credentialSource(ctx, profile) {
@@ -56,7 +55,7 @@ function withBroker(config) {
56
55
  const skewMs = config.skewMs ?? DEFAULT_SKEW_MS;
57
56
  const capturedEntry = entry;
58
57
  const inFlight = (async () => {
59
- const { mintStoreCredentials } = await import("../seed-CG7JMJNY.js");
58
+ const { mintStoreCredentials } = await import("../seed-G42JYN56.js");
60
59
  const creds = await mintStoreCredentials({ ...ctx, config }, profile);
61
60
  capturedEntry.cached = { creds, validUntil: cacheFloor(creds, skewMs) };
62
61
  return creds;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/with-party/broker/active.ts","../../src/with-party/broker/index.ts"],"sourcesContent":["/**\n * Enable the credential-broker capability (#479, spec §5).\n *\n * Pass to `createNoydb({ brokerStrategy: withBroker(config) })` to make\n * `vault.broker()` live. Each method dynamic-imports the seed lifecycle\n * engine (`./seed.js`) — mirroring `via/classified/active.ts`'s per-method\n * dynamic-import seam — so `with-party/broker/seed.ts` (the heavy module:\n * the CAS enrol, quiesce-then-swap rotate, and the challenge/response round\n * trip) is reachable only through the `@noy-db/hub/broker` subpath and\n * never enters the single-user floor bundle.\n *\n * The single-flight, per-vault-per-profile refresh cache (H-6/I6) lives\n * HERE, in this factory's closure — shared across every `credentialSource(profile)`\n * call for this one broker instance (in turn shared across every vault of a\n * `createNoydb()` instance — `vault.broker()` passes the SAME `BrokerStrategy`\n * for all of them), so `rotate()` can quiesce it (await any in-flight\n * round-trip, then drop it) before the seed swap. The cache key is\n * `${vault}\\0${profile}` — keyed by vault FIRST, or two vaults sharing this\n * one strategy would collide and hand vault-B a cached credential minted\n * (and STS-scoped) for vault-A.\n */\nimport type { BrokerStrategy, BrokerConfig, BrokerCtx } from '../../port/with/broker-strategy.js'\nimport type { StoreCredentials, StoreCredentialSource } from '../../kernel/types.js'\n\nconst DEFAULT_SKEW_MS = 60_000\n/** Floor under the skew-adjusted boundary so a sub-skew credential TTL\n * doesn't collapse to \"already expired\" and thrash re-proving every call (I6b). */\nconst MIN_CACHE_MS = 1_000\n\ninterface CacheEntry {\n cached?: { creds: StoreCredentials; validUntil: number } | undefined\n inFlight?: Promise<StoreCredentials> | undefined\n}\n\nfunction cacheFloor(creds: StoreCredentials, skewMs: number): number {\n const expiresAtMs = creds.expiresAt ? Date.parse(creds.expiresAt) : Date.now() + skewMs * 2\n return Math.max(expiresAtMs - skewMs, Date.now() + MIN_CACHE_MS)\n}\n\nexport function withBroker(config: BrokerConfig): BrokerStrategy {\n const cache = new Map<string, CacheEntry>()\n\n return {\n async enroll(ctx) {\n const { enrollSeed } = await import('./seed.js')\n return enrollSeed({ ...ctx, config })\n },\n async rotate(ctx) {\n // Quiesce (I5): let any in-flight round-trip finish (it may still be\n // proving under the pre-rotation seed) before the local record is\n // overwritten, then drop the cache — scoped to THIS vault's entries\n // only (`${ctx.vault}\\0`-prefixed keys). A global cache.clear() here\n // would blow away every OTHER vault's cache on this shared strategy\n // too — same root cause as the cross-vault read collision this fixes.\n const vaultPrefix = `${ctx.vault}\\0`\n const scoped = [...cache.entries()].filter(([key]) => key.startsWith(vaultPrefix))\n const inFlight = scoped.map(([, e]) => e.inFlight).filter((p): p is Promise<StoreCredentials> => p !== undefined)\n await Promise.allSettled(inFlight)\n for (const [key] of scoped) cache.delete(key)\n const { rotateSeed } = await import('./seed.js')\n return rotateSeed({ ...ctx, config })\n },\n credentialSource(ctx: BrokerCtx, profile?: string): StoreCredentialSource {\n const key = `${ctx.vault}\\0${profile ?? ''}`\n return async () => {\n let entry = cache.get(key)\n if (!entry) {\n entry = {}\n cache.set(key, entry)\n }\n const now = Date.now()\n if (entry.cached && now < entry.cached.validUntil) return entry.cached.creds\n if (entry.inFlight) return entry.inFlight\n\n const skewMs = config.skewMs ?? DEFAULT_SKEW_MS\n const capturedEntry = entry\n const inFlight = (async () => {\n const { mintStoreCredentials } = await import('./seed.js')\n const creds = await mintStoreCredentials({ ...ctx, config }, profile)\n capturedEntry.cached = { creds, validUntil: cacheFloor(creds, skewMs) }\n return creds\n })()\n entry.inFlight = inFlight\n try {\n return await inFlight\n } finally {\n // Clear-on-settle (I6a): a rejected in-flight promise must never\n // stay pinned in the cache, or every subsequent call would wedge\n // on the same rejection instead of retrying.\n capturedEntry.inFlight = undefined\n }\n }\n },\n }\n}\n","/**\n * `@noy-db/hub/broker` — subpath export for the credential-broker capability\n * (#479, credential-broker spec). Apps that never call `vault.broker()` can\n * exclude this subpath entirely: the floor default `NO_BROKER` throws, and\n * this module's real engine (`with-party/broker/{seed,active}.ts`) is only\n * ever reached through `withBroker()`'s dynamic imports, so it never enters\n * a floor bundle.\n *\n * Also re-exports the host-side helpers (`issueChallenge`, `verifyBrokerProof`)\n * from the enclave barrel, so a Lambda/Worker implementing the reference\n * broker host can import just this one subpath and get everything it\n * needs, `crypto.subtle`-only.\n */\n\n// ─── Capability opt-in seam ──────────────────────────────────\nexport { withBroker } from './active.js'\nexport {\n NO_BROKER,\n type BrokerStrategy,\n type BrokerCtx,\n type BrokerConfig,\n type CredentialBrokerHandle,\n} from '../../port/with/broker-strategy.js'\nexport { BrokerNotEnabledError, BrokerEnrolmentError, BrokerProofError } from '../../kernel/errors.js'\n\n// ─── Host helpers (verify side — for a reference broker host) ───\nimport { issueChallenge as issueChallengeRaw, verifyBrokerProof } from '../../kernel/enclave/index.js'\nimport type { IssuedChallenge, VerifyBrokerProofArgs } from '../../kernel/enclave/index.js'\n\n/**\n * Floor — a challenge TTL must survive network latency + clock drift\n * between host and client. The enclave's `issueChallenge` is deliberately\n * unclamped (a mechanical primitive, not a policy); this floor is host\n * POLICY, so it lives here in the party layer, not\n * `kernel/enclave/broker/proof.ts` (carried forward from Task 2's review,\n * I6b).\n */\nconst MIN_CHALLENGE_TTL_MS = 10_000\n/** Ceiling — spec §2 step 2: \"TTL ≤ 60 s\". */\nconst MAX_CHALLENGE_TTL_MS = 60_000\n\n/**\n * {@link issueChallengeRaw} (the enclave's mechanical primitive) with a\n * `[10s, 60s]` TTL clamp applied, so a reference host built on this barrel\n * gets a safe challenge TTL without having to know the bounds itself.\n */\nexport function issueChallenge(opts?: { ttlMs?: number }): IssuedChallenge {\n const requested = opts?.ttlMs ?? MAX_CHALLENGE_TTL_MS\n const clamped = Math.min(Math.max(requested, MIN_CHALLENGE_TTL_MS), MAX_CHALLENGE_TTL_MS)\n return issueChallengeRaw({ ttlMs: clamped })\n}\nexport { verifyBrokerProof }\nexport type { VerifyBrokerProofArgs }\n\n// #837 — issueChallenge's return type must be nameable from this entry.\nexport type { IssuedChallenge } from '../../kernel/enclave/index.js'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwBA,IAAM,kBAAkB;AAGxB,IAAM,eAAe;AAOrB,SAAS,WAAW,OAAyB,QAAwB;AACnE,QAAM,cAAc,MAAM,YAAY,KAAK,MAAM,MAAM,SAAS,IAAI,KAAK,IAAI,IAAI,SAAS;AAC1F,SAAO,KAAK,IAAI,cAAc,QAAQ,KAAK,IAAI,IAAI,YAAY;AACjE;AAEO,SAAS,WAAW,QAAsC;AAC/D,QAAM,QAAQ,oBAAI,IAAwB;AAE1C,SAAO;AAAA,IACL,MAAM,OAAO,KAAK;AAChB,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,qBAAW;AAC/C,aAAO,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC;AAAA,IACtC;AAAA,IACA,MAAM,OAAO,KAAK;AAOhB,YAAM,cAAc,GAAG,IAAI,KAAK;AAChC,YAAM,SAAS,CAAC,GAAG,MAAM,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,IAAI,WAAW,WAAW,CAAC;AACjF,YAAM,WAAW,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAsC,MAAM,MAAS;AAChH,YAAM,QAAQ,WAAW,QAAQ;AACjC,iBAAW,CAAC,GAAG,KAAK,OAAQ,OAAM,OAAO,GAAG;AAC5C,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,qBAAW;AAC/C,aAAO,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC;AAAA,IACtC;AAAA,IACA,iBAAiB,KAAgB,SAAyC;AACxE,YAAM,MAAM,GAAG,IAAI,KAAK,KAAK,WAAW,EAAE;AAC1C,aAAO,YAAY;AACjB,YAAI,QAAQ,MAAM,IAAI,GAAG;AACzB,YAAI,CAAC,OAAO;AACV,kBAAQ,CAAC;AACT,gBAAM,IAAI,KAAK,KAAK;AAAA,QACtB;AACA,cAAM,MAAM,KAAK,IAAI;AACrB,YAAI,MAAM,UAAU,MAAM,MAAM,OAAO,WAAY,QAAO,MAAM,OAAO;AACvE,YAAI,MAAM,SAAU,QAAO,MAAM;AAEjC,cAAM,SAAS,OAAO,UAAU;AAChC,cAAM,gBAAgB;AACtB,cAAM,YAAY,YAAY;AAC5B,gBAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,qBAAW;AACzD,gBAAM,QAAQ,MAAM,qBAAqB,EAAE,GAAG,KAAK,OAAO,GAAG,OAAO;AACpE,wBAAc,SAAS,EAAE,OAAO,YAAY,WAAW,OAAO,MAAM,EAAE;AACtE,iBAAO;AAAA,QACT,GAAG;AACH,cAAM,WAAW;AACjB,YAAI;AACF,iBAAO,MAAM;AAAA,QACf,UAAE;AAIA,wBAAc,WAAW;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACzDA,IAAM,uBAAuB;AAE7B,IAAM,uBAAuB;AAOtB,SAASA,gBAAe,MAA4C;AACzE,QAAM,YAAY,MAAM,SAAS;AACjC,QAAM,UAAU,KAAK,IAAI,KAAK,IAAI,WAAW,oBAAoB,GAAG,oBAAoB;AACxF,SAAO,eAAkB,EAAE,OAAO,QAAQ,CAAC;AAC7C;","names":["issueChallenge"]}
1
+ {"version":3,"sources":["../../src/with-party/broker/active.ts","../../src/with-party/broker/index.ts"],"sourcesContent":["/**\n * Enable the credential-broker capability (#479, spec §5).\n *\n * Pass to `createNoydb({ brokerStrategy: withBroker(config) })` to make\n * `vault.broker()` live. Each method dynamic-imports the seed lifecycle\n * engine (`./seed.js`) — mirroring `via/classified/active.ts`'s per-method\n * dynamic-import seam — so `with-party/broker/seed.ts` (the heavy module:\n * the CAS enrol, quiesce-then-swap rotate, and the challenge/response round\n * trip) is reachable only through the `@noy-db/hub/broker` subpath and\n * never enters the single-user floor bundle.\n *\n * The single-flight, per-vault-per-profile refresh cache (H-6/I6) lives\n * HERE, in this factory's closure — shared across every `credentialSource(profile)`\n * call for this one broker instance (in turn shared across every vault of a\n * `createNoydb()` instance — `vault.broker()` passes the SAME `BrokerStrategy`\n * for all of them), so `rotate()` can quiesce it (await any in-flight\n * round-trip, then drop it) before the seed swap. The cache key is\n * `${vault}\\0${profile}` — keyed by vault FIRST, or two vaults sharing this\n * one strategy would collide and hand vault-B a cached credential minted\n * (and STS-scoped) for vault-A.\n */\nimport type { BrokerStrategy, BrokerConfig, BrokerCtx } from '../../port/with/broker-strategy.js'\nimport type { StoreCredentials, StoreCredentialSource } from '../../kernel/types.js'\n\nconst DEFAULT_SKEW_MS = 60_000\n/** Floor under the skew-adjusted boundary so a sub-skew credential TTL\n * doesn't collapse to \"already expired\" and thrash re-proving every call (I6b). */\nconst MIN_CACHE_MS = 1_000\n\ninterface CacheEntry {\n cached?: { creds: StoreCredentials; validUntil: number } | undefined\n inFlight?: Promise<StoreCredentials> | undefined\n}\n\nfunction cacheFloor(creds: StoreCredentials, skewMs: number): number {\n const expiresAtMs = creds.expiresAt ? Date.parse(creds.expiresAt) : Date.now() + skewMs * 2\n return Math.max(expiresAtMs - skewMs, Date.now() + MIN_CACHE_MS)\n}\n\nexport function withBroker(config: BrokerConfig): BrokerStrategy {\n const cache = new Map<string, CacheEntry>()\n\n return {\n async enroll(ctx) {\n const { enrollSeed } = await import('./seed.js')\n return enrollSeed({ ...ctx, config })\n },\n async rotate(ctx) {\n // Quiesce (I5): let any in-flight round-trip finish (it may still be\n // proving under the pre-rotation seed) before the local record is\n // overwritten, then drop the cache — scoped to THIS vault's entries\n // only (`${ctx.vault}\\0`-prefixed keys). A global cache.clear() here\n // would blow away every OTHER vault's cache on this shared strategy\n // too — same root cause as the cross-vault read collision this fixes.\n const vaultPrefix = `${ctx.vault}\\0`\n const scoped = [...cache.entries()].filter(([key]) => key.startsWith(vaultPrefix))\n const inFlight = scoped.map(([, e]) => e.inFlight).filter((p): p is Promise<StoreCredentials> => p !== undefined)\n await Promise.allSettled(inFlight)\n for (const [key] of scoped) cache.delete(key)\n const { rotateSeed } = await import('./seed.js')\n return rotateSeed({ ...ctx, config })\n },\n credentialSource(ctx: BrokerCtx, profile?: string): StoreCredentialSource {\n const key = `${ctx.vault}\\0${profile ?? ''}`\n return async () => {\n let entry = cache.get(key)\n if (!entry) {\n entry = {}\n cache.set(key, entry)\n }\n const now = Date.now()\n if (entry.cached && now < entry.cached.validUntil) return entry.cached.creds\n if (entry.inFlight) return entry.inFlight\n\n const skewMs = config.skewMs ?? DEFAULT_SKEW_MS\n const capturedEntry = entry\n const inFlight = (async () => {\n const { mintStoreCredentials } = await import('./seed.js')\n const creds = await mintStoreCredentials({ ...ctx, config }, profile)\n capturedEntry.cached = { creds, validUntil: cacheFloor(creds, skewMs) }\n return creds\n })()\n entry.inFlight = inFlight\n try {\n return await inFlight\n } finally {\n // Clear-on-settle (I6a): a rejected in-flight promise must never\n // stay pinned in the cache, or every subsequent call would wedge\n // on the same rejection instead of retrying.\n capturedEntry.inFlight = undefined\n }\n }\n },\n }\n}\n","/**\n * `@noy-db/hub/broker` — subpath export for the credential-broker capability\n * (#479, credential-broker spec). Apps that never call `vault.broker()` can\n * exclude this subpath entirely: the floor default `NO_BROKER` throws, and\n * this module's real engine (`with-party/broker/{seed,active}.ts`) is only\n * ever reached through `withBroker()`'s dynamic imports, so it never enters\n * a floor bundle.\n *\n * Also re-exports the host-side helpers (`issueChallenge`, `verifyBrokerProof`)\n * from the enclave barrel, so a Lambda/Worker implementing the reference\n * broker host can import just this one subpath and get everything it\n * needs, `crypto.subtle`-only.\n */\n\n// ─── Capability opt-in seam ──────────────────────────────────\nexport { withBroker } from './active.js'\nexport {\n NO_BROKER,\n type BrokerStrategy,\n type BrokerCtx,\n type BrokerConfig,\n type CredentialBrokerHandle,\n} from '../../port/with/broker-strategy.js'\nexport { BrokerNotEnabledError, BrokerEnrolmentError, BrokerProofError } from '../../kernel/errors.js'\n\n// ─── Host helpers (verify side — for a reference broker host) ───\nimport { issueChallenge as issueChallengeRaw, verifyBrokerProof } from '../../kernel/enclave/index.js'\nimport type { IssuedChallenge, VerifyBrokerProofArgs } from '../../kernel/enclave/index.js'\n\n/**\n * Floor — a challenge TTL must survive network latency + clock drift\n * between host and client. The enclave's `issueChallenge` is deliberately\n * unclamped (a mechanical primitive, not a policy); this floor is host\n * POLICY, so it lives here in the party layer, not\n * `kernel/enclave/broker/proof.ts` (carried forward from Task 2's review,\n * I6b).\n */\nconst MIN_CHALLENGE_TTL_MS = 10_000\n/** Ceiling — spec §2 step 2: \"TTL ≤ 60 s\". */\nconst MAX_CHALLENGE_TTL_MS = 60_000\n\n/**\n * {@link issueChallengeRaw} (the enclave's mechanical primitive) with a\n * `[10s, 60s]` TTL clamp applied, so a reference host built on this barrel\n * gets a safe challenge TTL without having to know the bounds itself.\n */\nexport function issueChallenge(opts?: { ttlMs?: number }): IssuedChallenge {\n const requested = opts?.ttlMs ?? MAX_CHALLENGE_TTL_MS\n const clamped = Math.min(Math.max(requested, MIN_CHALLENGE_TTL_MS), MAX_CHALLENGE_TTL_MS)\n return issueChallengeRaw({ ttlMs: clamped })\n}\nexport { verifyBrokerProof }\nexport type { VerifyBrokerProofArgs }\n\n// #837 — issueChallenge's return type must be nameable from this entry.\nexport type { IssuedChallenge } from '../../kernel/enclave/index.js'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwBA,IAAM,kBAAkB;AAGxB,IAAM,eAAe;AAOrB,SAAS,WAAW,OAAyB,QAAwB;AACnE,QAAM,cAAc,MAAM,YAAY,KAAK,MAAM,MAAM,SAAS,IAAI,KAAK,IAAI,IAAI,SAAS;AAC1F,SAAO,KAAK,IAAI,cAAc,QAAQ,KAAK,IAAI,IAAI,YAAY;AACjE;AAEO,SAAS,WAAW,QAAsC;AAC/D,QAAM,QAAQ,oBAAI,IAAwB;AAE1C,SAAO;AAAA,IACL,MAAM,OAAO,KAAK;AAChB,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,qBAAW;AAC/C,aAAO,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC;AAAA,IACtC;AAAA,IACA,MAAM,OAAO,KAAK;AAOhB,YAAM,cAAc,GAAG,IAAI,KAAK;AAChC,YAAM,SAAS,CAAC,GAAG,MAAM,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,IAAI,WAAW,WAAW,CAAC;AACjF,YAAM,WAAW,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAsC,MAAM,MAAS;AAChH,YAAM,QAAQ,WAAW,QAAQ;AACjC,iBAAW,CAAC,GAAG,KAAK,OAAQ,OAAM,OAAO,GAAG;AAC5C,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,qBAAW;AAC/C,aAAO,WAAW,EAAE,GAAG,KAAK,OAAO,CAAC;AAAA,IACtC;AAAA,IACA,iBAAiB,KAAgB,SAAyC;AACxE,YAAM,MAAM,GAAG,IAAI,KAAK,KAAK,WAAW,EAAE;AAC1C,aAAO,YAAY;AACjB,YAAI,QAAQ,MAAM,IAAI,GAAG;AACzB,YAAI,CAAC,OAAO;AACV,kBAAQ,CAAC;AACT,gBAAM,IAAI,KAAK,KAAK;AAAA,QACtB;AACA,cAAM,MAAM,KAAK,IAAI;AACrB,YAAI,MAAM,UAAU,MAAM,MAAM,OAAO,WAAY,QAAO,MAAM,OAAO;AACvE,YAAI,MAAM,SAAU,QAAO,MAAM;AAEjC,cAAM,SAAS,OAAO,UAAU;AAChC,cAAM,gBAAgB;AACtB,cAAM,YAAY,YAAY;AAC5B,gBAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,qBAAW;AACzD,gBAAM,QAAQ,MAAM,qBAAqB,EAAE,GAAG,KAAK,OAAO,GAAG,OAAO;AACpE,wBAAc,SAAS,EAAE,OAAO,YAAY,WAAW,OAAO,MAAM,EAAE;AACtE,iBAAO;AAAA,QACT,GAAG;AACH,cAAM,WAAW;AACjB,YAAI;AACF,iBAAO,MAAM;AAAA,QACf,UAAE;AAIA,wBAAc,WAAW;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACzDA,IAAM,uBAAuB;AAE7B,IAAM,uBAAuB;AAOtB,SAASA,gBAAe,MAA4C;AACzE,QAAM,YAAY,MAAM,SAAS;AACjC,QAAM,UAAU,KAAK,IAAI,KAAK,IAAI,WAAW,oBAAoB,GAAG,oBAAoB;AACxF,SAAO,eAAkB,EAAE,OAAO,QAAQ,CAAC;AAC7C;","names":["issueChallenge"]}
package/dist/by/index.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import {
2
2
  isQuorum,
3
3
  runDrainBarrier
4
- } from "../chunk-GHADG5QZ.js";
5
- import "../chunk-SW4TOSJL.js";
6
- import "../chunk-PZ5AY32C.js";
4
+ } from "../chunk-VTFVLCUH.js";
5
+ import "../chunk-7O3Y4PPD.js";
7
6
  export {
8
7
  isQuorum,
9
8
  runDrainBarrier