@noy-db/hub 0.3.0-pre.11 → 0.3.0-pre.13

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 (395) hide show
  1. package/dist/aggregate/index.js +4 -4
  2. package/dist/api-ZGS6LCOF.js +20 -0
  3. package/dist/as/index.js +11 -11
  4. package/dist/attestation/index.js +18 -18
  5. package/dist/{backup-XA5STIYQ.js → backup-BJ57IKAO.js} +28 -11
  6. package/dist/backup-BJ57IKAO.js.map +1 -0
  7. package/dist/blobs/index.js +12 -10
  8. package/dist/blobs/index.js.map +1 -1
  9. package/dist/broker/index.js +12 -12
  10. package/dist/bundle/index.js +25 -22
  11. package/dist/bundle/index.js.map +1 -1
  12. package/dist/by/index.js +2 -2
  13. package/dist/cargo/index.js +22 -22
  14. package/dist/{chunk-WGV4CUZT.js → chunk-2NVOWNI3.js} +4 -4
  15. package/dist/{chunk-WGV4CUZT.js.map → chunk-2NVOWNI3.js.map} +1 -1
  16. package/dist/{chunk-OFJ5GPNA.js → chunk-3B5VVCNY.js} +2 -2
  17. package/dist/{chunk-KPGX66PM.js → chunk-3LQ2YKO4.js} +2 -2
  18. package/dist/{chunk-D26JB3LZ.js → chunk-3QCRBHCY.js} +2 -2
  19. package/dist/{chunk-H6CZSDWK.js → chunk-454JXE57.js} +3 -3
  20. package/dist/{chunk-H6CZSDWK.js.map → chunk-454JXE57.js.map} +1 -1
  21. package/dist/{chunk-DGH65E7Q.js → chunk-4CTHCN4J.js} +24 -10
  22. package/dist/chunk-4CTHCN4J.js.map +1 -0
  23. package/dist/{chunk-4N5QFSNQ.js → chunk-4JBYV75E.js} +5 -5
  24. package/dist/{chunk-UTLEAJXC.js → chunk-4NXKCLLQ.js} +2 -2
  25. package/dist/{chunk-ARSAMO24.js → chunk-4VNQOLML.js} +2 -2
  26. package/dist/{chunk-X6CMGUAG.js → chunk-5M5DVGV7.js} +2 -2
  27. package/dist/{chunk-DJ3VKYFA.js → chunk-5O3XF4DV.js} +4 -4
  28. package/dist/chunk-5O3XF4DV.js.map +1 -0
  29. package/dist/{chunk-XHV25KBM.js → chunk-5YOLBEQ6.js} +2 -2
  30. package/dist/{chunk-CB25ONKC.js → chunk-6CRIV7DE.js} +2 -2
  31. package/dist/{chunk-BE7N3AXA.js → chunk-6JTIAGHD.js} +3 -3
  32. package/dist/{chunk-JOQ53DMI.js → chunk-6QTNZJBS.js} +3 -3
  33. package/dist/{chunk-BZO4WCJI.js → chunk-6T2SCQRU.js} +4 -4
  34. package/dist/{chunk-FQQF23MC.js → chunk-7DSTRQIJ.js} +2 -2
  35. package/dist/{chunk-IP2QBAGS.js → chunk-AUSTCW2X.js} +10 -10
  36. package/dist/{chunk-A2Y6YFVN.js → chunk-B3HJYUOF.js} +2 -2
  37. package/dist/{chunk-SRVQHVNX.js → chunk-BDVFPG6Y.js} +5 -5
  38. package/dist/{chunk-FH542DDY.js → chunk-BIOUI4HL.js} +50 -1
  39. package/dist/chunk-BIOUI4HL.js.map +1 -0
  40. package/dist/{chunk-YXOUQ2H7.js → chunk-CAF6WOK7.js} +2 -2
  41. package/dist/{chunk-H6HM6CVR.js → chunk-CDUQTA3Z.js} +114 -12
  42. package/dist/chunk-CDUQTA3Z.js.map +1 -0
  43. package/dist/{chunk-HUS3J5WM.js → chunk-CIE2BASH.js} +2 -2
  44. package/dist/{chunk-DIRRS7WP.js → chunk-CRI4OUV4.js} +2 -2
  45. package/dist/{chunk-FXK4X4BL.js → chunk-DLG74CNB.js} +4 -4
  46. package/dist/{chunk-WTUNZACT.js → chunk-E5ZQT5KX.js} +2 -2
  47. package/dist/{chunk-DMFNPHCX.js → chunk-EQO2UVP4.js} +6 -6
  48. package/dist/{chunk-MCEKIAO4.js → chunk-ERJ7FU55.js} +3 -3
  49. package/dist/{chunk-6QILBDZU.js → chunk-EVVGJDRQ.js} +3 -3
  50. package/dist/{chunk-7VSGW5KJ.js → chunk-EVX47VBM.js} +2 -2
  51. package/dist/{chunk-D3EFFFOL.js → chunk-EXK7QRWF.js} +5 -5
  52. package/dist/{chunk-5JB73NMC.js → chunk-EYZ6IQ6X.js} +5 -5
  53. package/dist/{chunk-BCYQA5BK.js → chunk-F64IRYG3.js} +2 -2
  54. package/dist/{chunk-K62IUKOD.js → chunk-FHS2HQSH.js} +5 -5
  55. package/dist/{chunk-2JMMY7HZ.js → chunk-FM3G3NOY.js} +27 -9
  56. package/dist/chunk-FM3G3NOY.js.map +1 -0
  57. package/dist/{chunk-67TNU77I.js → chunk-FUG4SFN3.js} +2 -2
  58. package/dist/{chunk-ZP5PL65C.js → chunk-GKEWXIV5.js} +2 -2
  59. package/dist/{chunk-RKRGDAS7.js → chunk-GTGPO5KW.js} +5 -5
  60. package/dist/{chunk-MSPNM2OM.js → chunk-HB3RFQSC.js} +3 -3
  61. package/dist/{chunk-W5D62AQD.js → chunk-HDMEGAQE.js} +20 -7
  62. package/dist/chunk-HDMEGAQE.js.map +1 -0
  63. package/dist/chunk-HDQIIUPH.js +135 -0
  64. package/dist/chunk-HDQIIUPH.js.map +1 -0
  65. package/dist/{chunk-7QIXUSDQ.js → chunk-HTJQYHZP.js} +15 -12
  66. package/dist/chunk-HTJQYHZP.js.map +1 -0
  67. package/dist/{chunk-OOLO4LQG.js → chunk-I6GALP6E.js} +6 -6
  68. package/dist/{chunk-57V5S7PW.js → chunk-IL6POWCW.js} +6 -6
  69. package/dist/{chunk-7NS43EXZ.js → chunk-IU6SNYX6.js} +5 -5
  70. package/dist/{chunk-5ZOSG3RJ.js → chunk-J2ZX2XUV.js} +5 -5
  71. package/dist/{chunk-L2SNBIV7.js → chunk-JIF24JPM.js} +57 -15
  72. package/dist/chunk-JIF24JPM.js.map +1 -0
  73. package/dist/{chunk-SYMS4546.js → chunk-JKJOGPZN.js} +2 -2
  74. package/dist/{chunk-CKZW6P5V.js → chunk-JNAI2HN2.js} +1 -1
  75. package/dist/chunk-JNAI2HN2.js.map +1 -0
  76. package/dist/{chunk-AWB5JZW6.js → chunk-JZUV47FZ.js} +2 -2
  77. package/dist/{chunk-ODJWBC5I.js → chunk-K5IMOGHB.js} +2 -2
  78. package/dist/{chunk-3G4KMVUN.js → chunk-KSKBRKGJ.js} +3 -3
  79. package/dist/{chunk-HFJIGWJC.js → chunk-LASZKVMO.js} +3 -3
  80. package/dist/{chunk-IGJHJYM6.js → chunk-LXEXBTKL.js} +4 -4
  81. package/dist/{chunk-3CNQ7FQ3.js → chunk-M4CV6BRT.js} +119 -25
  82. package/dist/chunk-M4CV6BRT.js.map +1 -0
  83. package/dist/{chunk-H44ZE4IE.js → chunk-MEFJPTZ4.js} +33 -17
  84. package/dist/chunk-MEFJPTZ4.js.map +1 -0
  85. package/dist/{chunk-PR5LC5YX.js → chunk-MV43JSJF.js} +4 -4
  86. package/dist/{chunk-ELNBMFOS.js → chunk-NJ4EOKMB.js} +4 -4
  87. package/dist/{chunk-PXWVF7MC.js → chunk-NR5LT5RY.js} +7 -7
  88. package/dist/{chunk-QYPKGVT4.js → chunk-NWSGI5C7.js} +3 -3
  89. package/dist/{chunk-P5RY4ZWD.js → chunk-OSDB5WW3.js} +92 -15
  90. package/dist/chunk-OSDB5WW3.js.map +1 -0
  91. package/dist/chunk-PN2XMATY.js +37 -0
  92. package/dist/chunk-PN2XMATY.js.map +1 -0
  93. package/dist/{chunk-25NDNMQ7.js → chunk-Q5VNKNE5.js} +3 -3
  94. package/dist/{chunk-CIKY6I4W.js → chunk-QLWMEXCT.js} +2 -2
  95. package/dist/{chunk-VA4ZWLFY.js → chunk-QRB7NAOJ.js} +2 -2
  96. package/dist/{chunk-3MSQLQNZ.js → chunk-R4ROFEYC.js} +2 -2
  97. package/dist/{chunk-BEIRE5K4.js → chunk-RCVJZMFE.js} +4 -4
  98. package/dist/{chunk-VR24ILCR.js → chunk-RIX4V2TB.js} +3 -3
  99. package/dist/{chunk-Q3XSMOZM.js → chunk-RYCTDFUX.js} +2 -2
  100. package/dist/{chunk-7E67FJ33.js → chunk-RZ5SVOYR.js} +2 -2
  101. package/dist/{chunk-IDIV5NVH.js → chunk-SLFHQTTW.js} +5 -5
  102. package/dist/chunk-SNZ6URZZ.js +2782 -0
  103. package/dist/chunk-SNZ6URZZ.js.map +1 -0
  104. package/dist/{chunk-C3YH34IL.js → chunk-T2FFWNPK.js} +3 -3
  105. package/dist/{chunk-O2DYPAZY.js → chunk-UNFPPVNI.js} +2 -2
  106. package/dist/{chunk-MELR46EF.js → chunk-VFUPHI2Z.js} +63 -10
  107. package/dist/chunk-VFUPHI2Z.js.map +1 -0
  108. package/dist/{chunk-GA2QHD6P.js → chunk-VLFCJYTL.js} +9 -9
  109. package/dist/{chunk-YSXEFGND.js → chunk-VN3DBQAU.js} +2 -2
  110. package/dist/{chunk-C7NTK5I3.js → chunk-VZRODIM3.js} +4 -4
  111. package/dist/{chunk-QLLKLFE2.js → chunk-W22IKJE2.js} +2 -2
  112. package/dist/{chunk-5XIPOCQC.js → chunk-X3YYQWOQ.js} +3 -3
  113. package/dist/{chunk-A2QF4JUE.js → chunk-X7QBD67R.js} +625 -293
  114. package/dist/chunk-X7QBD67R.js.map +1 -0
  115. package/dist/{chunk-QQJXBZCO.js → chunk-XDYREZWE.js} +82 -10
  116. package/dist/chunk-XDYREZWE.js.map +1 -0
  117. package/dist/{chunk-OEAATWH5.js → chunk-XWZVFISC.js} +40 -6
  118. package/dist/{chunk-OEAATWH5.js.map → chunk-XWZVFISC.js.map} +1 -1
  119. package/dist/{chunk-XFXUTFWQ.js → chunk-YFXZEAYK.js} +6 -6
  120. package/dist/{chunk-7ITPJFGC.js → chunk-ZAJAVEXY.js} +2 -2
  121. package/dist/{chunk-4R4Q64W5.js → chunk-ZICD77GM.js} +2 -2
  122. package/dist/{chunk-45ZZLTFH.js → chunk-ZJ2AK4V7.js} +2 -2
  123. package/dist/{chunk-UFILRICG.js → chunk-ZUODRVHY.js} +2 -2
  124. package/dist/classified/index.js +5 -5
  125. package/dist/{classified-marker-LQWWQNIJ.js → classified-marker-CZKA6ITE.js} +8 -4
  126. package/dist/classified-marker-CZKA6ITE.js.map +1 -0
  127. package/dist/collection-facade-TLWIPI76.js +44 -0
  128. package/dist/{computed-W6MVAMWZ.js → computed-ZIQTYTDI.js} +3 -3
  129. package/dist/consent/index.js +9 -9
  130. package/dist/{dead-filter-4KXZEB3X.js → dead-filter-ESOBZZP5.js} +2 -2
  131. package/dist/delegation-W7ZV2322.js +25 -0
  132. package/dist/derivations/index.js +12 -12
  133. package/dist/derive-H2BJTLUI.js +21 -0
  134. package/dist/{enclave-VXAQD4XJ.js → enclave-AP3I5W7O.js} +15 -9
  135. package/dist/executor-KGWTNEQD.js +9 -0
  136. package/dist/executor-OVEXR6RT.js +9 -0
  137. package/dist/executor-UNEH5ZYH.js +25 -0
  138. package/dist/export-accessible-PCMXSUZS.js +23 -0
  139. package/dist/extract-partition-SWHFSYJO.js +38 -0
  140. package/dist/{fanout-sidecar-CKYFH33E.js → fanout-sidecar-A765THMX.js} +9 -9
  141. package/dist/find-N6345CNT.js +11 -0
  142. package/dist/forget/index.js +9 -9
  143. package/dist/guards/index.js +3 -3
  144. package/dist/history/index.js +14 -11
  145. package/dist/history/index.js.map +1 -1
  146. package/dist/i18n/index.js +14 -14
  147. package/dist/index.d.ts +5 -1
  148. package/dist/index.js +108 -89
  149. package/dist/index.js.map +1 -1
  150. package/dist/indexing/index.js +5 -5
  151. package/dist/indexing/index.js.map +1 -1
  152. package/dist/issue-5OKB6I2R.js +19 -0
  153. package/dist/kernel/best-effort-revert.d.ts +52 -0
  154. package/dist/kernel/collection-config.d.ts +28 -0
  155. package/dist/kernel/collection.d.ts +49 -32
  156. package/dist/kernel/enclave/classify/verify.d.ts +3 -0
  157. package/dist/kernel/enclave/index.d.ts +2 -1
  158. package/dist/kernel/enclave/record-keys/deterministic.d.ts +1 -0
  159. package/dist/kernel/enclave/record-keys/lifecycle.d.ts +50 -0
  160. package/dist/kernel/enclave/record-keys/record-codec.d.ts +27 -0
  161. package/dist/kernel/errors.d.ts +75 -1
  162. package/dist/kernel/lazy-count.d.ts +13 -0
  163. package/dist/kernel/noydb.d.ts +8 -0
  164. package/dist/kernel/tier-visibility.d.ts +54 -0
  165. package/dist/kernel/types.d.ts +92 -0
  166. package/dist/kernel/vault.d.ts +23 -6
  167. package/dist/kernel/via/dispatch.d.ts +10 -0
  168. package/dist/kernel/via/graph.d.ts +2 -1
  169. package/dist/{ledger-FU6GH5EH.js → ledger-GFBKVPV4.js} +11 -11
  170. package/dist/legacy/bundle.d.ts +1 -1
  171. package/dist/liberate-3VDOT4KO.js +24 -0
  172. package/dist/{link-set-MNADSH5M.js → link-set-Z7Q2ASFX.js} +11 -11
  173. package/dist/materialized-views/index.js +18 -18
  174. package/dist/noydb-ZCJOYBDI.js +68 -0
  175. package/dist/on/index.js +9 -9
  176. package/dist/overlay-views/index.js +4 -4
  177. package/dist/periods/index.js +12 -12
  178. package/dist/pod/index.js +11 -11
  179. package/dist/{policy-JTFOPPUU.js → policy-Z3RUAIY2.js} +5 -5
  180. package/dist/port/with/blob-strategy.d.ts +17 -0
  181. package/dist/port/with/lookup-strategy.d.ts +2 -1
  182. package/dist/portability/index.js +8 -8
  183. package/dist/{post-register-HAWO3O7O.js → post-register-JTH76BLY.js} +12 -7
  184. package/dist/post-register-JTH76BLY.js.map +1 -0
  185. package/dist/{public-envelope-NJVB7LPA.js → public-envelope-B4KNWVUA.js} +4 -4
  186. package/dist/query/index.js +5 -5
  187. package/dist/register-VAHONCID.js +23 -0
  188. package/dist/registry-7MLVD3VO.js +19 -0
  189. package/dist/registry-EPKPD5SM.js +18 -0
  190. package/dist/registry-P5T7PS2U.js +9 -0
  191. package/dist/request-withdrawal-TI3A5WPS.js +31 -0
  192. package/dist/{reveal-BOY7XYFH.js → reveal-DIBHLUZX.js} +7 -7
  193. package/dist/reveal-DIBHLUZX.js.map +1 -0
  194. package/dist/revoke-FDRD6GRW.js +24 -0
  195. package/dist/satellites/index.js +1 -1
  196. package/dist/sealed-record/index.js +12 -12
  197. package/dist/{seed-4RRXT42N.js → seed-Q6M2IZFL.js} +11 -11
  198. package/dist/session/index.js +9 -9
  199. package/dist/shadow/index.js +2 -2
  200. package/dist/signer-MUWEIUI6.js +25 -0
  201. package/dist/snapshots/index.js +10 -10
  202. package/dist/stale-OSQ7J3AA.js +29 -0
  203. package/dist/storage-MVFCGEQE.js +23 -0
  204. package/dist/{store-coordination-provider-HPYVFJCV.js → store-coordination-provider-64OEZFGS.js} +3 -3
  205. package/dist/sync/index.js +9 -9
  206. package/dist/team/index.js +15 -15
  207. package/dist/tiers/index.js +14 -10
  208. package/dist/to/index.js +1 -1
  209. package/dist/tx/index.js +3 -3
  210. package/dist/util/index.js +1 -1
  211. package/dist/{verify-66RHOW7N.js → verify-ZASTRNPR.js} +9 -8
  212. package/dist/verify-ZASTRNPR.js.map +1 -0
  213. package/dist/via/lookup/registry.d.ts +9 -0
  214. package/dist/via/money/where.d.ts +27 -6
  215. package/dist/{walk-2RWEOCAS.js → walk-SVNDIZ62.js} +11 -11
  216. package/dist/with/index.js +11 -11
  217. package/dist/with-audit/forget/strategy.d.ts +22 -0
  218. package/dist/with-audit/tiers/index.d.ts +275 -3
  219. package/dist/with-audit/tiers/strategy.d.ts +5 -4
  220. package/dist/with-cargo/describe-extraction.d.ts +9 -1
  221. package/dist/with-cargo/extract-partition.d.ts +9 -1
  222. package/dist/with-cargo/walk-closure.d.ts +32 -3
  223. package/dist/with-commit/history/history.d.ts +46 -0
  224. package/dist/with-commit/history/ledger/store.d.ts +21 -0
  225. package/dist/with-commit/history/strategy.d.ts +10 -0
  226. package/dist/with-commit/history/time-machine.d.ts +23 -0
  227. package/dist/with-commit/tx/elevated-handle.d.ts +2 -1
  228. package/dist/with-commit/tx/transaction.d.ts +5 -0
  229. package/dist/with-formula/materialized-views/executor.d.ts +9 -0
  230. package/dist/with-formula/materialized-views/stale.d.ts +52 -1
  231. package/dist/with-lookup/embeddings/index.d.ts +1 -0
  232. package/dist/with-lookup/embeddings/vec-id.d.ts +47 -0
  233. package/dist/with-lookup/indexing/collection-facade.d.ts +38 -1
  234. package/dist/with-lookup/indexing/lazy-builder.d.ts +35 -2
  235. package/dist/with-lookup/indexing/persisted-indexes.d.ts +44 -1
  236. package/dist/with-lookup/search/collection-facade.d.ts +40 -0
  237. package/dist/with-lookup/search/persisted-index-store.d.ts +82 -2
  238. package/dist/with-lookup/search/strategy.d.ts +4 -0
  239. package/dist/with-party/team/sync.d.ts +9 -0
  240. package/dist/with-shape/blobs/blob-intent.d.ts +153 -0
  241. package/dist/with-shape/blobs/blob-set.d.ts +949 -5
  242. package/dist/with-shape/satellites/fanout.d.ts +5 -4
  243. package/dist/with-shape/satellites/migrate-cek.d.ts +26 -0
  244. package/dist/with-shape/satellites/types.d.ts +11 -0
  245. package/dist/withdraw-accessible-WZIEVWSR.js +28 -0
  246. package/package.json +3 -3
  247. package/dist/api-YGMINAET.js +0 -20
  248. package/dist/backup-XA5STIYQ.js.map +0 -1
  249. package/dist/chunk-2JMMY7HZ.js.map +0 -1
  250. package/dist/chunk-3CNQ7FQ3.js.map +0 -1
  251. package/dist/chunk-7QIXUSDQ.js.map +0 -1
  252. package/dist/chunk-A2QF4JUE.js.map +0 -1
  253. package/dist/chunk-AOVDSIL3.js +0 -1221
  254. package/dist/chunk-AOVDSIL3.js.map +0 -1
  255. package/dist/chunk-CKZW6P5V.js.map +0 -1
  256. package/dist/chunk-DGH65E7Q.js.map +0 -1
  257. package/dist/chunk-DJ3VKYFA.js.map +0 -1
  258. package/dist/chunk-FH542DDY.js.map +0 -1
  259. package/dist/chunk-H44ZE4IE.js.map +0 -1
  260. package/dist/chunk-H6HM6CVR.js.map +0 -1
  261. package/dist/chunk-L2SNBIV7.js.map +0 -1
  262. package/dist/chunk-MELR46EF.js.map +0 -1
  263. package/dist/chunk-P5RY4ZWD.js.map +0 -1
  264. package/dist/chunk-QQJXBZCO.js.map +0 -1
  265. package/dist/chunk-TPH5EO6L.js +0 -54
  266. package/dist/chunk-TPH5EO6L.js.map +0 -1
  267. package/dist/chunk-W5D62AQD.js.map +0 -1
  268. package/dist/classified-marker-LQWWQNIJ.js.map +0 -1
  269. package/dist/collection-facade-YE2O4J4O.js +0 -39
  270. package/dist/delegation-OPUU3R2E.js +0 -25
  271. package/dist/derive-BGUHU663.js +0 -21
  272. package/dist/executor-GTVSUUBX.js +0 -25
  273. package/dist/executor-GZWMTOXB.js +0 -9
  274. package/dist/executor-XXGS4S3K.js +0 -9
  275. package/dist/export-accessible-BMULIOYB.js +0 -23
  276. package/dist/extract-partition-JUQTWDXR.js +0 -36
  277. package/dist/find-XRGCNGNN.js +0 -11
  278. package/dist/issue-UB6AA5M6.js +0 -19
  279. package/dist/liberate-YUN7W5QG.js +0 -24
  280. package/dist/noydb-6JLBZU4U.js +0 -67
  281. package/dist/post-register-HAWO3O7O.js.map +0 -1
  282. package/dist/register-VCKOBWKT.js +0 -23
  283. package/dist/registry-72UKJ2L4.js +0 -9
  284. package/dist/registry-BZFLJNEH.js +0 -18
  285. package/dist/registry-YJEYSYI5.js +0 -19
  286. package/dist/request-withdrawal-6MJRMFHF.js +0 -31
  287. package/dist/reveal-BOY7XYFH.js.map +0 -1
  288. package/dist/revoke-4KUNSVJC.js +0 -24
  289. package/dist/signer-DDDXP5JD.js +0 -25
  290. package/dist/stale-NXPT56JA.js +0 -14
  291. package/dist/storage-IR6EEAV2.js +0 -23
  292. package/dist/verify-66RHOW7N.js.map +0 -1
  293. package/dist/withdraw-accessible-CLMZEHQT.js +0 -28
  294. /package/dist/{api-YGMINAET.js.map → api-ZGS6LCOF.js.map} +0 -0
  295. /package/dist/{chunk-OFJ5GPNA.js.map → chunk-3B5VVCNY.js.map} +0 -0
  296. /package/dist/{chunk-KPGX66PM.js.map → chunk-3LQ2YKO4.js.map} +0 -0
  297. /package/dist/{chunk-D26JB3LZ.js.map → chunk-3QCRBHCY.js.map} +0 -0
  298. /package/dist/{chunk-4N5QFSNQ.js.map → chunk-4JBYV75E.js.map} +0 -0
  299. /package/dist/{chunk-UTLEAJXC.js.map → chunk-4NXKCLLQ.js.map} +0 -0
  300. /package/dist/{chunk-ARSAMO24.js.map → chunk-4VNQOLML.js.map} +0 -0
  301. /package/dist/{chunk-X6CMGUAG.js.map → chunk-5M5DVGV7.js.map} +0 -0
  302. /package/dist/{chunk-XHV25KBM.js.map → chunk-5YOLBEQ6.js.map} +0 -0
  303. /package/dist/{chunk-CB25ONKC.js.map → chunk-6CRIV7DE.js.map} +0 -0
  304. /package/dist/{chunk-BE7N3AXA.js.map → chunk-6JTIAGHD.js.map} +0 -0
  305. /package/dist/{chunk-JOQ53DMI.js.map → chunk-6QTNZJBS.js.map} +0 -0
  306. /package/dist/{chunk-BZO4WCJI.js.map → chunk-6T2SCQRU.js.map} +0 -0
  307. /package/dist/{chunk-FQQF23MC.js.map → chunk-7DSTRQIJ.js.map} +0 -0
  308. /package/dist/{chunk-IP2QBAGS.js.map → chunk-AUSTCW2X.js.map} +0 -0
  309. /package/dist/{chunk-A2Y6YFVN.js.map → chunk-B3HJYUOF.js.map} +0 -0
  310. /package/dist/{chunk-SRVQHVNX.js.map → chunk-BDVFPG6Y.js.map} +0 -0
  311. /package/dist/{chunk-YXOUQ2H7.js.map → chunk-CAF6WOK7.js.map} +0 -0
  312. /package/dist/{chunk-HUS3J5WM.js.map → chunk-CIE2BASH.js.map} +0 -0
  313. /package/dist/{chunk-DIRRS7WP.js.map → chunk-CRI4OUV4.js.map} +0 -0
  314. /package/dist/{chunk-FXK4X4BL.js.map → chunk-DLG74CNB.js.map} +0 -0
  315. /package/dist/{chunk-WTUNZACT.js.map → chunk-E5ZQT5KX.js.map} +0 -0
  316. /package/dist/{chunk-DMFNPHCX.js.map → chunk-EQO2UVP4.js.map} +0 -0
  317. /package/dist/{chunk-MCEKIAO4.js.map → chunk-ERJ7FU55.js.map} +0 -0
  318. /package/dist/{chunk-6QILBDZU.js.map → chunk-EVVGJDRQ.js.map} +0 -0
  319. /package/dist/{chunk-7VSGW5KJ.js.map → chunk-EVX47VBM.js.map} +0 -0
  320. /package/dist/{chunk-D3EFFFOL.js.map → chunk-EXK7QRWF.js.map} +0 -0
  321. /package/dist/{chunk-5JB73NMC.js.map → chunk-EYZ6IQ6X.js.map} +0 -0
  322. /package/dist/{chunk-BCYQA5BK.js.map → chunk-F64IRYG3.js.map} +0 -0
  323. /package/dist/{chunk-K62IUKOD.js.map → chunk-FHS2HQSH.js.map} +0 -0
  324. /package/dist/{chunk-67TNU77I.js.map → chunk-FUG4SFN3.js.map} +0 -0
  325. /package/dist/{chunk-ZP5PL65C.js.map → chunk-GKEWXIV5.js.map} +0 -0
  326. /package/dist/{chunk-RKRGDAS7.js.map → chunk-GTGPO5KW.js.map} +0 -0
  327. /package/dist/{chunk-MSPNM2OM.js.map → chunk-HB3RFQSC.js.map} +0 -0
  328. /package/dist/{chunk-OOLO4LQG.js.map → chunk-I6GALP6E.js.map} +0 -0
  329. /package/dist/{chunk-57V5S7PW.js.map → chunk-IL6POWCW.js.map} +0 -0
  330. /package/dist/{chunk-7NS43EXZ.js.map → chunk-IU6SNYX6.js.map} +0 -0
  331. /package/dist/{chunk-5ZOSG3RJ.js.map → chunk-J2ZX2XUV.js.map} +0 -0
  332. /package/dist/{chunk-SYMS4546.js.map → chunk-JKJOGPZN.js.map} +0 -0
  333. /package/dist/{chunk-AWB5JZW6.js.map → chunk-JZUV47FZ.js.map} +0 -0
  334. /package/dist/{chunk-ODJWBC5I.js.map → chunk-K5IMOGHB.js.map} +0 -0
  335. /package/dist/{chunk-3G4KMVUN.js.map → chunk-KSKBRKGJ.js.map} +0 -0
  336. /package/dist/{chunk-HFJIGWJC.js.map → chunk-LASZKVMO.js.map} +0 -0
  337. /package/dist/{chunk-IGJHJYM6.js.map → chunk-LXEXBTKL.js.map} +0 -0
  338. /package/dist/{chunk-PR5LC5YX.js.map → chunk-MV43JSJF.js.map} +0 -0
  339. /package/dist/{chunk-ELNBMFOS.js.map → chunk-NJ4EOKMB.js.map} +0 -0
  340. /package/dist/{chunk-PXWVF7MC.js.map → chunk-NR5LT5RY.js.map} +0 -0
  341. /package/dist/{chunk-QYPKGVT4.js.map → chunk-NWSGI5C7.js.map} +0 -0
  342. /package/dist/{chunk-25NDNMQ7.js.map → chunk-Q5VNKNE5.js.map} +0 -0
  343. /package/dist/{chunk-CIKY6I4W.js.map → chunk-QLWMEXCT.js.map} +0 -0
  344. /package/dist/{chunk-VA4ZWLFY.js.map → chunk-QRB7NAOJ.js.map} +0 -0
  345. /package/dist/{chunk-3MSQLQNZ.js.map → chunk-R4ROFEYC.js.map} +0 -0
  346. /package/dist/{chunk-BEIRE5K4.js.map → chunk-RCVJZMFE.js.map} +0 -0
  347. /package/dist/{chunk-VR24ILCR.js.map → chunk-RIX4V2TB.js.map} +0 -0
  348. /package/dist/{chunk-Q3XSMOZM.js.map → chunk-RYCTDFUX.js.map} +0 -0
  349. /package/dist/{chunk-7E67FJ33.js.map → chunk-RZ5SVOYR.js.map} +0 -0
  350. /package/dist/{chunk-IDIV5NVH.js.map → chunk-SLFHQTTW.js.map} +0 -0
  351. /package/dist/{chunk-C3YH34IL.js.map → chunk-T2FFWNPK.js.map} +0 -0
  352. /package/dist/{chunk-O2DYPAZY.js.map → chunk-UNFPPVNI.js.map} +0 -0
  353. /package/dist/{chunk-GA2QHD6P.js.map → chunk-VLFCJYTL.js.map} +0 -0
  354. /package/dist/{chunk-YSXEFGND.js.map → chunk-VN3DBQAU.js.map} +0 -0
  355. /package/dist/{chunk-C7NTK5I3.js.map → chunk-VZRODIM3.js.map} +0 -0
  356. /package/dist/{chunk-QLLKLFE2.js.map → chunk-W22IKJE2.js.map} +0 -0
  357. /package/dist/{chunk-5XIPOCQC.js.map → chunk-X3YYQWOQ.js.map} +0 -0
  358. /package/dist/{chunk-XFXUTFWQ.js.map → chunk-YFXZEAYK.js.map} +0 -0
  359. /package/dist/{chunk-7ITPJFGC.js.map → chunk-ZAJAVEXY.js.map} +0 -0
  360. /package/dist/{chunk-4R4Q64W5.js.map → chunk-ZICD77GM.js.map} +0 -0
  361. /package/dist/{chunk-45ZZLTFH.js.map → chunk-ZJ2AK4V7.js.map} +0 -0
  362. /package/dist/{chunk-UFILRICG.js.map → chunk-ZUODRVHY.js.map} +0 -0
  363. /package/dist/{collection-facade-YE2O4J4O.js.map → collection-facade-TLWIPI76.js.map} +0 -0
  364. /package/dist/{computed-W6MVAMWZ.js.map → computed-ZIQTYTDI.js.map} +0 -0
  365. /package/dist/{dead-filter-4KXZEB3X.js.map → dead-filter-ESOBZZP5.js.map} +0 -0
  366. /package/dist/{delegation-OPUU3R2E.js.map → delegation-W7ZV2322.js.map} +0 -0
  367. /package/dist/{derive-BGUHU663.js.map → derive-H2BJTLUI.js.map} +0 -0
  368. /package/dist/{enclave-VXAQD4XJ.js.map → enclave-AP3I5W7O.js.map} +0 -0
  369. /package/dist/{executor-GTVSUUBX.js.map → executor-KGWTNEQD.js.map} +0 -0
  370. /package/dist/{executor-GZWMTOXB.js.map → executor-OVEXR6RT.js.map} +0 -0
  371. /package/dist/{executor-XXGS4S3K.js.map → executor-UNEH5ZYH.js.map} +0 -0
  372. /package/dist/{export-accessible-BMULIOYB.js.map → export-accessible-PCMXSUZS.js.map} +0 -0
  373. /package/dist/{extract-partition-JUQTWDXR.js.map → extract-partition-SWHFSYJO.js.map} +0 -0
  374. /package/dist/{fanout-sidecar-CKYFH33E.js.map → fanout-sidecar-A765THMX.js.map} +0 -0
  375. /package/dist/{find-XRGCNGNN.js.map → find-N6345CNT.js.map} +0 -0
  376. /package/dist/{issue-UB6AA5M6.js.map → issue-5OKB6I2R.js.map} +0 -0
  377. /package/dist/{ledger-FU6GH5EH.js.map → ledger-GFBKVPV4.js.map} +0 -0
  378. /package/dist/{liberate-YUN7W5QG.js.map → liberate-3VDOT4KO.js.map} +0 -0
  379. /package/dist/{link-set-MNADSH5M.js.map → link-set-Z7Q2ASFX.js.map} +0 -0
  380. /package/dist/{noydb-6JLBZU4U.js.map → noydb-ZCJOYBDI.js.map} +0 -0
  381. /package/dist/{policy-JTFOPPUU.js.map → policy-Z3RUAIY2.js.map} +0 -0
  382. /package/dist/{public-envelope-NJVB7LPA.js.map → public-envelope-B4KNWVUA.js.map} +0 -0
  383. /package/dist/{register-VCKOBWKT.js.map → register-VAHONCID.js.map} +0 -0
  384. /package/dist/{registry-72UKJ2L4.js.map → registry-7MLVD3VO.js.map} +0 -0
  385. /package/dist/{registry-BZFLJNEH.js.map → registry-EPKPD5SM.js.map} +0 -0
  386. /package/dist/{registry-YJEYSYI5.js.map → registry-P5T7PS2U.js.map} +0 -0
  387. /package/dist/{request-withdrawal-6MJRMFHF.js.map → request-withdrawal-TI3A5WPS.js.map} +0 -0
  388. /package/dist/{revoke-4KUNSVJC.js.map → revoke-FDRD6GRW.js.map} +0 -0
  389. /package/dist/{seed-4RRXT42N.js.map → seed-Q6M2IZFL.js.map} +0 -0
  390. /package/dist/{signer-DDDXP5JD.js.map → signer-MUWEIUI6.js.map} +0 -0
  391. /package/dist/{stale-NXPT56JA.js.map → stale-OSQ7J3AA.js.map} +0 -0
  392. /package/dist/{storage-IR6EEAV2.js.map → storage-MVFCGEQE.js.map} +0 -0
  393. /package/dist/{store-coordination-provider-HPYVFJCV.js.map → store-coordination-provider-64OEZFGS.js.map} +0 -0
  394. /package/dist/{walk-2RWEOCAS.js.map → walk-SVNDIZ62.js.map} +0 -0
  395. /package/dist/{withdraw-accessible-CLMZEHQT.js.map → withdraw-accessible-WZIEVWSR.js.map} +0 -0
@@ -6,34 +6,36 @@ import {
6
6
  SEQUENCE_COLLECTION,
7
7
  compileSequenceFormat,
8
8
  resolveSequenceKey
9
- } from "./chunk-5JB73NMC.js";
9
+ } from "./chunk-EYZ6IQ6X.js";
10
10
  import {
11
11
  loadVaultPolicy
12
- } from "./chunk-DIRRS7WP.js";
12
+ } from "./chunk-CRI4OUV4.js";
13
13
  import {
14
14
  LinkIntegrityError,
15
15
  isLinkCollectionName,
16
16
  linkCollectionName,
17
17
  linkRowKey
18
- } from "./chunk-AWB5JZW6.js";
18
+ } from "./chunk-JZUV47FZ.js";
19
19
  import {
20
20
  hashFields,
21
21
  validateSatelliteDeclaration
22
- } from "./chunk-7ITPJFGC.js";
22
+ } from "./chunk-ZAJAVEXY.js";
23
23
  import {
24
24
  loadFence
25
- } from "./chunk-Q3XSMOZM.js";
25
+ } from "./chunk-RYCTDFUX.js";
26
26
  import {
27
27
  InvertedIndex,
28
28
  MemoryIndexStore,
29
29
  NO_SEARCH,
30
30
  VectorSet,
31
- buildPersistedIndexCallbacks
32
- } from "./chunk-P5RY4ZWD.js";
31
+ buildPersistedIndexCallbacks,
32
+ encodeVecId,
33
+ syncTierSearch
34
+ } from "./chunk-OSDB5WW3.js";
33
35
  import {
34
36
  derivePersistedSchema,
35
37
  isZod4Schema
36
- } from "./chunk-QLLKLFE2.js";
38
+ } from "./chunk-W22IKJE2.js";
37
39
  import {
38
40
  isBaseLive,
39
41
  liveBaseIdSet
@@ -42,7 +44,7 @@ import {
42
44
  CustodyApi,
43
45
  NO_CARGO,
44
46
  NO_CUSTODY
45
- } from "./chunk-BZO4WCJI.js";
47
+ } from "./chunk-6T2SCQRU.js";
46
48
  import {
47
49
  ServiceBus,
48
50
  WriteHookRegistry,
@@ -50,43 +52,45 @@ import {
50
52
  assertCanImport,
51
53
  canExport,
52
54
  canImport
53
- } from "./chunk-JOQ53DMI.js";
55
+ } from "./chunk-6QTNZJBS.js";
54
56
  import {
55
57
  runDrainBarrier
56
- } from "./chunk-D26JB3LZ.js";
58
+ } from "./chunk-3QCRBHCY.js";
57
59
  import {
58
60
  OverlayedCollection
59
- } from "./chunk-A2Y6YFVN.js";
61
+ } from "./chunk-B3HJYUOF.js";
60
62
  import {
61
63
  NO_ATTESTATION
62
- } from "./chunk-XHV25KBM.js";
64
+ } from "./chunk-5YOLBEQ6.js";
63
65
  import {
64
66
  NO_CLASSIFIED,
65
67
  guardClassifiedCompat,
66
68
  resolveClassifiedFields
67
- } from "./chunk-PR5LC5YX.js";
69
+ } from "./chunk-MV43JSJF.js";
68
70
  import {
69
71
  NO_TIERS,
70
- classifySealedShred
71
- } from "./chunk-H6HM6CVR.js";
72
+ classifySealedShred,
73
+ syncDerivedOutputs
74
+ } from "./chunk-CDUQTA3Z.js";
72
75
  import {
73
76
  NO_PORTABILITY
74
- } from "./chunk-ODJWBC5I.js";
77
+ } from "./chunk-K5IMOGHB.js";
75
78
  import {
76
79
  PERIODS_COLLECTION,
77
80
  PERIOD_ARCHIVES_COLLECTION,
78
81
  PERIOD_FREEZES_COLLECTION,
79
82
  PERIOD_TARGET_PURGES_COLLECTION,
80
83
  periodExclusiveUpperBound
81
- } from "./chunk-FXK4X4BL.js";
84
+ } from "./chunk-DLG74CNB.js";
82
85
  import {
83
86
  TxContext,
87
+ bestEffortRevert,
84
88
  revertExecuted
85
- } from "./chunk-H44ZE4IE.js";
89
+ } from "./chunk-MEFJPTZ4.js";
86
90
  import {
87
91
  DEFAULT_POSTURE,
88
92
  ViaGraph
89
- } from "./chunk-7QIXUSDQ.js";
93
+ } from "./chunk-HTJQYHZP.js";
90
94
  import {
91
95
  buildLookupAltIndex,
92
96
  buildLookupSnapshotRows,
@@ -102,28 +106,29 @@ import {
102
106
  matchesReferencingValue,
103
107
  putDerivedOutput,
104
108
  registerLookupRefEdges,
109
+ reservedDictDepsOf,
105
110
  resolveDictSource,
106
111
  resolveLabelFromMap,
107
112
  resolveRollupDeleteIntents,
108
113
  runGraphDispatchWave,
109
114
  touchFor,
110
115
  updateReferencingRecords
111
- } from "./chunk-DGH65E7Q.js";
116
+ } from "./chunk-4CTHCN4J.js";
112
117
  import {
113
118
  NO_AGGREGATE,
114
119
  Query,
115
120
  ScanBuilder
116
- } from "./chunk-H6CZSDWK.js";
121
+ } from "./chunk-454JXE57.js";
117
122
  import {
118
123
  EXPORT_AUDIT_COLLECTION,
119
124
  createExportBlobsHandle,
120
125
  runCompaction
121
- } from "./chunk-QYPKGVT4.js";
126
+ } from "./chunk-NWSGI5C7.js";
122
127
  import {
123
128
  LazyQuery,
124
129
  decodeIdxId,
125
130
  encodeIdxId
126
- } from "./chunk-3CNQ7FQ3.js";
131
+ } from "./chunk-M4CV6BRT.js";
127
132
  import {
128
133
  IMPLICIT_LAZY,
129
134
  Lru,
@@ -131,17 +136,17 @@ import {
131
136
  } from "./chunk-NO272T7Q.js";
132
137
  import {
133
138
  canonicalGroupKey
134
- } from "./chunk-IGJHJYM6.js";
139
+ } from "./chunk-LXEXBTKL.js";
135
140
  import {
136
141
  readPath
137
142
  } from "./chunk-IGJCYUT5.js";
138
143
  import {
139
144
  resolveManagedSecret,
140
145
  saveSealedPassphrase
141
- } from "./chunk-KPGX66PM.js";
146
+ } from "./chunk-3LQ2YKO4.js";
142
147
  import {
143
148
  dictCollectionName
144
- } from "./chunk-ELNBMFOS.js";
149
+ } from "./chunk-NJ4EOKMB.js";
145
150
  import {
146
151
  NO_I18N,
147
152
  getAtPath,
@@ -149,12 +154,12 @@ import {
149
154
  isDictKeyDescriptor,
150
155
  isI18nTextDescriptor,
151
156
  isStaticDictDescriptor
152
- } from "./chunk-BE7N3AXA.js";
157
+ } from "./chunk-6JTIAGHD.js";
153
158
  import {
154
159
  installViaBinder,
155
160
  isViaInstalled,
156
161
  viaBinder
157
- } from "./chunk-ARSAMO24.js";
162
+ } from "./chunk-4VNQOLML.js";
158
163
  import {
159
164
  NO_TEAM,
160
165
  enrollAuthenticator,
@@ -165,7 +170,7 @@ import {
165
170
  rotatePassphrase,
166
171
  updateAuthenticator,
167
172
  writeMagicLinkGrant
168
- } from "./chunk-IP2QBAGS.js";
173
+ } from "./chunk-AUSTCW2X.js";
169
174
  import {
170
175
  hasRecoveryEnrolled,
171
176
  hasStrongRecoveryEnrolled,
@@ -175,7 +180,7 @@ import {
175
180
  mintShamirRecoveryEntry,
176
181
  savePaperRecoveryEntries,
177
182
  saveShamirRecoveryEntries
178
- } from "./chunk-6QILBDZU.js";
183
+ } from "./chunk-EVVGJDRQ.js";
179
184
  import {
180
185
  INDEXED_STORE_POLICY
181
186
  } from "./chunk-VQNJ7UZL.js";
@@ -191,21 +196,26 @@ import {
191
196
  listUsers,
192
197
  loadKeyring,
193
198
  updateKeyringIdentity
194
- } from "./chunk-5ZOSG3RJ.js";
199
+ } from "./chunk-J2ZX2XUV.js";
195
200
  import {
196
201
  persistDirectoryConfig,
197
202
  readDirectoryConfig
198
- } from "./chunk-4N5QFSNQ.js";
203
+ } from "./chunk-4JBYV75E.js";
199
204
  import {
200
205
  NO_BROKER,
201
206
  buildCredentialBrokerHandle
202
- } from "./chunk-WTUNZACT.js";
207
+ } from "./chunk-E5ZQT5KX.js";
203
208
  import {
204
209
  generateULID
205
210
  } from "./chunk-ZJADGNYF.js";
211
+ import {
212
+ assertCutoverTierSafe,
213
+ assertTierWritable,
214
+ liveRecordIsElevated
215
+ } from "./chunk-PN2XMATY.js";
206
216
  import {
207
217
  sha256Hex
208
- } from "./chunk-25NDNMQ7.js";
218
+ } from "./chunk-Q5VNKNE5.js";
209
219
  import {
210
220
  NO_FORGET,
211
221
  addSubjectRef,
@@ -214,10 +224,10 @@ import {
214
224
  readDottedPath,
215
225
  rebuildSubjectIndex,
216
226
  removeSubjectRef
217
- } from "./chunk-DJ3VKYFA.js";
227
+ } from "./chunk-5O3XF4DV.js";
218
228
  import {
219
229
  NO_SEALED_RECORD
220
- } from "./chunk-CIKY6I4W.js";
230
+ } from "./chunk-QLWMEXCT.js";
221
231
  import {
222
232
  RecordCodec,
223
233
  SEALED_CEK_NS,
@@ -228,20 +238,20 @@ import {
228
238
  queryByDet,
229
239
  resolveStableCek,
230
240
  validateSchemaInput
231
- } from "./chunk-QQJXBZCO.js";
241
+ } from "./chunk-XDYREZWE.js";
232
242
  import {
233
243
  buildDeleteMarker,
234
244
  buildTombstone,
235
245
  isDeleteMarker,
236
246
  isTombstone
237
- } from "./chunk-FQQF23MC.js";
247
+ } from "./chunk-7DSTRQIJ.js";
238
248
  import {
239
249
  encrypt
240
- } from "./chunk-HUS3J5WM.js";
250
+ } from "./chunk-CIE2BASH.js";
241
251
  import {
242
252
  NOYDB_FORMAT_VERSION,
243
253
  SealedHandle
244
- } from "./chunk-CKZW6P5V.js";
254
+ } from "./chunk-JNAI2HN2.js";
245
255
  import {
246
256
  AlreadyElevatedError,
247
257
  AttestationError,
@@ -264,6 +274,7 @@ import {
264
274
  NoydbError,
265
275
  NumberingUncertaintyError,
266
276
  PermissionDeniedError,
277
+ PersistedIndexCompensationError,
267
278
  PolicyDeniedError,
268
279
  ReadOnlyError,
269
280
  RecoveryNotEnrolledError,
@@ -278,12 +289,13 @@ import {
278
289
  USER_ENVELOPE_COLLECTION,
279
290
  UniqueConstraintError,
280
291
  UnsupportedIndexOptionError,
292
+ UnsupportedTierCompositionError,
281
293
  ValidationError
282
- } from "./chunk-FH542DDY.js";
294
+ } from "./chunk-BIOUI4HL.js";
283
295
 
284
296
  // src/port/by/default-provider.ts
285
297
  async function createDefaultCoordinationProvider(store) {
286
- const { StoreCoordinationProvider } = await import("./store-coordination-provider-HPYVFJCV.js");
298
+ const { StoreCoordinationProvider } = await import("./store-coordination-provider-64OEZFGS.js");
287
299
  return new StoreCoordinationProvider(store);
288
300
  }
289
301
 
@@ -651,6 +663,34 @@ function exportRedact(coll, record) {
651
663
  return via2 ? via2.redactForExport(record) : record;
652
664
  }
653
665
 
666
+ // src/kernel/lazy-count.ts
667
+ var COUNT_PAGE_SIZE = 1e3;
668
+ function isLive(env, storeCiphertext) {
669
+ return !!env && !isTombstone(env, storeCiphertext) && !isDeleteMarker(env) && (env._tier ?? 0) === 0;
670
+ }
671
+ async function countLiveEnvelopes(adapter, vault, name, storeCiphertext) {
672
+ let n = 0;
673
+ if (adapter.listPage) {
674
+ let cursor;
675
+ let page = await adapter.listPage(vault, name, cursor, COUNT_PAGE_SIZE);
676
+ while (true) {
677
+ for (const { envelope } of page.items) {
678
+ if (isLive(envelope, storeCiphertext)) n++;
679
+ }
680
+ if (page.nextCursor === null) break;
681
+ cursor = page.nextCursor;
682
+ page = await adapter.listPage(vault, name, cursor, COUNT_PAGE_SIZE);
683
+ }
684
+ return n;
685
+ }
686
+ const ids = await adapter.list(vault, name);
687
+ for (const id of ids) {
688
+ const env = await adapter.get(vault, name, id);
689
+ if (isLive(env, storeCiphertext)) n++;
690
+ }
691
+ return n;
692
+ }
693
+
654
694
  // src/with-lookup/indexing/collection-facade.ts
655
695
  function readPersistedValue(record, field) {
656
696
  if (!field.includes(".")) return record[field];
@@ -736,6 +776,7 @@ async function rebuildIndexes(ctx) {
736
776
  for (const recordId of canonicalIds) {
737
777
  const envelope = await ctx.adapter.get(ctx.vault, ctx.name, recordId);
738
778
  if (!envelope) continue;
779
+ if ((envelope._tier ?? 0) > 0) continue;
739
780
  const record = await ctx.codec.decryptRecord(envelope, { skipValidation: true, id: recordId });
740
781
  if (record === null) continue;
741
782
  await maintainPersistedIndexesOnPut(ctx, recordId, record, null, envelope._v);
@@ -789,6 +830,7 @@ async function reconcileIndex(ctx, field, opts = {}) {
789
830
  if (id.startsWith("_")) continue;
790
831
  const env = await ctx.adapter.get(ctx.vault, ctx.name, id);
791
832
  if (!env) continue;
833
+ if ((env._tier ?? 0) > 0) continue;
792
834
  const record = await ctx.codec.decryptRecord(env, { skipValidation: true, id });
793
835
  if (record === null) continue;
794
836
  const live = readPersistedValue(record, field);
@@ -904,6 +946,66 @@ async function purgePersistedIndexes(ctx, id) {
904
946
  }
905
947
  return { purged, residue };
906
948
  }
949
+ async function syncTierIndexes(ctx, id, record, version, priorEnvelope) {
950
+ if (!ctx.indexes && !ctx.persistedIndexes) return;
951
+ const prior = await resolveTierSyncPrior(ctx, id, priorEnvelope);
952
+ if (record === null) {
953
+ await purgePersistedIndexes(ctx, id);
954
+ if (prior) ctx.indexes?.remove(id, prior);
955
+ } else {
956
+ await maintainPersistedIndexesOnPut(ctx, id, record, prior, version);
957
+ ctx.indexes?.upsert(id, record, prior);
958
+ }
959
+ }
960
+ async function resolveTierSyncPrior(ctx, id, priorEnvelope) {
961
+ const cached = ctx.cache.get(id)?.record;
962
+ if (cached !== void 0) return cached;
963
+ if (!ctx.lazy || !priorEnvelope || (priorEnvelope._tier ?? 0) > 0) return null;
964
+ return await ctx.codec.decryptRecord(priorEnvelope, { skipValidation: true, id });
965
+ }
966
+
967
+ // src/with-commit/history/strategy.ts
968
+ function notEnabled(op) {
969
+ return new Error(
970
+ `${op} requires the history strategy. Import \`{ withHistory }\` from "@noy-db/hub/history" and pass it to \`createNoydb({ historyStrategy: withHistory() })\`.`
971
+ );
972
+ }
973
+ var NO_HISTORY = {
974
+ async saveHistory() {
975
+ },
976
+ async getHistoryEntries() {
977
+ throw notEnabled("collection.history()");
978
+ },
979
+ async getVersionEnvelope() {
980
+ throw notEnabled("collection.getVersion()");
981
+ },
982
+ async pruneHistory() {
983
+ return 0;
984
+ },
985
+ async clearHistory() {
986
+ return 0;
987
+ },
988
+ async tombstoneHistory() {
989
+ return 0;
990
+ },
991
+ async rewrapHistory() {
992
+ },
993
+ async envelopePayloadHash() {
994
+ return "";
995
+ },
996
+ computePatch() {
997
+ return [];
998
+ },
999
+ diff() {
1000
+ throw notEnabled("collection.diff()");
1001
+ },
1002
+ buildLedger() {
1003
+ return null;
1004
+ },
1005
+ buildVaultInstant() {
1006
+ throw notEnabled("vault.at() / vault.timeMachine()");
1007
+ }
1008
+ };
907
1009
 
908
1010
  // src/with-lookup/indexing/strategy.ts
909
1011
  var NO_INDEXING = {
@@ -939,10 +1041,53 @@ var PersistedIndexStore = class {
939
1041
  timer = null;
940
1042
  lastBuild;
941
1043
  debounceMs;
1044
+ /**
1045
+ * Bumped by every purge (removePersisted). A save() captured under a since-stale
1046
+ * epoch undoes its own effect once it settles, however it interleaves with the
1047
+ * purge's own delete — a delete can never be overtaken by a save that was
1048
+ * scheduled before it (#725).
1049
+ *
1050
+ * Subsumes the issue's variant (b) (a stale, pre-purge in-memory index getting
1051
+ * paired with a live, post-purge fingerprint and TRUSTED by a cold load, defeating
1052
+ * the fingerprint backstop) for free — no separate handling needed: removePersisted()
1053
+ * always resets `index` to undefined in the SAME synchronous step that bumps the
1054
+ * epoch (below), and the only two paths that can repopulate `index` (ensureBuilt's
1055
+ * cold rebuild, rebuildAndPersist's rebuild) do so strictly from `lastBuild()`, which
1056
+ * the collection wires to read its LIVE cache at call time — not a frozen snapshot.
1057
+ * Cache eviction (the collection dropping the purged/forgotten record) always
1058
+ * precedes removePersisted() in both the elevate and forget call paths (#721's
1059
+ * syncCache eviction / forget's tombstone write both land before syncSearch /
1060
+ * _purgeSearchIndex runs). So any rebuild that executes strictly after
1061
+ * removePersisted() — the only way `index` becomes defined again post-purge —
1062
+ * necessarily observes the post-purge cache, and any rebuild that predates
1063
+ * removePersisted() has its `index` wiped by it. There is no ordering in which a
1064
+ * stale (pre-purge) index survives to be skip-rebuilt and persisted under a
1065
+ * matching live fingerprint. Regression-pinned in
1066
+ * `search-persisted-index-store.test.ts` ("variant (b) is subsumed...").
1067
+ */
1068
+ epoch = 0;
1069
+ /**
1070
+ * Set when a compensating/purging remove() (`compensate()` undoing a stale
1071
+ * save, or `removePersisted()`'s own purge, #764) fails. Unlike the routine
1072
+ * best-effort swallow on the debounced flush path (markDirty's timer
1073
+ * .catch(), below — safe there because the fingerprint backstop forces a
1074
+ * rebuild on the next cold load), a failed removal leaves a resurrected or
1075
+ * un-purged blob at rest whose fingerprint can still match the live cache —
1076
+ * a cold load would TRUST it, not rebuild past it. So this is never silently
1077
+ * dropped: every subsequent store entrypoint (ensureBuilt, rebuildAndPersist,
1078
+ * removePersisted) retries the remove first and refuses to proceed past it
1079
+ * until it succeeds (#725 review), and the raw adapter error is wrapped in
1080
+ * {@link PersistedIndexCompensationError} (#764) so a caller can catch a
1081
+ * stuck removal deliberately instead of an indistinguishable adapter error.
1082
+ * A crash between a landed put and its compensating remove (before this
1083
+ * flag or a retry can run) is a residual gap — see the class doc.
1084
+ */
1085
+ pendingCompensation = false;
942
1086
  get built() {
943
1087
  return this.index !== void 0;
944
1088
  }
945
1089
  async ensureBuilt(build) {
1090
+ await this.retryPendingCompensation();
946
1091
  this.lastBuild = build;
947
1092
  if (this.index !== void 0) return this.index;
948
1093
  const loaded = await this.cb.load();
@@ -971,26 +1116,70 @@ var PersistedIndexStore = class {
971
1116
  }
972
1117
  await this.rebuildAndPersist();
973
1118
  }
974
- /** Delete the persisted blob and drop the in-memory index (forget/erasure). */
1119
+ /** Delete the persisted blob and drop the in-memory index (forget/erasure/tier
1120
+ * move). A failed purge is wrapped in {@link PersistedIndexCompensationError}
1121
+ * (#764) and left sticky (`pendingCompensation`) so the next store entrypoint
1122
+ * retries it — never silently dropped, same posture #725 established for a
1123
+ * stale save's own compensating remove. */
975
1124
  async removePersisted() {
976
1125
  if (this.timer) {
977
1126
  clearTimeout(this.timer);
978
1127
  this.timer = null;
979
1128
  }
1129
+ await this.retryPendingCompensation();
1130
+ this.epoch++;
980
1131
  this.index = void 0;
981
- await this.cb.remove();
1132
+ try {
1133
+ await this.cb.remove();
1134
+ this.pendingCompensation = false;
1135
+ } catch (e) {
1136
+ this.pendingCompensation = true;
1137
+ throw new PersistedIndexCompensationError(e);
1138
+ }
982
1139
  }
983
1140
  /** Rebuild using the last known build thunk, then persist. */
984
1141
  async rebuildAndPersist() {
1142
+ await this.retryPendingCompensation();
985
1143
  if (this.lastBuild === void 0) return;
986
1144
  if (this.index === void 0) {
987
1145
  this.index = InvertedIndex.build(this.lastBuild());
988
1146
  }
989
1147
  await this.persist();
990
1148
  }
1149
+ /** Persist the current index, then undo it if a purge (removePersisted) landed
1150
+ * while the save was in flight — a delete can never be overtaken by a save
1151
+ * that was scheduled before it (#725). A failed undo does not silently vanish:
1152
+ * see `pendingCompensation`. */
991
1153
  async persist() {
992
1154
  if (this.index === void 0) return;
993
- await this.cb.save(serializeIndex(this.index), this.cb.currentFingerprint());
1155
+ const epoch = this.epoch;
1156
+ await this.cb.save(serializeIndex(this.index), this.cb.currentFingerprint(), () => this.epoch !== epoch);
1157
+ if (this.epoch !== epoch) await this.compensate();
1158
+ }
1159
+ /** Undo a stale save. Failure is sticky, not swallowed: see `pendingCompensation`.
1160
+ * Wraps the raw adapter error in {@link PersistedIndexCompensationError} (#764) so
1161
+ * a caller (e.g. the tier ops' `syncTierSearch`) can catch a stuck compensation
1162
+ * deliberately instead of treating it as an indistinguishable adapter failure. */
1163
+ async compensate() {
1164
+ try {
1165
+ await this.cb.remove();
1166
+ this.pendingCompensation = false;
1167
+ } catch (e) {
1168
+ this.pendingCompensation = true;
1169
+ throw new PersistedIndexCompensationError(e);
1170
+ }
1171
+ }
1172
+ /** Retries a sticky compensation before any store entrypoint proceeds. Failure
1173
+ * re-wraps the raw adapter error the same way `compensate()` does (#764) — the
1174
+ * flag stays set (untouched here) so the NEXT entrypoint retries again. */
1175
+ async retryPendingCompensation() {
1176
+ if (!this.pendingCompensation) return;
1177
+ try {
1178
+ await this.cb.remove();
1179
+ this.pendingCompensation = false;
1180
+ } catch (e) {
1181
+ throw new PersistedIndexCompensationError(e);
1182
+ }
994
1183
  }
995
1184
  };
996
1185
 
@@ -1432,6 +1621,54 @@ function buildDescription(input) {
1432
1621
  };
1433
1622
  }
1434
1623
 
1624
+ // src/via/blob/binding.ts
1625
+ async function eraseBlobs(ctx, cfg) {
1626
+ if (cfg.purgeBlobsForRecord) return cfg.purgeBlobsForRecord(ctx.id);
1627
+ return { shredded: 0, residue: [] };
1628
+ }
1629
+ function buildBlobDescribeFragment(fields) {
1630
+ return {
1631
+ blobFields: Object.fromEntries(
1632
+ Object.entries(fields).map(([field, p]) => [field, {
1633
+ ...p.retainDays !== void 0 ? { retainDays: p.retainDays } : {},
1634
+ ...p.evictWhen !== void 0 ? { evictWhen: true } : {},
1635
+ ...p.legalHold !== void 0 ? { legalHold: true } : {},
1636
+ ...p.retainUntil !== void 0 ? { retainUntil: true } : {},
1637
+ ...p.external === true ? { external: true } : {},
1638
+ ...p.public === true ? { public: true } : {},
1639
+ ...p.backlink !== void 0 ? { backlink: p.backlink } : {}
1640
+ }])
1641
+ )
1642
+ };
1643
+ }
1644
+ function blobBinding(cfg) {
1645
+ return {
1646
+ brand: "blob",
1647
+ // encryptedAtRest: 'envelope' — blob chunks are AEAD-encrypted envelopes
1648
+ // in `_blob_chunks` (service-side), not sealed record fields; queryable:
1649
+ // 'none' — nothing indexes blob content; exportable — vault.exportBlobs()
1650
+ // is a first-class door; forgettable — shredAllForRecord participates in
1651
+ // vault.forget().
1652
+ posture: { encryptedAtRest: "envelope", queryable: "none", exportable: true, forgettable: true },
1653
+ covers: (field) => field in cfg.fields,
1654
+ erase: (ctx) => eraseBlobs(ctx, cfg),
1655
+ describeFragment: () => buildBlobDescribeFragment(cfg.fields)
1656
+ };
1657
+ }
1658
+ function linkBlobVia() {
1659
+ installViaBinder("blob", (c) => blobBinding(c));
1660
+ }
1661
+
1662
+ // src/port/with/blob-strategy.ts
1663
+ linkBlobVia();
1664
+ var NO_BLOBS = {
1665
+ openSlot() {
1666
+ throw new Error(
1667
+ 'Blob storage is not enabled on this Noydb instance. Import `{ withBlobs }` from "@noy-db/hub/blobs" and pass `withBlobs()` to `createNoydb({ blobStrategy: withBlobs() })`.'
1668
+ );
1669
+ }
1670
+ };
1671
+
1435
1672
  // src/with-formula/derivations/stale.ts
1436
1673
  var _staleByRegistry = /* @__PURE__ */ new WeakMap();
1437
1674
  var keyFor = (source, sourceId) => `${source}/${sourceId}`;
@@ -1468,7 +1705,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
1468
1705
  }
1469
1706
  const sourceWithId = { ...source, id };
1470
1707
  if (DerivationExecutor === null) {
1471
- ({ DerivationExecutor } = await import("./executor-XXGS4S3K.js"));
1708
+ ({ DerivationExecutor } = await import("./executor-OVEXR6RT.js"));
1472
1709
  }
1473
1710
  const ctx = { vault: accessor.getReadOnlyFacade() };
1474
1711
  const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx);
@@ -1524,47 +1761,6 @@ var NO_CRDT = {
1524
1761
  }
1525
1762
  };
1526
1763
 
1527
- // src/with-commit/history/strategy.ts
1528
- function notEnabled(op) {
1529
- return new Error(
1530
- `${op} requires the history strategy. Import \`{ withHistory }\` from "@noy-db/hub/history" and pass it to \`createNoydb({ historyStrategy: withHistory() })\`.`
1531
- );
1532
- }
1533
- var NO_HISTORY = {
1534
- async saveHistory() {
1535
- },
1536
- async getHistoryEntries() {
1537
- throw notEnabled("collection.history()");
1538
- },
1539
- async getVersionEnvelope() {
1540
- throw notEnabled("collection.getVersion()");
1541
- },
1542
- async pruneHistory() {
1543
- return 0;
1544
- },
1545
- async clearHistory() {
1546
- return 0;
1547
- },
1548
- async tombstoneHistory() {
1549
- return 0;
1550
- },
1551
- async envelopePayloadHash() {
1552
- return "";
1553
- },
1554
- computePatch() {
1555
- return [];
1556
- },
1557
- diff() {
1558
- throw notEnabled("collection.diff()");
1559
- },
1560
- buildLedger() {
1561
- return null;
1562
- },
1563
- buildVaultInstant() {
1564
- throw notEnabled("vault.at() / vault.timeMachine()");
1565
- }
1566
- };
1567
-
1568
1764
  // src/with-party/team/sync-strategy.ts
1569
1765
  function notEnabled2(op) {
1570
1766
  return new Error(
@@ -1583,54 +1779,6 @@ var NO_SYNC = {
1583
1779
  }
1584
1780
  };
1585
1781
 
1586
- // src/via/blob/binding.ts
1587
- async function eraseBlobs(ctx, cfg) {
1588
- if (cfg.purgeBlobsForRecord) return cfg.purgeBlobsForRecord(ctx.id);
1589
- return { shredded: 0, residue: [] };
1590
- }
1591
- function buildBlobDescribeFragment(fields) {
1592
- return {
1593
- blobFields: Object.fromEntries(
1594
- Object.entries(fields).map(([field, p]) => [field, {
1595
- ...p.retainDays !== void 0 ? { retainDays: p.retainDays } : {},
1596
- ...p.evictWhen !== void 0 ? { evictWhen: true } : {},
1597
- ...p.legalHold !== void 0 ? { legalHold: true } : {},
1598
- ...p.retainUntil !== void 0 ? { retainUntil: true } : {},
1599
- ...p.external === true ? { external: true } : {},
1600
- ...p.public === true ? { public: true } : {},
1601
- ...p.backlink !== void 0 ? { backlink: p.backlink } : {}
1602
- }])
1603
- )
1604
- };
1605
- }
1606
- function blobBinding(cfg) {
1607
- return {
1608
- brand: "blob",
1609
- // encryptedAtRest: 'envelope' — blob chunks are AEAD-encrypted envelopes
1610
- // in `_blob_chunks` (service-side), not sealed record fields; queryable:
1611
- // 'none' — nothing indexes blob content; exportable — vault.exportBlobs()
1612
- // is a first-class door; forgettable — shredAllForRecord participates in
1613
- // vault.forget().
1614
- posture: { encryptedAtRest: "envelope", queryable: "none", exportable: true, forgettable: true },
1615
- covers: (field) => field in cfg.fields,
1616
- erase: (ctx) => eraseBlobs(ctx, cfg),
1617
- describeFragment: () => buildBlobDescribeFragment(cfg.fields)
1618
- };
1619
- }
1620
- function linkBlobVia() {
1621
- installViaBinder("blob", (c) => blobBinding(c));
1622
- }
1623
-
1624
- // src/port/with/blob-strategy.ts
1625
- linkBlobVia();
1626
- var NO_BLOBS = {
1627
- openSlot() {
1628
- throw new Error(
1629
- 'Blob storage is not enabled on this Noydb instance. Import `{ withBlobs }` from "@noy-db/hub/blobs" and pass `withBlobs()` to `createNoydb({ blobStrategy: withBlobs() })`.'
1630
- );
1631
- }
1632
- };
1633
-
1634
1782
  // src/kernel/via/compose.ts
1635
1783
  function via(...descriptors) {
1636
1784
  if (descriptors.length === 0) {
@@ -1908,6 +2056,34 @@ function resolveCollectionConfig(opts) {
1908
2056
  `Collection "${opts.name}": embeddings are not supported on CRDT collections (L2). Use a non-CRDT collection for semantic search.`
1909
2057
  );
1910
2058
  }
2059
+ if (opts.tiers && opts.tiers.length > 0 && opts.blobFields !== void 0 && Object.keys(opts.blobFields).length > 0 && opts.perRecordKeys !== true) {
2060
+ throw new UnsupportedTierCompositionError(
2061
+ "blobs",
2062
+ `Collection "${opts.name}": tiered collections that declare blobFields require \`perRecordKeys: true\` \u2014 legacy (non-perRecordKeys) blobs have no per-blob content CEK and cannot be tier-isolated on elevate/demote.`
2063
+ );
2064
+ }
2065
+ if (opts.tiers && opts.tiers.length > 0 && opts.blobFields !== void 0) {
2066
+ for (const [field, policy] of Object.entries(opts.blobFields)) {
2067
+ if (policy?.external && policy.public === true) {
2068
+ throw new UnsupportedTierCompositionError(
2069
+ "blobs",
2070
+ `Collection "${opts.name}": blob field "${field}" cannot be both \`external: true, public: true\` and declared on a tiered collection \u2014 the object key is deterministic and its bytes are world-readable by design, so tier-invisibility can never be enforced for it once elevated. Use a private/presigned external field (\`public\` omitted or \`false\`) or move this field to a non-tiered collection.`
2071
+ );
2072
+ }
2073
+ }
2074
+ }
2075
+ if (opts.tiers && opts.tiers.length > 0 && opts.encrypted === false) {
2076
+ throw new UnsupportedTierCompositionError(
2077
+ "plaintext",
2078
+ `Collection "${opts.name}": tiers are per-tier ENCRYPTION keys \u2014 a plaintext collection (\`encrypted: false\`) has nothing to re-key, so \`putAtTier\`/\`elevate\` would encrypt/decrypt incoherently. Use an encrypted collection.`
2079
+ );
2080
+ }
2081
+ if (opts.tiers && opts.tiers.length > 0 && opts.crdt !== void 0 && ((opts.derivationSource?.registry().strategiesForSource(opts.name).length ?? 0) > 0 || (opts.materializedViewSource?.registry().mvsForSource(opts.name).length ?? 0) > 0)) {
2082
+ throw new UnsupportedTierCompositionError(
2083
+ "crdt-derivation",
2084
+ `Collection "${opts.name}": tiers + crdt cannot be combined with this collection acting as a derivation/rollup source (#739) \u2014 the tier-aware pre-move decode \`syncDerived\` uses on elevate()/demote() does not resolve CRDT state, so a registered derivation/rollup reads raw CrdtState instead of the record and silently no-ops. Use a non-CRDT collection for a tiered derivation/rollup source, or move the derivation off this collection.`
2085
+ );
2086
+ }
1911
2087
  const effectiveViaFields = mergeViaFields(opts);
1912
2088
  const resolvedClassified = opts.classifiedFields !== void 0 ? resolveClassifiedFields(opts.name, opts.classifiedFields) : void 0;
1913
2089
  const allComputed = unifyComputedFields(opts, effectiveViaFields.computedFields);
@@ -2007,6 +2183,7 @@ function resolveCollectionConfig(opts) {
2007
2183
  reconcileOnOpen: opts.reconcileOnOpen ?? "off",
2008
2184
  getDEK: opts.getDEK,
2009
2185
  onDirty: opts.onDirty,
2186
+ tabCoordinated: opts.tabCoordinated,
2010
2187
  historyConfig: opts.historyConfig ?? { enabled: true },
2011
2188
  historyConfigExplicit: opts.historyConfigExplicit ?? false,
2012
2189
  schema: opts.schema,
@@ -2056,7 +2233,9 @@ function resolveCollectionConfig(opts) {
2056
2233
  tiersStrategy: opts.tiersStrategy ?? NO_TIERS,
2057
2234
  searchStrategy: opts.searchStrategy ?? NO_SEARCH,
2058
2235
  tierMode: opts.tierMode ?? "invisibility",
2236
+ blobTierPolicy: opts.blobTierPolicy ?? "isolate",
2059
2237
  onCrossTierAccess: opts.onCrossTierAccess,
2238
+ addSubjectRef: opts.addSubjectRef,
2060
2239
  deterministicFields,
2061
2240
  sensitiveFields,
2062
2241
  vdigFields,
@@ -2069,7 +2248,7 @@ function resolveCollectionConfig(opts) {
2069
2248
  // src/with-formula/computed/lazy.ts
2070
2249
  var fn = null;
2071
2250
  async function loadEvalComputedFields() {
2072
- fn ??= (await import("./computed-W6MVAMWZ.js")).evalComputedFields;
2251
+ fn ??= (await import("./computed-ZIQTYTDI.js")).evalComputedFields;
2073
2252
  return fn;
2074
2253
  }
2075
2254
 
@@ -2108,6 +2287,8 @@ var Collection = class {
2108
2287
  activeTxId;
2109
2288
  getDEK;
2110
2289
  onDirty;
2290
+ /** #693: live check — true when multi-tab write-propagation is active; gates the #606 marker-id-set fallback read. */
2291
+ tabCoordinated;
2111
2292
  historyConfig;
2112
2293
  /** True when the caller explicitly provided a `historyConfig` option (vs. inheriting the vault default). */
2113
2294
  historyConfigExplicit;
@@ -2123,6 +2304,8 @@ var Collection = class {
2123
2304
  blobStrategy;
2124
2305
  objectStore;
2125
2306
  blobFields;
2307
+ blobTierPolicy;
2308
+ // #724 T2/T3
2126
2309
  aggregateStrategy;
2127
2310
  crdtStrategy;
2128
2311
  tiersStrategy;
@@ -2134,6 +2317,20 @@ var Collection = class {
2134
2317
  // doesn't need a runtime branch on every cache access.
2135
2318
  cache = /* @__PURE__ */ new Map();
2136
2319
  hydrated = false;
2320
+ /**
2321
+ * #606: ids known to carry a delete marker in the store — lets the #589
2322
+ * re-create version-continuity gate in `_putInternal` read the store ONLY
2323
+ * for a known marker prior, instead of unconditionally on every insert.
2324
+ * Populated on hydration (`ensureHydrated`/`hydrateFromSnapshot`), local
2325
+ * delete (`_doDelete`), and the sync/tab/cutover choke point
2326
+ * (`_invalidateCacheEntry`). Accepted drift: `vault._purgeDeleteMarkers`/
2327
+ * `_purgeMarkersOn` remove markers directly on the raw store, bypassing
2328
+ * Collection, so this set can hold stale ids after a purge on an
2329
+ * already-loaded collection — perf-only and self-healing (a stale id just
2330
+ * costs one `adapter.get` that returns non-marker/null, and version
2331
+ * resolution falls back to 1 correctly). Do not try to wire purge into it.
2332
+ */
2333
+ markerIds = /* @__PURE__ */ new Set();
2137
2334
  /**
2138
2335
  * Lazy mode flag. `true` when constructed with `prefetch: false`.
2139
2336
  * In lazy mode the cache is bounded by an LRU and `list()`/`query()`
@@ -2162,8 +2359,7 @@ var Collection = class {
2162
2359
  indexState;
2163
2360
  /**
2164
2361
  * In-memory unique-constraint enforcement for eager mode.
2165
- * `null` when no `unique:true` indexes are declared on this collection,
2166
- * or when the collection is in lazy mode (which throws at registration).
2362
+ * `null` when no `unique:true` indexes are declared on this collection, or when the collection is in lazy mode (which throws at registration).
2167
2363
  */
2168
2364
  uniqueConstraints;
2169
2365
  /**
@@ -2184,8 +2380,7 @@ var Collection = class {
2184
2380
  return this.indexState.getEagerIndexes();
2185
2381
  }
2186
2382
  /**
2187
- * Accessor for the persisted-mirror (lazy-mode) index. Returns `null`
2188
- * when indexing is disabled or the collection is in eager mode.
2383
+ * Accessor for the persisted-mirror (lazy-mode) index. Returns `null` when indexing is disabled or the collection is in eager mode.
2189
2384
  */
2190
2385
  get persistedIndexes() {
2191
2386
  return this.indexState.getPersistedIndexes();
@@ -2348,11 +2543,10 @@ var Collection = class {
2348
2543
  tiers;
2349
2544
  tierMode;
2350
2545
  onCrossTierAccess;
2546
+ addSubjectRef;
2547
+ // #766: putAtTier's first-write subject-index registration (wired by the Vault; undefined ⇒ no forget-subject field declared)
2351
2548
  /**
2352
- * Optional reference to the vault-level hash-chained audit
2353
- * log. When present, every successful `put()` and `delete()` appends
2354
- * an entry to the ledger AFTER the adapter write succeeds (so a
2355
- * failed adapter write never produces an orphan ledger entry).
2549
+ * Optional reference to the vault-level hash-chained audit log. When present, every successful `put()` and `delete()` appends an entry to the ledger AFTER the adapter write succeeds (so a failed adapter write never produces an orphan ledger entry).
2356
2550
  *
2357
2551
  * The ledger is always a vault-wide singleton — all
2358
2552
  * collections in the same vault share the same LedgerStore.
@@ -2444,6 +2638,7 @@ var Collection = class {
2444
2638
  this.blobStrategy = cfg.blobStrategy;
2445
2639
  this.objectStore = cfg.objectStore;
2446
2640
  this.blobFields = cfg.blobFields;
2641
+ this.blobTierPolicy = cfg.blobTierPolicy ?? "isolate";
2447
2642
  this.aggregateStrategy = cfg.aggregateStrategy;
2448
2643
  this.crdtStrategy = cfg.crdtStrategy;
2449
2644
  this.tiersStrategy = cfg.tiersStrategy;
@@ -2453,6 +2648,7 @@ var Collection = class {
2453
2648
  this.reconcileOnOpen = cfg.reconcileOnOpen;
2454
2649
  this.getDEK = cfg.getDEK;
2455
2650
  this.onDirty = cfg.onDirty;
2651
+ this.tabCoordinated = cfg.tabCoordinated;
2456
2652
  this.historyConfig = cfg.historyConfig;
2457
2653
  this.historyConfigExplicit = cfg.historyConfigExplicit;
2458
2654
  this.schema = cfg.schema;
@@ -2488,6 +2684,7 @@ var Collection = class {
2488
2684
  this.tiers = cfg.tiers;
2489
2685
  this.tierMode = cfg.tierMode;
2490
2686
  this.onCrossTierAccess = cfg.onCrossTierAccess;
2687
+ this.addSubjectRef = cfg.addSubjectRef;
2491
2688
  this.deterministicFields = cfg.deterministicFields;
2492
2689
  this.sensitiveFields = cfg.sensitiveFields;
2493
2690
  this.perRecordCek = cfg.perRecordCek;
@@ -2540,9 +2737,7 @@ var Collection = class {
2540
2737
  const remoteJson = await this.codec.decryptJsonString(remote, id);
2541
2738
  if (localJson === null) return local;
2542
2739
  if (remoteJson === null) return remote;
2543
- const localState = JSON.parse(localJson);
2544
- const remoteState = JSON.parse(remoteJson);
2545
- const merged = this.crdtStrategy.mergeCrdtStates(localState, remoteState);
2740
+ const merged = this.crdtStrategy.mergeCrdtStates(JSON.parse(localJson), JSON.parse(remoteJson));
2546
2741
  const mergedVersion = Math.max(local._v, remote._v) + 1;
2547
2742
  const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
2548
2743
  return this.codec.encryptJsonString(JSON.stringify(merged), mergedVersion, cek);
@@ -2611,6 +2806,7 @@ var Collection = class {
2611
2806
  lazy: this.lazy
2612
2807
  });
2613
2808
  this.indexes?.setCanonicalizer((f, v) => this.via?.canonicalizeIndexKey(f, v));
2809
+ this.persistedIndexes?.setCanonicalizer((f, v) => this.via?.canonicalizeIndexKey(f, v));
2614
2810
  this.uniqueConstraints = buildUniqueConstraintSet(this.name, opts.indexes, {
2615
2811
  lazy: this.lazy,
2616
2812
  crdt: this.crdtMode != null,
@@ -2856,7 +3052,7 @@ var Collection = class {
2856
3052
  }
2857
3053
  await this.onAccess?.("find", "*");
2858
3054
  if (hits.length === 0) return [];
2859
- const { verifyDigestField } = await import("./verify-66RHOW7N.js");
3055
+ const { verifyDigestField } = await import("./verify-ZASTRNPR.js");
2860
3056
  const policy = {
2861
3057
  normalize: spec.verifyNormalize ?? "password",
2862
3058
  notLastN: spec.notLastN ?? 0,
@@ -2956,6 +3152,7 @@ var Collection = class {
2956
3152
  const virtualMoney = resolveVirtualMoneyFields(Object.keys(moneyFields), (f) => this.via?.bindings.find((b) => b.brand === "computed")?.covers?.(f) ?? false);
2957
3153
  this.via = ViaPipeline.build([viaBinder("money")({ moneyFields, ...virtualMoney.size > 0 ? { virtualMoneyFields: virtualMoney } : {} }), ...this.via?.bindings ?? []], this.via?.taint);
2958
3154
  this.moneyFields = moneyFields;
3155
+ if (this.hydrated) this.rebuildEagerIndexesFromCache();
2959
3156
  }
2960
3157
  /** @internal — attach computed fields post-construction. See {@link _applyMoneyFields}. */
2961
3158
  _applyComputed(computed) {
@@ -3040,6 +3237,20 @@ var Collection = class {
3040
3237
  * `null` if not found.
3041
3238
  */
3042
3239
  async get(id, locale) {
3240
+ const record = await this.#getRaw(id);
3241
+ if (record === null) return null;
3242
+ return this.applyLocaleToRecord(record, locale);
3243
+ }
3244
+ /**
3245
+ * Raw fetch: cache/adapter → decrypt → tombstone-null, WITHOUT `present()`.
3246
+ * Split out of `get()` (#684) so `lazyQuery()`'s `LazyQuerySource` can hand
3247
+ * `LazyQuery`'s post-filter the RAW (stored-form) record a `clause.via`
3248
+ * evaluator (e.g. money) needs — `present()`/locale decode is applied only
3249
+ * to survivors, via `applyLocaleToRecord` (see `lazyQuery()` below). `get()`
3250
+ * itself is unchanged: raw fetch, then `applyLocaleToRecord`, same order
3251
+ * as before this split.
3252
+ */
3253
+ async #getRaw(id) {
3043
3254
  if (this.derivationSource !== void 0) {
3044
3255
  const registry = this.derivationSource.registry();
3045
3256
  if (registry.strategiesProducingOutput(this.name).length > 0) {
@@ -3047,7 +3258,7 @@ var Collection = class {
3047
3258
  }
3048
3259
  }
3049
3260
  if (this.materializedViewSource !== void 0) {
3050
- const { resolveStaleMVOnRead } = await import("./stale-NXPT56JA.js");
3261
+ const { resolveStaleMVOnRead } = await import("./stale-OSQ7J3AA.js");
3051
3262
  await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: "resolve-on-read" }));
3052
3263
  }
3053
3264
  let record;
@@ -3058,7 +3269,7 @@ var Collection = class {
3058
3269
  } else {
3059
3270
  const envelope = await this.adapter.get(this.vault, this.name, id);
3060
3271
  if (!envelope) return null;
3061
- if (isTombstone(envelope, this.storeCiphertext) || isDeleteMarker(envelope)) return null;
3272
+ if (isTombstone(envelope, this.storeCiphertext) || isDeleteMarker(envelope) || (envelope._tier ?? 0) > 0) return null;
3062
3273
  record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true });
3063
3274
  if (record === null) return null;
3064
3275
  this.lru.set(id, { record, version: envelope._v }, estimateRecordBytes(record));
@@ -3070,7 +3281,7 @@ var Collection = class {
3070
3281
  }
3071
3282
  if (record === null) return null;
3072
3283
  await this.onAccess?.("get", id);
3073
- return this.applyLocaleToRecord(record, locale);
3284
+ return record;
3074
3285
  }
3075
3286
  /**
3076
3287
  * Return the raw CRDT state for a record.
@@ -3085,7 +3296,7 @@ var Collection = class {
3085
3296
  );
3086
3297
  }
3087
3298
  const envelope = await this.adapter.get(this.vault, this.name, id);
3088
- if (!envelope) return null;
3299
+ if (!envelope || (envelope._tier ?? 0) > 0) return null;
3089
3300
  const json = await this.codec.decryptJsonString(envelope);
3090
3301
  if (json === null) return null;
3091
3302
  return JSON.parse(json);
@@ -3202,7 +3413,7 @@ var Collection = class {
3202
3413
  const cached = this.lru.get(id);
3203
3414
  if (cached) return cached.record;
3204
3415
  const env = await this.adapter.get(this.vault, this.name, id);
3205
- if (!env) return void 0;
3416
+ if (!env || (env._tier ?? 0) > 0) return void 0;
3206
3417
  const rec = await this.codec.decryptRecord(env, { id });
3207
3418
  return rec === null ? void 0 : rec;
3208
3419
  }
@@ -3250,7 +3461,7 @@ var Collection = class {
3250
3461
  const cached2 = this.lru.get(id);
3251
3462
  if (cached2) return { record: cached2.record, version: cached2.version };
3252
3463
  const env = await this.adapter.get(this.vault, this.name, id);
3253
- if (!env) return { record: null, version: 0 };
3464
+ if (!env || (env._tier ?? 0) > 0) return { record: null, version: 0 };
3254
3465
  return { record: await this.codec.decryptRecord(env, { skipValidation: true, id }) ?? null, version: env._v };
3255
3466
  }
3256
3467
  await this.ensureHydrated();
@@ -3272,7 +3483,7 @@ var Collection = class {
3272
3483
  async resolvePriorValues(id) {
3273
3484
  if (this.sensitiveFields.size > 0 || this.via?.hasAtRestHooks === true) {
3274
3485
  const env = await this.adapter.get(this.vault, this.name, id);
3275
- if (!env || isTombstone(env, this.storeCiphertext)) return void 0;
3486
+ if (!env || isTombstone(env, this.storeCiphertext) || (env._tier ?? 0) > 0) return void 0;
3276
3487
  const rec = await this.codec.decryptRecord(env, { skipValidation: true, id });
3277
3488
  return rec === null ? void 0 : { record: rec, version: env._v };
3278
3489
  }
@@ -3284,11 +3495,8 @@ var Collection = class {
3284
3495
  if (!this.subsystemBus.gateNeedsPrior(point)) return { env: null, record: null, elided: true };
3285
3496
  const env = await this.adapter.get(this.vault, this.name, id);
3286
3497
  if (!env) return { env: null, record: null, elided: false };
3287
- try {
3288
- return { env, record: await this.codec.decryptRecord(env, { skipValidation: true, id }), elided: false };
3289
- } catch {
3290
- return { env, record: null, elided: false };
3291
- }
3498
+ if ((env._tier ?? 0) > 0) return { env, record: null, elided: false };
3499
+ return { env, record: await this.codec.decryptRecord(env, { skipValidation: true, id }), elided: false };
3292
3500
  }
3293
3501
  /**
3294
3502
  * Wraps {@link RecordCodec.toCacheRecord} with an additional strip for
@@ -3310,6 +3518,7 @@ var Collection = class {
3310
3518
  if (!hasWritePermission(this.keyring, this.name)) {
3311
3519
  throw new ReadOnlyError();
3312
3520
  }
3521
+ await assertTierWritable(this.adapter, this.vault, this.name, id, this.tiers !== null);
3313
3522
  if (this.via) record = this.via.ingest(record);
3314
3523
  if (this.subsystemBus?.hasGateHandlers("beforePut")) {
3315
3524
  const { env: existingEnv, record: existingRecord } = await this.resolveGatePrior("beforePut", id);
@@ -3375,8 +3584,7 @@ var Collection = class {
3375
3584
  }
3376
3585
  }
3377
3586
  }
3378
- const arr = Array.isArray(record) ? record : [record];
3379
- crdtState = this.crdtStrategy.buildRgaState(arr, existingState, generateULID);
3587
+ crdtState = this.crdtStrategy.buildRgaState(Array.isArray(record) ? record : [record], existingState, generateULID);
3380
3588
  } else {
3381
3589
  crdtState = { _crdt: "yjs", update: record };
3382
3590
  }
@@ -3388,9 +3596,7 @@ var Collection = class {
3388
3596
  const existingResolvedRecord = existingEnvelope ? await this.codec.decryptRecord(existingEnvelope, { skipValidation: true }) : null;
3389
3597
  const existingResolved = existingResolvedRecord !== null ? { record: existingResolvedRecord, version: existingVersion } : void 0;
3390
3598
  if (existingResolved && this.historyConfig.enabled !== false) {
3391
- const vdigCtx2 = this.vdigFields !== null ? { id, prev: existingEnvelope } : void 0;
3392
- const histEnvelope = await this.codec.encryptRecord(existingResolved.record, existingResolved.version, cek2, void 0, void 0, vdigCtx2, id);
3393
- await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, histEnvelope);
3599
+ await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, await this.codec.encryptRecord(existingResolved.record, existingResolved.version, cek2, void 0, void 0, this.vdigFields !== null ? { id, prev: existingEnvelope } : void 0, id));
3394
3600
  this.emitter.emit("history:save", { vault: this.vault, collection: this.name, id, version: existingResolved.version });
3395
3601
  if (this.historyConfig.maxVersions) {
3396
3602
  await this.historyStrategy.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
@@ -3443,29 +3649,27 @@ var Collection = class {
3443
3649
  }
3444
3650
  let version = existing ? existing.version + 1 : 1;
3445
3651
  if (!existing && this.onDirty) {
3446
- if (priorRaw === null) priorRaw = await this.adapter.get(this.vault, this.name, id);
3652
+ if (priorRaw === null && (this.markerIds.has(id) || this.tabCoordinated?.())) {
3653
+ priorRaw = await this.adapter.get(this.vault, this.name, id);
3654
+ }
3447
3655
  if (priorRaw && isDeleteMarker(priorRaw)) version = priorRaw._v + 1;
3448
3656
  }
3449
3657
  this.uniqueConstraints?.check(id, record);
3450
3658
  const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
3451
3659
  const vdigCtx = this.vdigFields !== null ? { id, prev: await this.adapter.get(this.vault, this.name, id) } : void 0;
3452
3660
  if (existing && this.historyConfig.enabled !== false) {
3453
- const historyEnvelope = await this.codec.encryptRecord(existing.record, existing.version, cek, void 0, void 0, vdigCtx, id);
3454
- await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, historyEnvelope);
3661
+ await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, await this.codec.encryptRecord(existing.record, existing.version, cek, void 0, void 0, vdigCtx, id));
3455
3662
  this.emitter.emit("history:save", {
3456
3663
  vault: this.vault,
3457
3664
  collection: this.name,
3458
3665
  id,
3459
3666
  version: existing.version
3460
3667
  });
3461
- if (this.historyConfig.maxVersions) {
3462
- await this.historyStrategy.pruneHistory(this.adapter, this.vault, this.name, id, {
3463
- keepVersions: this.historyConfig.maxVersions
3464
- });
3465
- }
3668
+ if (this.historyConfig.maxVersions) await this.historyStrategy.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
3466
3669
  }
3467
3670
  const envelope = await this.codec.encryptRecord(record, version, cek, options?.source, options?.sourceTs, vdigCtx, id);
3468
3671
  await this.adapter.put(this.vault, this.name, id, envelope);
3672
+ this.markerIds.delete(id);
3469
3673
  await this._ensureClassifiedMarker();
3470
3674
  if (this.embeddings) {
3471
3675
  await this.searchStrategy.embedOnWrite(this.searchContext(), id, record, version);
@@ -3523,7 +3727,7 @@ var Collection = class {
3523
3727
  if (wave?.seen(`mv\0${reg.spec.name}`)) continue;
3524
3728
  if (executor === null) {
3525
3729
  ;
3526
- ({ MaterializedViewExecutor: executor } = await import("./executor-GTVSUUBX.js"));
3730
+ ({ MaterializedViewExecutor: executor } = await import("./executor-UNEH5ZYH.js"));
3527
3731
  }
3528
3732
  await executor.refresh(reg, {
3529
3733
  getCollection: (name) => this.materializedViewSource.getCollection(name),
@@ -3533,7 +3737,7 @@ var Collection = class {
3533
3737
  });
3534
3738
  } else if (mode === "lazy") {
3535
3739
  if (staleHelpers === null) {
3536
- staleHelpers = await import("./stale-NXPT56JA.js");
3740
+ staleHelpers = await import("./stale-OSQ7J3AA.js");
3537
3741
  }
3538
3742
  staleHelpers.markMVStale(registry, reg.spec.name);
3539
3743
  }
@@ -3737,7 +3941,7 @@ var Collection = class {
3737
3941
  continue;
3738
3942
  }
3739
3943
  if (DerivationExecutor === null) {
3740
- ({ DerivationExecutor } = await import("./executor-XXGS4S3K.js"));
3944
+ ({ DerivationExecutor } = await import("./executor-OVEXR6RT.js"));
3741
3945
  }
3742
3946
  for (const run of runs) {
3743
3947
  const ctx = { vault: this.derivationSource.getReadOnlyFacade() };
@@ -3757,7 +3961,7 @@ var Collection = class {
3757
3961
  const outputCollection = this.derivationSource.getCollection(outSpec.collection);
3758
3962
  const txCtx = this.derivationSource.getActiveTxContext();
3759
3963
  if (out.kind === "array") {
3760
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-CKYFH33E.js");
3964
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-A765THMX.js");
3761
3965
  const prior = await loadFanoutSidecar(this.adapter, this.vault, spec.source, run.runId, key, this.getDEK, this.storeCiphertext);
3762
3966
  const prevKeys = new Set(prior?.keys ?? []);
3763
3967
  const newKeysList = out.entries.map((e) => e.key);
@@ -3867,13 +4071,11 @@ var Collection = class {
3867
4071
  }
3868
4072
  }
3869
4073
  /**
3870
- * @internal — bulk-rewrite every record through a cutover transform.
3871
- * Raw adapter path (bypasses the write gate + guards — the transform is
3872
- * trusted and runs only during the `migrating` phase). Bumps each
3873
- * record's `_v` and appends a ledger `op:'migration'` entry.
4074
+ * @internal — bulk-rewrite every record through a cutover transform. Raw adapter path (bypasses the write gate + guards — the transform is trusted and runs only during the `migrating` phase). Bumps each record's `_v` and appends a ledger `op:'migration'` entry. #708: refuses BEFORE any rewrite if a live record is elevated (assertCutoverTierSafe) — demote it first.
3874
4075
  */
3875
4076
  async _applyCutoverTransform(transform) {
3876
4077
  const ids = await this.adapter.list(this.vault, this.name);
4078
+ await assertCutoverTierSafe(this.adapter, this.vault, this.name, this.tiers !== null);
3877
4079
  let count = 0;
3878
4080
  for (const id of ids) {
3879
4081
  const env = await this.adapter.get(this.vault, this.name, id);
@@ -3884,8 +4086,7 @@ var Collection = class {
3884
4086
  const next = transform(record);
3885
4087
  const nextVersion = (env._v ?? 0) + 1;
3886
4088
  const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
3887
- const newEnv = await this.codec.encryptRecord(next, nextVersion, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: env } : void 0, id);
3888
- await this.adapter.put(this.vault, this.name, id, newEnv);
4089
+ await this.adapter.put(this.vault, this.name, id, await this.codec.encryptRecord(next, nextVersion, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: env } : void 0, id));
3889
4090
  await this._onRecordMutated(id, "put", "cutover");
3890
4091
  if (this.ledger) {
3891
4092
  await this.ledger.append({
@@ -3957,13 +4158,14 @@ var Collection = class {
3957
4158
  priorEnvelope: prior
3958
4159
  });
3959
4160
  }
3960
- await this._doDelete(id, true);
3961
- return true;
4161
+ return await this._doDelete(id, true);
3962
4162
  }
3963
4163
  async _doDelete(id, internal) {
3964
4164
  if (!hasWritePermission(this.keyring, this.name)) {
3965
4165
  throw new ReadOnlyError();
3966
4166
  }
4167
+ await assertTierWritable(this.adapter, this.vault, this.name, id, !internal && this.tiers !== null);
4168
+ if (internal && this.tiers !== null && await liveRecordIsElevated(this.adapter, this.vault, this.name, id)) return false;
3967
4169
  if (this.subsystemBus?.hasGateHandlers("beforeDelete")) {
3968
4170
  const { env: existingEnv, record: existingRecord, elided } = await this.resolveGatePrior("beforeDelete", id);
3969
4171
  if (existingEnv || elided) {
@@ -4001,17 +4203,17 @@ var Collection = class {
4001
4203
  if (existing && this.historyConfig.enabled !== false) {
4002
4204
  const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
4003
4205
  const prevForVdig = this.vdigFields !== null ? await this.adapter.get(this.vault, this.name, id) : null;
4004
- const historyEnvelope = await this.codec.encryptRecord(existing.record, existing.version, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: prevForVdig } : void 0, id);
4005
- await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, historyEnvelope);
4206
+ await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, await this.codec.encryptRecord(existing.record, existing.version, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: prevForVdig } : void 0, id));
4006
4207
  }
4007
4208
  const previousEnvelope = await this.adapter.get(this.vault, this.name, id);
4008
4209
  const previousPayloadHash = await this.historyStrategy.envelopePayloadHash(previousEnvelope);
4009
4210
  let markerVersion;
4010
4211
  if (this.onDirty) {
4011
4212
  const live = previousEnvelope;
4012
- if (!live || isTombstone(live, this.storeCiphertext) || isDeleteMarker(live)) return;
4213
+ if (!live || isTombstone(live, this.storeCiphertext) || isDeleteMarker(live)) return false;
4013
4214
  markerVersion = live._v + 1;
4014
4215
  await this.adapter.put(this.vault, this.name, id, buildDeleteMarker(markerVersion, this.keyring.userId));
4216
+ this.markerIds.add(id);
4015
4217
  } else {
4016
4218
  await this.adapter.delete(this.vault, this.name, id);
4017
4219
  }
@@ -4043,6 +4245,7 @@ var Collection = class {
4043
4245
  await this.dispatchArrayDerivationsOnDelete(id);
4044
4246
  if (existing) await this.dispatchRollupsOnDelete(id, existing.record);
4045
4247
  }
4248
+ return true;
4046
4249
  }
4047
4250
  /**
4048
4251
  * @internal — GDPR crypto-shred a LIVE record to a tombstone.
@@ -4116,7 +4319,7 @@ var Collection = class {
4116
4319
  continue;
4117
4320
  }
4118
4321
  if (helpers === null) {
4119
- helpers = await import("./fanout-sidecar-CKYFH33E.js");
4322
+ helpers = await import("./fanout-sidecar-A765THMX.js");
4120
4323
  }
4121
4324
  const sidecar = await helpers.loadFanoutSidecar(this.adapter, this.vault, spec.source, id, outputKey, this.getDEK, this.storeCiphertext);
4122
4325
  if (!sidecar) continue;
@@ -4132,39 +4335,49 @@ var Collection = class {
4132
4335
  /**
4133
4336
  * Mirror of {@link dispatchMaterializedViews} for the delete/forget path — no `_materializedFrom`
4134
4337
  * skip (record's gone); the `internal` gate at `_doDelete` is the recursion guard. Returns the
4135
- * row count TOMBSTONED across every eager MV sourced here (#638 T6 — `forgetDerivedFanout`'s
4136
- * `derivedRecordsErased`); a lazy MV only flips its stale bit (0 contribution — resolved on read).
4338
+ * row count TOMBSTONED across EVERY MV sourced here (#638 T6 — `forgetDerivedFanout`'s
4339
+ * `derivedRecordsErased`) eager AND lazy/manual `invalidateMVAtRest` purges both contribute now
4340
+ * (#761 item 1, previously eager-only); lazy persists a stale mark for cold-session recompute;
4341
+ * manual serves empty until `refreshView()`. `residueUndecodable`/`residueDeclined` (#776/#785) carry `outputCollection:id` entries whose ownership stamp `invalidateMVAtRest` could not decode, resp. decoded+stamp-matched but declined erasure — surfaced, not erased.
4137
4342
  * @internal
4138
4343
  */
4139
4344
  async dispatchMaterializedViewsOnDelete(id) {
4140
- if (this.materializedViewSource === void 0) return 0;
4345
+ if (this.materializedViewSource === void 0) return { deleted: 0, residueUndecodable: [], residueDeclined: [] };
4141
4346
  const registry = this.materializedViewSource.registry();
4142
4347
  const mvs = registry.mvsForSource(this.name);
4143
- if (mvs.length === 0) return 0;
4348
+ if (mvs.length === 0) return { deleted: 0, residueUndecodable: [], residueDeclined: [] };
4144
4349
  let executor = null;
4145
4350
  let staleHelpers = null;
4146
4351
  let deleted = 0;
4352
+ const residueUndecodable = [];
4353
+ const residueDeclined = [];
4147
4354
  for (const reg of mvs) {
4148
4355
  const mode = reg.spec.refresh;
4149
4356
  if (mode === "eager") {
4150
4357
  if (executor === null) {
4151
4358
  ;
4152
- ({ MaterializedViewExecutor: executor } = await import("./executor-GTVSUUBX.js"));
4359
+ ({ MaterializedViewExecutor: executor } = await import("./executor-UNEH5ZYH.js"));
4153
4360
  }
4154
- deleted += (await executor.refresh(reg, {
4361
+ const rr = await executor.refresh(reg, {
4155
4362
  getCollection: (name) => this.materializedViewSource.getCollection(name),
4156
4363
  getActiveTxContext: () => this.materializedViewSource.getActiveTxContext(),
4157
4364
  getQueryContext: () => this.materializedViewSource.getQueryContext(),
4158
4365
  dispatchCtx: this.#dispatchCtx({ collection: this.name, id })
4159
- })).deleted;
4160
- } else if (mode === "lazy") {
4366
+ });
4367
+ deleted += rr.deleted;
4368
+ residueUndecodable.push(...rr.residueUndecodable);
4369
+ residueDeclined.push(...rr.residueDeclined);
4370
+ } else {
4161
4371
  if (staleHelpers === null) {
4162
- staleHelpers = await import("./stale-NXPT56JA.js");
4372
+ staleHelpers = await import("./stale-OSQ7J3AA.js");
4163
4373
  }
4164
- staleHelpers.markMVStale(registry, reg.spec.name);
4374
+ const inv = await staleHelpers.invalidateMVAtRest(this.materializedViewSource, reg, mode);
4375
+ deleted += inv.deleted;
4376
+ residueUndecodable.push(...inv.residueUndecodable.map((rid) => `${reg.outputCollection}:${rid}`));
4377
+ residueDeclined.push(...inv.residueDeclined.map((rid) => `${reg.outputCollection}:${rid}`));
4165
4378
  }
4166
4379
  }
4167
- return deleted;
4380
+ return { deleted, residueUndecodable, residueDeclined };
4168
4381
  }
4169
4382
  /**
4170
4383
  * List all records in the collection.
@@ -4183,7 +4396,7 @@ var Collection = class {
4183
4396
  );
4184
4397
  }
4185
4398
  if (this.materializedViewSource !== void 0) {
4186
- const { resolveStaleMVOnRead } = await import("./stale-NXPT56JA.js");
4399
+ const { resolveStaleMVOnRead } = await import("./stale-OSQ7J3AA.js");
4187
4400
  await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: "resolve-on-read" }));
4188
4401
  }
4189
4402
  await this.ensureHydrated();
@@ -4222,6 +4435,11 @@ var Collection = class {
4222
4435
  similarTo(vector, opts = {}) {
4223
4436
  return this.searchStrategy.similarTo(this.searchContext(), vector, opts);
4224
4437
  }
4438
+ /** Opt-in bulk `_vec` re-derive (#788) — a plain collection has nothing to rebuild; gated behind `searchStrategy: withSearch()` otherwise. */
4439
+ rebuildEmbeddings() {
4440
+ if (!this.embeddings) return Promise.resolve({ rebuilt: 0, skipped: 0 });
4441
+ return this.searchStrategy.rebuildEmbeddings(this.searchContext());
4442
+ }
4225
4443
  /**
4226
4444
  * Bind the {@link SearchContext} the search/retrieval surface needs. The
4227
4445
  * `cache` is the SAME `Map` reference the eager read/write path owns (passed
@@ -4341,8 +4559,7 @@ var Collection = class {
4341
4559
  if (op.collectionName === this.name) {
4342
4560
  await this._invalidateCacheEntry(op.id);
4343
4561
  } else if (this.derivationSource) {
4344
- const sibling = this.derivationSource.getCollection(op.collectionName);
4345
- await sibling._invalidateCacheEntry(op.id);
4562
+ await this.derivationSource.getCollection(op.collectionName)._invalidateCacheEntry(op.id);
4346
4563
  }
4347
4564
  } catch {
4348
4565
  }
@@ -4552,8 +4769,10 @@ var Collection = class {
4552
4769
  id,
4553
4770
  options
4554
4771
  );
4772
+ if (await liveRecordIsElevated(this.adapter, this.vault, this.name, id)) return [];
4555
4773
  const entries = [];
4556
4774
  for (const env of envelopes) {
4775
+ if ((env._tier ?? 0) > 0) continue;
4557
4776
  const record = await this.codec.decryptRecord(env, { skipValidation: true, id });
4558
4777
  if (record === null) continue;
4559
4778
  entries.push({
@@ -4582,7 +4801,7 @@ var Collection = class {
4582
4801
  id,
4583
4802
  version
4584
4803
  );
4585
- if (!envelope) return null;
4804
+ if (!envelope || (envelope._tier ?? 0) > 0 || await liveRecordIsElevated(this.adapter, this.vault, this.name, id)) return null;
4586
4805
  return this.codec.decryptRecord(envelope, { skipValidation: true, id });
4587
4806
  }
4588
4807
  /** Revert a record to a past version. Creates a new version with the old content. */
@@ -4600,8 +4819,7 @@ var Collection = class {
4600
4819
  */
4601
4820
  async diff(id, versionA, versionB) {
4602
4821
  const recordA = versionA === 0 ? null : await this.resolveVersion(id, versionA);
4603
- const recordB = versionB === void 0 || versionB === 0 ? versionB === 0 ? null : await this.resolveCurrentOrVersion(id) : await this.resolveVersion(id, versionB);
4604
- return this.historyStrategy.diff(recordA, recordB);
4822
+ return this.historyStrategy.diff(recordA, versionB === void 0 || versionB === 0 ? versionB === 0 ? null : await this.resolveCurrentOrVersion(id) : await this.resolveVersion(id, versionB));
4605
4823
  }
4606
4824
  /** Resolve a version: try history first, then check if it's the current version. */
4607
4825
  async resolveVersion(id, version) {
@@ -4643,14 +4861,13 @@ var Collection = class {
4643
4861
  /**
4644
4862
  * Count records in the collection.
4645
4863
  *
4646
- * In eager mode this returns the in-memory cache size (instant). In
4647
- * lazy mode it asks the adapter via `list()` to enumerate idsslower
4648
- * but still correct, and avoids loading any record bodies into memory.
4864
+ * In eager mode this returns the in-memory cache size (instant). In lazy
4865
+ * mode it counts only LIVE tier-0 envelopes via envelope inspectionno
4866
+ * record bodies loaded matching eager's tombstone/tier exclusion (#706).
4649
4867
  */
4650
4868
  async count() {
4651
4869
  if (this.lazy) {
4652
- const ids = await this.adapter.list(this.vault, this.name);
4653
- return ids.length;
4870
+ return countLiveEnvelopes(this.adapter, this.vault, this.name, this.storeCiphertext);
4654
4871
  }
4655
4872
  await this.ensureHydrated();
4656
4873
  return this.cache.size;
@@ -4690,7 +4907,7 @@ var Collection = class {
4690
4907
  for (let i = start; i < end; i++) {
4691
4908
  const id = ids[i];
4692
4909
  const envelope = await this.adapter.get(this.vault, this.name, id);
4693
- if (envelope) {
4910
+ if (envelope && (envelope._tier ?? 0) === 0) {
4694
4911
  const record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true });
4695
4912
  if (record === null) continue;
4696
4913
  items.push(record);
@@ -4772,6 +4989,7 @@ var Collection = class {
4772
4989
  async decryptPage(items) {
4773
4990
  const out = [];
4774
4991
  for (const { id, envelope } of items) {
4992
+ if ((envelope._tier ?? 0) > 0) continue;
4775
4993
  const record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true });
4776
4994
  if (record === null) continue;
4777
4995
  out.push({ id, record, version: envelope._v });
@@ -4813,17 +5031,18 @@ var Collection = class {
4813
5031
  async _compensateRevertedWrite(id) {
4814
5032
  await this._invalidateCacheEntry(id);
4815
5033
  await this.onDirty?.(this.name, id, "revert", 0);
4816
- const restored = await this.get(id);
4817
- this.emitter.emit("change", { vault: this.vault, collection: this.name, id, action: restored !== null ? "put" : "delete" });
5034
+ this.emitter.emit("change", { vault: this.vault, collection: this.name, id, action: await this.get(id) !== null ? "put" : "delete" });
4818
5035
  }
4819
5036
  async _invalidateCacheEntry(id) {
4820
5037
  if (this.lazy && this.lru) {
4821
5038
  this.lru.remove(id);
4822
5039
  return;
4823
5040
  }
5041
+ const envelope = await this.adapter.get(this.vault, this.name, id);
5042
+ if (envelope && isDeleteMarker(envelope)) this.markerIds.add(id);
5043
+ else this.markerIds.delete(id);
4824
5044
  if (!this.hydrated) return;
4825
5045
  const previous = this.cache.get(id);
4826
- const envelope = await this.adapter.get(this.vault, this.name, id);
4827
5046
  if (!envelope) {
4828
5047
  this.cache.delete(id);
4829
5048
  if (previous) {
@@ -4872,6 +5091,10 @@ var Collection = class {
4872
5091
  * @internal
4873
5092
  */
4874
5093
  async _onRecordMutated(id, action, origin, ctx) {
5094
+ if (this.onDirty && !this.lazy) {
5095
+ if (action === "delete") this.markerIds.add(id);
5096
+ else this.markerIds.delete(id);
5097
+ }
4875
5098
  switch (origin) {
4876
5099
  case "local-write": {
4877
5100
  const record = ctx.record;
@@ -4923,10 +5146,12 @@ var Collection = class {
4923
5146
  const ids = await this.adapter.list(this.vault, this.name);
4924
5147
  for (const id of ids) {
4925
5148
  const envelope = await this.adapter.get(this.vault, this.name, id);
4926
- if (envelope && !isTombstone(envelope, this.storeCiphertext) && !isDeleteMarker(envelope)) {
5149
+ if (envelope && !isTombstone(envelope, this.storeCiphertext) && !isDeleteMarker(envelope) && (envelope._tier ?? 0) === 0) {
4927
5150
  const record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true });
4928
5151
  if (record === null) continue;
4929
5152
  this.cache.set(id, { record, version: envelope._v });
5153
+ } else if (envelope && isDeleteMarker(envelope)) {
5154
+ this.markerIds.add(id);
4930
5155
  }
4931
5156
  }
4932
5157
  this.hydrated = true;
@@ -4936,7 +5161,11 @@ var Collection = class {
4936
5161
  /** Hydrate from a pre-loaded snapshot (used by Vault). */
4937
5162
  async hydrateFromSnapshot(records) {
4938
5163
  for (const [id, envelope] of Object.entries(records)) {
4939
- if (isTombstone(envelope, this.storeCiphertext) || isDeleteMarker(envelope)) continue;
5164
+ if (isDeleteMarker(envelope)) {
5165
+ this.markerIds.add(id);
5166
+ continue;
5167
+ }
5168
+ if (isTombstone(envelope, this.storeCiphertext) || (envelope._tier ?? 0) > 0) continue;
4940
5169
  const record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true });
4941
5170
  if (record === null) continue;
4942
5171
  this.cache.set(id, { record, version: envelope._v });
@@ -5057,6 +5286,8 @@ var Collection = class {
5057
5286
  encrypted: this.storeCiphertext,
5058
5287
  userId: this.keyring.userId,
5059
5288
  erasableBlobs: this.perRecordCek,
5289
+ tiersActive: this.tiers !== null,
5290
+ keyring: this.keyring,
5060
5291
  debugPlaintext: this.keyring.debugPlaintext === true,
5061
5292
  ...this.objectStore !== void 0 ? { objectStore: this.objectStore } : {},
5062
5293
  ...this.blobFields !== void 0 ? { blobFields: this.blobFields } : {}
@@ -5149,7 +5380,7 @@ var Collection = class {
5149
5380
  /** Drop a record's encrypted _vec sidecar on erasure (a vector is text-invertible).
5150
5381
  * Called by vault.ts forget() inside a resilient try/catch; residue is reported in ForgetResult. */
5151
5382
  async _purgeVector(id) {
5152
- await this.adapter.delete(this.vault, "_vec", id);
5383
+ await this.adapter.delete(this.vault, "_vec", encodeVecId(this.name, id));
5153
5384
  this.vectorSet?.markDirty();
5154
5385
  }
5155
5386
  /** Drop the persisted lexical-index blob (forget/erasure): an opaque
@@ -5290,8 +5521,13 @@ var Collection = class {
5290
5521
  const source = {
5291
5522
  collectionName: this.name,
5292
5523
  persistedIndexes: persisted,
5524
+ canonicalizeIndexKey: (f, v) => this.via?.canonicalizeIndexKey(f, v),
5293
5525
  ensurePersistedIndexesLoaded: () => this.ensurePersistedIndexesLoaded(),
5294
- getRecord: (id) => this.get(id)
5526
+ // #684: raw-fetch seam — post-filter runs against the RAW record;
5527
+ // only survivors are decoded via `decodeRecord` below.
5528
+ getRawRecord: (id) => this.#getRaw(id),
5529
+ decodeRecord: (record) => this.applyLocaleToRecord(record, void 0),
5530
+ via: () => this.via
5295
5531
  };
5296
5532
  return new LazyQuery(source);
5297
5533
  }
@@ -5313,14 +5549,14 @@ var Collection = class {
5313
5549
  /** C-A/R10: persist the classified marker once per classified handle (store I/O in config-drift.ts). */
5314
5550
  async _ensureClassifiedMarker() {
5315
5551
  if (this._markerPersisted || this.vdigFields === null) return;
5316
- const { persistClassifiedMarkerForFields } = await import("./classified-marker-LQWWQNIJ.js");
5552
+ const { persistClassifiedMarkerForFields } = await import("./classified-marker-CZKA6ITE.js");
5317
5553
  await persistClassifiedMarkerForFields(this.adapter, this.vault, this.name, this.vdigFields, await this.getDEK(this.name));
5318
5554
  this._markerPersisted = true;
5319
5555
  }
5320
5556
  /** C-A/R10 drift signal — the marker's declared digest-only set, memoized to one store read per handle (see config-drift.ts). */
5321
5557
  async _classifiedMarkerDigestOnly() {
5322
5558
  if (this._markerDigestOnlyCache !== void 0) return this._markerDigestOnlyCache;
5323
- const { readClassifiedMarkerDigestOnly } = await import("./classified-marker-LQWWQNIJ.js");
5559
+ const { readClassifiedMarkerDigestOnly } = await import("./classified-marker-CZKA6ITE.js");
5324
5560
  this._markerDigestOnlyCache = await readClassifiedMarkerDigestOnly(this.adapter, this.vault, this.name, await this.getDEK(this.name));
5325
5561
  return this._markerDigestOnlyCache;
5326
5562
  }
@@ -5360,7 +5596,7 @@ var Collection = class {
5360
5596
  };
5361
5597
  }
5362
5598
  // ─── Hierarchical Access ──────────────────────────
5363
- /** tier-aware put — gated behind `tiersStrategy: withTiers()`. */
5599
+ /** tier-aware put — gated behind `tiersStrategy: withTiers()`. `searchResidue: true` = stuck search compensation (#774, mirroring #764's elevate/demote posture); the write itself always completes. */
5364
5600
  putAtTier(id, record, tier, opts) {
5365
5601
  return this.tiersStrategy.putAtTier(this.tiersContext(), id, record, tier, opts);
5366
5602
  }
@@ -5372,18 +5608,16 @@ var Collection = class {
5372
5608
  listAtTier() {
5373
5609
  return this.tiersStrategy.listAtTier(this.tiersContext());
5374
5610
  }
5375
- /** elevate a record to a higher tier — gated behind `withTiers()`. */
5611
+ /** elevate a record to a higher tier — gated behind `withTiers()`. `searchResidue: true` = stuck search compensation (#764); the move itself always completes. */
5376
5612
  elevate(id, toTier) {
5377
5613
  return this.tiersStrategy.elevate(this.tiersContext(), id, toTier);
5378
5614
  }
5379
- /** demote a record to a lower tier — gated behind `withTiers()`. */
5615
+ /** demote a record to a lower tier — gated behind `withTiers()`. Same `searchResidue` posture as {@link elevate} (#764). */
5380
5616
  demote(id, toTier) {
5381
5617
  return this.tiersStrategy.demote(this.tiersContext(), id, toTier);
5382
5618
  }
5383
5619
  /**
5384
- * Emit a cross-tier access event. The subscriber sink stays collection-
5385
- * resident (it captures `onCrossTierAccess`); the tiers module reaches it
5386
- * via the {@link TiersContext.emitCrossTierEvent} callback.
5620
+ * Emit a cross-tier access event. The subscriber sink stays collection-resident (it captures `onCrossTierAccess`); the tiers module reaches it via the {@link TiersContext.emitCrossTierEvent} callback.
5387
5621
  */
5388
5622
  emitCrossTierEvent(event) {
5389
5623
  try {
@@ -5424,9 +5658,7 @@ var Collection = class {
5424
5658
  if (patch.presentForJoin) this.presentForJoin = patch.presentForJoin;
5425
5659
  }
5426
5660
  /**
5427
- * Bind the {@link TiersContext} the tier ops need. The `cekCache` is passed
5428
- * by reference (the SAME `Lru` the kernel's read/write path owns) so an
5429
- * elevate/demote CEK re-wrap stays synchronous with cache eviction.
5661
+ * Bind the {@link TiersContext} the tier ops need `cekCache` by reference (same `Lru` the read/write path owns) for a synchronous re-wrap; `syncDerived` closes over `this` for {@link syncDerivedOutputs} (#722).
5430
5662
  */
5431
5663
  tiersContext() {
5432
5664
  return {
@@ -5436,19 +5668,43 @@ var Collection = class {
5436
5668
  keyring: this.keyring,
5437
5669
  codec: this.codec,
5438
5670
  cekCache: this.cekCache,
5671
+ syncCache: (id, e) => {
5672
+ if (e) this.cache.set(id, e);
5673
+ else this.cache.delete(id);
5674
+ this.lru?.remove(id);
5675
+ },
5676
+ syncIndexes: (id, rec, version, priorEnvelope) => syncTierIndexes(this.indexingContext(), id, rec, version, priorEnvelope),
5677
+ syncSearch: (id, rec, version) => syncTierSearch(this.searchContext(), id, rec, version),
5678
+ syncHistory: async (id, fromDek, toDek) => this.historyStrategy.rewrapHistory(this.adapter, this.vault, this.name, id, fromDek, toDek, await this.getDEK(this.name)),
5679
+ saveHistorySnapshot: async (id, envelope) => {
5680
+ if (this.historyConfig.enabled === false) return;
5681
+ await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, envelope);
5682
+ this.emitter.emit("history:save", { vault: this.vault, collection: this.name, id, version: envelope._v });
5683
+ if (this.historyConfig.maxVersions) await this.historyStrategy.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
5684
+ },
5685
+ historyEnabled: this.historyConfig.enabled !== false && this.historyStrategy !== NO_HISTORY,
5686
+ // #728/#737: lets putAtTier skip decrypting `existing` when no real history strategy is wired
5687
+ syncBlobs: (id, fromTier, toTier) => this.blobStrategy !== NO_BLOBS ? this.blob(id).syncTierMove(fromTier, toTier, this.blobTierPolicy) : Promise.resolve(),
5688
+ // #724 I1: gate on blob storage enabled (not on declared blobFields) so undeclared-field blobs still rehome; #746: syncTierMove mints/resumes the rehome journal marker; self-no-ops on an empty slot map
5689
+ syncLedger: async (id) => {
5690
+ await this.ledger?.purgeRecordDeltas(this.name, id);
5691
+ },
5692
+ syncDerived: (id, record, elevated, version) => syncDerivedOutputs(this, id, record, elevated, version),
5693
+ hasDerivedOutputs: this.materializedViewSource !== void 0 && this.materializedViewSource.registry().mvsForSource(this.name).length > 0 || this.derivationSource !== void 0 && this.derivationSource.registry().strategiesForSource(this.name).length > 0,
5694
+ // #737: source-grained (was vault-grained) — a derivation-free tiered collection skips the pre-move decode even when other collections in the vault have derivations
5439
5695
  provenance: this.provenance,
5440
5696
  tiers: this.tiers,
5441
5697
  tierMode: this.tierMode,
5442
5698
  getDEK: (key) => this.getDEK(key),
5443
- emitCrossTierEvent: (event) => this.emitCrossTierEvent(event)
5699
+ emitCrossTierEvent: (event) => this.emitCrossTierEvent(event),
5700
+ addSubjectRef: (id, record) => this.addSubjectRef?.(id, record) ?? Promise.resolve()
5444
5701
  };
5445
5702
  }
5446
5703
  /**
5447
5704
  * Bind the {@link IndexingContext} the index-maintenance surface needs. The
5448
5705
  * eager `cache` Map and the index / unique-constraint / persisted mirrors are
5449
5706
  * passed by reference (the SAME instances the query path reads, never
5450
- * copied); the `persistedIndexesLoaded` flag and `ensure*` hydration stay
5451
- * collection-resident, reached via callbacks.
5707
+ * copied); the `persistedIndexesLoaded` flag and `ensure*` hydration stay collection-resident, reached via callbacks.
5452
5708
  */
5453
5709
  indexingContext() {
5454
5710
  return {
@@ -5499,9 +5755,12 @@ var ElevatedHandle = class {
5499
5755
  */
5500
5756
  collection(name) {
5501
5757
  return {
5758
+ // #779 — surface `_elevatedPut`'s `TierMoveResult` (searchResidue) instead of
5759
+ // discarding it, so a stuck search compensation on this convenience path is
5760
+ // observable by the caller, mirroring `putAtTier`'s direct-call parity (#774).
5502
5761
  put: async (id, record) => {
5503
5762
  this.assertActive();
5504
- await this.vault._elevatedPut(name, id, record, this.tier, this.reason);
5763
+ return await this.vault._elevatedPut(name, id, record, this.tier, this.reason);
5505
5764
  }
5506
5765
  };
5507
5766
  }
@@ -6718,7 +6977,7 @@ var VaultLinks = class {
6718
6977
  // src/with-shape/links/lazy-handle.ts
6719
6978
  function makeLazyLinkSetHandle(d) {
6720
6979
  let engine = null;
6721
- const load = () => engine ??= import("./link-set-MNADSH5M.js").then(
6980
+ const load = () => engine ??= import("./link-set-Z7Q2ASFX.js").then(
6722
6981
  ({ LinkSet }) => new LinkSet(d.adapter, d.vault, d.name, d.spec, d.encrypted, d.getDEK, d.actor, d.emitter, d.endpointExists)
6723
6982
  );
6724
6983
  return {
@@ -7155,7 +7414,7 @@ var SatelliteRegistry = class {
7155
7414
  locks = /* @__PURE__ */ new Map();
7156
7415
  register(spec) {
7157
7416
  if (this.byBase.has(spec.base)) {
7158
- throw new SatelliteConfigError(`R-S1: base "${spec.base}" already has satellite "${this.byBase.get(spec.base).satellite}" \u2014 v1 allows exactly one satellite per base.`);
7417
+ throw new SatelliteConfigError(`R-S10: base "${spec.base}" already has satellite "${this.byBase.get(spec.base).satellite}" \u2014 v1 allows exactly one satellite per base.`);
7159
7418
  }
7160
7419
  if (this.byBase.has(spec.satellite)) {
7161
7420
  throw new SatelliteConfigError(`R-S3: "${spec.satellite}" is itself registered as a base (of "${this.byBase.get(spec.satellite).satellite}") \u2014 no satellite-of-satellite chains.`);
@@ -7256,7 +7515,7 @@ function declareSatellite(ctx, collectionName, options, existingRegistry) {
7256
7515
  ctx.forEachSyncEngine((e) => e.remirrorPairResolvers([spec.base, spec.satellite]));
7257
7516
  const registry = reg;
7258
7517
  const baseSchema = ctx.getBaseSchema(spec.base);
7259
- void import("./post-register-HAWO3O7O.js").then((m) => m.postRegister(ctx.adapter, ctx.vaultName, spec, ctx.getDEK, baseSchema, registry)).catch(() => {
7518
+ void import("./post-register-JTH76BLY.js").then((m) => m.postRegister(ctx.adapter, ctx.vaultName, spec, ctx.getDEK, baseSchema, registry)).catch(() => {
7260
7519
  });
7261
7520
  return reg;
7262
7521
  }
@@ -7269,14 +7528,9 @@ function unwrap(handle) {
7269
7528
  return handle[RAW_TARGET] ?? handle;
7270
7529
  }
7271
7530
  async function revertAndCompensate(deps, executed) {
7272
- for (const leg of [...executed].reverse()) {
7273
- try {
7274
- if (leg.prior !== null) await deps.adapter.put(deps.vaultName, leg.coll, leg.id, leg.prior);
7275
- else await deps.adapter.delete(deps.vaultName, leg.coll, leg.id);
7276
- await leg.handle._compensateRevertedWrite(leg.id);
7277
- } catch {
7278
- }
7279
- }
7531
+ await bestEffortRevert(executed, deps.adapter, async (leg) => {
7532
+ if (leg.wrote) await leg.handle._compensateRevertedWrite(leg.id);
7533
+ });
7280
7534
  }
7281
7535
  async function joinedPut(deps, id, record) {
7282
7536
  deps.registry.assertNotPoisoned(deps.spec.satellite);
@@ -7291,8 +7545,17 @@ async function joinedPut(deps, id, record) {
7291
7545
  return deps.registry.withPairLock(deps.spec.base, async () => {
7292
7546
  const executed = [];
7293
7547
  const run = async (handle, coll, rec) => {
7294
- executed.push({ coll, id, prior: await deps.adapter.get(deps.vaultName, coll, id), handle });
7548
+ const leg = {
7549
+ vaultName: deps.vaultName,
7550
+ collectionName: coll,
7551
+ id,
7552
+ prior: await deps.adapter.get(deps.vaultName, coll, id),
7553
+ handle,
7554
+ wrote: false
7555
+ };
7556
+ executed.push(leg);
7295
7557
  await handle.put(id, rec);
7558
+ leg.wrote = true;
7296
7559
  };
7297
7560
  try {
7298
7561
  await run(base, deps.spec.base, baseRec);
@@ -7309,8 +7572,17 @@ async function pairDelete(deps, id) {
7309
7572
  return deps.registry.withPairLock(deps.spec.base, async () => {
7310
7573
  const executed = [];
7311
7574
  const run = async (handle, coll) => {
7312
- executed.push({ coll, id, prior: await deps.adapter.get(deps.vaultName, coll, id), handle });
7575
+ const leg = {
7576
+ vaultName: deps.vaultName,
7577
+ collectionName: coll,
7578
+ id,
7579
+ prior: await deps.adapter.get(deps.vaultName, coll, id),
7580
+ handle,
7581
+ wrote: false
7582
+ };
7583
+ executed.push(leg);
7313
7584
  await handle.delete(id);
7585
+ leg.wrote = true;
7314
7586
  };
7315
7587
  try {
7316
7588
  await run(satellite, deps.spec.satellite);
@@ -7563,6 +7835,17 @@ function expandRefsWithSatellites(refs, registry) {
7563
7835
  return anySat ? out : refs;
7564
7836
  }
7565
7837
 
7838
+ // src/with-shape/satellites/migrate-cek.ts
7839
+ async function migrateSatelliteCek(name, coll) {
7840
+ if (coll.getConfig()?.perRecordKeys !== true) {
7841
+ throw new SatelliteConfigError(
7842
+ `migrateSatellitePerRecordKeys: collection "${name}" was already opened this session without perRecordKeys (construction-only); migrate before its first open, or restart the session.`
7843
+ );
7844
+ }
7845
+ const migrated = await coll._applyCutoverTransform((doc) => doc);
7846
+ return { migrated };
7847
+ }
7848
+
7566
7849
  // src/with-shape/schema-update/gate.ts
7567
7850
  var SchemaUpdateGate = class {
7568
7851
  #decision;
@@ -8226,7 +8509,7 @@ var Vault = class {
8226
8509
  const strategies = options.schemaUpdate ?? [];
8227
8510
  const work = (async () => {
8228
8511
  const dek = await this.getDEK(collectionName);
8229
- const { persistSchemaIfNeeded } = await import("./register-VCKOBWKT.js");
8512
+ const { persistSchemaIfNeeded } = await import("./register-VAHONCID.js");
8230
8513
  const result = await persistSchemaIfNeeded({
8231
8514
  store: this.adapter,
8232
8515
  vault: this.name,
@@ -8263,6 +8546,8 @@ var Vault = class {
8263
8546
  schemaFence: this.schemaFence,
8264
8547
  getDEK: this.getDEK,
8265
8548
  onDirty: this.onDirty,
8549
+ tabCoordinated: () => this.noydb._tabCoordinationActive,
8550
+ // #693: re-create gate fallback
8266
8551
  historyConfig: effectiveHistoryConfig,
8267
8552
  historyConfigExplicit: options?.historyConfig !== void 0,
8268
8553
  // thread the vault-wide blob strategy into every
@@ -8337,9 +8622,7 @@ var Vault = class {
8337
8622
  if (options?.sensitive !== void 0) {
8338
8623
  collOpts.sensitive = options.sensitive;
8339
8624
  }
8340
- if (options?.perRecordKeys !== void 0) {
8341
- collOpts.perRecordKeys = options.perRecordKeys;
8342
- }
8625
+ if (options?.perRecordKeys !== void 0) collOpts.perRecordKeys = options.perRecordKeys;
8343
8626
  const subjectKey = this.forgetStrategy.subjects[collectionName];
8344
8627
  if (subjectKey !== void 0) {
8345
8628
  if (options?.perRecordKeys === false) {
@@ -8349,11 +8632,16 @@ var Vault = class {
8349
8632
  }
8350
8633
  collOpts.perRecordKeys = true;
8351
8634
  collOpts.subjectKeyField = subjectKey;
8635
+ collOpts.addSubjectRef = async (id, record) => {
8636
+ const value = readDottedPath(record, subjectKey);
8637
+ if (value !== void 0 && value !== null) await this._addSubjectRef(coerceSubjectId(value), { collection: collectionName, id });
8638
+ };
8352
8639
  }
8353
8640
  if (options?.provenance !== void 0) collOpts.provenance = options.provenance;
8354
8641
  if (options?.ramCiphertext !== void 0) collOpts.ramCiphertext = options.ramCiphertext;
8355
8642
  if (options?.tiers !== void 0) collOpts.tiers = options.tiers;
8356
8643
  if (options?.tierMode !== void 0) collOpts.tierMode = options.tierMode;
8644
+ if (options?.blobTierPolicy !== void 0) collOpts.blobTierPolicy = options.blobTierPolicy;
8357
8645
  collOpts.onCrossTierAccess = (event) => this.emitCrossTier(event);
8358
8646
  if (this.syncAdapter !== void 0) collOpts.syncAdapter = this.syncAdapter;
8359
8647
  if (options?.i18nFields !== void 0) collOpts.i18nFields = options.i18nFields;
@@ -8420,7 +8708,7 @@ var Vault = class {
8420
8708
  const work = (async () => {
8421
8709
  try {
8422
8710
  const dek = await this.getDEK(collectionName);
8423
- await (await import("./register-VCKOBWKT.js")).persistSchemaIfNeeded({
8711
+ await (await import("./register-VAHONCID.js")).persistSchemaIfNeeded({
8424
8712
  store: this.adapter,
8425
8713
  vault: this.name,
8426
8714
  collectionName,
@@ -8457,6 +8745,16 @@ var Vault = class {
8457
8745
  registry: this.satelliteRegistry
8458
8746
  });
8459
8747
  }
8748
+ /**
8749
+ * Migrate an existing satellite's records onto per-record CEKs (#599) —
8750
+ * unblocks R-S7 when a base gains forget coverage after its satellite was
8751
+ * already declared without `perRecordKeys`. Call BEFORE re-declaring with
8752
+ * `{ satelliteOf, perRecordKeys: true }` AND before this collection serves
8753
+ * writes (unfenced walk — see {@link migrateSatelliteCek}); resumable.
8754
+ */
8755
+ async migrateSatellitePerRecordKeys(satelliteName) {
8756
+ return migrateSatelliteCek(satelliteName, this.collection(satelliteName, { perRecordKeys: true }));
8757
+ }
8460
8758
  /**
8461
8759
  * Await all background persisted-schema writes triggered by
8462
8760
  * `collection({ persistJsonSchema: true })` calls on this vault.
@@ -8517,6 +8815,12 @@ var Vault = class {
8517
8815
  _reservedLookupCollectionNames() {
8518
8816
  return [...this.reservedLookupCollections.keys()];
8519
8817
  }
8818
+ /** @internal #653 — one-hop reserved-dict deps of `names`, for `SyncEngine`'s partial-sync
8819
+ * filter expansion. Provably complete at one hop: `vault.collection()` refuses `_dict_*`
8820
+ * names, so a dict can never itself declare lookup fields (no dict-of-dict chain). */
8821
+ _reservedDictDepsOf(names) {
8822
+ return reservedDictDepsOf(names, this.dictKeyFieldRegistry);
8823
+ }
8520
8824
  /** @internal #638 Task 4 — open a graph-dispatch touch batch (sync pull()/push()/cutover). */
8521
8825
  _beginGraphBatch() {
8522
8826
  this._graphBatch = /* @__PURE__ */ new Map();
@@ -9278,6 +9582,8 @@ var Vault = class {
9278
9582
  if (Object.keys(this.forgetStrategy.subjects).length === 0) {
9279
9583
  throw new ForgetStrategyNotConfiguredError();
9280
9584
  }
9585
+ const ledger = this.getLedgerOrNull();
9586
+ if (!ledger) throw new Error('vault.forget() requires the history strategy for the erasure-proof ledger entry. Pass `historyStrategy: withHistory()` from "@noy-db/hub/history" to createNoydb().');
9281
9587
  const refs = await lookupSubject(this.adapter, this.name, this.getDEK, this.encrypted, subjectId);
9282
9588
  const allRefs = expandRefsWithSatellites(refs, this.satelliteRegistry);
9283
9589
  let recordsShredded = 0;
@@ -9290,12 +9596,14 @@ var Vault = class {
9290
9596
  let indexPostingsPurged = 0;
9291
9597
  let sealedFieldsShredded = 0;
9292
9598
  let sealedCekEnvelopesPurged = 0;
9599
+ let ledgerDeltasPurged = 0;
9293
9600
  const sealedCekResidue = [];
9294
9601
  const sealedResidue = [];
9295
9602
  const indexResidue = [];
9603
+ const ledgerDeltaResidue = [];
9296
9604
  const blobsEnabled = this.blobStrategy !== void 0;
9297
9605
  const actor = this.keyring.userId;
9298
- const fanoutStats = { recordsErased: 0, aggregatesRecomputed: 0, residueFrozen: [], lookupReferencesCascaded: 0, lookupReferencesNullified: 0, lookupReferencesResidue: [] };
9606
+ const fanoutStats = { recordsErased: 0, aggregatesRecomputed: 0, residueFrozen: [], lookupReferencesCascaded: 0, lookupReferencesNullified: 0, lookupReferencesResidue: [], derivedResidueUndecodable: [], derivedResidueDeclined: [] };
9299
9607
  const { partitionSealedCekKeys, shouldSkipBlobScan, bumpResidueCount, residueNoticesFromMap } = await import("./purge-scope-FGNNLWHD.js");
9300
9608
  const scopedPurge = this.forgetStrategy.scopedPurge === true;
9301
9609
  const sealedCekScopedSkipped = /* @__PURE__ */ new Map();
@@ -9340,6 +9648,13 @@ var Vault = class {
9340
9648
  } catch {
9341
9649
  sealedCekResidue.push(`${ref2.collection}:${ref2.id}`);
9342
9650
  }
9651
+ if (blobsEnabled && !shouldSkipBlobScan(scopedPurge, this.blobFieldsRegistry.has(ref2.collection))) {
9652
+ try {
9653
+ await coll.blob(ref2.id).mintShredIntent(live?._tier ?? 0);
9654
+ } catch {
9655
+ blobResidueCollections.add(ref2.collection);
9656
+ }
9657
+ }
9343
9658
  let shred;
9344
9659
  try {
9345
9660
  shred = await coll._writeTombstone(ref2.id, actor);
@@ -9364,6 +9679,11 @@ var Vault = class {
9364
9679
  actor,
9365
9680
  this.encrypted
9366
9681
  );
9682
+ try {
9683
+ ledgerDeltasPurged += await ledger.purgeRecordDeltas(ref2.collection, ref2.id);
9684
+ } catch {
9685
+ ledgerDeltaResidue.push(`${ref2.collection}:${ref2.id}`);
9686
+ }
9367
9687
  const idxPurge = await coll._purgePersistedIndexes(ref2.id);
9368
9688
  indexPostingsPurged += idxPurge.purged;
9369
9689
  for (const field of idxPurge.residue) indexResidue.push(`${ref2.collection}:${ref2.id}:${field}`);
@@ -9375,14 +9695,14 @@ var Vault = class {
9375
9695
  if (blobsEnabled && shouldSkipBlobScan(scopedPurge, this.blobFieldsRegistry.has(ref2.collection))) {
9376
9696
  bumpResidueCount(blobScopedSkipped, ref2.collection, 1);
9377
9697
  } else if (blobsEnabled) {
9378
- const r = await this.collection(ref2.collection).blob(ref2.id).shredAllForRecord();
9698
+ const r = await this.collection(ref2.collection).blob(ref2.id).shredAllForRecord(live?._tier ?? 0);
9379
9699
  blobsShredded += r.shredded.length;
9380
9700
  blobsRetainedShared += r.retainedShared.length;
9381
9701
  if (r.residue.length > 0) blobResidueCollections.add(ref2.collection);
9382
9702
  } else {
9383
9703
  try {
9384
- const slotIds = await this.adapter.list(this.name, `_blob_slots_${ref2.collection}`);
9385
- if (slotIds.includes(ref2.id)) blobResidueCollections.add(ref2.collection);
9704
+ const [slotIds, verKeys] = await Promise.all([this.adapter.list(this.name, `_blob_slots_${ref2.collection}`), this.adapter.list(this.name, `_blob_versions_${ref2.collection}`)]);
9705
+ if (slotIds.includes(ref2.id) || verKeys.some((k) => k.startsWith(`${ref2.id}::`))) blobResidueCollections.add(ref2.collection);
9386
9706
  } catch {
9387
9707
  }
9388
9708
  }
@@ -9396,12 +9716,6 @@ var Vault = class {
9396
9716
  }
9397
9717
  }
9398
9718
  const subjectHash = await sha256Hex(subjectId);
9399
- const ledger = this.getLedgerOrNull();
9400
- if (!ledger) {
9401
- throw new Error(
9402
- 'vault.forget() requires the history strategy for the erasure-proof ledger entry. Pass `historyStrategy: withHistory()` from "@noy-db/hub/history" to createNoydb().'
9403
- );
9404
- }
9405
9719
  const ledgerEntry = await ledger.append({
9406
9720
  op: "forget",
9407
9721
  collection: "",
@@ -9422,7 +9736,9 @@ var Vault = class {
9422
9736
  sealedFieldsShredded,
9423
9737
  sealedCekEnvelopesPurged,
9424
9738
  sealedCekResidueCount: sealedCekResidue.length,
9425
- sealedResidueCount: sealedResidue.length
9739
+ sealedResidueCount: sealedResidue.length,
9740
+ ledgerDeltasPurged,
9741
+ ledgerDeltaResidueCount: ledgerDeltaResidue.length
9426
9742
  })
9427
9743
  });
9428
9744
  const scopedPurgeResidue = [...residueNoticesFromMap(sealedCekScopedSkipped, "skipped-undeclared-sealed-cek"), ...residueNoticesFromMap(blobScopedSkipped, "skipped-undeclared-blob-scan")];
@@ -9448,8 +9764,13 @@ var Vault = class {
9448
9764
  lookupReferencesCascaded: fanoutStats.lookupReferencesCascaded,
9449
9765
  lookupReferencesNullified: fanoutStats.lookupReferencesNullified,
9450
9766
  lookupReferencesResidue: fanoutStats.lookupReferencesResidue,
9451
- scopedPurgeResidue
9452
- // #650 Task 5 (+ review Important fix: residue) + #633
9767
+ scopedPurgeResidue,
9768
+ ledgerDeltasPurged,
9769
+ ledgerDeltaResidue,
9770
+ // #650 Task 5 (+ review Important fix: residue) + #633 + #734
9771
+ derivedResidueUndecodable: fanoutStats.derivedResidueUndecodable,
9772
+ derivedResidueDeclined: fanoutStats.derivedResidueDeclined
9773
+ // #776/#785
9453
9774
  };
9454
9775
  }
9455
9776
  // ─── Record-scoped CEK sealing ─────────────────────────────────────
@@ -9572,7 +9893,7 @@ var Vault = class {
9572
9893
  async _initDerivations(handles) {
9573
9894
  if (handles.length === 0) return;
9574
9895
  const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
9575
- import("./registry-BZFLJNEH.js"),
9896
+ import("./registry-EPKPD5SM.js"),
9576
9897
  import("./read-only-facade-CHCKSEPD.js")
9577
9898
  ]);
9578
9899
  const registry = new DerivationRegistry();
@@ -9604,7 +9925,7 @@ var Vault = class {
9604
9925
  */
9605
9926
  async _initMaterializedViews(handles) {
9606
9927
  if (handles.length === 0) return;
9607
- const { MaterializedViewRegistry } = await import("./registry-YJEYSYI5.js");
9928
+ const { MaterializedViewRegistry } = await import("./registry-7MLVD3VO.js");
9608
9929
  const registry = new MaterializedViewRegistry();
9609
9930
  this.materializedViewRegistry = registry;
9610
9931
  const db = this;
@@ -9629,7 +9950,7 @@ var Vault = class {
9629
9950
  */
9630
9951
  async _initOverlayedViews(handles) {
9631
9952
  if (handles.length === 0) return;
9632
- const { OverlayedViewRegistry } = await import("./registry-72UKJ2L4.js");
9953
+ const { OverlayedViewRegistry } = await import("./registry-P5T7PS2U.js");
9633
9954
  const registry = new OverlayedViewRegistry();
9634
9955
  const mvRegistry = this.materializedViewRegistry;
9635
9956
  const overlayNames = /* @__PURE__ */ new Set();
@@ -9664,27 +9985,27 @@ var Vault = class {
9664
9985
  /**
9665
9986
  * Manual re-materialize for a single registered MV (`refresh: 'manual'` consumers,
9666
9987
  * stale-bit recovery on vault reopen, bulk-recompute escape hatch after a strategy
9667
- * change). Returns `{ written, deleted, failed }` (`deleted` always 0 without
9668
- * tombstoning). Throws if `name` is not a registered MV.
9988
+ * change). Returns `{ written, deleted, failed, residueUndecodable, residueDeclined }` (`deleted`
9989
+ * always 0 without tombstoning; #785 splits the #782 leftovers — undecodable vs #718-declined). Throws if not registered.
9669
9990
  */
9670
9991
  async refreshView(name) {
9671
9992
  const registry = this.materializedViewRegistry;
9672
9993
  if (registry === null) {
9673
- return { written: 0, deleted: 0, failed: 0 };
9994
+ return { written: 0, deleted: 0, failed: 0, residueUndecodable: [], residueDeclined: [] };
9674
9995
  }
9675
9996
  const reg = registry.byName(name);
9676
9997
  if (!reg) {
9677
9998
  throw new Error(`refreshView: no MV registered with name "${name}"`);
9678
9999
  }
9679
- const { MaterializedViewExecutor } = await import("./executor-GTVSUUBX.js");
10000
+ const { MaterializedViewExecutor } = await import("./executor-UNEH5ZYH.js");
9680
10001
  const result = await MaterializedViewExecutor.refresh(reg, {
9681
10002
  getCollection: (n) => this.collection(n),
9682
10003
  getActiveTxContext: () => this.noydb._activeTxContextOrNull,
9683
10004
  getQueryContext: () => this,
9684
10005
  dispatchCtx: this._dispatchCtx({ collection: name, id: "refreshView" })
9685
10006
  });
9686
- const { clearMVStale } = await import("./stale-NXPT56JA.js");
9687
- clearMVStale(registry, name);
10007
+ const { clearMVStaleFully } = await import("./stale-OSQ7J3AA.js");
10008
+ await clearMVStaleFully(this.adapter, this.name, registry, name);
9688
10009
  return result;
9689
10010
  }
9690
10011
  /**
@@ -9696,7 +10017,7 @@ var Vault = class {
9696
10017
  if (registry === null) return { derived: 0, failed: 0, skippedFrozen: 0 };
9697
10018
  const strategies = registry.strategiesForSource(sourceCollection);
9698
10019
  if (strategies.length === 0) return { derived: 0, failed: 0, skippedFrozen: 0 };
9699
- const { DerivationExecutor } = await import("./executor-XXGS4S3K.js");
10020
+ const { DerivationExecutor } = await import("./executor-OVEXR6RT.js");
9700
10021
  const sourceColl = this.collection(sourceCollection);
9701
10022
  const records = await sourceColl.list();
9702
10023
  const ctx = { vault: this.derivationFacade ?? new (await import("./read-only-facade-CHCKSEPD.js")).ReadOnlyVaultFacade(this, "derivation") };
@@ -9723,7 +10044,7 @@ var Vault = class {
9723
10044
  if (!outSpec) continue;
9724
10045
  const outputColl = this.collection(outSpec.collection);
9725
10046
  if (out.kind === "array") {
9726
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-CKYFH33E.js");
10047
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-A765THMX.js");
9727
10048
  const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key, this.getDEK, this.encrypted);
9728
10049
  const prevKeys = new Set(prior?.keys ?? []);
9729
10050
  const newKeysList = out.entries.map((e) => e.key);
@@ -9950,7 +10271,7 @@ var Vault = class {
9950
10271
  * collection.
9951
10272
  */
9952
10273
  async delegate(opts) {
9953
- const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-OPUU3R2E.js");
10274
+ const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-W7ZV2322.js");
9954
10275
  if (!this.keyring.kek) {
9955
10276
  throw new ValidationError(
9956
10277
  "issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (passphrase) first."
@@ -9972,7 +10293,7 @@ var Vault = class {
9972
10293
  * if the id does not exist.
9973
10294
  */
9974
10295
  async revokeDelegation(id) {
9975
- const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-OPUU3R2E.js");
10296
+ const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-W7ZV2322.js");
9976
10297
  await revokeDelegation(this.adapter, this.name, id);
9977
10298
  void DELEGATIONS_COLLECTION;
9978
10299
  }
@@ -10057,11 +10378,11 @@ var Vault = class {
10057
10378
  * Internal — invoked by an `ElevatedHandle.collection().put()` call.
10058
10379
  * Routes through the existing `Collection.putAtTier` code path with
10059
10380
  * the elevation context attached so the cross-tier event reflects
10060
- * the right authorization class.
10381
+ * the right authorization class. Returns `putAtTier`'s `TierMoveResult` (#779).
10061
10382
  */
10062
10383
  async _elevatedPut(collectionName, id, record, tier, reason) {
10063
10384
  const coll = this.collection(collectionName);
10064
- await coll.putAtTier(id, record, tier, {
10385
+ return coll.putAtTier(id, record, tier, {
10065
10386
  elevation: { reason, fromTier: 0 }
10066
10387
  });
10067
10388
  }
@@ -10220,7 +10541,7 @@ var Vault = class {
10220
10541
  * @see docs/superpowers/specs/2026-05-22-schema-dump-design.md
10221
10542
  */
10222
10543
  async dumpSchema(opts = {}) {
10223
- const { dumpVaultSchema } = await import("./walk-2RWEOCAS.js");
10544
+ const { dumpVaultSchema } = await import("./walk-SVNDIZ62.js");
10224
10545
  return dumpVaultSchema(this, opts);
10225
10546
  }
10226
10547
  /**
@@ -10355,7 +10676,7 @@ var Vault = class {
10355
10676
  * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md
10356
10677
  */
10357
10678
  async getPublicEnvelope(opts = {}) {
10358
- const { readPublicEnvelope } = await import("./public-envelope-NJVB7LPA.js");
10679
+ const { readPublicEnvelope } = await import("./public-envelope-B4KNWVUA.js");
10359
10680
  return readPublicEnvelope(this.adapter, this.name, opts);
10360
10681
  }
10361
10682
  /**
@@ -10370,7 +10691,7 @@ var Vault = class {
10370
10691
  * both modes round-trip cleanly.
10371
10692
  */
10372
10693
  async dump() {
10373
- const { dumpVault } = await import("./backup-XA5STIYQ.js");
10694
+ const { dumpVault } = await import("./backup-BJ57IKAO.js");
10374
10695
  return dumpVault(this.backupContext());
10375
10696
  }
10376
10697
  /**
@@ -10422,7 +10743,7 @@ var Vault = class {
10422
10743
  * — there's no chain to verify against.
10423
10744
  */
10424
10745
  async load(backupJson) {
10425
- const { loadVault } = await import("./backup-XA5STIYQ.js");
10746
+ const { loadVault } = await import("./backup-BJ57IKAO.js");
10426
10747
  return loadVault(this.backupContext(), backupJson);
10427
10748
  }
10428
10749
  /**
@@ -10454,7 +10775,7 @@ var Vault = class {
10454
10775
  * way to detect tampering of an in-place vault.
10455
10776
  */
10456
10777
  async verifyBackupIntegrity() {
10457
- const { verifyBackupIntegrity } = await import("./backup-XA5STIYQ.js");
10778
+ const { verifyBackupIntegrity } = await import("./backup-BJ57IKAO.js");
10458
10779
  return verifyBackupIntegrity(this.backupContext());
10459
10780
  }
10460
10781
  /**
@@ -10672,7 +10993,7 @@ var Vault = class {
10672
10993
  * is the live validator object, not a serialization of it).
10673
10994
  */
10674
10995
  async exportJSON(opts = {}) {
10675
- const { exportVaultJSON } = await import("./backup-XA5STIYQ.js");
10996
+ const { exportVaultJSON } = await import("./backup-BJ57IKAO.js");
10676
10997
  return exportVaultJSON(this.backupContext(), opts);
10677
10998
  }
10678
10999
  };
@@ -12543,7 +12864,7 @@ var Noydb = class {
12543
12864
  if (!facade) return;
12544
12865
  const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
12545
12866
  await registry.runChecks(e.collection, incoming, ctx);
12546
- const { GuardExecutor } = await import("./executor-GZWMTOXB.js");
12867
+ const { GuardExecutor } = await import("./executor-KGWTNEQD.js");
12547
12868
  for (const g of guards) {
12548
12869
  await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming, e.computedFieldNames);
12549
12870
  }
@@ -12765,6 +13086,7 @@ var Noydb = class {
12765
13086
  engine.setCacheInvalidator((collection, id, action) => comp._invalidateSyncApplied(collection, id, action));
12766
13087
  engine.setGraphBatchController({ begin: () => comp._beginGraphBatch(), flush: () => comp._flushGraphBatch() });
12767
13088
  engine.setReservedLookupSource({ collections: () => comp._reservedLookupCollectionNames() });
13089
+ engine.setReservedDictExpander((names) => comp._reservedDictDepsOf(names));
12768
13090
  });
12769
13091
  await comp._initGuards(this.options.guardStrategies ?? []);
12770
13092
  await comp._initDerivations(this.options.derivationStrategies ?? []);
@@ -13539,6 +13861,16 @@ var Noydb = class {
13539
13861
  get coordination() {
13540
13862
  return this.coordinationProvider;
13541
13863
  }
13864
+ /**
13865
+ * #693: true when multi-tab coordination is active at all — presence/election
13866
+ * alone (`propagateWrites: false`) or full write-propagation — a peer tab can
13867
+ * write this instance's shared store out-of-band either way, so per-collection
13868
+ * marker-id sets are not authoritative and the re-create gate must fall back to
13869
+ * a store read. Live (tab coordination is enable/disable-able at runtime).
13870
+ */
13871
+ get _tabCoordinationActive() {
13872
+ return this.tabCoordinator !== void 0;
13873
+ }
13542
13874
  /**
13543
13875
  * Soft-lock a single vault: clear its in-memory keyring, DEKs, vault
13544
13876
  * instance, sync engine, policy enforcer, and active-tier entry —
@@ -13811,7 +14143,7 @@ var Noydb = class {
13811
14143
  "setPublicEnvelope: the public-envelope feature is not enabled. Pass `publicEnvelope: true` (or a schema object) to `createNoydb`."
13812
14144
  );
13813
14145
  }
13814
- const { loadPublicEnvelope, savePublicEnvelope, resolveSchema, validatePublicEnvelopeInput } = await import("./public-envelope-NJVB7LPA.js");
14146
+ const { loadPublicEnvelope, savePublicEnvelope, resolveSchema, validatePublicEnvelopeInput } = await import("./public-envelope-B4KNWVUA.js");
13815
14147
  const schema = resolveSchema(this.options.publicEnvelope);
13816
14148
  validatePublicEnvelopeInput(input, schema);
13817
14149
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -13840,7 +14172,7 @@ var Noydb = class {
13840
14172
  * regardless).
13841
14173
  */
13842
14174
  async getPublicEnvelope(vault, opts = {}) {
13843
- const { readPublicEnvelope } = await import("./public-envelope-NJVB7LPA.js");
14175
+ const { readPublicEnvelope } = await import("./public-envelope-B4KNWVUA.js");
13844
14176
  return readPublicEnvelope(this.options.store, vault, opts);
13845
14177
  }
13846
14178
  // ─── Auth introspection ─────────────────────────────────────────
@@ -14031,9 +14363,9 @@ async function createNoydb(options) {
14031
14363
  throw new ValidationError("A secret (passphrase) or getKeyring callback is required when encryption is enabled");
14032
14364
  }
14033
14365
  if (!options.coordinationStrategy) options = { ...options, coordinationStrategy: await createDefaultCoordinationProvider(options.store) };
14034
- if (!options.userApiFactory) options = { ...options, userApiFactory: (await import("./api-YGMINAET.js")).createUserApi };
14366
+ if (!options.userApiFactory) options = { ...options, userApiFactory: (await import("./api-ZGS6LCOF.js")).createUserApi };
14035
14367
  if (!options.policyFactory) {
14036
- const policyModule = await import("./policy-JTFOPPUU.js");
14368
+ const policyModule = await import("./policy-Z3RUAIY2.js");
14037
14369
  options = { ...options, policyFactory: policyModule.createNoydbPolicy, policyCheckGateFn: policyModule.checkGate };
14038
14370
  }
14039
14371
  return new Noydb(options);
@@ -14070,4 +14402,4 @@ export {
14070
14402
  Noydb,
14071
14403
  createNoydb
14072
14404
  };
14073
- //# sourceMappingURL=chunk-A2QF4JUE.js.map
14405
+ //# sourceMappingURL=chunk-X7QBD67R.js.map