@noy-db/hub 0.7.0-pre.9 → 0.7.1-pre.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 (452) hide show
  1. package/CHANGELOG.md +1327 -0
  2. package/README.md +29 -11
  3. package/dist/api-WYW4YEQG.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-XKCXVKV3.js} +23 -18
  9. package/dist/backup-XKCXVKV3.js.map +1 -0
  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-SWFIXQF5.js → chunk-2ENE6445.js} +6 -6
  18. package/dist/{chunk-HLFLJCDX.js → chunk-2N5ML6HT.js} +7 -7
  19. package/dist/{chunk-X6YRP5EC.js → chunk-334WSVOW.js} +5 -5
  20. package/dist/{chunk-5EC7X5QA.js → chunk-3BVH633C.js} +5 -5
  21. package/dist/chunk-3BZZJJMQ.js +176 -0
  22. package/dist/chunk-3BZZJJMQ.js.map +1 -0
  23. package/dist/{chunk-7XT7KZTN.js → chunk-3PGS7TYR.js} +10 -10
  24. package/dist/{chunk-OHGCRKWA.js → chunk-3V4KWFX7.js} +18 -8
  25. package/dist/chunk-3V4KWFX7.js.map +1 -0
  26. package/dist/{chunk-AHIIBDNH.js → chunk-3VF3WQ4F.js} +7 -7
  27. package/dist/{chunk-GM4IM7TC.js → chunk-453F654R.js} +2 -2
  28. package/dist/{chunk-5W5CEHLA.js → chunk-4GFX6MPA.js} +6 -6
  29. package/dist/{chunk-JUBWUJY5.js → chunk-4GVM6QZA.js} +2 -2
  30. package/dist/{chunk-2DGBRE4K.js → chunk-4OZNXTO4.js} +2 -2
  31. package/dist/{chunk-DOPZWTMJ.js → chunk-4ZS56W5S.js} +8 -8
  32. package/dist/{chunk-P2RJAVMR.js → chunk-5VCRVKOZ.js} +4 -4
  33. package/dist/chunk-66TQOPFM.js +37 -0
  34. package/dist/chunk-66TQOPFM.js.map +1 -0
  35. package/dist/{chunk-FN26SFGH.js → chunk-6LKOJBV6.js} +2 -2
  36. package/dist/{chunk-P7KJME6C.js → chunk-6YXCPL4T.js} +2 -2
  37. package/dist/{chunk-IS5LFHV2.js → chunk-7APJ6CO6.js} +7 -7
  38. package/dist/{chunk-LAI7ENPW.js → chunk-7MG2LHO5.js} +3 -3
  39. package/dist/{chunk-N4CHCXDL.js → chunk-7MG7SJT7.js} +1 -1
  40. package/dist/{chunk-N4CHCXDL.js.map → chunk-7MG7SJT7.js.map} +1 -1
  41. package/dist/{chunk-SW4TOSJL.js → chunk-7O3Y4PPD.js} +1 -1
  42. package/dist/chunk-7O3Y4PPD.js.map +1 -0
  43. package/dist/{chunk-MU74BYOD.js → chunk-A2HKRLPV.js} +3 -3
  44. package/dist/{chunk-357ECVLE.js → chunk-A66I4JOA.js} +3 -3
  45. package/dist/{chunk-VT4DTCK5.js → chunk-ACAQ2DSG.js} +3 -3
  46. package/dist/chunk-ACAQ2DSG.js.map +1 -0
  47. package/dist/{chunk-TAJZ7GXO.js → chunk-AYX7AINO.js} +3 -3
  48. package/dist/{chunk-RPX2H2OL.js → chunk-BLN54W3L.js} +3 -3
  49. package/dist/{chunk-XGXVPCYW.js → chunk-BRLKZUBT.js} +3 -3
  50. package/dist/{chunk-CWFH36SI.js → chunk-BTDR2PXY.js} +2 -2
  51. package/dist/{chunk-65ZYRK7O.js → chunk-BUE2D7PX.js} +26 -3
  52. package/dist/chunk-BUE2D7PX.js.map +1 -0
  53. package/dist/{chunk-RCONOOVF.js → chunk-BVN6KXL2.js} +5 -5
  54. package/dist/chunk-BVN6KXL2.js.map +1 -0
  55. package/dist/{chunk-UTFY6W6X.js → chunk-BZ3534YM.js} +2 -2
  56. package/dist/{chunk-KZTPL7NL.js → chunk-CHQCZZWC.js} +2 -2
  57. package/dist/chunk-CUQPWYRX.js +1652 -0
  58. package/dist/chunk-CUQPWYRX.js.map +1 -0
  59. package/dist/{chunk-MQPHKJ74.js → chunk-DFMWUOU5.js} +12 -12
  60. package/dist/{chunk-3GIA3HJ2.js → chunk-DGOZ4UZD.js} +2 -2
  61. package/dist/{chunk-NMDMSHBF.js → chunk-EQEYOJBM.js} +3 -3
  62. package/dist/{chunk-OQDHIAR2.js → chunk-F3W6YMDC.js} +80 -8
  63. package/dist/chunk-F3W6YMDC.js.map +1 -0
  64. package/dist/{chunk-Q2ZN5DWZ.js → chunk-FAHMLERK.js} +2 -2
  65. package/dist/{chunk-PCIBCL26.js → chunk-FET5XCAT.js} +7 -5
  66. package/dist/{chunk-PCIBCL26.js.map → chunk-FET5XCAT.js.map} +1 -1
  67. package/dist/chunk-FFWI7UH7.js +53 -0
  68. package/dist/chunk-FFWI7UH7.js.map +1 -0
  69. package/dist/{chunk-GKOJR53Y.js → chunk-G73UVHCA.js} +5 -5
  70. package/dist/{chunk-H5GVPOB4.js → chunk-GPNTB4Y7.js} +5 -5
  71. package/dist/{chunk-DNMTN46H.js → chunk-GY4WYNNG.js} +2 -2
  72. package/dist/{chunk-HS3LEVT4.js → chunk-HIWCKBEY.js} +7 -7
  73. package/dist/{chunk-UL7TLJ54.js → chunk-HJUWN7JN.js} +6 -4
  74. package/dist/{chunk-UL7TLJ54.js.map → chunk-HJUWN7JN.js.map} +1 -1
  75. package/dist/{chunk-USKHHOIV.js → chunk-HPVZCW43.js} +30 -2
  76. package/dist/chunk-HPVZCW43.js.map +1 -0
  77. package/dist/{chunk-PV7XXAXK.js → chunk-JBDFMYKQ.js} +2 -2
  78. package/dist/{chunk-IZTU6RKH.js → chunk-JMGDHKQF.js} +2 -2
  79. package/dist/{chunk-P22XPNFW.js → chunk-JVIBCBC7.js} +2 -2
  80. package/dist/{chunk-OLUTCM23.js → chunk-K23VKTN4.js} +7 -7
  81. package/dist/{chunk-3SWP2FYA.js → chunk-KKEESNPE.js} +8 -8
  82. package/dist/{chunk-ZB2K3FV7.js → chunk-KTFRCC5C.js} +2 -2
  83. package/dist/{chunk-IAHDSFFA.js → chunk-LH5A3ZPG.js} +10 -10
  84. package/dist/{chunk-QOHGWFAW.js → chunk-LWBCUYZW.js} +2 -2
  85. package/dist/{chunk-5NKHCJU5.js → chunk-M4YPHYEH.js} +8 -8
  86. package/dist/{chunk-JFSUYGNE.js → chunk-MVMXZYXT.js} +2 -2
  87. package/dist/{chunk-FKQCC4C5.js → chunk-NQKIUNW5.js} +2 -2
  88. package/dist/{chunk-Q2OAAREU.js → chunk-OTQZ7ZWU.js} +6 -6
  89. package/dist/{chunk-MOQ6OGKS.js → chunk-P3MG6QCN.js} +4 -4
  90. package/dist/{chunk-75WNTBZL.js → chunk-PPTHY5QO.js} +3 -3
  91. package/dist/{chunk-TQGT5BZE.js → chunk-Q2MPFCQ7.js} +4 -4
  92. package/dist/{chunk-MTTPHBIE.js → chunk-Q2PU57HC.js} +2 -2
  93. package/dist/{chunk-FLRLZ4XZ.js → chunk-Q7HZX3IF.js} +2 -2
  94. package/dist/{chunk-KQIDBIZL.js → chunk-QIZPZMUI.js} +2 -2
  95. package/dist/{chunk-JRWLUWDM.js → chunk-QPQUVOZ2.js} +3 -3
  96. package/dist/{chunk-7YVSWPZB.js → chunk-QTQUH4DS.js} +7 -7
  97. package/dist/{chunk-2MQ2D5OZ.js → chunk-R42NSZI6.js} +5 -5
  98. package/dist/{chunk-FRIVOR5N.js → chunk-R7BX2NB3.js} +5 -172
  99. package/dist/chunk-R7BX2NB3.js.map +1 -0
  100. package/dist/{chunk-HOIWW2LV.js → chunk-RF6D3Y5E.js} +4 -4
  101. package/dist/{chunk-OEJ4R52I.js → chunk-RMS3NEA3.js} +2 -2
  102. package/dist/{chunk-FPN5D4JX.js → chunk-RSGLUIO6.js} +6 -6
  103. package/dist/chunk-RTBJ5IOO.js +87 -0
  104. package/dist/chunk-RTBJ5IOO.js.map +1 -0
  105. package/dist/chunk-RXLYKVTF.js +17 -0
  106. package/dist/chunk-RXLYKVTF.js.map +1 -0
  107. package/dist/{chunk-XKA6UH5V.js → chunk-SFAWCTEM.js} +2 -2
  108. package/dist/{chunk-I5LSKXT6.js → chunk-SGZAIJCV.js} +4 -4
  109. package/dist/{chunk-FYT3DXPN.js → chunk-SKGMN35F.js} +2 -2
  110. package/dist/chunk-SMH6SRX7.js +87 -0
  111. package/dist/chunk-SMH6SRX7.js.map +1 -0
  112. package/dist/{chunk-JILOSL4O.js → chunk-SPYWXKJN.js} +3 -3
  113. package/dist/{chunk-4RUFYGWG.js → chunk-SZJ3DLZA.js} +2 -2
  114. package/dist/chunk-TFMM5DBB.js +20 -0
  115. package/dist/chunk-TFMM5DBB.js.map +1 -0
  116. package/dist/{chunk-O3SNM66K.js → chunk-TFR7DSOV.js} +2 -2
  117. package/dist/{chunk-DIVY2CJZ.js → chunk-TRGTKX5E.js} +3 -3
  118. package/dist/{chunk-JY4U6CYV.js → chunk-TUFM4UZP.js} +2 -2
  119. package/dist/{chunk-LUVGSKXE.js → chunk-UDHWDSRL.js} +6 -6
  120. package/dist/{chunk-DZPMKY3J.js → chunk-UGTBXF5U.js} +3 -3
  121. package/dist/{chunk-K432FT7T.js → chunk-UHHPLO3I.js} +4 -4
  122. package/dist/{chunk-THNJ3IKU.js → chunk-ULUMAZ5S.js} +2 -2
  123. package/dist/{chunk-QJLOWGOU.js → chunk-UP4BECPY.js} +12 -82
  124. package/dist/chunk-UP4BECPY.js.map +1 -0
  125. package/dist/{chunk-YHIAWECL.js → chunk-UXVWEX5L.js} +2 -2
  126. package/dist/{chunk-NO272T7Q.js → chunk-V4PXLYWM.js} +2 -31
  127. package/dist/chunk-V4PXLYWM.js.map +1 -0
  128. package/dist/{chunk-OKCQNMO6.js → chunk-V7ZRRCRJ.js} +6 -6
  129. package/dist/{chunk-GHADG5QZ.js → chunk-VTFVLCUH.js} +2 -2
  130. package/dist/{chunk-U3RMWOXY.js → chunk-VXANTWBJ.js} +3 -3
  131. package/dist/{chunk-KHKKD62N.js → chunk-VYYM3MEN.js} +2 -16
  132. package/dist/chunk-VYYM3MEN.js.map +1 -0
  133. package/dist/{chunk-VTTDPGEK.js → chunk-WQBG4SZS.js} +26 -57
  134. package/dist/chunk-WQBG4SZS.js.map +1 -0
  135. package/dist/{chunk-MV2OEK3K.js → chunk-XKWGNJ26.js} +5 -5
  136. package/dist/{chunk-2E2LT37H.js → chunk-XLMEZIAJ.js} +2 -2
  137. package/dist/{chunk-RHTPGS56.js → chunk-YJRT5UQM.js} +3 -3
  138. package/dist/{chunk-FZWAGG5T.js → chunk-YJX7EOJD.js} +6 -6
  139. package/dist/{chunk-ZQGRZN5L.js → chunk-YYP7WSEB.js} +2 -2
  140. package/dist/{chunk-MENI33ZV.js → chunk-ZHKOPKE3.js} +3 -3
  141. package/dist/{chunk-4U52PMEL.js → chunk-ZN4FD4PE.js} +4 -4
  142. package/dist/{chunk-AW4KTQA4.js → chunk-ZORTV6NH.js} +2 -2
  143. package/dist/{chunk-6L5IMNJX.js → chunk-ZYIYHJ5R.js} +236 -1333
  144. package/dist/chunk-ZYIYHJ5R.js.map +1 -0
  145. package/dist/classified/index.js +5 -6
  146. package/dist/{classified-marker-R37XW5PC.js → classified-marker-BWOFVYAC.js} +3 -5
  147. package/dist/{classified-marker-R37XW5PC.js.map → classified-marker-BWOFVYAC.js.map} +1 -1
  148. package/dist/collection-facade-JSJYIKS4.js +45 -0
  149. package/dist/computed-VPOKQK4N.js +10 -0
  150. package/dist/consent/index.js +9 -10
  151. package/dist/consent/index.js.map +1 -1
  152. package/dist/cover/index.js +9 -10
  153. package/dist/crdt/index.js +0 -1
  154. package/dist/crdt/index.js.map +1 -1
  155. package/dist/custody/index.js +12 -13
  156. package/dist/{dead-filter-GRT6RAML.js → dead-filter-PKQDLOT4.js} +2 -3
  157. package/dist/{dead-filter-GRT6RAML.js.map → dead-filter-PKQDLOT4.js.map} +1 -1
  158. package/dist/debug/index.js +1 -2
  159. package/dist/debug/index.js.map +1 -1
  160. package/dist/{delegation-6QRAYSK6.js → delegation-DS5NRILW.js} +11 -12
  161. package/dist/{delegation-6QRAYSK6.js.map → delegation-DS5NRILW.js.map} +1 -1
  162. package/dist/derivations/index.js +30 -16
  163. package/dist/derive-E642AOUB.js +21 -0
  164. package/dist/directory/index.js +10 -11
  165. package/dist/{dispatch-QCF7KPIP.js → dispatch-IEPAVQUM.js} +5 -7
  166. package/dist/{dispatch-QCF7KPIP.js.map → dispatch-IEPAVQUM.js.map} +1 -1
  167. package/dist/dispatch-Q6MWLOJY.js +302 -0
  168. package/dist/dispatch-Q6MWLOJY.js.map +1 -0
  169. package/dist/{enclave-OXZY3NOP.js → enclave-55PAM4YO.js} +15 -10
  170. package/dist/executor-5NIMLSKZ.js +8 -0
  171. package/dist/executor-7UQ3BZ4F.js +29 -0
  172. package/dist/executor-AQVXV5GZ.js +8 -0
  173. package/dist/export-accessible-ORMKLA3E.js +22 -0
  174. package/dist/extract-partition-NKYO3WNG.js +37 -0
  175. package/dist/{fanout-sidecar-KGQCUJ7P.js → fanout-sidecar-S3QL53YX.js} +9 -10
  176. package/dist/{fanout-sidecar-KGQCUJ7P.js.map → fanout-sidecar-S3QL53YX.js.map} +1 -1
  177. package/dist/{fence-watcher-ZVSMLKQD.js → fence-watcher-U2PW6JU5.js} +1 -3
  178. package/dist/{fence-watcher-ZVSMLKQD.js.map → fence-watcher-U2PW6JU5.js.map} +1 -1
  179. package/dist/find-NOGJ25VX.js +10 -0
  180. package/dist/forget/index.js +9 -10
  181. package/dist/forget/index.js.map +1 -1
  182. package/dist/guards/index.js +4 -5
  183. package/dist/history/index.js +13 -14
  184. package/dist/history/index.js.map +1 -1
  185. package/dist/i18n/index.js +14 -15
  186. package/dist/i18n/index.js.map +1 -1
  187. package/dist/index.d.ts +21 -4
  188. package/dist/index.js +122 -115
  189. package/dist/index.js.map +1 -1
  190. package/dist/indexing/index.js +2 -3
  191. package/dist/indexing/index.js.map +1 -1
  192. package/dist/introspection/index.js +13 -13
  193. package/dist/issue-3DTQ7VJJ.js +18 -0
  194. package/dist/{json-schema-I22JCYCG.js → json-schema-V3M5MUCM.js} +1 -3
  195. package/dist/{json-schema-I22JCYCG.js.map → json-schema-V3M5MUCM.js.map} +1 -1
  196. package/dist/kernel/collection-config.d.ts +34 -0
  197. package/dist/kernel/collection.d.ts +11 -6
  198. package/dist/kernel/enclave/crypto.d.ts +16 -0
  199. package/dist/kernel/enclave/index.d.ts +1 -1
  200. package/dist/kernel/errors.d.ts +28 -0
  201. package/dist/kernel/match-pairs.d.ts +30 -0
  202. package/dist/kernel/memory-store.d.ts +35 -7
  203. package/dist/kernel/types.d.ts +39 -0
  204. package/dist/lazy/index.js +3 -3
  205. package/dist/{ledger-ZAFULLAF.js → ledger-EDXFFZQL.js} +11 -12
  206. package/dist/liberate-V35QUHJP.js +24 -0
  207. package/dist/link-set-2TTM3IZC.js +30 -0
  208. package/dist/{managed-secret-7OH7HKXV.js → managed-secret-NCWEMPUQ.js} +10 -11
  209. package/dist/materialized-views/index.js +21 -21
  210. package/dist/{migrate-cek-QHZ75E6E.js → migrate-cek-5ENH64AA.js} +2 -3
  211. package/dist/{migrate-cek-QHZ75E6E.js.map → migrate-cek-5ENH64AA.js.map} +1 -1
  212. package/dist/money/index.js +4 -5
  213. package/dist/noydb-62MX4QUG.js +90 -0
  214. package/dist/overlay-views/index.js +4 -5
  215. package/dist/periods/index.js +12 -13
  216. package/dist/pod/index.js +64 -60
  217. package/dist/{pod-handle-BLOI4IFY.js → pod-handle-ECVCDIXW.js} +10 -11
  218. package/dist/{pod-handle-BLOI4IFY.js.map → pod-handle-ECVCDIXW.js.map} +1 -1
  219. package/dist/policy/index.js +10 -11
  220. package/dist/port/to/index.d.ts +40 -0
  221. package/dist/portability/index.js +8 -9
  222. package/dist/portability/index.js.map +1 -1
  223. package/dist/{post-register-R33EKJQR.js → post-register-3IPCSG6Q.js} +6 -7
  224. package/dist/{post-register-R33EKJQR.js.map → post-register-3IPCSG6Q.js.map} +1 -1
  225. package/dist/{purge-scope-FGNNLWHD.js → purge-scope-4HEFPDOW.js} +1 -3
  226. package/dist/{purge-scope-FGNNLWHD.js.map → purge-scope-4HEFPDOW.js.map} +1 -1
  227. package/dist/query/index.js +3 -4
  228. package/dist/{read-only-facade-CHCKSEPD.js → read-only-facade-BIGO37U3.js} +1 -2
  229. package/dist/reduce/index.js +4 -5
  230. package/dist/reduce/index.js.map +1 -1
  231. package/dist/register-HHLXEQDN.js +31 -0
  232. package/dist/registry-23WF3TGH.js +8 -0
  233. package/dist/registry-4AYVUNXK.js +8 -0
  234. package/dist/registry-JS3YFQQM.js +18 -0
  235. package/dist/registry-XX2Z7B46.js +32 -0
  236. package/dist/request-withdrawal-CHPATE4G.js +30 -0
  237. package/dist/{reveal-PI6ADRQU.js → reveal-QZDHSGD4.js} +6 -7
  238. package/dist/{reveal-PI6ADRQU.js.map → reveal-QZDHSGD4.js.map} +1 -1
  239. package/dist/revoke-7M2VW4ON.js +23 -0
  240. package/dist/satellites/index.js +1 -2
  241. package/dist/schema-update/index.js +2 -3
  242. package/dist/sealed-record/index.js +12 -13
  243. package/dist/sealed-record/index.js.map +1 -1
  244. package/dist/search/index.js +4 -5
  245. package/dist/{seed-CG7JMJNY.js → seed-X5CC22CQ.js} +12 -13
  246. package/dist/{seed-CG7JMJNY.js.map → seed-X5CC22CQ.js.map} +1 -1
  247. package/dist/sequence/index.js +9 -10
  248. package/dist/session/index.js +9 -10
  249. package/dist/session/index.js.map +1 -1
  250. package/dist/shadow/index.js +2 -3
  251. package/dist/shadow/index.js.map +1 -1
  252. package/dist/share-link/index.js +0 -1
  253. package/dist/share-link/index.js.map +1 -1
  254. package/dist/signer-SJQJVSM6.js +24 -0
  255. package/dist/snapshots/index.js +10 -11
  256. package/dist/snapshots/index.js.map +1 -1
  257. package/dist/{stale-HZR7745Y.js → stale-BZS6H2RY.js} +10 -11
  258. package/dist/storage-RW4QBS23.js +22 -0
  259. package/dist/store/index.js +0 -1
  260. package/dist/{store-coordination-provider-MYIHSZXT.js → store-coordination-provider-4WZAIRHC.js} +10 -11
  261. package/dist/{store-coordination-provider-MYIHSZXT.js.map → store-coordination-provider-4WZAIRHC.js.map} +1 -1
  262. package/dist/sync/index.js +10 -11
  263. package/dist/sync/index.js.map +1 -1
  264. package/dist/team/index.js +15 -16
  265. package/dist/tiers/index.js +11 -12
  266. package/dist/to/index.js +2 -3
  267. package/dist/to/index.js.map +1 -1
  268. package/dist/transactions/index.js +3 -4
  269. package/dist/transactions/index.js.map +1 -1
  270. package/dist/{ulid-VQW6ERQN.js → ulid-4MKXG325.js} +1 -2
  271. package/dist/util/index.js +1 -2
  272. package/dist/util/index.js.map +1 -1
  273. package/dist/{vault-diff-FE5J35NJ.js → vault-diff-C6WUJFNP.js} +1 -2
  274. package/dist/vault-head/index.js +8 -9
  275. package/dist/vault-head/index.js.map +1 -1
  276. package/dist/{verify-R6CCBUA3.js → verify-6MDTIUEV.js} +5 -6
  277. package/dist/{verify-R6CCBUA3.js.map → verify-6MDTIUEV.js.map} +1 -1
  278. package/dist/walk-ZURCH6RZ.js +21 -0
  279. package/dist/with-formula/derivations/dispatch.d.ts +16 -1
  280. package/dist/with-formula/derivations/registry.d.ts +20 -0
  281. package/dist/with-formula/derivations/trigger-match.d.ts +104 -0
  282. package/dist/with-formula/derivations/types.d.ts +61 -0
  283. package/dist/with-party/team/keyring.d.ts +12 -5
  284. package/dist/with-party/team/wrapped-deks.d.ts +4 -4
  285. package/dist/with-pod/pod.d.ts +4 -4
  286. package/dist/with-shape/introspection/behaviors.d.ts +7 -0
  287. package/dist/with-shape/introspection/describe.d.ts +10 -1
  288. package/dist/with-shape/introspection/field-meta.d.ts +86 -0
  289. package/dist/withdraw-accessible-PXR4IXDX.js +27 -0
  290. package/package.json +8 -3
  291. package/dist/api-GJQF7OAJ.js +0 -20
  292. package/dist/backup-QZQEP5RO.js.map +0 -1
  293. package/dist/chunk-65ZYRK7O.js.map +0 -1
  294. package/dist/chunk-6L5IMNJX.js.map +0 -1
  295. package/dist/chunk-FRIVOR5N.js.map +0 -1
  296. package/dist/chunk-J6FXVDKC.js +0 -81
  297. package/dist/chunk-J6FXVDKC.js.map +0 -1
  298. package/dist/chunk-KHKKD62N.js.map +0 -1
  299. package/dist/chunk-NO272T7Q.js.map +0 -1
  300. package/dist/chunk-OHGCRKWA.js.map +0 -1
  301. package/dist/chunk-OQDHIAR2.js.map +0 -1
  302. package/dist/chunk-PZ5AY32C.js +0 -10
  303. package/dist/chunk-QJLOWGOU.js.map +0 -1
  304. package/dist/chunk-RCONOOVF.js.map +0 -1
  305. package/dist/chunk-SW4TOSJL.js.map +0 -1
  306. package/dist/chunk-USKHHOIV.js.map +0 -1
  307. package/dist/chunk-VT4DTCK5.js.map +0 -1
  308. package/dist/chunk-VTTDPGEK.js.map +0 -1
  309. package/dist/chunk-XJP66QEN.js +0 -344
  310. package/dist/chunk-XJP66QEN.js.map +0 -1
  311. package/dist/collection-facade-OPJ3EC4L.js +0 -45
  312. package/dist/computed-HW6IG5UH.js +0 -11
  313. package/dist/derive-AAIXSQIE.js +0 -22
  314. package/dist/dispatch-DR3XITEC.js +0 -194
  315. package/dist/dispatch-DR3XITEC.js.map +0 -1
  316. package/dist/executor-67NA4KPO.js +0 -29
  317. package/dist/executor-7JDP7UBK.js +0 -9
  318. package/dist/executor-CRH5OB4V.js +0 -9
  319. package/dist/export-accessible-K4GJAU7U.js +0 -23
  320. package/dist/extract-partition-YJFL5OKK.js +0 -38
  321. package/dist/find-SVZHMEQI.js +0 -11
  322. package/dist/issue-64N6OG7U.js +0 -19
  323. package/dist/liberate-XL6NSGOL.js +0 -25
  324. package/dist/link-set-LQI2IJX6.js +0 -31
  325. package/dist/noydb-SWUGPFBK.js +0 -86
  326. package/dist/register-AYBQNTM3.js +0 -32
  327. package/dist/registry-CQWWOBO4.js +0 -9
  328. package/dist/registry-JCZ4BNLV.js +0 -18
  329. package/dist/registry-JFFENZ44.js +0 -9
  330. package/dist/registry-ZA4HACYR.js +0 -19
  331. package/dist/request-withdrawal-7IKUIAEB.js +0 -31
  332. package/dist/revoke-PUJKRYJF.js +0 -24
  333. package/dist/signer-5TA7FUC3.js +0 -25
  334. package/dist/storage-J2QHNJCB.js +0 -23
  335. package/dist/walk-3PA4ZOKS.js +0 -21
  336. package/dist/withdraw-accessible-62VI4W7D.js +0 -28
  337. package/dist/withdraw-accessible-62VI4W7D.js.map +0 -1
  338. package/dist/zod-HAJM7LMS.js +0 -14763
  339. package/dist/zod-HAJM7LMS.js.map +0 -1
  340. /package/dist/{api-GJQF7OAJ.js.map → api-WYW4YEQG.js.map} +0 -0
  341. /package/dist/{chunk-5UKIZIO3.js.map → chunk-2577DKXB.js.map} +0 -0
  342. /package/dist/{chunk-SWFIXQF5.js.map → chunk-2ENE6445.js.map} +0 -0
  343. /package/dist/{chunk-HLFLJCDX.js.map → chunk-2N5ML6HT.js.map} +0 -0
  344. /package/dist/{chunk-X6YRP5EC.js.map → chunk-334WSVOW.js.map} +0 -0
  345. /package/dist/{chunk-5EC7X5QA.js.map → chunk-3BVH633C.js.map} +0 -0
  346. /package/dist/{chunk-7XT7KZTN.js.map → chunk-3PGS7TYR.js.map} +0 -0
  347. /package/dist/{chunk-AHIIBDNH.js.map → chunk-3VF3WQ4F.js.map} +0 -0
  348. /package/dist/{chunk-GM4IM7TC.js.map → chunk-453F654R.js.map} +0 -0
  349. /package/dist/{chunk-5W5CEHLA.js.map → chunk-4GFX6MPA.js.map} +0 -0
  350. /package/dist/{chunk-JUBWUJY5.js.map → chunk-4GVM6QZA.js.map} +0 -0
  351. /package/dist/{chunk-2DGBRE4K.js.map → chunk-4OZNXTO4.js.map} +0 -0
  352. /package/dist/{chunk-DOPZWTMJ.js.map → chunk-4ZS56W5S.js.map} +0 -0
  353. /package/dist/{chunk-P2RJAVMR.js.map → chunk-5VCRVKOZ.js.map} +0 -0
  354. /package/dist/{chunk-FN26SFGH.js.map → chunk-6LKOJBV6.js.map} +0 -0
  355. /package/dist/{chunk-P7KJME6C.js.map → chunk-6YXCPL4T.js.map} +0 -0
  356. /package/dist/{chunk-IS5LFHV2.js.map → chunk-7APJ6CO6.js.map} +0 -0
  357. /package/dist/{chunk-LAI7ENPW.js.map → chunk-7MG2LHO5.js.map} +0 -0
  358. /package/dist/{chunk-MU74BYOD.js.map → chunk-A2HKRLPV.js.map} +0 -0
  359. /package/dist/{chunk-357ECVLE.js.map → chunk-A66I4JOA.js.map} +0 -0
  360. /package/dist/{chunk-TAJZ7GXO.js.map → chunk-AYX7AINO.js.map} +0 -0
  361. /package/dist/{chunk-RPX2H2OL.js.map → chunk-BLN54W3L.js.map} +0 -0
  362. /package/dist/{chunk-XGXVPCYW.js.map → chunk-BRLKZUBT.js.map} +0 -0
  363. /package/dist/{chunk-CWFH36SI.js.map → chunk-BTDR2PXY.js.map} +0 -0
  364. /package/dist/{chunk-UTFY6W6X.js.map → chunk-BZ3534YM.js.map} +0 -0
  365. /package/dist/{chunk-KZTPL7NL.js.map → chunk-CHQCZZWC.js.map} +0 -0
  366. /package/dist/{chunk-MQPHKJ74.js.map → chunk-DFMWUOU5.js.map} +0 -0
  367. /package/dist/{chunk-3GIA3HJ2.js.map → chunk-DGOZ4UZD.js.map} +0 -0
  368. /package/dist/{chunk-NMDMSHBF.js.map → chunk-EQEYOJBM.js.map} +0 -0
  369. /package/dist/{chunk-Q2ZN5DWZ.js.map → chunk-FAHMLERK.js.map} +0 -0
  370. /package/dist/{chunk-GKOJR53Y.js.map → chunk-G73UVHCA.js.map} +0 -0
  371. /package/dist/{chunk-H5GVPOB4.js.map → chunk-GPNTB4Y7.js.map} +0 -0
  372. /package/dist/{chunk-DNMTN46H.js.map → chunk-GY4WYNNG.js.map} +0 -0
  373. /package/dist/{chunk-HS3LEVT4.js.map → chunk-HIWCKBEY.js.map} +0 -0
  374. /package/dist/{chunk-PV7XXAXK.js.map → chunk-JBDFMYKQ.js.map} +0 -0
  375. /package/dist/{chunk-IZTU6RKH.js.map → chunk-JMGDHKQF.js.map} +0 -0
  376. /package/dist/{chunk-P22XPNFW.js.map → chunk-JVIBCBC7.js.map} +0 -0
  377. /package/dist/{chunk-OLUTCM23.js.map → chunk-K23VKTN4.js.map} +0 -0
  378. /package/dist/{chunk-3SWP2FYA.js.map → chunk-KKEESNPE.js.map} +0 -0
  379. /package/dist/{chunk-ZB2K3FV7.js.map → chunk-KTFRCC5C.js.map} +0 -0
  380. /package/dist/{chunk-IAHDSFFA.js.map → chunk-LH5A3ZPG.js.map} +0 -0
  381. /package/dist/{chunk-QOHGWFAW.js.map → chunk-LWBCUYZW.js.map} +0 -0
  382. /package/dist/{chunk-5NKHCJU5.js.map → chunk-M4YPHYEH.js.map} +0 -0
  383. /package/dist/{chunk-JFSUYGNE.js.map → chunk-MVMXZYXT.js.map} +0 -0
  384. /package/dist/{chunk-FKQCC4C5.js.map → chunk-NQKIUNW5.js.map} +0 -0
  385. /package/dist/{chunk-Q2OAAREU.js.map → chunk-OTQZ7ZWU.js.map} +0 -0
  386. /package/dist/{chunk-MOQ6OGKS.js.map → chunk-P3MG6QCN.js.map} +0 -0
  387. /package/dist/{chunk-75WNTBZL.js.map → chunk-PPTHY5QO.js.map} +0 -0
  388. /package/dist/{chunk-TQGT5BZE.js.map → chunk-Q2MPFCQ7.js.map} +0 -0
  389. /package/dist/{chunk-MTTPHBIE.js.map → chunk-Q2PU57HC.js.map} +0 -0
  390. /package/dist/{chunk-FLRLZ4XZ.js.map → chunk-Q7HZX3IF.js.map} +0 -0
  391. /package/dist/{chunk-KQIDBIZL.js.map → chunk-QIZPZMUI.js.map} +0 -0
  392. /package/dist/{chunk-JRWLUWDM.js.map → chunk-QPQUVOZ2.js.map} +0 -0
  393. /package/dist/{chunk-7YVSWPZB.js.map → chunk-QTQUH4DS.js.map} +0 -0
  394. /package/dist/{chunk-2MQ2D5OZ.js.map → chunk-R42NSZI6.js.map} +0 -0
  395. /package/dist/{chunk-HOIWW2LV.js.map → chunk-RF6D3Y5E.js.map} +0 -0
  396. /package/dist/{chunk-OEJ4R52I.js.map → chunk-RMS3NEA3.js.map} +0 -0
  397. /package/dist/{chunk-FPN5D4JX.js.map → chunk-RSGLUIO6.js.map} +0 -0
  398. /package/dist/{chunk-XKA6UH5V.js.map → chunk-SFAWCTEM.js.map} +0 -0
  399. /package/dist/{chunk-I5LSKXT6.js.map → chunk-SGZAIJCV.js.map} +0 -0
  400. /package/dist/{chunk-FYT3DXPN.js.map → chunk-SKGMN35F.js.map} +0 -0
  401. /package/dist/{chunk-JILOSL4O.js.map → chunk-SPYWXKJN.js.map} +0 -0
  402. /package/dist/{chunk-4RUFYGWG.js.map → chunk-SZJ3DLZA.js.map} +0 -0
  403. /package/dist/{chunk-O3SNM66K.js.map → chunk-TFR7DSOV.js.map} +0 -0
  404. /package/dist/{chunk-DIVY2CJZ.js.map → chunk-TRGTKX5E.js.map} +0 -0
  405. /package/dist/{chunk-JY4U6CYV.js.map → chunk-TUFM4UZP.js.map} +0 -0
  406. /package/dist/{chunk-LUVGSKXE.js.map → chunk-UDHWDSRL.js.map} +0 -0
  407. /package/dist/{chunk-DZPMKY3J.js.map → chunk-UGTBXF5U.js.map} +0 -0
  408. /package/dist/{chunk-K432FT7T.js.map → chunk-UHHPLO3I.js.map} +0 -0
  409. /package/dist/{chunk-THNJ3IKU.js.map → chunk-ULUMAZ5S.js.map} +0 -0
  410. /package/dist/{chunk-YHIAWECL.js.map → chunk-UXVWEX5L.js.map} +0 -0
  411. /package/dist/{chunk-OKCQNMO6.js.map → chunk-V7ZRRCRJ.js.map} +0 -0
  412. /package/dist/{chunk-GHADG5QZ.js.map → chunk-VTFVLCUH.js.map} +0 -0
  413. /package/dist/{chunk-U3RMWOXY.js.map → chunk-VXANTWBJ.js.map} +0 -0
  414. /package/dist/{chunk-MV2OEK3K.js.map → chunk-XKWGNJ26.js.map} +0 -0
  415. /package/dist/{chunk-2E2LT37H.js.map → chunk-XLMEZIAJ.js.map} +0 -0
  416. /package/dist/{chunk-RHTPGS56.js.map → chunk-YJRT5UQM.js.map} +0 -0
  417. /package/dist/{chunk-FZWAGG5T.js.map → chunk-YJX7EOJD.js.map} +0 -0
  418. /package/dist/{chunk-ZQGRZN5L.js.map → chunk-YYP7WSEB.js.map} +0 -0
  419. /package/dist/{chunk-MENI33ZV.js.map → chunk-ZHKOPKE3.js.map} +0 -0
  420. /package/dist/{chunk-4U52PMEL.js.map → chunk-ZN4FD4PE.js.map} +0 -0
  421. /package/dist/{chunk-AW4KTQA4.js.map → chunk-ZORTV6NH.js.map} +0 -0
  422. /package/dist/{chunk-PZ5AY32C.js.map → collection-facade-JSJYIKS4.js.map} +0 -0
  423. /package/dist/{collection-facade-OPJ3EC4L.js.map → computed-VPOKQK4N.js.map} +0 -0
  424. /package/dist/{computed-HW6IG5UH.js.map → derive-E642AOUB.js.map} +0 -0
  425. /package/dist/{derive-AAIXSQIE.js.map → enclave-55PAM4YO.js.map} +0 -0
  426. /package/dist/{enclave-OXZY3NOP.js.map → executor-5NIMLSKZ.js.map} +0 -0
  427. /package/dist/{executor-67NA4KPO.js.map → executor-7UQ3BZ4F.js.map} +0 -0
  428. /package/dist/{executor-7JDP7UBK.js.map → executor-AQVXV5GZ.js.map} +0 -0
  429. /package/dist/{executor-CRH5OB4V.js.map → export-accessible-ORMKLA3E.js.map} +0 -0
  430. /package/dist/{export-accessible-K4GJAU7U.js.map → extract-partition-NKYO3WNG.js.map} +0 -0
  431. /package/dist/{extract-partition-YJFL5OKK.js.map → find-NOGJ25VX.js.map} +0 -0
  432. /package/dist/{find-SVZHMEQI.js.map → issue-3DTQ7VJJ.js.map} +0 -0
  433. /package/dist/{issue-64N6OG7U.js.map → ledger-EDXFFZQL.js.map} +0 -0
  434. /package/dist/{ledger-ZAFULLAF.js.map → liberate-V35QUHJP.js.map} +0 -0
  435. /package/dist/{liberate-XL6NSGOL.js.map → link-set-2TTM3IZC.js.map} +0 -0
  436. /package/dist/{link-set-LQI2IJX6.js.map → managed-secret-NCWEMPUQ.js.map} +0 -0
  437. /package/dist/{managed-secret-7OH7HKXV.js.map → noydb-62MX4QUG.js.map} +0 -0
  438. /package/dist/{noydb-SWUGPFBK.js.map → read-only-facade-BIGO37U3.js.map} +0 -0
  439. /package/dist/{read-only-facade-CHCKSEPD.js.map → register-HHLXEQDN.js.map} +0 -0
  440. /package/dist/{register-AYBQNTM3.js.map → registry-23WF3TGH.js.map} +0 -0
  441. /package/dist/{registry-CQWWOBO4.js.map → registry-4AYVUNXK.js.map} +0 -0
  442. /package/dist/{registry-JCZ4BNLV.js.map → registry-JS3YFQQM.js.map} +0 -0
  443. /package/dist/{registry-JFFENZ44.js.map → registry-XX2Z7B46.js.map} +0 -0
  444. /package/dist/{registry-ZA4HACYR.js.map → request-withdrawal-CHPATE4G.js.map} +0 -0
  445. /package/dist/{request-withdrawal-7IKUIAEB.js.map → revoke-7M2VW4ON.js.map} +0 -0
  446. /package/dist/{revoke-PUJKRYJF.js.map → signer-SJQJVSM6.js.map} +0 -0
  447. /package/dist/{signer-5TA7FUC3.js.map → stale-BZS6H2RY.js.map} +0 -0
  448. /package/dist/{stale-HZR7745Y.js.map → storage-RW4QBS23.js.map} +0 -0
  449. /package/dist/{storage-J2QHNJCB.js.map → ulid-4MKXG325.js.map} +0 -0
  450. /package/dist/{ulid-VQW6ERQN.js.map → vault-diff-C6WUJFNP.js.map} +0 -0
  451. /package/dist/{vault-diff-FE5J35NJ.js.map → walk-ZURCH6RZ.js.map} +0 -0
  452. /package/dist/{walk-3PA4ZOKS.js.map → withdraw-accessible-PXR4IXDX.js.map} +0 -0
package/README.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @noy-db/hub
2
2
 
3
+ <!-- prose-preamble
4
+ // Bindings the illustrative blocks below elide. Typed on purpose (#1310).
5
+ import type { Noydb, Vault, Collection } from '@noy-db/hub'
6
+ import { money } from '@noy-db/hub'
7
+ import { sum } from '@noy-db/hub/reduce'
8
+ import { promises as fs } from 'node:fs'
9
+ import { z } from 'zod'
10
+ interface Invoice { id: string; month?: string; total?: number | string; underLitigation?: boolean; fiscalYearEnd?: string }
11
+ interface Line { id: string; unitPrice: number; qty: number; netAmount?: number; taxAmount?: number; total?: number }
12
+ declare const db: Noydb
13
+ declare const vault: Vault
14
+ declare const acme: Vault
15
+ declare const otherAcme: Vault
16
+ declare const invoices: Collection<Invoice>
17
+ declare const lines: Collection<Line>
18
+ -->
19
+
3
20
  > Zero-knowledge, offline-first, encrypted document store — core library.
4
21
 
5
22
  [![npm](https://img.shields.io/npm/v/@noy-db/hub.svg)](https://www.npmjs.com/package/@noy-db/hub)
@@ -44,7 +61,7 @@ pnpm add @noy-db/hub @noy-db/to-memory
44
61
 
45
62
  - **Framework integrations** — [`@noy-db/in-*`](https://www.npmjs.com/search?q=%40noy-db%2Fin-): vue, pinia, nuxt, react, nextjs, svelte, solid, zustand, tanstack-query, tanstack-table, yjs, ai, rest.
46
63
  - **Authentication paths** — [`@noy-db/on-*`](https://www.npmjs.com/search?q=%40noy-db%2Fon-): webauthn, oidc, totp, email-otp, magic-link, recovery, shamir, pin, threat.
47
- - **Export formats** — [`@noy-db/as-*`](https://www.npmjs.com/search?q=%40noy-db%2Fas-): csv, json, ndjson, xml, sql, xlsx, blob, zip, noydb (encrypted bundle).
64
+ - **Export formats** — [`@noy-db/as-*`](https://www.npmjs.com/search?q=%40noy-db%2Fas-): csv, json, ndjson, xml, sql, xlsx, blob, zip, noydb (encrypted pod).
48
65
  - **Session-share transports** — [`@noy-db/by-*`](https://www.npmjs.com/search?q=%40noy-db%2Fby-): tabs (BroadcastChannel multi-tab), peer (WebRTC).
49
66
  - **CLI tooling** — [`@noy-db/cli`](https://www.npmjs.com/package/@noy-db/cli) (`noydb` binary; inspect/verify `.noydb` files), [`create-noy-db`](https://www.npmjs.com/package/create-noy-db) (`npm create noy-db` scaffolder).
50
67
 
@@ -52,13 +69,13 @@ pnpm add @noy-db/hub @noy-db/to-memory
52
69
 
53
70
  ```ts
54
71
  import { createNoydb } from '@noy-db/hub'
55
- import { memory } from '@noy-db/to-memory'
72
+ import { toMemory } from '@noy-db/to-memory'
56
73
 
57
74
  type Invoice = { id: string; amount: number; customer: string }
58
75
 
59
76
  const db = await createNoydb({
60
77
  store: toMemory(),
61
- userId: 'alice',
78
+ user: 'alice',
62
79
  secret: 'correct horse battery staple',
63
80
  })
64
81
 
@@ -77,9 +94,10 @@ const all = await invoices.list()
77
94
  - **Offline-first sync** — push/pull with optimistic concurrency on encrypted envelopes
78
95
  - **Audit history** — full-copy snapshots with `history()`, `diff()`, `revert()`, `pruneHistory()`
79
96
  - **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.)
97
+ `@noy-db/attestation`, on the same version line. `zod` (v3 or v4) and `zod-to-json-schema` are
98
+ OPTIONAL peers used by the persisted-schema converter: nothing is installed on your behalf, nothing is
99
+ vendored into the bundle, and if you do use Zod schemas the converter reads YOUR copy rather
100
+ than a second one frozen at hub's build time.
83
101
 
84
102
  ## Cross-vault queries
85
103
 
@@ -100,7 +118,7 @@ const admin = await db.listAccessibleVaults({ minRole: 'admin' })
100
118
 
101
119
  **Existence-leak guarantee.** The return value never reveals the existence of a vault the caller cannot unwrap. The store sees the enumeration call (it owns the storage), but downstream consumers of `listAccessibleVaults()` only see the filtered list.
102
120
 
103
- **Store capability.** Requires the optional `NoydbStore.listVaults()` method. The `@noy-db/to-memory` and `@noy-db/to-file` stores implement it; cloud stores (`@noy-db/to-aws-dynamo`, `@noy-db/to-aws-s3`) and `@noy-db/to-browser-idb` do not (cloud enumeration needs a GSI or list-bucket permission that has to be configured by the consumer). Calling `listAccessibleVaults()` against a store that doesn't implement `listVaults` throws `StoreCapabilityError`. Workaround: maintain the candidate list out of band and pass it directly to `queryAcross()`.
121
+ **Store capability.** Requires the optional `NoydbStore.listVaults()` method. The built-in `memoryStore({ full: true })` and the `@noy-db/to-file` store implement it; cloud stores (`@noy-db/to-aws-dynamo`, `@noy-db/to-aws-s3`) and `@noy-db/to-browser-idb` do not (cloud enumeration needs a GSI or list-bucket permission that has to be configured by the consumer). Calling `listAccessibleVaults()` against a store that doesn't implement `listVaults` throws `StoreCapabilityError`. Workaround: maintain the candidate list out of band and pass it directly to `queryAcross()`.
104
122
 
105
123
  ### `db.queryAcross(ids, fn, options?)` — fan out
106
124
 
@@ -178,7 +196,7 @@ Core has zero `node:` imports — it runs unchanged in browsers, Node, Bun, Deno
178
196
 
179
197
  #### Other plaintext formats
180
198
 
181
- CSV, XML, xlsx, and the rest of the plaintext tier — plus encrypted `.noydb` bundles under the `as-noydb` encrypted tier — all live in the [`@noy-db/as-*`](https://www.npmjs.com/search?q=%40noy-db%2Fas-) family. Every invocation is gated by the two-tier authorization model (`assertCanExport('plaintext')` default off, `canExportBundle` default on for owner/admin) and lands in the audit ledger.
199
+ CSV, XML, xlsx, and the rest of the plaintext tier — plus encrypted `.noydb` pods under the `as-noydb` encrypted tier — all live in the [`@noy-db/as-*`](https://www.npmjs.com/search?q=%40noy-db%2Fas-) family. Every invocation is gated by the two-tier authorization model (`assertCanExport('plaintext')` default off, `canExportBundle` default on for owner/admin) and lands in the audit ledger.
182
200
 
183
201
  ## Money fields
184
202
 
@@ -216,8 +234,8 @@ vault.collection('lines', {
216
234
  }),
217
235
  computed: {
218
236
  netAmount: (r) => r.unitPrice * r.qty,
219
- taxAmount: (r) => r.netAmount * 0.22, // reads the field computed above
220
- total: (r) => r.netAmount + r.taxAmount,
237
+ taxAmount: (r) => r.netAmount! * 0.22, // reads the field computed above
238
+ total: (r) => r.netAmount! + r.taxAmount!,
221
239
  },
222
240
  })
223
241
 
@@ -281,7 +299,7 @@ const { evicted, held } = await vault.compact() // held = retained-by-hold count
281
299
  ```ts
282
300
  import { createNoydb, withArchive } from '@noy-db/hub'
283
301
 
284
- const db = await createNoydb({ store: primary, archiveStrategy: withArchive({ store: coldStore }) })
302
+ const db = await createNoydb({ store: primary, user, secret, archiveStrategy: withArchive({ store: coldStore }) })
285
303
  vault.collection('invoices', {
286
304
  archive: { archiveWhen: (r) => r.fiscalYear <= thisYear - 1, legalHold: (r) => r.underHold },
287
305
  })
@@ -0,0 +1,19 @@
1
+ import {
2
+ UserApi,
3
+ createUserApi
4
+ } from "./chunk-A66I4JOA.js";
5
+ import "./chunk-XKWGNJ26.js";
6
+ import "./chunk-4ZS56W5S.js";
7
+ import "./chunk-SZJ3DLZA.js";
8
+ import "./chunk-BRLKZUBT.js";
9
+ import "./chunk-BTDR2PXY.js";
10
+ import "./chunk-CHQCZZWC.js";
11
+ import "./chunk-LP7BEXCT.js";
12
+ import "./chunk-HPVZCW43.js";
13
+ import "./chunk-7MG7SJT7.js";
14
+ import "./chunk-7O3Y4PPD.js";
15
+ export {
16
+ UserApi,
17
+ createUserApi
18
+ };
19
+ //# sourceMappingURL=api-WYW4YEQG.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-FET5XCAT.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-ACAQ2DSG.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-SGZAIJCV.js";
11
+ import "../chunk-4ZS56W5S.js";
12
+ import "../chunk-SZJ3DLZA.js";
13
+ import "../chunk-BRLKZUBT.js";
14
+ import "../chunk-BTDR2PXY.js";
15
+ import "../chunk-CHQCZZWC.js";
15
16
  import "../chunk-LP7BEXCT.js";
16
- import "../chunk-USKHHOIV.js";
17
- import "../chunk-N4CHCXDL.js";
17
+ import "../chunk-HPVZCW43.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-4ZS56W5S.js";
8
+ import "../chunk-SZJ3DLZA.js";
9
+ import "../chunk-BRLKZUBT.js";
10
+ import "../chunk-BTDR2PXY.js";
11
+ import "../chunk-CHQCZZWC.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-HPVZCW43.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-UDHWDSRL.js";
4
4
  import {
5
5
  getRevokedDocIdsCore,
6
6
  publishRevocationListCore,
7
7
  revokeDocCore,
8
8
  unrevokeDocCore
9
- } from "../chunk-FPN5D4JX.js";
9
+ } from "../chunk-RSGLUIO6.js";
10
10
  import {
11
11
  ATTESTATIONS_COLLECTION
12
- } from "../chunk-GKOJR53Y.js";
12
+ } from "../chunk-G73UVHCA.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-4ZS56W5S.js";
18
+ import "../chunk-SZJ3DLZA.js";
19
+ import "../chunk-BRLKZUBT.js";
20
+ import "../chunk-BTDR2PXY.js";
21
+ import "../chunk-CHQCZZWC.js";
22
22
  import "../chunk-LP7BEXCT.js";
23
- import "../chunk-USKHHOIV.js";
24
- import "../chunk-N4CHCXDL.js";
23
+ import "../chunk-HPVZCW43.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-3DTQ7VJJ.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-SJQJVSM6.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-7M2VW4ON.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-7M2VW4ON.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-7M2VW4ON.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-7M2VW4ON.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-GPNTB4Y7.js";
7
+ import {
8
+ SCHEMAS_COLLECTION
9
+ } from "./chunk-SGZAIJCV.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-4ZS56W5S.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-BRLKZUBT.js";
26
+ import "./chunk-BTDR2PXY.js";
27
+ import "./chunk-CHQCZZWC.js";
28
28
  import "./chunk-LP7BEXCT.js";
29
- import "./chunk-USKHHOIV.js";
29
+ import "./chunk-HPVZCW43.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) {
@@ -142,9 +141,15 @@ async function loadVault(ctx, backupJson) {
142
141
  ctx.clearCollectionCache();
143
142
  ctx.resetLedgerStore();
144
143
  if (!backup.ledgerHead) {
145
- console.warn(
146
- `[noy-db] Loaded a legacy backup with no ledgerHead \u2014 verifiable-backup integrity check skipped. Re-export with a ledger-aware build to get tamper detection.`
147
- );
144
+ if (ctx.getLedgerOrNull()) {
145
+ console.warn(
146
+ `[noy-db] Loaded a legacy backup with no ledgerHead \u2014 verifiable-backup integrity check skipped. Re-export with a ledger-aware build to get tamper detection.`
147
+ );
148
+ } else {
149
+ console.warn(
150
+ `[noy-db] Loaded a backup with no ledgerHead \u2014 this pod is not integrity-checked. This reader has no ledger enabled (withHistory() is not configured), so nothing is stale: enable the ledger on both the exporter and this reader if tamper detection is wanted.`
151
+ );
152
+ }
148
153
  return;
149
154
  }
150
155
  const result = await verifyBackupIntegrity(ctx);
@@ -262,4 +267,4 @@ export {
262
267
  loadVault,
263
268
  verifyBackupIntegrity
264
269
  };
265
- //# sourceMappingURL=backup-QZQEP5RO.js.map
270
+ //# sourceMappingURL=backup-XKCXVKV3.js.map
@@ -0,0 +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. A backup with no ledgerHead cannot be\n // integrity-checked, and skipping silently would collapse\n // *unverifiable* into *clean* — so it always warns. But the REMEDY\n // depends on the reader, not the pod (#1303): the pod cannot say\n // whether its exporter predates the ledger or never enabled it, and\n // the reader knows its own configuration.\n //\n // - Reader HAS the ledger: the pod is behind it. \"Re-export\" is\n // actionable; keep the migration wording.\n // - Reader has NO ledger: nothing is stale and nothing is migrating —\n // the consumer priced the ledger (#1248 measured ~2.4x) and declined.\n // Prescribing a re-export is advice they should not take, and\n // repeating it on every read trains people to filter the one line\n // that also fires on a genuinely stale pod. State the consequence,\n // name the discriminator, prescribe nothing.\n if (!backup.ledgerHead) {\n if (ctx.getLedgerOrNull()) {\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 } else {\n console.warn(\n `[noy-db] Loaded a backup with no ledgerHead — this pod is not integrity-checked. ` +\n `This reader has no ledger enabled (withHistory() is not configured), so nothing is stale: ` +\n `enable the ledger on both the exporter and this reader if tamper detection is wanted.`,\n )\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-7APJ6CO6.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-HIWCKBEY.js";
29
+ import "../chunk-UXVWEX5L.js";
30
+ import "../chunk-UGTBXF5U.js";
31
+ import "../chunk-JMGDHKQF.js";
32
+ import "../chunk-4ZS56W5S.js";
33
+ import "../chunk-SZJ3DLZA.js";
34
+ import "../chunk-BRLKZUBT.js";
35
+ import "../chunk-BTDR2PXY.js";
36
+ import "../chunk-CHQCZZWC.js";
37
37
  import "../chunk-LP7BEXCT.js";
38
- import "../chunk-USKHHOIV.js";
39
- import "../chunk-N4CHCXDL.js";
38
+ import "../chunk-HPVZCW43.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-4ZS56W5S.js";
8
+ import "../chunk-SZJ3DLZA.js";
9
+ import "../chunk-BRLKZUBT.js";
10
+ import "../chunk-BTDR2PXY.js";
11
+ import "../chunk-CHQCZZWC.js";
12
12
  import "../chunk-LP7BEXCT.js";
13
- import "../chunk-USKHHOIV.js";
14
- import "../chunk-N4CHCXDL.js";
13
+ import "../chunk-HPVZCW43.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-X5CC22CQ.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-X5CC22CQ.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-X5CC22CQ.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