@noy-db/hub 0.8.0 → 0.9.0-pre.1

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 (567) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +8 -8
  3. package/codemods/0.4.0-pre.json +1 -1
  4. package/codemods/0.8.0-pre.json +1 -1
  5. package/dist/api-6EFD43KN.js +18 -0
  6. package/dist/as/index.js +33 -23
  7. package/dist/as/index.js.map +1 -1
  8. package/dist/at/index.js +8 -8
  9. package/dist/attestation/index.js +18 -18
  10. package/dist/{backup-YE2VQ26S.js → backup-RJBFQSHE.js} +92 -31
  11. package/dist/backup-RJBFQSHE.js.map +1 -0
  12. package/dist/blobs/index.js +12 -12
  13. package/dist/broker/index.js +19 -11
  14. package/dist/broker/index.js.map +1 -1
  15. package/dist/by/index.js +2 -2
  16. package/dist/capsule/contract.d.ts +1 -1
  17. package/dist/capsule/contract.js +6 -6
  18. package/dist/capsule/enclave-aes/broker/proof.d.ts +12 -3
  19. package/dist/capsule/enclave-aes/crypto.d.ts +18 -0
  20. package/dist/capsule/enclave-aes/index.d.ts +3 -3
  21. package/dist/capsule/enclave-aes/index.js +46 -14
  22. package/dist/capsule/enclave-aes/index.js.map +1 -1
  23. package/dist/capsule/index.d.ts +2 -2
  24. package/dist/capsule/plumbing/record-codec.d.ts +7 -0
  25. package/dist/{capsule-VOLX3QRQ.js → capsule-6LJAVQNM.js} +14 -8
  26. package/dist/cargo/index.js +35 -35
  27. package/dist/{chunk-GZT3NQRA.js → chunk-25FXU6WS.js} +8 -2
  28. package/dist/chunk-25FXU6WS.js.map +1 -0
  29. package/dist/{chunk-OYW3I5M4.js → chunk-2DOCDOPL.js} +6 -6
  30. package/dist/chunk-2DX4JCRI.js +1 -0
  31. package/dist/{chunk-FLPCETP6.js → chunk-2LBS62AC.js} +2 -2
  32. package/dist/{chunk-WXE4W2U6.js → chunk-2ST3WA3C.js} +4 -4
  33. package/dist/{chunk-DQESF6RP.js → chunk-3G3GOGZZ.js} +50 -40
  34. package/dist/chunk-3G3GOGZZ.js.map +1 -0
  35. package/dist/{chunk-O2IMQSNA.js → chunk-3YBIVLTC.js} +2 -2
  36. package/dist/{chunk-LGNDFRYC.js → chunk-4CFHL5RY.js} +1 -1
  37. package/dist/chunk-4CFHL5RY.js.map +1 -0
  38. package/dist/{chunk-DIZLQVAA.js → chunk-4CHM2TRS.js} +2 -2
  39. package/dist/{chunk-V7ADQF5O.js → chunk-4CUJLEOA.js} +4 -4
  40. package/dist/{chunk-3EWS67C7.js → chunk-4TG2ITRW.js} +2 -2
  41. package/dist/{chunk-HS554XAF.js → chunk-5HQFROZS.js} +2 -2
  42. package/dist/{chunk-IUBMZPHM.js → chunk-5ZVE3N5C.js} +5 -6
  43. package/dist/chunk-5ZVE3N5C.js.map +1 -0
  44. package/dist/{chunk-PP3K67AJ.js → chunk-654RE5YC.js} +3 -3
  45. package/dist/{chunk-FOEDQATO.js → chunk-66GD7XXU.js} +2 -2
  46. package/dist/{chunk-BNWA3WG5.js → chunk-72FQ46VW.js} +3 -3
  47. package/dist/{chunk-EYG2CY2X.js → chunk-7JPA3LIH.js} +11 -11
  48. package/dist/chunk-7JPA3LIH.js.map +1 -0
  49. package/dist/{chunk-JQYKPKG6.js → chunk-7K42TSCY.js} +4 -4
  50. package/dist/{chunk-BPWYQ25R.js → chunk-7Q6IU3R7.js} +4 -4
  51. package/dist/{chunk-BPWYQ25R.js.map → chunk-7Q6IU3R7.js.map} +1 -1
  52. package/dist/{chunk-T7IR4N2S.js → chunk-7UHLO4ZN.js} +37 -2
  53. package/dist/chunk-7UHLO4ZN.js.map +1 -0
  54. package/dist/{chunk-UEFOQH74.js → chunk-ADCXTW7L.js} +2 -2
  55. package/dist/{chunk-MBMTND6D.js → chunk-AGGPT4UE.js} +2 -2
  56. package/dist/{chunk-RB4DOPGZ.js → chunk-AKIEBFIJ.js} +10 -10
  57. package/dist/{chunk-VHBKYN2J.js → chunk-B3B6HV5S.js} +2 -2
  58. package/dist/{chunk-JWWYRR4Q.js → chunk-B6EWMGFX.js} +2 -2
  59. package/dist/{chunk-H7JBY4P7.js → chunk-B7Y2BRQA.js} +14 -14
  60. package/dist/chunk-B7Y2BRQA.js.map +1 -0
  61. package/dist/{chunk-4CIQDWRB.js → chunk-BFJE2GPP.js} +14 -8
  62. package/dist/{chunk-4CIQDWRB.js.map → chunk-BFJE2GPP.js.map} +1 -1
  63. package/dist/{chunk-WPOYWFSE.js → chunk-BJRKXNFP.js} +7 -7
  64. package/dist/{chunk-H427H63K.js → chunk-BPQ5CRJF.js} +2 -2
  65. package/dist/{chunk-VFHCKG5M.js → chunk-BVRJYMFZ.js} +3 -3
  66. package/dist/{chunk-244QBK7Z.js → chunk-C4XV3PSJ.js} +4 -4
  67. package/dist/{chunk-244QBK7Z.js.map → chunk-C4XV3PSJ.js.map} +1 -1
  68. package/dist/{chunk-SMV2HRDU.js → chunk-DFC4WTJW.js} +2 -2
  69. package/dist/{chunk-5A4345TG.js → chunk-DMIEKD24.js} +3 -3
  70. package/dist/{chunk-TKVUE4JF.js → chunk-DQAXA2GK.js} +9 -9
  71. package/dist/{chunk-AL6ML4LA.js → chunk-DWCFGF2K.js} +5 -5
  72. package/dist/{chunk-Y3LPTBG7.js → chunk-E2C6FFSI.js} +6 -9
  73. package/dist/chunk-E2C6FFSI.js.map +1 -0
  74. package/dist/{chunk-LNSVGRHO.js → chunk-EQ6C2ZPT.js} +17 -51
  75. package/dist/chunk-EQ6C2ZPT.js.map +1 -0
  76. package/dist/chunk-EZOFTI4K.js +60 -0
  77. package/dist/chunk-EZOFTI4K.js.map +1 -0
  78. package/dist/{chunk-PD64727P.js → chunk-FMINS2B6.js} +2 -2
  79. package/dist/chunk-FMINS2B6.js.map +1 -0
  80. package/dist/{chunk-QBLT6POL.js → chunk-FPF5HRBE.js} +2 -2
  81. package/dist/{chunk-UA372JHH.js → chunk-FZVCZEVI.js} +3 -3
  82. package/dist/chunk-FZVCZEVI.js.map +1 -0
  83. package/dist/{chunk-FFWI7UH7.js → chunk-GAGT3YZN.js} +1 -1
  84. package/dist/chunk-GAGT3YZN.js.map +1 -0
  85. package/dist/{chunk-5WWDGFOS.js → chunk-GIQJGXV7.js} +2 -2
  86. package/dist/{chunk-V3RWOOSO.js → chunk-GYZICGRU.js} +4 -4
  87. package/dist/chunk-GYZICGRU.js.map +1 -0
  88. package/dist/{chunk-BVCUTXE3.js → chunk-H334G6KU.js} +2 -2
  89. package/dist/{chunk-AEQGFRU4.js → chunk-HE7EAHGS.js} +3 -3
  90. package/dist/chunk-HKB4HZDU.js +74 -0
  91. package/dist/chunk-HKB4HZDU.js.map +1 -0
  92. package/dist/{chunk-4V3Q35WG.js → chunk-ICF3TIGY.js} +3 -3
  93. package/dist/{chunk-3L2NBKDR.js → chunk-IF2M43G4.js} +2 -2
  94. package/dist/{chunk-37EPTBBR.js → chunk-IKPQ2GGB.js} +46 -4
  95. package/dist/chunk-IKPQ2GGB.js.map +1 -0
  96. package/dist/{chunk-DHHGL42E.js → chunk-IKS2CPAG.js} +27 -11
  97. package/dist/chunk-IKS2CPAG.js.map +1 -0
  98. package/dist/{chunk-3A5DUZ56.js → chunk-IMIQAGR7.js} +6 -6
  99. package/dist/{chunk-3A5DUZ56.js.map → chunk-IMIQAGR7.js.map} +1 -1
  100. package/dist/{chunk-A4XMIZT3.js → chunk-IQAJ4OR6.js} +41 -6
  101. package/dist/chunk-IQAJ4OR6.js.map +1 -0
  102. package/dist/{chunk-IUT3GWP3.js → chunk-IUD7WU67.js} +17 -93
  103. package/dist/chunk-IUD7WU67.js.map +1 -0
  104. package/dist/{chunk-AUKKUPVB.js → chunk-IVLRPRXM.js} +2 -2
  105. package/dist/{chunk-GUZET4SG.js → chunk-JAQHWHUN.js} +4 -4
  106. package/dist/chunk-JAQHWHUN.js.map +1 -0
  107. package/dist/{chunk-Y2RKVFKR.js → chunk-K4JSTGXT.js} +2 -2
  108. package/dist/{chunk-EJLV62NI.js → chunk-KN4LUMH6.js} +2 -2
  109. package/dist/{chunk-23D6M6VM.js → chunk-KZA3DITX.js} +4 -4
  110. package/dist/{chunk-E2N2T5ZO.js → chunk-L2VM64HK.js} +2 -2
  111. package/dist/chunk-L4UL4IAR.js +55 -0
  112. package/dist/chunk-L4UL4IAR.js.map +1 -0
  113. package/dist/{chunk-UIYESRD6.js → chunk-LUCQY3OM.js} +10 -10
  114. package/dist/{chunk-UIYESRD6.js.map → chunk-LUCQY3OM.js.map} +1 -1
  115. package/dist/{chunk-O46CHQT7.js → chunk-MAQBYBUX.js} +4 -4
  116. package/dist/{chunk-EZOAKKTB.js → chunk-MBPZMZVB.js} +2 -2
  117. package/dist/{chunk-XQRFSKYM.js → chunk-MCNNZBG7.js} +2 -2
  118. package/dist/{chunk-YRXFFWG4.js → chunk-MLVPMDOZ.js} +2 -2
  119. package/dist/{chunk-5FE75J4S.js → chunk-MMCN7TLK.js} +5 -5
  120. package/dist/{chunk-MXOQ5JCG.js → chunk-MRCR7ZMC.js} +686 -202
  121. package/dist/chunk-MRCR7ZMC.js.map +1 -0
  122. package/dist/{chunk-SYNY3VB5.js → chunk-NCTN2FW4.js} +2 -2
  123. package/dist/{chunk-4T3SE27M.js → chunk-ND6S2DKC.js} +2 -2
  124. package/dist/{chunk-3XJQBBZD.js → chunk-NTVKHQ3L.js} +2 -2
  125. package/dist/{chunk-RHVMZSUU.js → chunk-NV4OESHC.js} +1 -1
  126. package/dist/chunk-NV4OESHC.js.map +1 -0
  127. package/dist/chunk-NXQEOC3X.js +40 -0
  128. package/dist/chunk-NXQEOC3X.js.map +1 -0
  129. package/dist/{chunk-Q4UHJ5SN.js → chunk-O2VQ3K36.js} +2 -2
  130. package/dist/{chunk-HW7CMKUG.js → chunk-OFD2HD6F.js} +1 -1
  131. package/dist/{chunk-HW7CMKUG.js.map → chunk-OFD2HD6F.js.map} +1 -1
  132. package/dist/{chunk-2GHDLTPE.js → chunk-OGKMRIIJ.js} +2 -2
  133. package/dist/{chunk-N7EVQD5S.js → chunk-ONZ3B5EW.js} +4 -4
  134. package/dist/{chunk-VKI2EB3N.js → chunk-OOPSMQX5.js} +3 -3
  135. package/dist/{chunk-VMV5SBE4.js → chunk-OYEBSWLE.js} +5 -5
  136. package/dist/{chunk-JDEYF3PJ.js → chunk-P6FATPXQ.js} +2 -2
  137. package/dist/chunk-P6FATPXQ.js.map +1 -0
  138. package/dist/{chunk-VVOLDVIR.js → chunk-PLTIJDQN.js} +2 -2
  139. package/dist/{chunk-OKSTSITU.js → chunk-PR7ILCIH.js} +3 -3
  140. package/dist/{chunk-7R2Q7CPL.js → chunk-QE3TLZ6Z.js} +7 -7
  141. package/dist/{chunk-G2MVBDFP.js → chunk-QFW4MYGN.js} +39 -9
  142. package/dist/chunk-QFW4MYGN.js.map +1 -0
  143. package/dist/{chunk-6QVKPHBF.js → chunk-QHG7GQKM.js} +2 -2
  144. package/dist/chunk-QJNAHPVT.js +91 -0
  145. package/dist/chunk-QJNAHPVT.js.map +1 -0
  146. package/dist/{chunk-LIOVX5TJ.js → chunk-QT5ITL25.js} +3 -3
  147. package/dist/{chunk-IMQKWR46.js → chunk-R2ZULFXU.js} +4 -5
  148. package/dist/chunk-R2ZULFXU.js.map +1 -0
  149. package/dist/{chunk-Q2XRFWOI.js → chunk-RRTQAQ3N.js} +2 -2
  150. package/dist/{chunk-H23XHRTT.js → chunk-RUE6TCES.js} +809 -101
  151. package/dist/chunk-RUE6TCES.js.map +1 -0
  152. package/dist/chunk-RWFQVNXR.js +24 -0
  153. package/dist/chunk-RWFQVNXR.js.map +1 -0
  154. package/dist/{chunk-2PVXF5CS.js → chunk-SALY3LIJ.js} +3 -3
  155. package/dist/{chunk-JOSPH3E5.js → chunk-SBAR5JQ6.js} +2 -2
  156. package/dist/{chunk-N7UDP5VU.js → chunk-SCH2F7R2.js} +7 -7
  157. package/dist/{chunk-MXKI4ABF.js → chunk-SOOAW6HK.js} +3 -3
  158. package/dist/{chunk-VQDZYB2B.js → chunk-T4VTRKCY.js} +3 -3
  159. package/dist/{chunk-VQDZYB2B.js.map → chunk-T4VTRKCY.js.map} +1 -1
  160. package/dist/{chunk-TEHHROZL.js → chunk-T5EXREMW.js} +5 -5
  161. package/dist/{chunk-M5B2W6YY.js → chunk-TDJVQTXD.js} +3 -3
  162. package/dist/{chunk-QMWY2FDS.js → chunk-THQ3BHLM.js} +2 -2
  163. package/dist/{chunk-VAORSCSU.js → chunk-TLIFNRU5.js} +2 -2
  164. package/dist/chunk-TLIFNRU5.js.map +1 -0
  165. package/dist/{chunk-FVH5QYY2.js → chunk-TRHUNPXP.js} +2 -2
  166. package/dist/{chunk-EGVJ7TM4.js → chunk-UL6MTRMJ.js} +8 -9
  167. package/dist/chunk-UL6MTRMJ.js.map +1 -0
  168. package/dist/chunk-UNL6YGL5.js +169 -0
  169. package/dist/chunk-UNL6YGL5.js.map +1 -0
  170. package/dist/{chunk-747G6CT3.js → chunk-UORWAG7K.js} +2 -2
  171. package/dist/{chunk-XSPFDUDG.js → chunk-V7AKGAXY.js} +314 -77
  172. package/dist/chunk-V7AKGAXY.js.map +1 -0
  173. package/dist/{chunk-TZZBXPZK.js → chunk-VLQ6KT7F.js} +2 -2
  174. package/dist/{chunk-NCO25JZO.js → chunk-VP37VUKQ.js} +4 -4
  175. package/dist/{chunk-52MGURXO.js → chunk-WBUHHMLN.js} +2 -2
  176. package/dist/{chunk-EZGV6F47.js → chunk-WRLWEYHY.js} +7 -1
  177. package/dist/chunk-WRLWEYHY.js.map +1 -0
  178. package/dist/{chunk-2MG3SW7Q.js → chunk-X6Z2SIRF.js} +2 -2
  179. package/dist/{chunk-U2FZNEWJ.js → chunk-XLKWF3L4.js} +8 -6
  180. package/dist/{chunk-U2FZNEWJ.js.map → chunk-XLKWF3L4.js.map} +1 -1
  181. package/dist/{chunk-5UMK7GRI.js → chunk-XPNJH7GN.js} +5 -5
  182. package/dist/{chunk-KZXDLBY6.js → chunk-XPW7T2GN.js} +5 -5
  183. package/dist/{chunk-SV2PM2OY.js → chunk-XX4R7TUB.js} +1 -1
  184. package/dist/chunk-XX4R7TUB.js.map +1 -0
  185. package/dist/{chunk-NBQ3KK6X.js → chunk-Y55XHMQB.js} +4 -4
  186. package/dist/chunk-Y55XHMQB.js.map +1 -0
  187. package/dist/{chunk-5KC7QYEC.js → chunk-YH4OUOSI.js} +33 -7
  188. package/dist/chunk-YH4OUOSI.js.map +1 -0
  189. package/dist/{chunk-FFJFE4T7.js → chunk-YJGKOSQD.js} +2 -2
  190. package/dist/{chunk-2AFX33YA.js → chunk-Z3STG43F.js} +3 -3
  191. package/dist/chunk-Z3STG43F.js.map +1 -0
  192. package/dist/{chunk-OIEO4WDL.js → chunk-ZD7WFMV2.js} +2 -2
  193. package/dist/chunk-ZD7WFMV2.js.map +1 -0
  194. package/dist/{chunk-42ALPZ2B.js → chunk-ZF6JECDT.js} +4 -4
  195. package/dist/{chunk-42ALPZ2B.js.map → chunk-ZF6JECDT.js.map} +1 -1
  196. package/dist/{chunk-4JPMZTJY.js → chunk-ZF7KNSLU.js} +2 -2
  197. package/dist/{chunk-2ODVB6LZ.js → chunk-ZGKODRGB.js} +2 -2
  198. package/dist/{chunk-JIBUPZHA.js → chunk-ZNEKQFGF.js} +4 -4
  199. package/dist/{chunk-DLD5LGDS.js → chunk-ZUTUNVFD.js} +3 -3
  200. package/dist/{chunk-JSMTXZR3.js → chunk-ZWMOHANW.js} +8 -6
  201. package/dist/chunk-ZWMOHANW.js.map +1 -0
  202. package/dist/{chunk-MILI22XQ.js → chunk-ZZZ4VCY2.js} +10 -10
  203. package/dist/chunk-ZZZ4VCY2.js.map +1 -0
  204. package/dist/classified/index.js +5 -5
  205. package/dist/{classified-marker-SIYKUU5L.js → classified-marker-WKP33U2R.js} +3 -3
  206. package/dist/collection-facade-COSGZKLC.js +41 -0
  207. package/dist/{computed-FAD7SED4.js → computed-WN6V53ZV.js} +3 -3
  208. package/dist/consent/index.js +8 -8
  209. package/dist/cover/index.js +8 -8
  210. package/dist/coverage/index.js +1 -1
  211. package/dist/custody/index.js +12 -11
  212. package/dist/{dead-filter-4F3LWYKH.js → dead-filter-43WL3Y5H.js} +10 -10
  213. package/dist/debug/index.js +7 -7
  214. package/dist/delegation-5UWT4JGT.js +26 -0
  215. package/dist/derivations/index.js +24 -23
  216. package/dist/derive-IL5JNLEE.js +20 -0
  217. package/dist/directory/index.js +9 -9
  218. package/dist/{dispatch-JDZNGEB3.js → dispatch-LOQQD5JK.js} +20 -20
  219. package/dist/{dispatch-H4HV32AM.js → dispatch-SHKTG57L.js} +5 -5
  220. package/dist/executor-6PQ7WAGV.js +35 -0
  221. package/dist/executor-6ZPQA6HS.js +8 -0
  222. package/dist/executor-OXRA64TY.js +8 -0
  223. package/dist/export-accessible-XG3FKJWW.js +22 -0
  224. package/dist/extract-partition-33747NY5.js +35 -0
  225. package/dist/{fanout-sidecar-L7NHPIOC.js → fanout-sidecar-NEB6IYV7.js} +8 -8
  226. package/dist/find-VW543G3J.js +10 -0
  227. package/dist/forget/index.js +25 -8
  228. package/dist/forget/index.js.map +1 -1
  229. package/dist/guards/index.js +4 -4
  230. package/dist/history/index.js +15 -13
  231. package/dist/history/index.js.map +1 -1
  232. package/dist/i18n/index.js +13 -13
  233. package/dist/index.d.ts +9 -6
  234. package/dist/index.js +126 -110
  235. package/dist/index.js.map +1 -1
  236. package/dist/indexing/index.js +6 -6
  237. package/dist/introspection/index.js +15 -11
  238. package/dist/issue-4ZPSY44M.js +19 -0
  239. package/dist/kernel/cache/index.d.ts +1 -1
  240. package/dist/kernel/collection.d.ts +86 -6
  241. package/dist/kernel/constants.d.ts +7 -0
  242. package/dist/kernel/errors.d.ts +42 -4
  243. package/dist/kernel/export-scope.d.ts +40 -0
  244. package/dist/kernel/merge-authority.d.ts +5 -1
  245. package/dist/kernel/noydb.d.ts +118 -21
  246. package/dist/kernel/put-many-atomic.d.ts +1 -1
  247. package/dist/kernel/query/live/live.d.ts +2 -1
  248. package/dist/kernel/query/sort-key.d.ts +0 -2
  249. package/dist/kernel/rejection-seal.d.ts +13 -0
  250. package/dist/kernel/sync-wiring.d.ts +55 -0
  251. package/dist/kernel/tx-write-gate.d.ts +2 -4
  252. package/dist/kernel/types.d.ts +463 -14
  253. package/dist/kernel/validation.d.ts +0 -10
  254. package/dist/kernel/vault.d.ts +42 -4
  255. package/dist/kernel/via/reconcile.d.ts +1 -42
  256. package/dist/{ledger-5ZMGE44K.js → ledger-MZ25UFT2.js} +10 -10
  257. package/dist/liberate-OJIP2ZFX.js +25 -0
  258. package/dist/{link-set-MFXC24VK.js → link-set-4FRRAVTH.js} +10 -10
  259. package/dist/{managed-secret-MFTFT22X.js → managed-secret-SQWO2EUR.js} +9 -9
  260. package/dist/materialized-views/index.js +26 -26
  261. package/dist/{migrate-cek-DZRFFOHW.js → migrate-cek-JWEM4RP6.js} +2 -2
  262. package/dist/money/index.js +5 -5
  263. package/dist/noydb-U62OVKXB.js +100 -0
  264. package/dist/on/index.js +25 -0
  265. package/dist/overlay-views/index.js +4 -4
  266. package/dist/periods/index.js +11 -11
  267. package/dist/pod/index.js +71 -67
  268. package/dist/{pod-handle-A3LET7NO.js → pod-handle-R6Y4MILX.js} +8 -8
  269. package/dist/policy/index.js +9 -9
  270. package/dist/port/as/active.d.ts +4 -0
  271. package/dist/port/as/index.d.ts +1 -0
  272. package/dist/port/by/index.d.ts +14 -5
  273. package/dist/port/on/index.d.ts +26 -0
  274. package/dist/port/to/index.d.ts +1 -1
  275. package/dist/port/with/admission-authority.d.ts +34 -0
  276. package/dist/port/with/broker-strategy.d.ts +24 -0
  277. package/dist/port/with/coverage-strategy.d.ts +17 -1
  278. package/dist/port/with/formats-strategy.d.ts +34 -1
  279. package/dist/port/with/lookup-strategy.d.ts +85 -4
  280. package/dist/port/with/rejection-courier.d.ts +37 -0
  281. package/dist/port/with/restore-host.d.ts +33 -0
  282. package/dist/port/with/service-bus.d.ts +20 -1
  283. package/dist/port/with/team-strategy.d.ts +2 -2
  284. package/dist/port/with/write-hooks.d.ts +2 -0
  285. package/dist/portability/index.js +8 -8
  286. package/dist/{post-register-7ND27CF2.js → post-register-GRVQHBOH.js} +6 -6
  287. package/dist/query/all/index.js +16 -16
  288. package/dist/query/index.js +8 -8
  289. package/dist/query/live/index.js +7 -7
  290. package/dist/query/reduce/index.js +10 -10
  291. package/dist/query/relate/index.js +10 -10
  292. package/dist/reduce/index.js +8 -8
  293. package/dist/register-YJ5YLQ36.js +30 -0
  294. package/dist/registry-ICOHBQFD.js +8 -0
  295. package/dist/registry-MJ7MWCSW.js +35 -0
  296. package/dist/registry-MVEKKGWL.js +23 -0
  297. package/dist/registry-XP744FAP.js +8 -0
  298. package/dist/request-withdrawal-LSU4G6W3.js +28 -0
  299. package/dist/restore-to-DVBHAQAA.js +66 -0
  300. package/dist/restore-to-DVBHAQAA.js.map +1 -0
  301. package/dist/{reveal-B2TLP4JQ.js → reveal-AIHOIK2N.js} +7 -7
  302. package/dist/revoke-QUT7WWG3.js +24 -0
  303. package/dist/satellites/index.js +1 -1
  304. package/dist/schema-update/index.js +2 -2
  305. package/dist/sealed-record/index.js +11 -11
  306. package/dist/search/index.js +4 -4
  307. package/dist/{seed-XNSE4U3S.js → seed-GFLA4FCK.js} +136 -27
  308. package/dist/seed-GFLA4FCK.js.map +1 -0
  309. package/dist/sequence/index.js +8 -8
  310. package/dist/session/index.js +8 -8
  311. package/dist/shadow/index.js +2 -2
  312. package/dist/signer-NYR4I3FO.js +23 -0
  313. package/dist/snapshots/index.js +9 -9
  314. package/dist/{stale-6GCFMOOR.js → stale-PIJPAL5T.js} +9 -9
  315. package/dist/storage-VH6SPXHC.js +21 -0
  316. package/dist/{store-coordination-provider-C4BPT5XF.js → store-coordination-provider-2KSHCOPU.js} +9 -9
  317. package/dist/sync/index.js +19 -13
  318. package/dist/sync/index.js.map +1 -1
  319. package/dist/team/index.js +17 -15
  320. package/dist/tiers/index.js +10 -10
  321. package/dist/to/index.js +2 -2
  322. package/dist/transactions/index.js +3 -3
  323. package/dist/util/index.js +1 -1
  324. package/dist/vault-head/index.js +8 -8
  325. package/dist/{verify-UKALW7C2.js → verify-PCFS4PNS.js} +7 -7
  326. package/dist/via/classified/presets.d.ts +29 -0
  327. package/dist/via/classified/resolve.d.ts +7 -0
  328. package/dist/via/geo/binding.d.ts +0 -4
  329. package/dist/via/lookup/index.d.ts +32 -0
  330. package/dist/via/money/binding.d.ts +0 -9
  331. package/dist/walk-OZCN6LJS.js +20 -0
  332. package/dist/with-audit/attestation/strategy.d.ts +2 -1
  333. package/dist/with-audit/attestation/vault-facade.d.ts +7 -0
  334. package/dist/with-audit/forget/completeness.d.ts +66 -0
  335. package/dist/with-audit/forget/index.d.ts +2 -0
  336. package/dist/with-audit/forget/strategy.d.ts +65 -0
  337. package/dist/with-audit/guards/types.d.ts +2 -0
  338. package/dist/with-audit/periods/periods.d.ts +0 -9
  339. package/dist/with-audit/periods/reserved-collections.d.ts +7 -0
  340. package/dist/with-audit/portability/request-withdrawal.d.ts +0 -1
  341. package/dist/with-audit/portability/withdraw-accessible.d.ts +0 -1
  342. package/dist/with-audit/tiers/index.d.ts +6 -6
  343. package/dist/with-audit/tiers/strategy.d.ts +19 -0
  344. package/dist/with-cargo/extract-partition.d.ts +0 -46
  345. package/dist/with-commit/history/history.d.ts +16 -0
  346. package/dist/with-commit/history/restore-to.d.ts +40 -0
  347. package/dist/with-commit/numbering/index.d.ts +0 -2
  348. package/dist/with-commit/tx/transaction.d.ts +2 -24
  349. package/dist/with-commit/vault-head/strategy.d.ts +7 -0
  350. package/dist/with-fork/snapshots/noydb-facade.d.ts +7 -0
  351. package/dist/with-formula/derivations/trigger-match.d.ts +8 -5
  352. package/dist/with-formula/materialized-views/emit-memo.d.ts +0 -2
  353. package/dist/with-lookup/embeddings/index.d.ts +1 -2
  354. package/dist/with-lookup/indexing/collection-facade.d.ts +1 -15
  355. package/dist/with-lookup/indexing/eager-indexes.d.ts +2 -1
  356. package/dist/with-lookup/search/collection-facade.d.ts +0 -12
  357. package/dist/with-party/broker/index.d.ts +2 -2
  358. package/dist/with-party/broker/seed.d.ts +29 -10
  359. package/dist/with-party/custody/strategy.d.ts +2 -2
  360. package/dist/with-party/policy/noydb-facade.d.ts +1 -31
  361. package/dist/with-party/team/delegation.d.ts +93 -7
  362. package/dist/with-party/team/echo-secret.d.ts +0 -2
  363. package/dist/with-party/team/index.d.ts +2 -0
  364. package/dist/with-party/team/keyring.d.ts +133 -24
  365. package/dist/with-party/team/magic-link-grant.d.ts +11 -1
  366. package/dist/with-party/team/noydb-facade.d.ts +19 -2
  367. package/dist/with-party/team/reserved-secret-collections.d.ts +10 -8
  368. package/dist/with-party/team/roster-tag.d.ts +42 -1
  369. package/dist/with-party/team/tiers.d.ts +36 -5
  370. package/dist/with-pod/backup.d.ts +9 -17
  371. package/dist/with-shape/blobs/blob-set.d.ts +23 -0
  372. package/dist/with-shape/blobs/legacy-sweep.d.ts +16 -0
  373. package/dist/with-shape/introspection/describe.d.ts +1 -2
  374. package/dist/with-shape/introspection/index.d.ts +1 -0
  375. package/dist/with-shape/introspection/types.d.ts +2 -1
  376. package/dist/with-shape/schema-update/fence.d.ts +7 -0
  377. package/dist/with-sync/active.d.ts +28 -1
  378. package/dist/with-sync/engine.d.ts +88 -2
  379. package/dist/with-sync/index.d.ts +1 -0
  380. package/dist/with-sync/reserved-mirror.d.ts +112 -0
  381. package/dist/with-sync/strategy.d.ts +9 -0
  382. package/dist/with-sync/tab-write-relay.d.ts +0 -10
  383. package/dist/withdraw-accessible-MTFP7OIB.js +25 -0
  384. package/dist/withdraw-accessible-MTFP7OIB.js.map +1 -0
  385. package/package.json +3 -3
  386. package/dist/api-OS747DS4.js +0 -18
  387. package/dist/backup-YE2VQ26S.js.map +0 -1
  388. package/dist/chunk-2AFX33YA.js.map +0 -1
  389. package/dist/chunk-2RH777HH.js +0 -126
  390. package/dist/chunk-2RH777HH.js.map +0 -1
  391. package/dist/chunk-37EPTBBR.js.map +0 -1
  392. package/dist/chunk-5KC7QYEC.js.map +0 -1
  393. package/dist/chunk-7XMHMVTS.js +0 -20
  394. package/dist/chunk-7XMHMVTS.js.map +0 -1
  395. package/dist/chunk-A4XMIZT3.js.map +0 -1
  396. package/dist/chunk-DHHGL42E.js.map +0 -1
  397. package/dist/chunk-DQESF6RP.js.map +0 -1
  398. package/dist/chunk-EGVJ7TM4.js.map +0 -1
  399. package/dist/chunk-EYG2CY2X.js.map +0 -1
  400. package/dist/chunk-EZGV6F47.js.map +0 -1
  401. package/dist/chunk-FFWI7UH7.js.map +0 -1
  402. package/dist/chunk-G2MVBDFP.js.map +0 -1
  403. package/dist/chunk-GUZET4SG.js.map +0 -1
  404. package/dist/chunk-GZT3NQRA.js.map +0 -1
  405. package/dist/chunk-H23XHRTT.js.map +0 -1
  406. package/dist/chunk-H7JBY4P7.js.map +0 -1
  407. package/dist/chunk-IMQKWR46.js.map +0 -1
  408. package/dist/chunk-IUBMZPHM.js.map +0 -1
  409. package/dist/chunk-IUT3GWP3.js.map +0 -1
  410. package/dist/chunk-JDEYF3PJ.js.map +0 -1
  411. package/dist/chunk-JSMTXZR3.js.map +0 -1
  412. package/dist/chunk-LGNDFRYC.js.map +0 -1
  413. package/dist/chunk-LNSVGRHO.js.map +0 -1
  414. package/dist/chunk-MILI22XQ.js.map +0 -1
  415. package/dist/chunk-MXOQ5JCG.js.map +0 -1
  416. package/dist/chunk-NBQ3KK6X.js.map +0 -1
  417. package/dist/chunk-OIEO4WDL.js.map +0 -1
  418. package/dist/chunk-PD64727P.js.map +0 -1
  419. package/dist/chunk-RHVMZSUU.js.map +0 -1
  420. package/dist/chunk-SV2PM2OY.js.map +0 -1
  421. package/dist/chunk-T7IR4N2S.js.map +0 -1
  422. package/dist/chunk-UA372JHH.js.map +0 -1
  423. package/dist/chunk-UBSFPGVJ.js +0 -1
  424. package/dist/chunk-V3RWOOSO.js.map +0 -1
  425. package/dist/chunk-VAORSCSU.js.map +0 -1
  426. package/dist/chunk-XSPFDUDG.js.map +0 -1
  427. package/dist/chunk-Y3LPTBG7.js.map +0 -1
  428. package/dist/collection-facade-CS7CA2XO.js +0 -47
  429. package/dist/delegation-NANZDG4N.js +0 -102
  430. package/dist/delegation-NANZDG4N.js.map +0 -1
  431. package/dist/derive-XLOJVXPU.js +0 -20
  432. package/dist/executor-FMPVN6DT.js +0 -35
  433. package/dist/executor-LBBBRTN5.js +0 -8
  434. package/dist/executor-OSRZST2U.js +0 -8
  435. package/dist/export-accessible-RAOJAAU5.js +0 -22
  436. package/dist/extract-partition-JD5CUSTG.js +0 -37
  437. package/dist/find-JRN4RNQ5.js +0 -10
  438. package/dist/issue-YIVBZUTH.js +0 -19
  439. package/dist/liberate-WZSZM2W6.js +0 -24
  440. package/dist/noydb-ITIGNKUF.js +0 -96
  441. package/dist/register-DT5HZ2LZ.js +0 -30
  442. package/dist/registry-BHRZGZHF.js +0 -8
  443. package/dist/registry-ET6ZFFWA.js +0 -34
  444. package/dist/registry-HXFGLGTG.js +0 -8
  445. package/dist/registry-THCPDEOD.js +0 -23
  446. package/dist/request-withdrawal-AV2MJJKY.js +0 -30
  447. package/dist/revoke-6DWIEOCV.js +0 -24
  448. package/dist/seed-XNSE4U3S.js.map +0 -1
  449. package/dist/signer-MHGW3OIL.js +0 -23
  450. package/dist/storage-BYN5LO6Z.js +0 -21
  451. package/dist/walk-4VPK7AS4.js +0 -20
  452. package/dist/withdraw-accessible-HL7GACUE.js +0 -27
  453. /package/dist/{api-OS747DS4.js.map → api-6EFD43KN.js.map} +0 -0
  454. /package/dist/{capsule-VOLX3QRQ.js.map → capsule-6LJAVQNM.js.map} +0 -0
  455. /package/dist/{chunk-OYW3I5M4.js.map → chunk-2DOCDOPL.js.map} +0 -0
  456. /package/dist/{chunk-UBSFPGVJ.js.map → chunk-2DX4JCRI.js.map} +0 -0
  457. /package/dist/{chunk-FLPCETP6.js.map → chunk-2LBS62AC.js.map} +0 -0
  458. /package/dist/{chunk-WXE4W2U6.js.map → chunk-2ST3WA3C.js.map} +0 -0
  459. /package/dist/{chunk-O2IMQSNA.js.map → chunk-3YBIVLTC.js.map} +0 -0
  460. /package/dist/{chunk-DIZLQVAA.js.map → chunk-4CHM2TRS.js.map} +0 -0
  461. /package/dist/{chunk-V7ADQF5O.js.map → chunk-4CUJLEOA.js.map} +0 -0
  462. /package/dist/{chunk-3EWS67C7.js.map → chunk-4TG2ITRW.js.map} +0 -0
  463. /package/dist/{chunk-HS554XAF.js.map → chunk-5HQFROZS.js.map} +0 -0
  464. /package/dist/{chunk-PP3K67AJ.js.map → chunk-654RE5YC.js.map} +0 -0
  465. /package/dist/{chunk-FOEDQATO.js.map → chunk-66GD7XXU.js.map} +0 -0
  466. /package/dist/{chunk-BNWA3WG5.js.map → chunk-72FQ46VW.js.map} +0 -0
  467. /package/dist/{chunk-JQYKPKG6.js.map → chunk-7K42TSCY.js.map} +0 -0
  468. /package/dist/{chunk-UEFOQH74.js.map → chunk-ADCXTW7L.js.map} +0 -0
  469. /package/dist/{chunk-MBMTND6D.js.map → chunk-AGGPT4UE.js.map} +0 -0
  470. /package/dist/{chunk-RB4DOPGZ.js.map → chunk-AKIEBFIJ.js.map} +0 -0
  471. /package/dist/{chunk-VHBKYN2J.js.map → chunk-B3B6HV5S.js.map} +0 -0
  472. /package/dist/{chunk-JWWYRR4Q.js.map → chunk-B6EWMGFX.js.map} +0 -0
  473. /package/dist/{chunk-WPOYWFSE.js.map → chunk-BJRKXNFP.js.map} +0 -0
  474. /package/dist/{chunk-H427H63K.js.map → chunk-BPQ5CRJF.js.map} +0 -0
  475. /package/dist/{chunk-VFHCKG5M.js.map → chunk-BVRJYMFZ.js.map} +0 -0
  476. /package/dist/{chunk-SMV2HRDU.js.map → chunk-DFC4WTJW.js.map} +0 -0
  477. /package/dist/{chunk-5A4345TG.js.map → chunk-DMIEKD24.js.map} +0 -0
  478. /package/dist/{chunk-TKVUE4JF.js.map → chunk-DQAXA2GK.js.map} +0 -0
  479. /package/dist/{chunk-AL6ML4LA.js.map → chunk-DWCFGF2K.js.map} +0 -0
  480. /package/dist/{chunk-QBLT6POL.js.map → chunk-FPF5HRBE.js.map} +0 -0
  481. /package/dist/{chunk-5WWDGFOS.js.map → chunk-GIQJGXV7.js.map} +0 -0
  482. /package/dist/{chunk-BVCUTXE3.js.map → chunk-H334G6KU.js.map} +0 -0
  483. /package/dist/{chunk-AEQGFRU4.js.map → chunk-HE7EAHGS.js.map} +0 -0
  484. /package/dist/{chunk-4V3Q35WG.js.map → chunk-ICF3TIGY.js.map} +0 -0
  485. /package/dist/{chunk-3L2NBKDR.js.map → chunk-IF2M43G4.js.map} +0 -0
  486. /package/dist/{chunk-AUKKUPVB.js.map → chunk-IVLRPRXM.js.map} +0 -0
  487. /package/dist/{chunk-Y2RKVFKR.js.map → chunk-K4JSTGXT.js.map} +0 -0
  488. /package/dist/{chunk-EJLV62NI.js.map → chunk-KN4LUMH6.js.map} +0 -0
  489. /package/dist/{chunk-23D6M6VM.js.map → chunk-KZA3DITX.js.map} +0 -0
  490. /package/dist/{chunk-E2N2T5ZO.js.map → chunk-L2VM64HK.js.map} +0 -0
  491. /package/dist/{chunk-O46CHQT7.js.map → chunk-MAQBYBUX.js.map} +0 -0
  492. /package/dist/{chunk-EZOAKKTB.js.map → chunk-MBPZMZVB.js.map} +0 -0
  493. /package/dist/{chunk-XQRFSKYM.js.map → chunk-MCNNZBG7.js.map} +0 -0
  494. /package/dist/{chunk-YRXFFWG4.js.map → chunk-MLVPMDOZ.js.map} +0 -0
  495. /package/dist/{chunk-5FE75J4S.js.map → chunk-MMCN7TLK.js.map} +0 -0
  496. /package/dist/{chunk-SYNY3VB5.js.map → chunk-NCTN2FW4.js.map} +0 -0
  497. /package/dist/{chunk-4T3SE27M.js.map → chunk-ND6S2DKC.js.map} +0 -0
  498. /package/dist/{chunk-3XJQBBZD.js.map → chunk-NTVKHQ3L.js.map} +0 -0
  499. /package/dist/{chunk-Q4UHJ5SN.js.map → chunk-O2VQ3K36.js.map} +0 -0
  500. /package/dist/{chunk-2GHDLTPE.js.map → chunk-OGKMRIIJ.js.map} +0 -0
  501. /package/dist/{chunk-N7EVQD5S.js.map → chunk-ONZ3B5EW.js.map} +0 -0
  502. /package/dist/{chunk-VKI2EB3N.js.map → chunk-OOPSMQX5.js.map} +0 -0
  503. /package/dist/{chunk-VMV5SBE4.js.map → chunk-OYEBSWLE.js.map} +0 -0
  504. /package/dist/{chunk-VVOLDVIR.js.map → chunk-PLTIJDQN.js.map} +0 -0
  505. /package/dist/{chunk-OKSTSITU.js.map → chunk-PR7ILCIH.js.map} +0 -0
  506. /package/dist/{chunk-7R2Q7CPL.js.map → chunk-QE3TLZ6Z.js.map} +0 -0
  507. /package/dist/{chunk-6QVKPHBF.js.map → chunk-QHG7GQKM.js.map} +0 -0
  508. /package/dist/{chunk-LIOVX5TJ.js.map → chunk-QT5ITL25.js.map} +0 -0
  509. /package/dist/{chunk-Q2XRFWOI.js.map → chunk-RRTQAQ3N.js.map} +0 -0
  510. /package/dist/{chunk-2PVXF5CS.js.map → chunk-SALY3LIJ.js.map} +0 -0
  511. /package/dist/{chunk-JOSPH3E5.js.map → chunk-SBAR5JQ6.js.map} +0 -0
  512. /package/dist/{chunk-N7UDP5VU.js.map → chunk-SCH2F7R2.js.map} +0 -0
  513. /package/dist/{chunk-MXKI4ABF.js.map → chunk-SOOAW6HK.js.map} +0 -0
  514. /package/dist/{chunk-TEHHROZL.js.map → chunk-T5EXREMW.js.map} +0 -0
  515. /package/dist/{chunk-M5B2W6YY.js.map → chunk-TDJVQTXD.js.map} +0 -0
  516. /package/dist/{chunk-QMWY2FDS.js.map → chunk-THQ3BHLM.js.map} +0 -0
  517. /package/dist/{chunk-FVH5QYY2.js.map → chunk-TRHUNPXP.js.map} +0 -0
  518. /package/dist/{chunk-747G6CT3.js.map → chunk-UORWAG7K.js.map} +0 -0
  519. /package/dist/{chunk-TZZBXPZK.js.map → chunk-VLQ6KT7F.js.map} +0 -0
  520. /package/dist/{chunk-NCO25JZO.js.map → chunk-VP37VUKQ.js.map} +0 -0
  521. /package/dist/{chunk-52MGURXO.js.map → chunk-WBUHHMLN.js.map} +0 -0
  522. /package/dist/{chunk-2MG3SW7Q.js.map → chunk-X6Z2SIRF.js.map} +0 -0
  523. /package/dist/{chunk-5UMK7GRI.js.map → chunk-XPNJH7GN.js.map} +0 -0
  524. /package/dist/{chunk-KZXDLBY6.js.map → chunk-XPW7T2GN.js.map} +0 -0
  525. /package/dist/{chunk-FFJFE4T7.js.map → chunk-YJGKOSQD.js.map} +0 -0
  526. /package/dist/{chunk-4JPMZTJY.js.map → chunk-ZF7KNSLU.js.map} +0 -0
  527. /package/dist/{chunk-2ODVB6LZ.js.map → chunk-ZGKODRGB.js.map} +0 -0
  528. /package/dist/{chunk-JIBUPZHA.js.map → chunk-ZNEKQFGF.js.map} +0 -0
  529. /package/dist/{chunk-DLD5LGDS.js.map → chunk-ZUTUNVFD.js.map} +0 -0
  530. /package/dist/{classified-marker-SIYKUU5L.js.map → classified-marker-WKP33U2R.js.map} +0 -0
  531. /package/dist/{collection-facade-CS7CA2XO.js.map → collection-facade-COSGZKLC.js.map} +0 -0
  532. /package/dist/{computed-FAD7SED4.js.map → computed-WN6V53ZV.js.map} +0 -0
  533. /package/dist/{dead-filter-4F3LWYKH.js.map → dead-filter-43WL3Y5H.js.map} +0 -0
  534. /package/dist/{derive-XLOJVXPU.js.map → delegation-5UWT4JGT.js.map} +0 -0
  535. /package/dist/{executor-FMPVN6DT.js.map → derive-IL5JNLEE.js.map} +0 -0
  536. /package/dist/{dispatch-JDZNGEB3.js.map → dispatch-LOQQD5JK.js.map} +0 -0
  537. /package/dist/{dispatch-H4HV32AM.js.map → dispatch-SHKTG57L.js.map} +0 -0
  538. /package/dist/{executor-LBBBRTN5.js.map → executor-6PQ7WAGV.js.map} +0 -0
  539. /package/dist/{executor-OSRZST2U.js.map → executor-6ZPQA6HS.js.map} +0 -0
  540. /package/dist/{export-accessible-RAOJAAU5.js.map → executor-OXRA64TY.js.map} +0 -0
  541. /package/dist/{extract-partition-JD5CUSTG.js.map → export-accessible-XG3FKJWW.js.map} +0 -0
  542. /package/dist/{find-JRN4RNQ5.js.map → extract-partition-33747NY5.js.map} +0 -0
  543. /package/dist/{fanout-sidecar-L7NHPIOC.js.map → fanout-sidecar-NEB6IYV7.js.map} +0 -0
  544. /package/dist/{issue-YIVBZUTH.js.map → find-VW543G3J.js.map} +0 -0
  545. /package/dist/{ledger-5ZMGE44K.js.map → issue-4ZPSY44M.js.map} +0 -0
  546. /package/dist/{liberate-WZSZM2W6.js.map → ledger-MZ25UFT2.js.map} +0 -0
  547. /package/dist/{link-set-MFXC24VK.js.map → liberate-OJIP2ZFX.js.map} +0 -0
  548. /package/dist/{managed-secret-MFTFT22X.js.map → link-set-4FRRAVTH.js.map} +0 -0
  549. /package/dist/{noydb-ITIGNKUF.js.map → managed-secret-SQWO2EUR.js.map} +0 -0
  550. /package/dist/{migrate-cek-DZRFFOHW.js.map → migrate-cek-JWEM4RP6.js.map} +0 -0
  551. /package/dist/{register-DT5HZ2LZ.js.map → noydb-U62OVKXB.js.map} +0 -0
  552. /package/dist/{pod-handle-A3LET7NO.js.map → pod-handle-R6Y4MILX.js.map} +0 -0
  553. /package/dist/{post-register-7ND27CF2.js.map → post-register-GRVQHBOH.js.map} +0 -0
  554. /package/dist/{registry-BHRZGZHF.js.map → register-YJ5YLQ36.js.map} +0 -0
  555. /package/dist/{registry-ET6ZFFWA.js.map → registry-ICOHBQFD.js.map} +0 -0
  556. /package/dist/{registry-HXFGLGTG.js.map → registry-MJ7MWCSW.js.map} +0 -0
  557. /package/dist/{registry-THCPDEOD.js.map → registry-MVEKKGWL.js.map} +0 -0
  558. /package/dist/{request-withdrawal-AV2MJJKY.js.map → registry-XP744FAP.js.map} +0 -0
  559. /package/dist/{revoke-6DWIEOCV.js.map → request-withdrawal-LSU4G6W3.js.map} +0 -0
  560. /package/dist/{reveal-B2TLP4JQ.js.map → reveal-AIHOIK2N.js.map} +0 -0
  561. /package/dist/{signer-MHGW3OIL.js.map → revoke-QUT7WWG3.js.map} +0 -0
  562. /package/dist/{stale-6GCFMOOR.js.map → signer-NYR4I3FO.js.map} +0 -0
  563. /package/dist/{storage-BYN5LO6Z.js.map → stale-PIJPAL5T.js.map} +0 -0
  564. /package/dist/{walk-4VPK7AS4.js.map → storage-VH6SPXHC.js.map} +0 -0
  565. /package/dist/{store-coordination-provider-C4BPT5XF.js.map → store-coordination-provider-2KSHCOPU.js.map} +0 -0
  566. /package/dist/{verify-UKALW7C2.js.map → verify-PCFS4PNS.js.map} +0 -0
  567. /package/dist/{withdraw-accessible-HL7GACUE.js.map → walk-OZCN6LJS.js.map} +0 -0
@@ -1,31 +1,38 @@
1
1
  import {
2
- SyncScheduler
3
- } from "./chunk-T7IR4N2S.js";
2
+ REJECTIONS_COLLECTION,
3
+ SyncScheduler,
4
+ rejectionKey
5
+ } from "./chunk-7UHLO4ZN.js";
4
6
  import {
5
7
  PERIODS_COLLECTION,
6
8
  PERIOD_ARCHIVES_COLLECTION,
7
9
  PERIOD_FREEZES_COLLECTION,
8
10
  PERIOD_TARGET_PURGES_COLLECTION,
9
11
  periodExclusiveUpperBound
10
- } from "./chunk-QBLT6POL.js";
12
+ } from "./chunk-FPF5HRBE.js";
11
13
  import {
14
+ parseKeyringEnvelope
15
+ } from "./chunk-V7AKGAXY.js";
16
+ import {
17
+ buildDeleteMarker,
12
18
  buildRecordEnvelope,
13
19
  decrypt,
14
20
  derivePresenceKey,
15
21
  derivePresenceTagKey,
16
22
  encrypt,
23
+ envelopeBodyForHash,
17
24
  envelopeBodySize,
18
25
  hmacSignHex,
19
26
  isDeleteMarker,
20
27
  isTombstoneShape
21
- } from "./chunk-EZGV6F47.js";
28
+ } from "./chunk-WRLWEYHY.js";
22
29
  import {
23
30
  NOYDB_SYNC_VERSION
24
- } from "./chunk-SV2PM2OY.js";
31
+ } from "./chunk-XX4R7TUB.js";
25
32
  import {
26
33
  ValidationError,
27
34
  isConflictError
28
- } from "./chunk-37EPTBBR.js";
35
+ } from "./chunk-IKPQ2GGB.js";
29
36
 
30
37
  // src/with-sync/presence.ts
31
38
  var PresenceHandle = class {
@@ -273,6 +280,126 @@ var PresenceHandle = class {
273
280
  }
274
281
  };
275
282
 
283
+ // src/with-sync/reserved-mirror.ts
284
+ var KEYRING_COLLECTION = "_keyring";
285
+ function keyringEpoch(envelope) {
286
+ if (!envelope) return void 0;
287
+ try {
288
+ const epoch = parseKeyringEnvelope(envelope).roster_epoch;
289
+ return typeof epoch === "number" ? epoch : void 0;
290
+ } catch {
291
+ return void 0;
292
+ }
293
+ }
294
+ function keyringIdentity(envelope) {
295
+ const file = parseKeyringEnvelope(envelope);
296
+ return `${file.roster_epoch ?? ""}:${file.roster_tag.data}:${file.display_name}`;
297
+ }
298
+ function keyringSupersedes(candidate, current) {
299
+ if (!current) return true;
300
+ const c = keyringEpoch(candidate);
301
+ const k = keyringEpoch(current);
302
+ if (c === void 0) return false;
303
+ if (k === void 0) return true;
304
+ return c > k;
305
+ }
306
+ function versionSupersedes(candidate, current) {
307
+ if (!current) return true;
308
+ return candidate._v > current._v;
309
+ }
310
+ var RESERVED_REPLICATION = [
311
+ { collection: KEYRING_COLLECTION, supersedes: keyringSupersedes, propagateDeletes: true },
312
+ // core#91 — the broker seeds. `_broker/<brokerId>` is sealed under the
313
+ // admin `_broker` DEK (owner/admin only hold it), `_broker_member/<userId>`
314
+ // under that grantee's own DEK: both are ciphertext to the mover and to every
315
+ // other device, and both are exactly what a fresh device needs to mint its
316
+ // first credential. Revocation is a delete that rides the dirty log.
317
+ // core#97 — SECOND, right behind the roster: on a fresh device every target
318
+ // request before the seed has landed cannot be served by the device's own
319
+ // mint, so the seed travels before anything else a first pull carries.
320
+ { collection: "_broker_member", supersedes: versionSupersedes, propagateDeletes: true },
321
+ { collection: "_broker", supersedes: versionSupersedes, propagateDeletes: true },
322
+ { collection: "_meta", idPrefix: "invite-audit-", supersedes: versionSupersedes, propagateDeletes: false },
323
+ { collection: "_users", supersedes: versionSupersedes, propagateDeletes: true },
324
+ { collection: "_delegations", supersedes: versionSupersedes, propagateDeletes: true },
325
+ // core#107 — the arbiter's admission refusals, so the WRITER learns its
326
+ // offline record was rejected instead of the verdict staying on the device
327
+ // that made it. Sealed under the refused record's OWN collection DEK, so
328
+ // this mover still reads nothing (`_v` is on the envelope) and a member
329
+ // without that collection receives ciphertext they quietly skip.
330
+ // `propagateDeletes: true` — clearing a refusal is how it stops being shown.
331
+ { collection: REJECTIONS_COLLECTION, supersedes: versionSupersedes, propagateDeletes: true }
332
+ ];
333
+ function inScope(rule, id) {
334
+ return rule.idPrefix === void 0 || id.startsWith(rule.idPrefix);
335
+ }
336
+ async function mirrorRule(rule, from, to, vault, fromIds) {
337
+ const copied = [];
338
+ for (const id of fromIds ?? await from.list(vault, rule.collection)) {
339
+ if (!inScope(rule, id)) continue;
340
+ const candidate = await from.get(vault, rule.collection, id);
341
+ if (!candidate) continue;
342
+ const current = await to.get(vault, rule.collection, id);
343
+ if (!rule.supersedes(candidate, current)) continue;
344
+ await to.put(vault, rule.collection, id, candidate);
345
+ copied.push(id);
346
+ }
347
+ return copied;
348
+ }
349
+ async function pushReserved(local, remote, vault) {
350
+ let copied = 0;
351
+ let keyringsCopied = [];
352
+ const staleKeyrings = [];
353
+ for (const rule of RESERVED_REPLICATION) {
354
+ const ids = await mirrorRule(rule, local, remote, vault);
355
+ copied += ids.length;
356
+ if (rule.collection === KEYRING_COLLECTION) {
357
+ keyringsCopied = ids;
358
+ for (const id of await local.list(vault, KEYRING_COLLECTION)) {
359
+ if (ids.includes(id)) continue;
360
+ const [mine, theirs] = await Promise.all([local.get(vault, KEYRING_COLLECTION, id), remote.get(vault, KEYRING_COLLECTION, id)]);
361
+ if (mine && theirs && keyringIdentity(mine) !== keyringIdentity(theirs)) staleKeyrings.push({ id, local: mine, remote: theirs });
362
+ }
363
+ }
364
+ }
365
+ return { copied, deleted: 0, keyringsCopied, ...staleKeyrings.length > 0 && { staleKeyrings } };
366
+ }
367
+ async function pullKeyringFile(remote, local, vault, userId) {
368
+ const rule = RESERVED_REPLICATION[0];
369
+ const ids = await mirrorRule(rule, remote, local, vault, [userId]);
370
+ return ids.length > 0;
371
+ }
372
+ async function pullReserved(remote, local, vault, protectedIds) {
373
+ const localKeyrings = await local.list(vault, KEYRING_COLLECTION);
374
+ if (localKeyrings.length === 0) return { copied: 0, deleted: 0, keyringsCopied: [] };
375
+ let copied = 0;
376
+ let deleted = 0;
377
+ let keyringsCopied = [];
378
+ let remoteInitialised = false;
379
+ for (const rule of RESERVED_REPLICATION) {
380
+ const remoteIds = (await remote.list(vault, rule.collection)).filter((id) => inScope(rule, id));
381
+ if (rule.collection === KEYRING_COLLECTION) remoteInitialised = remoteIds.length > 0;
382
+ const ids = await mirrorRule(rule, remote, local, vault, remoteIds);
383
+ copied += ids.length;
384
+ if (rule.collection === KEYRING_COLLECTION) keyringsCopied = ids;
385
+ if (!rule.propagateDeletes || !remoteInitialised) continue;
386
+ const remoteSet = new Set(remoteIds);
387
+ const protectedSet = protectedIds.get(rule.collection);
388
+ const localIds = rule.collection === KEYRING_COLLECTION ? localKeyrings : await local.list(vault, rule.collection);
389
+ for (const id of localIds) {
390
+ if (!inScope(rule, id) || remoteSet.has(id) || protectedSet?.has(id)) continue;
391
+ await local.delete(vault, rule.collection, id);
392
+ deleted++;
393
+ }
394
+ }
395
+ return { copied, deleted, keyringsCopied };
396
+ }
397
+ async function bootstrapKeyrings(local, peer, vault) {
398
+ if (!peer) return;
399
+ if ((await local.list(vault, KEYRING_COLLECTION)).length > 0) return;
400
+ await mirrorRule(RESERVED_REPLICATION[0], peer, local, vault);
401
+ }
402
+
276
403
  // src/with-sync/period-scope.ts
277
404
  var PERIOD_SUMMARY_COLLECTIONS = [
278
405
  PERIODS_COLLECTION,
@@ -319,8 +446,22 @@ function buildPeriodScope(option, records) {
319
446
  }
320
447
 
321
448
  // src/with-sync/engine.ts
449
+ var REJECTED_COLLECTION = "_sync_rejected";
450
+ function parseParked(env) {
451
+ return JSON.parse(envelopeBodyForHash(env));
452
+ }
322
453
  var SyncEngine = class {
323
454
  mergeAuthority;
455
+ /** core#74 — the vault's admission gate for incoming records; wired at open like the other vault seams. */
456
+ admission;
457
+ #applied = [];
458
+ #rejected = [];
459
+ /** core#108 — this device's own records, refused by its own gates on the way OUT. */
460
+ #pushRejected = [];
461
+ /** core#107 — the vault's sealing capability for replicated refusals; wired at open like `admission`. */
462
+ courier;
463
+ /** core#107 — this device's refusals replicate. Configuration, not an authority proof — see `withSync`. */
464
+ arbiter;
324
465
  local;
325
466
  remote;
326
467
  strategy;
@@ -336,6 +477,8 @@ var SyncEngine = class {
336
477
  /** #1036 — last SUCCESSFUL push/pull. Never advanced by a failed attempt. */
337
478
  lastPush = null;
338
479
  lastPull = null;
480
+ /** core#72 — the target's restore epoch this device adopted; null before any. */
481
+ epoch = null;
339
482
  /**
340
483
  * #1036 — the failure that ended the most recent attempt, cleared by the next
341
484
  * success. Live state only: deliberately NOT persisted in `_sync/meta`, since a
@@ -403,11 +546,216 @@ var SyncEngine = class {
403
546
  setPeriodPullSource(source) {
404
547
  this.periodPullSource = source;
405
548
  }
549
+ /** core#81 — the collections this keyring names; the walk set for a paged pull. Wired by the vault at open. */
550
+ collectionNames;
551
+ /** Wire the paged-pull walk set (core#81). Same injection pattern as `setCacheInvalidator`. */
552
+ setCollectionNames(fn) {
553
+ this.collectionNames = fn;
554
+ }
555
+ /**
556
+ * core#81 — one chunk per page of one collection, for `pull({ paged: true })`.
557
+ * `listPage` when the store offers it (200 per page), else `list` + `get` in
558
+ * batches of the same size. Never more than one page in memory.
559
+ */
560
+ async *pagedChunks(names) {
561
+ const PAGE = 200;
562
+ const remote = this.remote;
563
+ for (const coll of names) {
564
+ if (typeof remote.listPage === "function") {
565
+ let cursor;
566
+ do {
567
+ const page = await remote.listPage(this.vault, coll, cursor, PAGE);
568
+ const records = {};
569
+ for (const { id, envelope } of page.items) records[id] = envelope;
570
+ if (page.items.length > 0) yield [coll, records];
571
+ cursor = page.nextCursor ?? void 0;
572
+ } while (cursor !== void 0);
573
+ } else {
574
+ const ids = await remote.list(this.vault, coll);
575
+ for (let i = 0; i < ids.length; i += PAGE) {
576
+ const records = {};
577
+ for (const id of ids.slice(i, i + PAGE)) {
578
+ const env = await remote.get(this.vault, coll, id);
579
+ if (env) records[id] = env;
580
+ }
581
+ if (Object.keys(records).length > 0) yield [coll, records];
582
+ }
583
+ }
584
+ }
585
+ }
586
+ /** core#82 — when a pull replaces the caller's OWN keyring file, the vault reloads it in place. */
587
+ rosterReload;
588
+ /** Wire the roster-reload seam (core#82). Same injection pattern as `setCacheInvalidator`. */
589
+ /** core#107 — wire the vault's rejection sealing capability. */
590
+ setRejectionCourier(c) {
591
+ this.courier = c;
592
+ }
593
+ /** core#74 — wire the vault's admission gate. */
594
+ setAdmission(a) {
595
+ this.admission = a;
596
+ }
597
+ /** core#71 — after `vault.load()`: a new base. Drops the dirty log, the watermarks and the adopted epoch. */
598
+ async resetAfterRestore() {
599
+ await this.ensureLoaded();
600
+ this.dirty = [];
601
+ this.lastPush = null;
602
+ this.lastPull = null;
603
+ this.epoch = null;
604
+ await this.persistMeta();
605
+ }
606
+ /** core#72 — the target's epoch record, or null when the target was never replaced. */
607
+ async #remoteEpoch() {
608
+ const env = await this.remote.get(this.vault, "_sync", "epoch");
609
+ return env ? JSON.parse(envelopeBodyForHash(env)) : null;
610
+ }
611
+ /**
612
+ * core#72 — make the LOCAL vault authoritative on this target. Every local
613
+ * record goes up unconditionally, re-sealed above the target's version where
614
+ * the target moved on (so every peer's copy is superseded); every id the
615
+ * target holds that the local vault lacks gets a delete marker at
616
+ * `remote._v + 1` (so every peer removes it); the reserved collections are
617
+ * mirrored; then a new epoch is written at `_sync/epoch`. The dirty log is
618
+ * cleared: the target IS the local state now.
619
+ */
620
+ async replaceRemote() {
621
+ await this.ensureLoaded();
622
+ const actor = this.rosterReload?.userId ?? "sync";
623
+ const [localSnapshot, remoteSnapshot] = await Promise.all([this.local.loadAll(this.vault), this.remote.loadAll(this.vault)]);
624
+ let replaced = 0;
625
+ let tombstoned = 0;
626
+ for (const [collection, records] of Object.entries(localSnapshot)) {
627
+ if (collection === REJECTED_COLLECTION) continue;
628
+ for (const [id, envelope] of Object.entries(records)) {
629
+ const current = remoteSnapshot[collection]?.[id];
630
+ let out = envelope;
631
+ if (current && current._v >= envelope._v) {
632
+ out = this.mergeAuthority ? await this.mergeAuthority.advance(collection, id, envelope, current._v + 1) : { ...envelope, _v: current._v + 1 };
633
+ await this.local.put(this.vault, collection, id, out);
634
+ }
635
+ await this.remote.put(this.vault, collection, id, out);
636
+ replaced++;
637
+ }
638
+ }
639
+ for (const [collection, records] of Object.entries(remoteSnapshot)) {
640
+ if (collection === REJECTED_COLLECTION) continue;
641
+ for (const [id, envelope] of Object.entries(records)) {
642
+ if (localSnapshot[collection]?.[id] !== void 0) continue;
643
+ if (isTombstoneShape(envelope) || isDeleteMarker(envelope)) continue;
644
+ const marker = buildDeleteMarker({ collection, id }, envelope._v + 1, actor);
645
+ await this.remote.put(this.vault, collection, id, marker);
646
+ await this.local.put(this.vault, collection, id, marker);
647
+ tombstoned++;
648
+ }
649
+ }
650
+ const mirrored = await pushReserved(this.local, this.remote, this.vault);
651
+ const previous = await this.#remoteEpoch();
652
+ const epoch = (previous?.epoch ?? 0) + 1;
653
+ const record = { epoch, at: (/* @__PURE__ */ new Date()).toISOString(), by: actor, replaced, tombstoned };
654
+ await this.remote.put(this.vault, "_sync", "epoch", buildRecordEnvelope({ collection: "_sync", id: "epoch", version: epoch }, { iv: "", data: JSON.stringify(record) }));
655
+ this.dirty = [];
656
+ this.epoch = epoch;
657
+ this.lastPush = (/* @__PURE__ */ new Date()).toISOString();
658
+ await this.persistMeta();
659
+ const result = { epoch, replaced, tombstoned, reserved: mirrored.copied };
660
+ this.emitter.emit("sync:replace", { vault: this.vault, ...result });
661
+ return result;
662
+ }
663
+ /**
664
+ * core#72 — at the start of a pull: has the target been replaced since this
665
+ * device last synced? If so, park every unpushed local edit (same fate as an
666
+ * admission refusal, reason `restore-epoch`), drop the dirty log, adopt the
667
+ * epoch. The pull that follows then adopts the target: the restorer lifted
668
+ * its records above every peer's version and tombstoned what it removed.
669
+ */
670
+ async #crossEpoch() {
671
+ const remote = await this.#remoteEpoch();
672
+ if (!remote || remote.epoch === this.epoch) return { epoch: remote?.epoch ?? 0, resynced: false, parked: 0 };
673
+ const from = this.epoch;
674
+ let parked = 0;
675
+ for (const entry of this.dirty) {
676
+ if (entry.action === "delete") continue;
677
+ const env = await this.local.get(this.vault, entry.collection, entry.id);
678
+ if (!env) continue;
679
+ const rejection = {
680
+ vault: this.vault,
681
+ collection: entry.collection,
682
+ id: entry.id,
683
+ version: env._v,
684
+ reason: `restore-epoch: the target was replaced (epoch ${remote.epoch}) after this edit; readmit to keep it locally, then put again to push`,
685
+ ...env._by !== void 0 ? { by: env._by } : {},
686
+ at: (/* @__PURE__ */ new Date()).toISOString()
687
+ };
688
+ const parkedRecord = { rejection, envelope: env };
689
+ await this.local.put(
690
+ this.vault,
691
+ REJECTED_COLLECTION,
692
+ `${entry.collection}::${entry.id}`,
693
+ buildRecordEnvelope({ collection: REJECTED_COLLECTION, id: `${entry.collection}::${entry.id}`, version: 1 }, { iv: "", data: JSON.stringify(parkedRecord) })
694
+ );
695
+ this.#rejected.push(rejection);
696
+ this.emitter.emit("sync:rejected", rejection);
697
+ await this.local.delete(this.vault, entry.collection, entry.id);
698
+ await this.cacheInvalidator?.(entry.collection, entry.id, "delete");
699
+ parked++;
700
+ }
701
+ this.dirty = [];
702
+ this.epoch = remote.epoch;
703
+ this.emitter.emit("sync:epoch", { vault: this.vault, from, to: remote.epoch, parked });
704
+ return { epoch: remote.epoch, resynced: true, parked };
705
+ }
706
+ /** core#74 — the parked refusals on this device, and their two fates. */
707
+ rejected() {
708
+ const key = (collection, id) => `${collection}::${id}`;
709
+ return {
710
+ list: async () => {
711
+ const out = [];
712
+ for (const id of await this.local.list(this.vault, REJECTED_COLLECTION)) {
713
+ const env = await this.local.get(this.vault, REJECTED_COLLECTION, id);
714
+ if (!env) continue;
715
+ out.push(parseParked(env).rejection);
716
+ }
717
+ return out;
718
+ },
719
+ readmit: async (collection, id) => {
720
+ const env = await this.local.get(this.vault, REJECTED_COLLECTION, key(collection, id));
721
+ if (!env) throw new ValidationError(`sync: no rejected record parked for "${collection}/${id}".`);
722
+ await this.local.put(this.vault, collection, id, parseParked(env).envelope);
723
+ await this.local.delete(this.vault, REJECTED_COLLECTION, key(collection, id));
724
+ await this.cacheInvalidator?.(collection, id, "put");
725
+ },
726
+ discard: async (collection, id) => {
727
+ await this.local.delete(this.vault, REJECTED_COLLECTION, key(collection, id));
728
+ }
729
+ };
730
+ }
731
+ setRosterReload(seam) {
732
+ this.rosterReload = seam;
733
+ }
734
+ /** core#81 — the running sync's latest progress sample; `null` when idle. Read by `status()`. */
735
+ inFlight = null;
736
+ progressLastEmit = 0;
737
+ progressLastRecords = 0;
738
+ /** Emit `sync:progress` no more than every 25 records or ~250 ms; `force` for the final sample. */
739
+ progress(sample, force = false) {
740
+ this.inFlight = sample;
741
+ const now = Date.now();
742
+ if (!force && sample.records - this.progressLastRecords < 25 && now - this.progressLastEmit < 250) return;
743
+ this.progressLastEmit = now;
744
+ this.progressLastRecords = sample.records;
745
+ this.emitter.emit("sync:progress", sample);
746
+ }
747
+ progressDone() {
748
+ this.inFlight = null;
749
+ this.progressLastEmit = 0;
750
+ this.progressLastRecords = 0;
751
+ }
406
752
  /** #807: KPI accumulator `applyRemote` feeds during a period-scoped `pull()` — pointed at the
407
753
  * active phase's counters (summaries → records) and cleared before pull returns. Approximate
408
754
  * by design: a push interleaved mid-pull on the same engine would attribute its converge
409
755
  * applies to the open phase; the counters are a download-budget KPI, not an audit source. */
410
756
  pullByteSink = null;
757
+ /** core#81 — ciphertext bytes applied by the running pull, for `sync:progress`. */
758
+ pullBytes = 0;
411
759
  constructor(opts) {
412
760
  this.local = opts.local;
413
761
  this.remote = opts.remote;
@@ -418,6 +766,7 @@ var SyncEngine = class {
418
766
  this.label = opts.label;
419
767
  this.policy = opts.syncPolicy;
420
768
  this.mergeAuthority = opts.mergeAuthority;
769
+ this.arbiter = opts.arbiter === true;
421
770
  const policy = opts.syncPolicy;
422
771
  if (policy && (policy.push.mode !== "manual" || policy.pull.mode !== "manual")) {
423
772
  this.scheduler = new SyncScheduler(policy, {
@@ -510,112 +859,305 @@ var SyncEngine = class {
510
859
  this.dirty = this.dirty.filter((d) => !(d.collection === collection && d.id === id));
511
860
  if (this.dirty.length !== before) await this.persistMeta();
512
861
  }
862
+ /**
863
+ * core#74/#108 — park a refused envelope under `_sync_rejected` and announce
864
+ * it. One helper for both fates: a record that ARRIVED and was turned away,
865
+ * and (core#108) this device's own record refused on the way out. The
866
+ * parking key is `collection::id`, so re-refusing the same record overwrites
867
+ * rather than accumulating.
868
+ */
869
+ async #park(collection, id, envelope, reason, origin) {
870
+ const rejection = {
871
+ vault: this.vault,
872
+ collection,
873
+ id,
874
+ reason,
875
+ version: envelope._v,
876
+ ...envelope._by !== void 0 ? { by: envelope._by } : {},
877
+ at: (/* @__PURE__ */ new Date()).toISOString(),
878
+ ...envelope._ts !== void 0 ? { recordAt: envelope._ts } : {},
879
+ origin
880
+ };
881
+ await this.#parkBuilt(collection, id, envelope, rejection);
882
+ if (origin === "sync-apply") await this.#publishRejection(collection, id, rejection);
883
+ return rejection;
884
+ }
885
+ /** Store half of `#park`, also used for a refusal that arrived already made (core#107). */
886
+ async #parkBuilt(collection, id, envelope, rejection) {
887
+ const parked = { rejection, envelope };
888
+ await this.local.put(
889
+ this.vault,
890
+ REJECTED_COLLECTION,
891
+ `${collection}::${id}`,
892
+ buildRecordEnvelope({ collection: REJECTED_COLLECTION, id: `${collection}::${id}`, version: 1 }, { iv: "", data: JSON.stringify(parked) })
893
+ );
894
+ this.emitter.emit("sync:rejected", rejection);
895
+ }
896
+ /**
897
+ * core#107 — turn the arbiter's replicated refusals into THIS device's
898
+ * notification. Runs after the reserved phase has brought `_sync_rejections`.
899
+ *
900
+ * Three filters, each load-bearing:
901
+ * - `courier.open` returns `null` for a member who holds no DEK for that
902
+ * collection. They received the ciphertext like everyone else and skip it.
903
+ * - a refusal names a VERSION. If this device's copy has moved on, the
904
+ * refusal is about a record that no longer exists here and is ignored —
905
+ * otherwise a stale verdict would re-fire against an edit that may well
906
+ * pass now.
907
+ * - an existing parking at the same version means this was already
908
+ * reported; the parking record IS the dedupe, so no extra state is kept
909
+ * and it survives a restart.
910
+ *
911
+ * ⛔ REPORT ONLY (ruled): the local record is never deleted, tombstoned or
912
+ * hidden. The refusal is information; what to do about it is the writer's.
913
+ */
914
+ async #scanReplicatedRejections() {
915
+ if (!this.courier) return 0;
916
+ let keys;
917
+ try {
918
+ keys = await this.local.list(this.vault, REJECTIONS_COLLECTION);
919
+ } catch {
920
+ return 0;
921
+ }
922
+ let seen = 0;
923
+ for (const parkKey of keys) {
924
+ const sep = parkKey.indexOf("::");
925
+ if (sep < 0) continue;
926
+ const collection = parkKey.slice(0, sep), id = parkKey.slice(sep + 2);
927
+ const env = await this.local.get(this.vault, REJECTIONS_COLLECTION, parkKey);
928
+ if (!env) continue;
929
+ const rejection = await this.courier.open(collection, id, env);
930
+ if (!rejection) continue;
931
+ const mine = await this.local.get(this.vault, collection, id);
932
+ if (!mine || mine._v !== rejection.version) continue;
933
+ const existing = await this.local.get(this.vault, REJECTED_COLLECTION, parkKey);
934
+ if (existing && parseParked(existing).rejection.version === rejection.version) continue;
935
+ const replicated = { ...rejection, origin: "arbiter" };
936
+ await this.#parkBuilt(collection, id, mine, replicated);
937
+ this.#rejected.push(replicated);
938
+ seen++;
939
+ }
940
+ return seen;
941
+ }
942
+ /**
943
+ * core#107 — the ARBITER's refusals replicate, so the writer finds out.
944
+ *
945
+ * Only `sync-apply` refusals: a `push-recheck` refusal (core#108) never left
946
+ * this device, so there is no other device to tell, and a `restore-epoch`
947
+ * parking is this device adopting a new base rather than a judgement about
948
+ * the record.
949
+ *
950
+ * ⛔ Best-effort by construction: a failure to publish must not fail the
951
+ * pull that produced it. The local parking, the `PullResult.rejected` row
952
+ * and the event have already happened and are this device's real answer;
953
+ * replication is the courtesy on top. So a courier that cannot seal (no DEK
954
+ * for that collection) or a store that refuses the write leaves the refusal
955
+ * exactly as it was before core#107.
956
+ */
957
+ async #publishRejection(collection, id, rejection) {
958
+ if (!this.arbiter || !this.courier) return;
959
+ try {
960
+ const key = rejectionKey(collection, id);
961
+ const current = await this.local.get(this.vault, REJECTIONS_COLLECTION, key);
962
+ const envelope = await this.courier.seal(collection, id, rejection, (current?._v ?? 0) + 1);
963
+ if (envelope) await this.local.put(this.vault, REJECTIONS_COLLECTION, key, envelope);
964
+ } catch {
965
+ }
966
+ }
967
+ /**
968
+ * core#108 — re-run this device's OWN gates against a dirty record before it
969
+ * is pushed. A record written offline may no longer pass the rules this
970
+ * device now holds (a period closed while it was away); today it pushes and
971
+ * every OTHER device refuses it at admission, so the writer is the last to
972
+ * know. Judging it here means the writer's own device catches it the moment
973
+ * it reconnects, before anyone else sees the record.
974
+ *
975
+ * Returns `true` when the entry was WITHHELD. The entry stays dirty and the
976
+ * local copy is untouched, so nothing is lost and a later push carries it
977
+ * unchanged once the rule passes again — which is why a refusal here needs
978
+ * no `readmit()` and no dirty-log surgery.
979
+ *
980
+ * ⛔ `rekey` is never re-checked: core#100 rewrites the SAME content under a
981
+ * new key, so judging it would refuse a record for its content having been
982
+ * legal at write time — the same wrong answer core#74 fixed with
983
+ * `admit: false` for a device's own re-versioned records.
984
+ */
985
+ async #withheldByRecheck(entry, envelope) {
986
+ if (!this.admission || entry.action === "rekey") return false;
987
+ if (isTombstoneShape(envelope) || isDeleteMarker(envelope)) return false;
988
+ const verdict = await this.admission.admit(entry.collection, entry.id, envelope, "push-recheck");
989
+ if (verdict.admitted) return false;
990
+ this.#pushRejected.push(await this.#park(entry.collection, entry.id, envelope, verdict.reason, "push-recheck"));
991
+ return true;
992
+ }
993
+ /** One dirty entry of `push()`: the CAS put, the tombstone assertion, the delete, and every conflict branch. Extracted so `push({ concurrency })` can run entries in a bounded pool (core#93). */
994
+ async #pushOne(i, entry, acc) {
995
+ try {
996
+ if (entry.action === "delete") {
997
+ await this.remote.delete(this.vault, entry.collection, entry.id);
998
+ acc.completed.push(i);
999
+ acc.pushed++;
1000
+ } else {
1001
+ const envelope = await this.local.get(this.vault, entry.collection, entry.id);
1002
+ if (!envelope) {
1003
+ acc.completed.push(i);
1004
+ return;
1005
+ }
1006
+ if (isTombstoneShape(envelope)) {
1007
+ await this.remote.put(this.vault, entry.collection, entry.id, envelope);
1008
+ acc.completed.push(i);
1009
+ acc.pushed++;
1010
+ return;
1011
+ }
1012
+ if (await this.#withheldByRecheck(entry, envelope)) return;
1013
+ try {
1014
+ await this.remote.put(
1015
+ this.vault,
1016
+ entry.collection,
1017
+ entry.id,
1018
+ envelope,
1019
+ // core#100 — a `rekey` re-encrypted the record in place: same `_v`,
1020
+ // new bytes; the target still at that version takes it.
1021
+ entry.action === "rekey" ? entry.version : entry.version - 1
1022
+ );
1023
+ acc.completed.push(i);
1024
+ acc.pushed++;
1025
+ acc.bytes += envelopeBodySize(envelope);
1026
+ } catch (err) {
1027
+ if (isConflictError(err)) {
1028
+ const remoteEnvelope = await this.remote.get(this.vault, entry.collection, entry.id);
1029
+ if (remoteEnvelope) {
1030
+ if (remoteEnvelope._v === envelope._v && envelopeBodyForHash(remoteEnvelope) === envelopeBodyForHash(envelope)) {
1031
+ acc.completed.push(i);
1032
+ } else if (isTombstoneShape(remoteEnvelope)) {
1033
+ await this.applyRemote(entry.collection, entry.id, remoteEnvelope);
1034
+ acc.erasures.push(this.reportErasure(entry.collection, entry.id, remoteEnvelope, envelope, "push"));
1035
+ acc.completed.push(i);
1036
+ } else if (remoteEnvelope._v === envelope._v && isDeleteMarker(remoteEnvelope) !== isDeleteMarker(envelope) && !this.conflictResolvers.get(entry.collection)) {
1037
+ if (isDeleteMarker(remoteEnvelope)) {
1038
+ await this.applyRemote(entry.collection, entry.id, remoteEnvelope);
1039
+ acc.completed.push(i);
1040
+ } else {
1041
+ await this.remote.put(this.vault, entry.collection, entry.id, envelope);
1042
+ acc.completed.push(i);
1043
+ acc.pushed++;
1044
+ }
1045
+ } else {
1046
+ const { handled, conflict } = await this.handleConflict(
1047
+ entry.collection,
1048
+ entry.id,
1049
+ envelope,
1050
+ remoteEnvelope,
1051
+ "push"
1052
+ );
1053
+ acc.conflicts.push(conflict);
1054
+ if (handled === "local") {
1055
+ const winner = await this.advancePastRemote(conflict.local, entry.collection, entry.id, remoteEnvelope);
1056
+ await this.remote.put(this.vault, entry.collection, entry.id, winner);
1057
+ if (winner !== conflict.local) await this.applyRemote(entry.collection, entry.id, winner, { admit: false });
1058
+ acc.completed.push(i);
1059
+ acc.pushed++;
1060
+ } else if (handled === "remote") {
1061
+ await this.applyRemote(entry.collection, entry.id, conflict.remote);
1062
+ acc.completed.push(i);
1063
+ } else if (handled === "merged" && conflict.local !== envelope) {
1064
+ const merged = conflict.local;
1065
+ await this.remote.put(this.vault, entry.collection, entry.id, merged);
1066
+ await this.applyRemote(entry.collection, entry.id, merged);
1067
+ acc.completed.push(i);
1068
+ acc.pushed++;
1069
+ }
1070
+ }
1071
+ }
1072
+ } else {
1073
+ throw err;
1074
+ }
1075
+ }
1076
+ }
1077
+ } catch (err) {
1078
+ acc.errors.push(err instanceof Error ? err : new Error(String(err)));
1079
+ }
1080
+ }
1081
+ /**
1082
+ * core#92 — mark every user-collection record in the local store dirty at its
1083
+ * current version, so the next push sends it (CAS against `_v - 1`, so a
1084
+ * remote that already holds a newer copy resolves through the conflict path
1085
+ * instead of being overwritten). Records already dirty keep their entry.
1086
+ */
1087
+ async markAllDirty() {
1088
+ await this.ensureLoaded();
1089
+ const snapshot = await this.local.loadAll(this.vault);
1090
+ for (const [collection, records] of Object.entries(snapshot)) {
1091
+ if (collection === REJECTED_COLLECTION) continue;
1092
+ for (const [id, envelope] of Object.entries(records)) {
1093
+ if (this.dirty.some((d) => d.collection === collection && d.id === id)) continue;
1094
+ this.dirty.push({ vault: this.vault, collection, id, action: "put", version: envelope._v, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1095
+ }
1096
+ }
1097
+ await this.persistMeta();
1098
+ }
513
1099
  /** Push dirty records to remote adapter. Accepts optional `PushOptions` for partial sync. */
514
1100
  async push(options) {
515
1101
  await this.ensureLoaded();
1102
+ if (options?.full) await this.markAllDirty();
516
1103
  this.graphBatchController?.begin();
517
- let pushed = 0;
1104
+ let reserved = 0;
1105
+ this.#pushRejected = [];
518
1106
  const conflicts = [];
519
1107
  const erasures = [];
520
1108
  const errors = [];
521
1109
  const completed = [];
522
1110
  const expanded = options?.collections ? this.pairExpander?.(options.collections) ?? options.collections : null;
523
1111
  const filter = expanded ? /* @__PURE__ */ new Set([...expanded, ...this.reservedDictExpander?.(expanded) ?? []]) : null;
524
- for (let i = 0; i < this.dirty.length; i++) {
525
- const entry = this.dirty[i];
526
- if (filter && !filter.has(entry.collection)) {
527
- continue;
1112
+ const pushTotal = filter ? this.dirty.filter((d) => filter.has(d.collection)).length : this.dirty.length;
1113
+ const acc = { pushed: 0, bytes: 0, completed, conflicts, erasures, errors };
1114
+ const eligible = [...this.dirty.keys()].filter((i) => !filter || filter.has(this.dirty[i].collection));
1115
+ const width = Math.max(1, Math.floor(options?.concurrency ?? 1));
1116
+ let next = 0;
1117
+ const worker = async () => {
1118
+ while (next < eligible.length) {
1119
+ const i = eligible[next++];
1120
+ this.progress({ direction: "push", phase: "records", records: acc.pushed, bytes: acc.bytes, total: { records: pushTotal } });
1121
+ await this.#pushOne(i, this.dirty[i], acc);
528
1122
  }
1123
+ };
1124
+ await Promise.all(Array.from({ length: Math.min(width, eligible.length) }, () => worker()));
1125
+ const pushed = acc.pushed;
1126
+ const pushBytes = acc.bytes;
1127
+ for (const i of completed.sort((a, b) => b - a)) {
1128
+ this.dirty.splice(i, 1);
1129
+ }
1130
+ if (!filter) {
1131
+ this.progress({ direction: "push", phase: "reserved", records: pushed, bytes: pushBytes, total: { records: pushTotal } });
529
1132
  try {
530
- if (entry.action === "delete") {
531
- await this.remote.delete(this.vault, entry.collection, entry.id);
532
- completed.push(i);
533
- pushed++;
534
- } else {
535
- const envelope = await this.local.get(this.vault, entry.collection, entry.id);
536
- if (!envelope) {
537
- completed.push(i);
538
- continue;
539
- }
540
- if (isTombstoneShape(envelope)) {
541
- await this.remote.put(this.vault, entry.collection, entry.id, envelope);
542
- completed.push(i);
543
- pushed++;
544
- continue;
545
- }
546
- try {
547
- await this.remote.put(
548
- this.vault,
549
- entry.collection,
550
- entry.id,
551
- envelope,
552
- entry.version - 1
553
- );
554
- completed.push(i);
555
- pushed++;
556
- } catch (err) {
557
- if (isConflictError(err)) {
558
- const remoteEnvelope = await this.remote.get(this.vault, entry.collection, entry.id);
559
- if (remoteEnvelope) {
560
- if (isTombstoneShape(remoteEnvelope)) {
561
- await this.applyRemote(entry.collection, entry.id, remoteEnvelope);
562
- erasures.push(this.reportErasure(entry.collection, entry.id, remoteEnvelope, envelope, "push"));
563
- completed.push(i);
564
- } else if (remoteEnvelope._v === envelope._v && isDeleteMarker(remoteEnvelope) !== isDeleteMarker(envelope) && !this.conflictResolvers.get(entry.collection)) {
565
- if (isDeleteMarker(remoteEnvelope)) {
566
- await this.applyRemote(entry.collection, entry.id, remoteEnvelope);
567
- completed.push(i);
568
- } else {
569
- await this.remote.put(this.vault, entry.collection, entry.id, envelope);
570
- completed.push(i);
571
- pushed++;
572
- }
573
- } else {
574
- const { handled, conflict } = await this.handleConflict(
575
- entry.collection,
576
- entry.id,
577
- envelope,
578
- remoteEnvelope,
579
- "push"
580
- );
581
- conflicts.push(conflict);
582
- if (handled === "local") {
583
- const winner = await this.advancePastRemote(conflict.local, entry.collection, entry.id, remoteEnvelope);
584
- await this.remote.put(this.vault, entry.collection, entry.id, winner);
585
- if (winner !== conflict.local) await this.applyRemote(entry.collection, entry.id, winner);
586
- completed.push(i);
587
- pushed++;
588
- } else if (handled === "remote") {
589
- await this.applyRemote(entry.collection, entry.id, conflict.remote);
590
- completed.push(i);
591
- } else if (handled === "merged" && conflict.local !== envelope) {
592
- const merged = conflict.local;
593
- await this.remote.put(this.vault, entry.collection, entry.id, merged);
594
- await this.applyRemote(entry.collection, entry.id, merged);
595
- completed.push(i);
596
- pushed++;
597
- }
598
- }
599
- }
600
- } else {
601
- throw err;
602
- }
603
- }
1133
+ const mirrored = await pushReserved(this.local, this.remote, this.vault);
1134
+ reserved = mirrored.copied;
1135
+ for (const stale of mirrored.staleKeyrings ?? []) {
1136
+ conflicts.push({
1137
+ vault: this.vault,
1138
+ collection: "_keyring",
1139
+ id: stale.id,
1140
+ local: stale.local,
1141
+ remote: stale.remote,
1142
+ localVersion: stale.local._v,
1143
+ remoteVersion: stale.remote._v
1144
+ });
604
1145
  }
605
1146
  } catch (err) {
606
1147
  errors.push(err instanceof Error ? err : new Error(String(err)));
607
1148
  }
608
1149
  }
609
- for (const i of completed.sort((a, b) => b - a)) {
610
- this.dirty.splice(i, 1);
611
- }
1150
+ this.progress({ direction: "push", phase: "records", records: pushed, bytes: pushBytes, total: { records: pushTotal } }, true);
1151
+ this.progressDone();
612
1152
  this.recordOutcome("push", errors);
613
1153
  try {
614
1154
  await this.persistMeta();
615
1155
  } finally {
616
1156
  await this.graphBatchController?.flush();
617
1157
  }
618
- const result = { pushed, conflicts, errors, erasures };
1158
+ const pushRejected = this.#pushRejected;
1159
+ this.#pushRejected = [];
1160
+ const result = { pushed, conflicts, errors, erasures, ...reserved > 0 && { reserved }, ...pushRejected.length > 0 && { rejected: pushRejected } };
619
1161
  this.emitter.emit("sync:push", result);
620
1162
  return result;
621
1163
  }
@@ -623,9 +1165,43 @@ var SyncEngine = class {
623
1165
  async pull(options) {
624
1166
  await this.ensureLoaded();
625
1167
  let pulled = 0;
1168
+ let reserved = 0;
1169
+ this.#applied = [];
1170
+ this.#rejected = [];
626
1171
  const conflicts = [];
627
- const erasures = [];
628
1172
  const errors = [];
1173
+ let crossed = { epoch: 0, resynced: false, parked: 0 };
1174
+ const erasures = [];
1175
+ if (!options?.collections) {
1176
+ this.progress({ direction: "pull", phase: "reserved", records: 0, bytes: 0 });
1177
+ try {
1178
+ const protectedIds = /* @__PURE__ */ new Map();
1179
+ for (const d of this.dirty) {
1180
+ if (d.action === "delete") continue;
1181
+ let set = protectedIds.get(d.collection);
1182
+ if (!set) {
1183
+ set = /* @__PURE__ */ new Set();
1184
+ protectedIds.set(d.collection, set);
1185
+ }
1186
+ set.add(d.id);
1187
+ }
1188
+ const mirrored = await pullReserved(this.remote, this.local, this.vault, protectedIds);
1189
+ reserved = mirrored.copied + mirrored.deleted;
1190
+ if (this.rosterReload && mirrored.keyringsCopied.includes(this.rosterReload.userId)) await this.rosterReload.reload();
1191
+ } catch (err) {
1192
+ errors.push(err instanceof Error ? err : new Error(String(err)));
1193
+ }
1194
+ try {
1195
+ await this.#scanReplicatedRejections();
1196
+ } catch (err) {
1197
+ errors.push(err instanceof Error ? err : new Error(String(err)));
1198
+ }
1199
+ }
1200
+ try {
1201
+ crossed = await this.#crossEpoch();
1202
+ } catch (err) {
1203
+ errors.push(err instanceof Error ? err : new Error(String(err)));
1204
+ }
629
1205
  let periodScope = null;
630
1206
  let phases = null;
631
1207
  if (options?.periods !== void 0) {
@@ -646,7 +1222,7 @@ var SyncEngine = class {
646
1222
  const remoteEnvelope = await this.remote.get(this.vault, collName, id);
647
1223
  if (!remoteEnvelope) continue;
648
1224
  const localEnvelope = await this.local.get(this.vault, collName, id);
649
- if (!localEnvelope || remoteEnvelope._v > localEnvelope._v) {
1225
+ if (!localEnvelope || this.#remoteSupersedes(collName, id, remoteEnvelope, localEnvelope)) {
650
1226
  await this.applyRemote(collName, id, remoteEnvelope);
651
1227
  pulled++;
652
1228
  }
@@ -671,12 +1247,35 @@ var SyncEngine = class {
671
1247
  const expanded = options?.collections ? this.pairExpander?.(options.collections) ?? options.collections : null;
672
1248
  const filter = expanded ? /* @__PURE__ */ new Set([...expanded, ...this.reservedDictExpander?.(expanded) ?? []]) : null;
673
1249
  try {
674
- const remoteSnapshot = await this.remote.loadAll(this.vault);
675
- for (const [collName, records] of Object.entries(remoteSnapshot)) {
1250
+ let pullTotal = 0;
1251
+ let chunks;
1252
+ if (options?.paged) {
1253
+ const known = new Set(this.collectionNames?.() ?? []);
1254
+ for (const name of filter ?? []) if (!name.startsWith("_")) known.add(name);
1255
+ const names = [...known].filter((n) => !n.startsWith("_") && (!filter || filter.has(n)));
1256
+ for (const name of names) pullTotal += (await this.remote.list(this.vault, name)).length;
1257
+ chunks = this.pagedChunks(names);
1258
+ } else {
1259
+ const remoteSnapshot = await this.remote.loadAll(this.vault);
1260
+ for (const [collName, records] of Object.entries(remoteSnapshot)) {
1261
+ if (filter && !filter.has(collName)) continue;
1262
+ pullTotal += Object.keys(records).length;
1263
+ }
1264
+ chunks = Object.entries(remoteSnapshot);
1265
+ }
1266
+ const pullSample = () => ({
1267
+ direction: "pull",
1268
+ phase: "records",
1269
+ records: pulled,
1270
+ bytes: this.pullBytes,
1271
+ total: { records: pullTotal }
1272
+ });
1273
+ for await (const [collName, records] of chunks) {
676
1274
  if (filter && !filter.has(collName)) {
677
1275
  continue;
678
1276
  }
679
1277
  for (const [id, remoteEnvelope] of Object.entries(records)) {
1278
+ this.progress(pullSample());
680
1279
  if (options?.modifiedSince && remoteEnvelope._ts <= options.modifiedSince && !isTombstoneShape(remoteEnvelope) && !isDeleteMarker(remoteEnvelope)) {
681
1280
  continue;
682
1281
  }
@@ -718,7 +1317,7 @@ var SyncEngine = class {
718
1317
  this.dirty = this.dirty.filter((d) => !(d.collection === collName && d.id === id));
719
1318
  pulled++;
720
1319
  }
721
- } else if (remoteEnvelope._v > localEnvelope._v) {
1320
+ } else if (this.#remoteSupersedes(collName, id, remoteEnvelope, localEnvelope)) {
722
1321
  const isDirty = this.dirty.some((d) => d.collection === collName && d.id === id);
723
1322
  if (isDirty) {
724
1323
  const { handled, conflict } = await this.handleConflict(
@@ -768,7 +1367,7 @@ var SyncEngine = class {
768
1367
  this.dirty = this.dirty.filter((d) => !(d.collection === collName && d.id === id));
769
1368
  pulled++;
770
1369
  }
771
- } else if (remoteEnvelope._v > localEnvelope._v) {
1370
+ } else if (this.#remoteSupersedes(collName, id, remoteEnvelope, localEnvelope)) {
772
1371
  await this.applyRemote(collName, id, remoteEnvelope);
773
1372
  this.dirty = this.dirty.filter((d) => !(d.collection === collName && d.id === id));
774
1373
  pulled++;
@@ -781,6 +1380,9 @@ var SyncEngine = class {
781
1380
  } catch (err) {
782
1381
  errors.push(err instanceof Error ? err : new Error(String(err)));
783
1382
  }
1383
+ this.progress({ direction: "pull", phase: "records", records: pulled, bytes: this.pullBytes, total: { records: pulled } }, true);
1384
+ this.progressDone();
1385
+ this.pullBytes = 0;
784
1386
  this.recordOutcome("pull", errors);
785
1387
  try {
786
1388
  await this.persistMeta();
@@ -788,7 +1390,22 @@ var SyncEngine = class {
788
1390
  this.pullByteSink = null;
789
1391
  await this.graphBatchController?.flush();
790
1392
  }
791
- const result = { pulled, conflicts, errors, erasures, ...phases !== null ? { phases } : {} };
1393
+ pulled = Math.max(0, pulled - this.#rejected.length);
1394
+ const applied = this.#applied, rejected = this.#rejected;
1395
+ this.#applied = [];
1396
+ this.#rejected = [];
1397
+ const result = {
1398
+ pulled,
1399
+ conflicts,
1400
+ errors,
1401
+ erasures,
1402
+ ...reserved > 0 && { reserved },
1403
+ ...phases !== null ? { phases } : {},
1404
+ ...applied.length > 0 && { applied },
1405
+ ...rejected.length > 0 && { rejected },
1406
+ ...crossed.epoch > 0 && { epoch: crossed.epoch },
1407
+ ...crossed.resynced && { resynced: true }
1408
+ };
792
1409
  this.emitter.emit("sync:pull", result);
793
1410
  return result;
794
1411
  }
@@ -806,6 +1423,7 @@ var SyncEngine = class {
806
1423
  async pushFiltered(predicate) {
807
1424
  await this.ensureLoaded();
808
1425
  let pushed = 0;
1426
+ this.#pushRejected = [];
809
1427
  const conflicts = [];
810
1428
  const erasures = [];
811
1429
  const errors = [];
@@ -830,6 +1448,7 @@ var SyncEngine = class {
830
1448
  pushed++;
831
1449
  continue;
832
1450
  }
1451
+ if (await this.#withheldByRecheck(entry, envelope)) continue;
833
1452
  try {
834
1453
  await this.remote.put(
835
1454
  this.vault,
@@ -869,7 +1488,7 @@ var SyncEngine = class {
869
1488
  if (handled === "local") {
870
1489
  const winner = await this.advancePastRemote(conflict.local, entry.collection, entry.id, remoteEnvelope);
871
1490
  await this.remote.put(this.vault, entry.collection, entry.id, winner);
872
- if (winner !== conflict.local) await this.applyRemote(entry.collection, entry.id, winner);
1491
+ if (winner !== conflict.local) await this.applyRemote(entry.collection, entry.id, winner, { admit: false });
873
1492
  completed.push(i);
874
1493
  pushed++;
875
1494
  } else if (handled === "remote") {
@@ -898,7 +1517,9 @@ var SyncEngine = class {
898
1517
  }
899
1518
  this.recordOutcome("push", errors);
900
1519
  await this.persistMeta();
901
- const result = { pushed, conflicts, errors, erasures };
1520
+ const pushRejected = this.#pushRejected;
1521
+ this.#pushRejected = [];
1522
+ const result = { pushed, conflicts, errors, erasures, ...pushRejected.length > 0 && { rejected: pushRejected } };
902
1523
  this.emitter.emit("sync:push", result);
903
1524
  return result;
904
1525
  }
@@ -924,12 +1545,67 @@ var SyncEngine = class {
924
1545
  else this.lastPull = at;
925
1546
  }
926
1547
  /** Get current sync status. */
1548
+ /**
1549
+ * core#82 — re-align a CORRUPTED local from the target. An ordinary pull
1550
+ * cannot repair a damaged local envelope: it keeps its `_v`, so it wins
1551
+ * (or ties) against the target's healthy copy. Here every local
1552
+ * user-collection envelope is verified with the same `MergeAuthority`
1553
+ * check pull runs on remote envelopes; one that fails is replaced by the
1554
+ * target's copy when THAT verifies, and the dirty log is dropped (a dirty
1555
+ * entry over a damaged record would push the damage). Records at a tier
1556
+ * the caller holds no key for pass unverified, as in pull — this repairs
1557
+ * what the caller can read. Requires a `MergeAuthority` (a vault-attached
1558
+ * engine on an encrypted vault).
1559
+ */
1560
+ /**
1561
+ * core#96 (pilot-1, finding B) — bring one member's keyring file down from
1562
+ * this target if the target's copy supersedes ours. Called by the kernel
1563
+ * before an authority edit; reloads the caller's own keyring in place when
1564
+ * it is the one refreshed (core#82).
1565
+ */
1566
+ async refreshKeyring(userId) {
1567
+ await this.ensureLoaded();
1568
+ const copied = await pullKeyringFile(this.remote, this.local, this.vault, userId);
1569
+ if (copied && this.rosterReload && userId === this.rosterReload.userId) await this.rosterReload.reload();
1570
+ return copied;
1571
+ }
1572
+ async realign() {
1573
+ await this.ensureLoaded();
1574
+ if (!this.mergeAuthority) throw new ValidationError("realign: requires a vault-attached engine on an encrypted vault (no MergeAuthority).");
1575
+ const errors = [];
1576
+ let checked = 0;
1577
+ let replaced = 0;
1578
+ let unrecoverable = 0;
1579
+ const local = await this.local.loadAll(this.vault);
1580
+ for (const [collection, records] of Object.entries(local)) {
1581
+ for (const [id, envelope] of Object.entries(records)) {
1582
+ checked++;
1583
+ if (isTombstoneShape(envelope) || isDeleteMarker(envelope)) continue;
1584
+ if (await this.mergeAuthority.verify(collection, id, envelope)) continue;
1585
+ const remote = await this.remote.get(this.vault, collection, id);
1586
+ if (remote && await this.mergeAuthority.verify(collection, id, remote)) {
1587
+ await this.local.put(this.vault, collection, id, remote);
1588
+ await this.cacheInvalidator?.(collection, id, "put");
1589
+ replaced++;
1590
+ } else {
1591
+ unrecoverable++;
1592
+ errors.push(new ValidationError(`realign: "${collection}/${id}" fails to authenticate locally and the target holds no healthy copy.`));
1593
+ }
1594
+ }
1595
+ }
1596
+ this.dirty = [];
1597
+ await this.persistMeta();
1598
+ return { checked, replaced, unrecoverable, errors };
1599
+ }
927
1600
  status() {
928
1601
  const scheduled = this.scheduler?.status;
929
1602
  return {
930
1603
  dirty: this.dirty.length,
931
1604
  lastPush: this.lastPush,
932
1605
  lastPull: this.lastPull,
1606
+ ...this.epoch !== null ? { epoch: this.epoch } : {},
1607
+ // core#72
1608
+ ...this.inFlight ? { inFlight: this.inFlight } : {},
933
1609
  online: this.isOnline,
934
1610
  ...this.lastError ? { lastError: this.lastError } : {},
935
1611
  ...scheduled && scheduled.readiness.size > 0 ? { readiness: scheduled.readiness, phase: scheduled.phase } : {}
@@ -1012,13 +1688,42 @@ var SyncEngine = class {
1012
1688
  if (!this.mergeAuthority) return { ...winner, _v: toVersion };
1013
1689
  return this.mergeAuthority.advance(collection, id, winner, toVersion);
1014
1690
  }
1015
- async applyRemote(collection, id, envelope) {
1691
+ /**
1692
+ * core#100 — does the remote copy supersede ours? A higher `_v`, as always;
1693
+ * or the SAME `_v` with different bytes while we hold no pending write for
1694
+ * it: a DEK rotation re-encrypts records in place, and a replica that kept
1695
+ * the old ciphertext would read `TamperedError` under the delivered key.
1696
+ * `applyRemote` still authenticates it (`MergeAuthority`) before it lands.
1697
+ */
1698
+ #remoteSupersedes(collection, id, remote, local) {
1699
+ if (remote._v > local._v) return true;
1700
+ if (remote._v !== local._v) return false;
1701
+ if (this.dirty.some((d) => d.collection === collection && d.id === id)) return false;
1702
+ return envelopeBodyForHash(remote) !== envelopeBodyForHash(local);
1703
+ }
1704
+ async applyRemote(collection, id, envelope, opts) {
1016
1705
  if (this.mergeAuthority && !await this.mergeAuthority.verify(collection, id, envelope)) {
1017
1706
  throw new ValidationError(
1018
1707
  `sync: refusing remote envelope for "${collection}/${id}" \u2014 it does not authenticate at the identity and version it claims. The local copy is unchanged.`
1019
1708
  );
1020
1709
  }
1710
+ const isErasure = isTombstoneShape(envelope) || isDeleteMarker(envelope);
1711
+ if (this.admission && !isErasure && opts?.admit !== false) {
1712
+ const verdict = await this.admission.admit(collection, id, envelope);
1713
+ if (!verdict.admitted) {
1714
+ this.#rejected.push(await this.#park(collection, id, envelope, verdict.reason, "sync-apply"));
1715
+ return;
1716
+ }
1717
+ }
1718
+ const prior = await this.local.get(this.vault, collection, id);
1021
1719
  await this.local.put(this.vault, collection, id, envelope);
1720
+ this.#applied.push({
1721
+ collection,
1722
+ id,
1723
+ action: isErasure ? "delete" : "put",
1724
+ ...prior && prior._v < envelope._v ? { replaced: { version: prior._v, ...prior._by !== void 0 ? { by: prior._by } : {} } } : {}
1725
+ });
1726
+ this.pullBytes += envelopeBodySize(envelope);
1022
1727
  if (this.pullByteSink !== null) {
1023
1728
  this.pullByteSink.records++;
1024
1729
  this.pullByteSink.bytes += envelopeBodySize(envelope);
@@ -1117,6 +1822,7 @@ var SyncEngine = class {
1117
1822
  this.dirty = [...meta.dirty];
1118
1823
  this.lastPush = meta.last_push;
1119
1824
  this.lastPull = meta.last_pull;
1825
+ this.epoch = meta.epoch ?? null;
1120
1826
  }
1121
1827
  this.loaded = true;
1122
1828
  }
@@ -1125,7 +1831,8 @@ var SyncEngine = class {
1125
1831
  _noydb_sync: NOYDB_SYNC_VERSION,
1126
1832
  last_push: this.lastPush,
1127
1833
  last_pull: this.lastPull,
1128
- dirty: this.dirty
1834
+ dirty: this.dirty,
1835
+ ...this.epoch !== null ? { epoch: this.epoch } : {}
1129
1836
  };
1130
1837
  const envelope = buildRecordEnvelope(
1131
1838
  { collection: "_sync", id: "meta", version: 1 },
@@ -1195,7 +1902,8 @@ var SyncTransaction = class {
1195
1902
 
1196
1903
  export {
1197
1904
  PresenceHandle,
1905
+ bootstrapKeyrings,
1198
1906
  SyncEngine,
1199
1907
  SyncTransaction
1200
1908
  };
1201
- //# sourceMappingURL=chunk-H23XHRTT.js.map
1909
+ //# sourceMappingURL=chunk-RUE6TCES.js.map