@noy-db/hub 0.4.0-pre.3 → 0.4.0-pre.5

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 (381) hide show
  1. package/README.md +2 -2
  2. package/dist/aggregate/index.js +4 -4
  3. package/dist/api-22ES33N3.js +20 -0
  4. package/dist/as/index.js +11 -11
  5. package/dist/attestation/index.js +20 -20
  6. package/dist/{backup-JL2GOTYQ.js → backup-YCHAC575.js} +11 -11
  7. package/dist/blobs/index.js +12 -12
  8. package/dist/broker/index.js +12 -12
  9. package/dist/by/index.js +2 -2
  10. package/dist/cargo/index.js +29 -29
  11. package/dist/{chunk-2RMDVWGB.js → chunk-2CRZOVDI.js} +2 -2
  12. package/dist/{chunk-T7S4V52L.js → chunk-2PDBYF2O.js} +4 -4
  13. package/dist/{chunk-WJDYZP3U.js → chunk-3LJYHE7S.js} +36 -36
  14. package/dist/chunk-3LJYHE7S.js.map +1 -0
  15. package/dist/{chunk-CCT4WZI6.js → chunk-3OWYOECI.js} +5 -5
  16. package/dist/chunk-3OWYOECI.js.map +1 -0
  17. package/dist/{chunk-L4OA7G5T.js → chunk-522MBPE5.js} +2 -2
  18. package/dist/{chunk-ZJGZDOQO.js → chunk-5ATANZSW.js} +6 -6
  19. package/dist/{chunk-M25ZIEB2.js → chunk-5HSSTOOG.js} +2 -2
  20. package/dist/{chunk-LLVW4V7R.js → chunk-5WLDZZ6S.js} +3 -3
  21. package/dist/{chunk-7B4GPCX7.js → chunk-6RPWILRH.js} +5 -5
  22. package/dist/{chunk-IGM563N5.js → chunk-6SYOHUHM.js} +6 -6
  23. package/dist/chunk-6SYOHUHM.js.map +1 -0
  24. package/dist/{chunk-HGVFJL63.js → chunk-7BIJS6II.js} +15 -5
  25. package/dist/{chunk-HGVFJL63.js.map → chunk-7BIJS6II.js.map} +1 -1
  26. package/dist/{chunk-KR5EGWI4.js → chunk-7ICV4ASA.js} +5 -5
  27. package/dist/{chunk-J3VW4J4E.js → chunk-7LP7FFJ2.js} +2 -2
  28. package/dist/chunk-7LP7FFJ2.js.map +1 -0
  29. package/dist/{chunk-5P5AAXYA.js → chunk-7U6AB7DZ.js} +7 -7
  30. package/dist/chunk-7U6AB7DZ.js.map +1 -0
  31. package/dist/{chunk-KMONEHDJ.js → chunk-AFAPBZAA.js} +2 -2
  32. package/dist/{chunk-GBEXTC6Z.js → chunk-BAAUFCJK.js} +3 -3
  33. package/dist/chunk-BAAUFCJK.js.map +1 -0
  34. package/dist/{chunk-CGPO3ZYB.js → chunk-BY5YBSXA.js} +2 -2
  35. package/dist/{chunk-3O62PVDW.js → chunk-CJVEAVYH.js} +5 -5
  36. package/dist/chunk-CJVEAVYH.js.map +1 -0
  37. package/dist/{chunk-3XVOLB75.js → chunk-CKUYQO2P.js} +3 -3
  38. package/dist/{chunk-2JZ763FV.js → chunk-D4LAJ737.js} +2 -2
  39. package/dist/{chunk-OOTTXUNV.js → chunk-DYZ5CCVM.js} +2 -2
  40. package/dist/{chunk-LUH2MPEF.js → chunk-EEZCB74X.js} +808 -1175
  41. package/dist/chunk-EEZCB74X.js.map +1 -0
  42. package/dist/{chunk-N4FZ6ITM.js → chunk-EGU4PWQW.js} +2 -2
  43. package/dist/{chunk-JKWNG3TM.js → chunk-FHHYCBBP.js} +2 -2
  44. package/dist/{chunk-UBF7HTOR.js → chunk-FIP7KI2P.js} +40 -40
  45. package/dist/chunk-FIP7KI2P.js.map +1 -0
  46. package/dist/{chunk-N4A3DCBT.js → chunk-FTCGEUOY.js} +8 -8
  47. package/dist/{chunk-5BB3N4KU.js → chunk-G4MFQXYX.js} +2 -2
  48. package/dist/{chunk-PEY6ZTCF.js → chunk-GEEJPID6.js} +9 -9
  49. package/dist/{chunk-PEY6ZTCF.js.map → chunk-GEEJPID6.js.map} +1 -1
  50. package/dist/{chunk-KVHWEPT2.js → chunk-GHEMAVTN.js} +2 -2
  51. package/dist/{chunk-OVFCAS7U.js → chunk-GP54LU5N.js} +9 -9
  52. package/dist/{chunk-XW7NWO4A.js → chunk-GTNRMJYH.js} +2 -2
  53. package/dist/{chunk-J6U4BOKP.js → chunk-HAPY7WFP.js} +12 -12
  54. package/dist/{chunk-GU5AYA2Q.js → chunk-HQKRZIX6.js} +5 -5
  55. package/dist/{chunk-OWE4BNTM.js → chunk-I2XEBEEF.js} +4 -4
  56. package/dist/{chunk-WEC3JGBA.js → chunk-IGLU4ME7.js} +3 -3
  57. package/dist/{chunk-BZK6JEX4.js → chunk-ILM6X6CP.js} +5 -5
  58. package/dist/{chunk-2KL6NDD4.js → chunk-J5TEU77Q.js} +4 -4
  59. package/dist/{chunk-UEO5CHOP.js → chunk-JAMDDLIM.js} +13 -13
  60. package/dist/chunk-JAMDDLIM.js.map +1 -0
  61. package/dist/{chunk-V7RGFJ3Z.js → chunk-JIHH26WQ.js} +6 -6
  62. package/dist/{chunk-XGVDLQJE.js → chunk-JN3SGXJE.js} +3 -3
  63. package/dist/{chunk-XULHFSHO.js → chunk-K4BWPNJO.js} +5 -5
  64. package/dist/chunk-K4BWPNJO.js.map +1 -0
  65. package/dist/{chunk-BZEPJJOK.js → chunk-K7BADAOS.js} +4 -4
  66. package/dist/{chunk-OWLPX2GI.js → chunk-KJTIAECI.js} +17 -17
  67. package/dist/chunk-KJTIAECI.js.map +1 -0
  68. package/dist/{chunk-SN75YVM5.js → chunk-L2CAWCQL.js} +18 -18
  69. package/dist/{chunk-SN75YVM5.js.map → chunk-L2CAWCQL.js.map} +1 -1
  70. package/dist/{chunk-MSO2C3KG.js → chunk-LC7DSMHR.js} +2 -2
  71. package/dist/{chunk-JA5B3SLH.js → chunk-M6QA2KK2.js} +2 -2
  72. package/dist/{chunk-IUIVDVXM.js → chunk-MUPZ6IZX.js} +2 -2
  73. package/dist/{chunk-QAFWRGVD.js → chunk-OGVE4IJW.js} +7 -7
  74. package/dist/{chunk-BCOKZC4B.js → chunk-OHV6T5JB.js} +19 -19
  75. package/dist/chunk-OHV6T5JB.js.map +1 -0
  76. package/dist/{chunk-25ZDB25Z.js → chunk-OMSKGLYA.js} +3 -3
  77. package/dist/chunk-OMSKGLYA.js.map +1 -0
  78. package/dist/{chunk-2U7Y7BNJ.js → chunk-ONB627HU.js} +2 -2
  79. package/dist/{chunk-GYB2QK5H.js → chunk-OWLZONGX.js} +2 -2
  80. package/dist/{chunk-YHPUDB7Q.js → chunk-OWOT7CFC.js} +2 -2
  81. package/dist/{chunk-VEX6G3YL.js → chunk-P4NUJVWL.js} +2 -2
  82. package/dist/{chunk-NM4LVUXH.js → chunk-PTT2NB46.js} +2 -2
  83. package/dist/{chunk-2ITLQZV5.js → chunk-PWWWMRT7.js} +2 -2
  84. package/dist/{chunk-GS3Q2KOZ.js → chunk-QBOQI6PG.js} +2 -2
  85. package/dist/{chunk-JIMEB4C6.js → chunk-QMMOMBH6.js} +4 -4
  86. package/dist/{chunk-QDNVHA2F.js → chunk-QMZ5A6FQ.js} +2 -2
  87. package/dist/{chunk-FLHOTGOO.js → chunk-QVGEVZ5F.js} +3 -3
  88. package/dist/{chunk-AFBJHD55.js → chunk-QZJEYZ4I.js} +5 -5
  89. package/dist/{chunk-V3YB7RGR.js → chunk-R2N37AA6.js} +3 -3
  90. package/dist/{chunk-JLHKBAFY.js → chunk-RWW3I3PO.js} +3 -3
  91. package/dist/{chunk-IGAIOGCN.js → chunk-S4YERMGJ.js} +4 -4
  92. package/dist/{chunk-OGFPMCSP.js → chunk-SBOHNJUD.js} +2 -2
  93. package/dist/{chunk-QXPOEAKR.js → chunk-SC4JLMZI.js} +2 -2
  94. package/dist/{chunk-EDC6MLXV.js → chunk-SEU6QHH4.js} +2 -2
  95. package/dist/{chunk-F4COUZLL.js → chunk-TMR64XPL.js} +2 -2
  96. package/dist/{chunk-DEQ2JTBR.js → chunk-TNATF3HB.js} +3 -3
  97. package/dist/{chunk-GZ2GKOF6.js → chunk-TNJVDG2B.js} +3 -3
  98. package/dist/{chunk-5OZCCLNC.js → chunk-TSNRZSRC.js} +2 -2
  99. package/dist/{chunk-QCUH2G77.js → chunk-UTEATWHO.js} +6 -6
  100. package/dist/{chunk-JA5O7UEZ.js → chunk-UVBHM7AK.js} +6 -6
  101. package/dist/chunk-UVBHM7AK.js.map +1 -0
  102. package/dist/{chunk-HKR25MGX.js → chunk-V5JUAW4M.js} +10 -10
  103. package/dist/chunk-V5JUAW4M.js.map +1 -0
  104. package/dist/{chunk-YGBIBOCR.js → chunk-VEGQYPCP.js} +7 -7
  105. package/dist/{chunk-25G7U6RD.js → chunk-WQN5SM7P.js} +2 -2
  106. package/dist/{chunk-NOT7XA7Q.js → chunk-X3MWEFPT.js} +5 -5
  107. package/dist/chunk-XUFAFHQM.js +78 -0
  108. package/dist/chunk-XUFAFHQM.js.map +1 -0
  109. package/dist/{chunk-MEKAMERX.js → chunk-YCAJDK4O.js} +29 -29
  110. package/dist/chunk-YCAJDK4O.js.map +1 -0
  111. package/dist/{chunk-BVZGNMVM.js → chunk-YFFEF6HR.js} +3 -3
  112. package/dist/{chunk-H4SMS4O2.js → chunk-YJ3TREAC.js} +2 -2
  113. package/dist/{chunk-5SZ24DL5.js → chunk-YQQPNXNO.js} +6 -6
  114. package/dist/{chunk-5BHNQNBI.js → chunk-YTW6ZIPD.js} +1 -1
  115. package/dist/chunk-YTW6ZIPD.js.map +1 -0
  116. package/dist/{chunk-EW4HFWGJ.js → chunk-YWZEDG7F.js} +6 -6
  117. package/dist/{chunk-2VUISNGP.js → chunk-YXIVUWDU.js} +5 -5
  118. package/dist/{chunk-YG2EG6CB.js → chunk-YXZNGHID.js} +4 -4
  119. package/dist/{chunk-QYJIOWKN.js → chunk-YZN6NRTR.js} +9 -9
  120. package/dist/{chunk-IZX3WZBF.js → chunk-YZNKFYDC.js} +4 -4
  121. package/dist/{chunk-E2R5NRZD.js → chunk-Z4D3YGAB.js} +2 -2
  122. package/dist/{chunk-STR7WBOB.js → chunk-ZUDAK436.js} +2 -2
  123. package/dist/{chunk-ITI3SJRB.js → chunk-ZX5FNWH7.js} +2 -2
  124. package/dist/classified/index.js +5 -5
  125. package/dist/{classified-marker-7S5IEP6Q.js → classified-marker-52P3D72W.js} +3 -3
  126. package/dist/collection-facade-XKCFHSLR.js +44 -0
  127. package/dist/{computed-WZNKRLCY.js → computed-33DRJDOC.js} +3 -3
  128. package/dist/consent/index.js +9 -9
  129. package/dist/{cover-B5MY43CK.js → cover-5BSNJREH.js} +4 -4
  130. package/dist/{dead-filter-KRRD57MR.js → dead-filter-JXVCKS6W.js} +2 -2
  131. package/dist/delegation-WWZPEDK2.js +25 -0
  132. package/dist/derivations/index.js +12 -12
  133. package/dist/derive-CWWFEQ4N.js +21 -0
  134. package/dist/dispatch-PKQQFDBT.js +193 -0
  135. package/dist/dispatch-PKQQFDBT.js.map +1 -0
  136. package/dist/dispatch-SMXUO7W5.js +72 -0
  137. package/dist/dispatch-SMXUO7W5.js.map +1 -0
  138. package/dist/{enclave-YFKA3GJT.js → enclave-I5H3GINP.js} +11 -11
  139. package/dist/executor-FCJEH3FU.js +9 -0
  140. package/dist/executor-OHET7TF7.js +9 -0
  141. package/dist/executor-SHYLIBOM.js +26 -0
  142. package/dist/export-accessible-FBL6TDSK.js +23 -0
  143. package/dist/extract-partition-ZYIRYMTI.js +38 -0
  144. package/dist/{fanout-sidecar-HJV3A7PM.js → fanout-sidecar-WWXVHHUH.js} +9 -9
  145. package/dist/find-LEBUXVL7.js +11 -0
  146. package/dist/forget/index.js +9 -9
  147. package/dist/guards/index.js +3 -3
  148. package/dist/history/index.js +12 -12
  149. package/dist/i18n/index.js +14 -14
  150. package/dist/index.d.ts +13 -9
  151. package/dist/index.js +119 -118
  152. package/dist/index.js.map +1 -1
  153. package/dist/indexing/index.js +2 -2
  154. package/dist/issue-F76PAGIR.js +19 -0
  155. package/dist/kernel/collection-config.d.ts +11 -69
  156. package/dist/kernel/collection.d.ts +10 -22
  157. package/dist/kernel/enclave/crypto.d.ts +8 -8
  158. package/dist/kernel/enclave/index.d.ts +2 -2
  159. package/dist/kernel/errors.d.ts +20 -20
  160. package/dist/kernel/noydb.d.ts +43 -103
  161. package/dist/kernel/types.d.ts +82 -41
  162. package/dist/kernel/validation.d.ts +33 -33
  163. package/dist/kernel/vault.d.ts +31 -215
  164. package/dist/kernel/via/dispatch.d.ts +7 -0
  165. package/dist/{ledger-SW6QQOAV.js → ledger-M2BKCNVS.js} +11 -11
  166. package/dist/liberate-ZP7UB57K.js +24 -0
  167. package/dist/{link-set-GNGGCFI4.js → link-set-ZU4E5J5S.js} +11 -11
  168. package/dist/materialized-views/index.js +19 -19
  169. package/dist/noydb-BNDGEK5X.js +71 -0
  170. package/dist/on/index.js +9 -9
  171. package/dist/overlay-views/index.js +4 -4
  172. package/dist/periods/index.js +13 -13
  173. package/dist/pod/index.js +11 -11
  174. package/dist/{policy-EAXSJNOT.js → policy-IY2YEA3A.js} +5 -5
  175. package/dist/port/at/index.d.ts +4 -4
  176. package/dist/port/with/archive-strategy.d.ts +31 -0
  177. package/dist/port/with/collection-options.d.ts +171 -0
  178. package/dist/port/with/strategies.d.ts +134 -0
  179. package/dist/port/with/team-strategy.d.ts +1 -1
  180. package/dist/portability/index.js +8 -8
  181. package/dist/{post-register-A7HCFBP5.js → post-register-XIAHB6KF.js} +6 -6
  182. package/dist/query/index.js +6 -6
  183. package/dist/register-HB4TQZSV.js +23 -0
  184. package/dist/registry-6BMBFEXT.js +19 -0
  185. package/dist/registry-7CZWF3EQ.js +9 -0
  186. package/dist/registry-JOFO7RAH.js +18 -0
  187. package/dist/request-withdrawal-UN3TRHWI.js +31 -0
  188. package/dist/{reveal-PB3YG544.js → reveal-VWXRV2XU.js} +6 -6
  189. package/dist/revoke-OLO2OVR7.js +24 -0
  190. package/dist/satellites/index.js +1 -1
  191. package/dist/sealed-record/index.js +12 -12
  192. package/dist/{seed-EKF4DIBB.js → seed-CDBFOTIK.js} +12 -12
  193. package/dist/seed-CDBFOTIK.js.map +1 -0
  194. package/dist/session/index.js +9 -9
  195. package/dist/shadow/index.js +2 -2
  196. package/dist/signer-MGGKPYAN.js +25 -0
  197. package/dist/snapshots/index.js +10 -10
  198. package/dist/{stale-4UNPHWOU.js → stale-NBROTA66.js} +10 -10
  199. package/dist/storage-3R37QZLA.js +23 -0
  200. package/dist/{store-coordination-provider-3AELCZ4Y.js → store-coordination-provider-P3IU5JHD.js} +3 -3
  201. package/dist/sync/index.js +10 -10
  202. package/dist/team/index.js +20 -20
  203. package/dist/tiers/index.js +10 -10
  204. package/dist/to/index.js +1 -1
  205. package/dist/tx/index.js +3 -3
  206. package/dist/util/index.js +1 -1
  207. package/dist/{verify-MXN66IIH.js → verify-5X37OXRY.js} +5 -5
  208. package/dist/{walk-H4YE52S2.js → walk-E3OVLBFR.js} +11 -11
  209. package/dist/with/index.js +11 -11
  210. package/dist/with-audit/portability/export-accessible.d.ts +4 -4
  211. package/dist/with-audit/portability/request-withdrawal.d.ts +3 -3
  212. package/dist/with-audit/portability/withdraw-accessible.d.ts +2 -2
  213. package/dist/with-audit/sealed-record/strategy.d.ts +1 -1
  214. package/dist/with-cargo/adopt-partition.d.ts +7 -7
  215. package/dist/with-cargo/index.d.ts +1 -1
  216. package/dist/with-commit/history/time-machine.d.ts +2 -2
  217. package/dist/with-formula/derivations/dispatch.d.ts +98 -0
  218. package/dist/with-formula/materialized-views/dispatch.d.ts +75 -0
  219. package/dist/with-party/custody/liberate.d.ts +3 -3
  220. package/dist/with-party/session/dev-unlock.d.ts +2 -2
  221. package/dist/with-party/session/session.d.ts +2 -2
  222. package/dist/with-party/team/deed.d.ts +8 -8
  223. package/dist/with-party/team/index.d.ts +2 -2
  224. package/dist/with-party/team/keyring.d.ts +19 -19
  225. package/dist/with-party/team/{managed-passphrase.d.ts → managed-secret.d.ts} +27 -27
  226. package/dist/with-party/team/noydb-facade.d.ts +41 -41
  227. package/dist/with-party/team/peer-recover.d.ts +13 -13
  228. package/dist/with-party/team/recovery.d.ts +5 -5
  229. package/dist/with-party/team/rotate-recover.d.ts +30 -30
  230. package/dist/with-pod/bundle.d.ts +30 -30
  231. package/dist/with-pod/format.d.ts +2 -2
  232. package/dist/withdraw-accessible-Q2EMATCU.js +28 -0
  233. package/package.json +3 -3
  234. package/dist/api-UPAT2O3M.js +0 -20
  235. package/dist/chunk-25ZDB25Z.js.map +0 -1
  236. package/dist/chunk-3O62PVDW.js.map +0 -1
  237. package/dist/chunk-5BHNQNBI.js.map +0 -1
  238. package/dist/chunk-5P5AAXYA.js.map +0 -1
  239. package/dist/chunk-BCOKZC4B.js.map +0 -1
  240. package/dist/chunk-CCT4WZI6.js.map +0 -1
  241. package/dist/chunk-GBEXTC6Z.js.map +0 -1
  242. package/dist/chunk-HKR25MGX.js.map +0 -1
  243. package/dist/chunk-IGM563N5.js.map +0 -1
  244. package/dist/chunk-J3VW4J4E.js.map +0 -1
  245. package/dist/chunk-JA5O7UEZ.js.map +0 -1
  246. package/dist/chunk-LUH2MPEF.js.map +0 -1
  247. package/dist/chunk-MEKAMERX.js.map +0 -1
  248. package/dist/chunk-OWLPX2GI.js.map +0 -1
  249. package/dist/chunk-UBF7HTOR.js.map +0 -1
  250. package/dist/chunk-UEO5CHOP.js.map +0 -1
  251. package/dist/chunk-WJDYZP3U.js.map +0 -1
  252. package/dist/chunk-XULHFSHO.js.map +0 -1
  253. package/dist/collection-facade-ENLTJZBT.js +0 -44
  254. package/dist/delegation-UT76AQIG.js +0 -25
  255. package/dist/derive-SGRCCKVP.js +0 -21
  256. package/dist/executor-TEZYRDN3.js +0 -9
  257. package/dist/executor-WQQRU6DO.js +0 -9
  258. package/dist/executor-YORMIBWV.js +0 -26
  259. package/dist/export-accessible-HXMKW5LJ.js +0 -23
  260. package/dist/extract-partition-QGQ2R42J.js +0 -38
  261. package/dist/find-VV6PBIHK.js +0 -11
  262. package/dist/issue-7JJ4Z7E2.js +0 -19
  263. package/dist/liberate-FK7JI2QX.js +0 -24
  264. package/dist/noydb-KUX2TJMX.js +0 -70
  265. package/dist/register-YBMRLZLO.js +0 -23
  266. package/dist/registry-3LXKNXWI.js +0 -9
  267. package/dist/registry-4V4YQCXJ.js +0 -19
  268. package/dist/registry-ZULMLCJK.js +0 -18
  269. package/dist/request-withdrawal-SEVUEUDG.js +0 -31
  270. package/dist/revoke-5QULL5GT.js +0 -24
  271. package/dist/seed-EKF4DIBB.js.map +0 -1
  272. package/dist/signer-ZMH35FT4.js +0 -25
  273. package/dist/storage-QOZKQMID.js +0 -23
  274. package/dist/withdraw-accessible-HPOVNG2G.js +0 -28
  275. /package/dist/{api-UPAT2O3M.js.map → api-22ES33N3.js.map} +0 -0
  276. /package/dist/{backup-JL2GOTYQ.js.map → backup-YCHAC575.js.map} +0 -0
  277. /package/dist/{chunk-2RMDVWGB.js.map → chunk-2CRZOVDI.js.map} +0 -0
  278. /package/dist/{chunk-T7S4V52L.js.map → chunk-2PDBYF2O.js.map} +0 -0
  279. /package/dist/{chunk-L4OA7G5T.js.map → chunk-522MBPE5.js.map} +0 -0
  280. /package/dist/{chunk-ZJGZDOQO.js.map → chunk-5ATANZSW.js.map} +0 -0
  281. /package/dist/{chunk-M25ZIEB2.js.map → chunk-5HSSTOOG.js.map} +0 -0
  282. /package/dist/{chunk-LLVW4V7R.js.map → chunk-5WLDZZ6S.js.map} +0 -0
  283. /package/dist/{chunk-7B4GPCX7.js.map → chunk-6RPWILRH.js.map} +0 -0
  284. /package/dist/{chunk-KR5EGWI4.js.map → chunk-7ICV4ASA.js.map} +0 -0
  285. /package/dist/{chunk-KMONEHDJ.js.map → chunk-AFAPBZAA.js.map} +0 -0
  286. /package/dist/{chunk-CGPO3ZYB.js.map → chunk-BY5YBSXA.js.map} +0 -0
  287. /package/dist/{chunk-3XVOLB75.js.map → chunk-CKUYQO2P.js.map} +0 -0
  288. /package/dist/{chunk-2JZ763FV.js.map → chunk-D4LAJ737.js.map} +0 -0
  289. /package/dist/{chunk-OOTTXUNV.js.map → chunk-DYZ5CCVM.js.map} +0 -0
  290. /package/dist/{chunk-N4FZ6ITM.js.map → chunk-EGU4PWQW.js.map} +0 -0
  291. /package/dist/{chunk-JKWNG3TM.js.map → chunk-FHHYCBBP.js.map} +0 -0
  292. /package/dist/{chunk-N4A3DCBT.js.map → chunk-FTCGEUOY.js.map} +0 -0
  293. /package/dist/{chunk-5BB3N4KU.js.map → chunk-G4MFQXYX.js.map} +0 -0
  294. /package/dist/{chunk-KVHWEPT2.js.map → chunk-GHEMAVTN.js.map} +0 -0
  295. /package/dist/{chunk-OVFCAS7U.js.map → chunk-GP54LU5N.js.map} +0 -0
  296. /package/dist/{chunk-XW7NWO4A.js.map → chunk-GTNRMJYH.js.map} +0 -0
  297. /package/dist/{chunk-J6U4BOKP.js.map → chunk-HAPY7WFP.js.map} +0 -0
  298. /package/dist/{chunk-GU5AYA2Q.js.map → chunk-HQKRZIX6.js.map} +0 -0
  299. /package/dist/{chunk-OWE4BNTM.js.map → chunk-I2XEBEEF.js.map} +0 -0
  300. /package/dist/{chunk-WEC3JGBA.js.map → chunk-IGLU4ME7.js.map} +0 -0
  301. /package/dist/{chunk-BZK6JEX4.js.map → chunk-ILM6X6CP.js.map} +0 -0
  302. /package/dist/{chunk-2KL6NDD4.js.map → chunk-J5TEU77Q.js.map} +0 -0
  303. /package/dist/{chunk-V7RGFJ3Z.js.map → chunk-JIHH26WQ.js.map} +0 -0
  304. /package/dist/{chunk-XGVDLQJE.js.map → chunk-JN3SGXJE.js.map} +0 -0
  305. /package/dist/{chunk-BZEPJJOK.js.map → chunk-K7BADAOS.js.map} +0 -0
  306. /package/dist/{chunk-MSO2C3KG.js.map → chunk-LC7DSMHR.js.map} +0 -0
  307. /package/dist/{chunk-JA5B3SLH.js.map → chunk-M6QA2KK2.js.map} +0 -0
  308. /package/dist/{chunk-IUIVDVXM.js.map → chunk-MUPZ6IZX.js.map} +0 -0
  309. /package/dist/{chunk-QAFWRGVD.js.map → chunk-OGVE4IJW.js.map} +0 -0
  310. /package/dist/{chunk-2U7Y7BNJ.js.map → chunk-ONB627HU.js.map} +0 -0
  311. /package/dist/{chunk-GYB2QK5H.js.map → chunk-OWLZONGX.js.map} +0 -0
  312. /package/dist/{chunk-YHPUDB7Q.js.map → chunk-OWOT7CFC.js.map} +0 -0
  313. /package/dist/{chunk-VEX6G3YL.js.map → chunk-P4NUJVWL.js.map} +0 -0
  314. /package/dist/{chunk-NM4LVUXH.js.map → chunk-PTT2NB46.js.map} +0 -0
  315. /package/dist/{chunk-2ITLQZV5.js.map → chunk-PWWWMRT7.js.map} +0 -0
  316. /package/dist/{chunk-GS3Q2KOZ.js.map → chunk-QBOQI6PG.js.map} +0 -0
  317. /package/dist/{chunk-JIMEB4C6.js.map → chunk-QMMOMBH6.js.map} +0 -0
  318. /package/dist/{chunk-QDNVHA2F.js.map → chunk-QMZ5A6FQ.js.map} +0 -0
  319. /package/dist/{chunk-FLHOTGOO.js.map → chunk-QVGEVZ5F.js.map} +0 -0
  320. /package/dist/{chunk-AFBJHD55.js.map → chunk-QZJEYZ4I.js.map} +0 -0
  321. /package/dist/{chunk-V3YB7RGR.js.map → chunk-R2N37AA6.js.map} +0 -0
  322. /package/dist/{chunk-JLHKBAFY.js.map → chunk-RWW3I3PO.js.map} +0 -0
  323. /package/dist/{chunk-IGAIOGCN.js.map → chunk-S4YERMGJ.js.map} +0 -0
  324. /package/dist/{chunk-OGFPMCSP.js.map → chunk-SBOHNJUD.js.map} +0 -0
  325. /package/dist/{chunk-QXPOEAKR.js.map → chunk-SC4JLMZI.js.map} +0 -0
  326. /package/dist/{chunk-EDC6MLXV.js.map → chunk-SEU6QHH4.js.map} +0 -0
  327. /package/dist/{chunk-F4COUZLL.js.map → chunk-TMR64XPL.js.map} +0 -0
  328. /package/dist/{chunk-DEQ2JTBR.js.map → chunk-TNATF3HB.js.map} +0 -0
  329. /package/dist/{chunk-GZ2GKOF6.js.map → chunk-TNJVDG2B.js.map} +0 -0
  330. /package/dist/{chunk-5OZCCLNC.js.map → chunk-TSNRZSRC.js.map} +0 -0
  331. /package/dist/{chunk-QCUH2G77.js.map → chunk-UTEATWHO.js.map} +0 -0
  332. /package/dist/{chunk-YGBIBOCR.js.map → chunk-VEGQYPCP.js.map} +0 -0
  333. /package/dist/{chunk-25G7U6RD.js.map → chunk-WQN5SM7P.js.map} +0 -0
  334. /package/dist/{chunk-NOT7XA7Q.js.map → chunk-X3MWEFPT.js.map} +0 -0
  335. /package/dist/{chunk-BVZGNMVM.js.map → chunk-YFFEF6HR.js.map} +0 -0
  336. /package/dist/{chunk-H4SMS4O2.js.map → chunk-YJ3TREAC.js.map} +0 -0
  337. /package/dist/{chunk-5SZ24DL5.js.map → chunk-YQQPNXNO.js.map} +0 -0
  338. /package/dist/{chunk-EW4HFWGJ.js.map → chunk-YWZEDG7F.js.map} +0 -0
  339. /package/dist/{chunk-2VUISNGP.js.map → chunk-YXIVUWDU.js.map} +0 -0
  340. /package/dist/{chunk-YG2EG6CB.js.map → chunk-YXZNGHID.js.map} +0 -0
  341. /package/dist/{chunk-QYJIOWKN.js.map → chunk-YZN6NRTR.js.map} +0 -0
  342. /package/dist/{chunk-IZX3WZBF.js.map → chunk-YZNKFYDC.js.map} +0 -0
  343. /package/dist/{chunk-E2R5NRZD.js.map → chunk-Z4D3YGAB.js.map} +0 -0
  344. /package/dist/{chunk-STR7WBOB.js.map → chunk-ZUDAK436.js.map} +0 -0
  345. /package/dist/{chunk-ITI3SJRB.js.map → chunk-ZX5FNWH7.js.map} +0 -0
  346. /package/dist/{classified-marker-7S5IEP6Q.js.map → classified-marker-52P3D72W.js.map} +0 -0
  347. /package/dist/{collection-facade-ENLTJZBT.js.map → collection-facade-XKCFHSLR.js.map} +0 -0
  348. /package/dist/{computed-WZNKRLCY.js.map → computed-33DRJDOC.js.map} +0 -0
  349. /package/dist/{cover-B5MY43CK.js.map → cover-5BSNJREH.js.map} +0 -0
  350. /package/dist/{dead-filter-KRRD57MR.js.map → dead-filter-JXVCKS6W.js.map} +0 -0
  351. /package/dist/{delegation-UT76AQIG.js.map → delegation-WWZPEDK2.js.map} +0 -0
  352. /package/dist/{derive-SGRCCKVP.js.map → derive-CWWFEQ4N.js.map} +0 -0
  353. /package/dist/{enclave-YFKA3GJT.js.map → enclave-I5H3GINP.js.map} +0 -0
  354. /package/dist/{executor-TEZYRDN3.js.map → executor-FCJEH3FU.js.map} +0 -0
  355. /package/dist/{executor-WQQRU6DO.js.map → executor-OHET7TF7.js.map} +0 -0
  356. /package/dist/{executor-YORMIBWV.js.map → executor-SHYLIBOM.js.map} +0 -0
  357. /package/dist/{export-accessible-HXMKW5LJ.js.map → export-accessible-FBL6TDSK.js.map} +0 -0
  358. /package/dist/{extract-partition-QGQ2R42J.js.map → extract-partition-ZYIRYMTI.js.map} +0 -0
  359. /package/dist/{fanout-sidecar-HJV3A7PM.js.map → fanout-sidecar-WWXVHHUH.js.map} +0 -0
  360. /package/dist/{find-VV6PBIHK.js.map → find-LEBUXVL7.js.map} +0 -0
  361. /package/dist/{issue-7JJ4Z7E2.js.map → issue-F76PAGIR.js.map} +0 -0
  362. /package/dist/{ledger-SW6QQOAV.js.map → ledger-M2BKCNVS.js.map} +0 -0
  363. /package/dist/{liberate-FK7JI2QX.js.map → liberate-ZP7UB57K.js.map} +0 -0
  364. /package/dist/{link-set-GNGGCFI4.js.map → link-set-ZU4E5J5S.js.map} +0 -0
  365. /package/dist/{noydb-KUX2TJMX.js.map → noydb-BNDGEK5X.js.map} +0 -0
  366. /package/dist/{policy-EAXSJNOT.js.map → policy-IY2YEA3A.js.map} +0 -0
  367. /package/dist/{post-register-A7HCFBP5.js.map → post-register-XIAHB6KF.js.map} +0 -0
  368. /package/dist/{register-YBMRLZLO.js.map → register-HB4TQZSV.js.map} +0 -0
  369. /package/dist/{registry-3LXKNXWI.js.map → registry-6BMBFEXT.js.map} +0 -0
  370. /package/dist/{registry-4V4YQCXJ.js.map → registry-7CZWF3EQ.js.map} +0 -0
  371. /package/dist/{registry-ZULMLCJK.js.map → registry-JOFO7RAH.js.map} +0 -0
  372. /package/dist/{request-withdrawal-SEVUEUDG.js.map → request-withdrawal-UN3TRHWI.js.map} +0 -0
  373. /package/dist/{reveal-PB3YG544.js.map → reveal-VWXRV2XU.js.map} +0 -0
  374. /package/dist/{revoke-5QULL5GT.js.map → revoke-OLO2OVR7.js.map} +0 -0
  375. /package/dist/{signer-ZMH35FT4.js.map → signer-MGGKPYAN.js.map} +0 -0
  376. /package/dist/{stale-4UNPHWOU.js.map → stale-NBROTA66.js.map} +0 -0
  377. /package/dist/{storage-QOZKQMID.js.map → storage-3R37QZLA.js.map} +0 -0
  378. /package/dist/{store-coordination-provider-3AELCZ4Y.js.map → store-coordination-provider-P3IU5JHD.js.map} +0 -0
  379. /package/dist/{verify-MXN66IIH.js.map → verify-5X37OXRY.js.map} +0 -0
  380. /package/dist/{walk-H4YE52S2.js.map → walk-E3OVLBFR.js.map} +0 -0
  381. /package/dist/{withdraw-accessible-HPOVNG2G.js.map → withdraw-accessible-Q2EMATCU.js.map} +0 -0
@@ -1,3 +1,6 @@
1
+ import {
2
+ loadVaultPolicy
3
+ } from "./chunk-QMZ5A6FQ.js";
1
4
  import {
2
5
  jsonSchemaToFields
3
6
  } from "./chunk-VYYM3MEN.js";
@@ -6,23 +9,23 @@ import {
6
9
  SEQUENCE_COLLECTION,
7
10
  compileSequenceFormat,
8
11
  resolveSequenceKey
9
- } from "./chunk-NOT7XA7Q.js";
10
- import {
11
- loadVaultPolicy
12
- } from "./chunk-QDNVHA2F.js";
12
+ } from "./chunk-X3MWEFPT.js";
13
13
  import {
14
14
  LinkIntegrityError,
15
15
  isLinkCollectionName,
16
16
  linkCollectionName,
17
17
  linkRowKey
18
- } from "./chunk-IUIVDVXM.js";
18
+ } from "./chunk-MUPZ6IZX.js";
19
19
  import {
20
20
  hashFields,
21
21
  validateSatelliteDeclaration
22
- } from "./chunk-L4OA7G5T.js";
22
+ } from "./chunk-522MBPE5.js";
23
+ import {
24
+ resolveStaleOnRead
25
+ } from "./chunk-XUFAFHQM.js";
23
26
  import {
24
27
  loadFence
25
- } from "./chunk-JA5B3SLH.js";
28
+ } from "./chunk-M6QA2KK2.js";
26
29
  import {
27
30
  InvertedIndex,
28
31
  MemoryIndexStore,
@@ -31,11 +34,11 @@ import {
31
34
  buildPersistedIndexCallbacks,
32
35
  encodeVecId,
33
36
  syncTierSearch
34
- } from "./chunk-J6U4BOKP.js";
37
+ } from "./chunk-HAPY7WFP.js";
35
38
  import {
36
39
  derivePersistedSchema,
37
40
  isZod4Schema
38
- } from "./chunk-EDC6MLXV.js";
41
+ } from "./chunk-SEU6QHH4.js";
39
42
  import {
40
43
  isBaseLive,
41
44
  liveBaseIdSet
@@ -44,11 +47,11 @@ import {
44
47
  CustodyApi,
45
48
  NO_CARGO,
46
49
  NO_CUSTODY
47
- } from "./chunk-SN75YVM5.js";
50
+ } from "./chunk-L2CAWCQL.js";
48
51
  import {
49
52
  resolveManagedSecret,
50
- saveSealedPassphrase
51
- } from "./chunk-BCOKZC4B.js";
53
+ saveSealedSecret
54
+ } from "./chunk-OHV6T5JB.js";
52
55
  import {
53
56
  ServiceBus,
54
57
  WriteHookRegistry,
@@ -56,35 +59,35 @@ import {
56
59
  assertCanImport,
57
60
  canExport,
58
61
  canImport
59
- } from "./chunk-WEC3JGBA.js";
62
+ } from "./chunk-IGLU4ME7.js";
60
63
  import {
61
64
  runDrainBarrier
62
- } from "./chunk-KMONEHDJ.js";
65
+ } from "./chunk-AFAPBZAA.js";
63
66
  import {
64
67
  NO_ATTESTATION
65
- } from "./chunk-XW7NWO4A.js";
68
+ } from "./chunk-GTNRMJYH.js";
66
69
  import {
67
70
  NO_CLASSIFIED,
68
71
  guardClassifiedCompat,
69
72
  resolveClassifiedFields
70
- } from "./chunk-IZX3WZBF.js";
73
+ } from "./chunk-YZNKFYDC.js";
71
74
  import {
72
75
  NO_TIERS,
73
76
  classifySealedShred,
74
77
  syncDerivedOutputs
75
- } from "./chunk-N4A3DCBT.js";
78
+ } from "./chunk-FTCGEUOY.js";
76
79
  import {
77
80
  NO_PORTABILITY
78
- } from "./chunk-GYB2QK5H.js";
81
+ } from "./chunk-OWLZONGX.js";
79
82
  import {
80
83
  TxContext,
81
84
  bestEffortRevert,
82
85
  revertExecuted
83
- } from "./chunk-FLHOTGOO.js";
86
+ } from "./chunk-QVGEVZ5F.js";
84
87
  import {
85
88
  DEFAULT_POSTURE,
86
89
  ViaGraph
87
- } from "./chunk-E2R5NRZD.js";
90
+ } from "./chunk-Z4D3YGAB.js";
88
91
  import {
89
92
  buildLookupAltIndex,
90
93
  buildLookupSnapshotRows,
@@ -105,27 +108,28 @@ import {
105
108
  resolveLabelFromMap,
106
109
  resolveRollupDeleteIntents,
107
110
  runGraphDispatchWave,
111
+ selfWriteFieldEqual,
108
112
  touchFor,
109
113
  updateReferencingRecords
110
- } from "./chunk-HGVFJL63.js";
114
+ } from "./chunk-7BIJS6II.js";
111
115
  import {
112
116
  OverlayedCollection
113
- } from "./chunk-2ITLQZV5.js";
117
+ } from "./chunk-PWWWMRT7.js";
114
118
  import {
115
119
  NO_AGGREGATE,
116
120
  Query,
117
121
  ScanBuilder
118
- } from "./chunk-GU5AYA2Q.js";
122
+ } from "./chunk-HQKRZIX6.js";
119
123
  import {
120
124
  EXPORT_AUDIT_COLLECTION,
121
125
  createExportBlobsHandle,
122
126
  runCompaction
123
- } from "./chunk-2KL6NDD4.js";
127
+ } from "./chunk-J5TEU77Q.js";
124
128
  import {
125
129
  LazyQuery,
126
130
  decodeIdxId,
127
131
  encodeIdxId
128
- } from "./chunk-CGPO3ZYB.js";
132
+ } from "./chunk-BY5YBSXA.js";
129
133
  import {
130
134
  IMPLICIT_LAZY,
131
135
  Lru,
@@ -133,13 +137,13 @@ import {
133
137
  } from "./chunk-NO272T7Q.js";
134
138
  import {
135
139
  canonicalGroupKey
136
- } from "./chunk-JIMEB4C6.js";
140
+ } from "./chunk-QMMOMBH6.js";
137
141
  import {
138
142
  readPath
139
143
  } from "./chunk-IGJCYUT5.js";
140
144
  import {
141
145
  dictCollectionName
142
- } from "./chunk-BZEPJJOK.js";
146
+ } from "./chunk-K7BADAOS.js";
143
147
  import {
144
148
  NO_I18N,
145
149
  getAtPath,
@@ -147,23 +151,23 @@ import {
147
151
  isDictKeyDescriptor,
148
152
  isI18nTextDescriptor,
149
153
  isStaticDictDescriptor
150
- } from "./chunk-XGVDLQJE.js";
154
+ } from "./chunk-JN3SGXJE.js";
151
155
  import {
152
156
  installViaBinder,
153
157
  isViaInstalled,
154
158
  viaBinder
155
- } from "./chunk-STR7WBOB.js";
159
+ } from "./chunk-ZUDAK436.js";
156
160
  import {
157
161
  NO_TEAM,
158
162
  enrollAuthenticator,
159
163
  findAuthenticator,
160
- recoverPassphrase,
164
+ recoverSecret,
161
165
  recoverUser,
162
166
  removeAuthenticator,
163
- rotatePassphrase,
167
+ rotateSecret,
164
168
  updateAuthenticator,
165
169
  writeMagicLinkGrant
166
- } from "./chunk-UBF7HTOR.js";
170
+ } from "./chunk-FIP7KI2P.js";
167
171
  import {
168
172
  assertKeyringOpenAllowed,
169
173
  buildRecipientKeyringFile,
@@ -176,11 +180,11 @@ import {
176
180
  listUsers,
177
181
  loadKeyring,
178
182
  updateKeyringIdentity
179
- } from "./chunk-WJDYZP3U.js";
183
+ } from "./chunk-3LJYHE7S.js";
180
184
  import {
181
185
  persistDirectoryConfig,
182
186
  readDirectoryConfig
183
- } from "./chunk-7B4GPCX7.js";
187
+ } from "./chunk-6RPWILRH.js";
184
188
  import {
185
189
  hasRecoveryEnrolled,
186
190
  hasStrongRecoveryEnrolled,
@@ -190,7 +194,7 @@ import {
190
194
  mintShamirRecoveryEntry,
191
195
  savePaperRecoveryEntries,
192
196
  saveShamirRecoveryEntries
193
- } from "./chunk-3O62PVDW.js";
197
+ } from "./chunk-CJVEAVYH.js";
194
198
  import {
195
199
  INDEXED_STORE_POLICY
196
200
  } from "./chunk-VQNJ7UZL.js";
@@ -200,11 +204,11 @@ import {
200
204
  PERIOD_FREEZES_COLLECTION,
201
205
  PERIOD_TARGET_PURGES_COLLECTION,
202
206
  periodExclusiveUpperBound
203
- } from "./chunk-F4COUZLL.js";
207
+ } from "./chunk-TMR64XPL.js";
204
208
  import {
205
209
  NO_BROKER,
206
210
  buildCredentialBrokerHandle
207
- } from "./chunk-VEX6G3YL.js";
211
+ } from "./chunk-P4NUJVWL.js";
208
212
  import {
209
213
  generateULID
210
214
  } from "./chunk-ZJADGNYF.js";
@@ -212,10 +216,10 @@ import {
212
216
  assertCutoverTierSafe,
213
217
  assertTierWritable,
214
218
  liveRecordIsElevated
215
- } from "./chunk-NM4LVUXH.js";
219
+ } from "./chunk-PTT2NB46.js";
216
220
  import {
217
221
  sha256Hex
218
- } from "./chunk-JLHKBAFY.js";
222
+ } from "./chunk-RWW3I3PO.js";
219
223
  import {
220
224
  NO_FORGET,
221
225
  addSubjectRef,
@@ -224,10 +228,10 @@ import {
224
228
  readDottedPath,
225
229
  rebuildSubjectIndex,
226
230
  removeSubjectRef
227
- } from "./chunk-OWE4BNTM.js";
231
+ } from "./chunk-I2XEBEEF.js";
228
232
  import {
229
233
  NO_SEALED_RECORD
230
- } from "./chunk-J3VW4J4E.js";
234
+ } from "./chunk-7LP7FFJ2.js";
231
235
  import {
232
236
  RecordCodec,
233
237
  SEALED_CEK_NS,
@@ -238,20 +242,20 @@ import {
238
242
  queryByDet,
239
243
  resolveStableCek,
240
244
  validateSchemaInput
241
- } from "./chunk-PEY6ZTCF.js";
245
+ } from "./chunk-GEEJPID6.js";
242
246
  import {
243
247
  buildDeleteMarker,
244
248
  buildTombstone,
245
249
  isDeleteMarker,
246
250
  isTombstone
247
- } from "./chunk-QXPOEAKR.js";
251
+ } from "./chunk-SC4JLMZI.js";
248
252
  import {
249
253
  encrypt
250
- } from "./chunk-5P5AAXYA.js";
254
+ } from "./chunk-7U6AB7DZ.js";
251
255
  import {
252
256
  NOYDB_FORMAT_VERSION,
253
257
  SealedHandle
254
- } from "./chunk-5BHNQNBI.js";
258
+ } from "./chunk-YTW6ZIPD.js";
255
259
  import {
256
260
  AlreadyElevatedError,
257
261
  AttestationError,
@@ -260,7 +264,6 @@ import {
260
264
  ClassifiedVerifyError,
261
265
  ConflictError,
262
266
  DebugPlaintextError,
263
- DerivationCapExceededError,
264
267
  DictKeyInUseError,
265
268
  ElevationExpiredError,
266
269
  FieldNotQueryableError,
@@ -291,11 +294,289 @@ import {
291
294
  UnsupportedIndexOptionError,
292
295
  UnsupportedTierCompositionError,
293
296
  ValidationError
294
- } from "./chunk-IGM563N5.js";
297
+ } from "./chunk-6SYOHUHM.js";
298
+
299
+ // src/via/blob/binding.ts
300
+ async function eraseBlobs(ctx, cfg) {
301
+ if (cfg.purgeBlobsForRecord) return cfg.purgeBlobsForRecord(ctx.id);
302
+ return { shredded: 0, residue: [] };
303
+ }
304
+ function buildBlobDescribeFragment(fields) {
305
+ return {
306
+ blobFields: Object.fromEntries(
307
+ Object.entries(fields).map(([field, p]) => [field, {
308
+ ...p.retainDays !== void 0 ? { retainDays: p.retainDays } : {},
309
+ ...p.evictWhen !== void 0 ? { evictWhen: true } : {},
310
+ ...p.legalHold !== void 0 ? { legalHold: true } : {},
311
+ ...p.retainUntil !== void 0 ? { retainUntil: true } : {},
312
+ ...p.external === true ? { external: true } : {},
313
+ ...p.public === true ? { public: true } : {},
314
+ ...p.backlink !== void 0 ? { backlink: p.backlink } : {}
315
+ }])
316
+ )
317
+ };
318
+ }
319
+ function blobBinding(cfg) {
320
+ return {
321
+ brand: "blob",
322
+ // encryptedAtRest: 'envelope' — blob chunks are AEAD-encrypted envelopes
323
+ // in `_blob_chunks` (service-side), not sealed record fields; queryable:
324
+ // 'none' — nothing indexes blob content; exportable — vault.exportBlobs()
325
+ // is a first-class door; forgettable — shredAllForRecord participates in
326
+ // vault.forget().
327
+ posture: { encryptedAtRest: "envelope", queryable: "none", exportable: true, forgettable: true },
328
+ covers: (field) => field in cfg.fields,
329
+ erase: (ctx) => eraseBlobs(ctx, cfg),
330
+ describeFragment: () => buildBlobDescribeFragment(cfg.fields)
331
+ };
332
+ }
333
+ function linkBlobVia() {
334
+ installViaBinder("blob", (c) => blobBinding(c));
335
+ }
336
+
337
+ // src/port/with/blob-strategy.ts
338
+ linkBlobVia();
339
+ var NO_BLOBS = {
340
+ openSlot() {
341
+ throw new Error(
342
+ 'Blob storage is not enabled on this Noydb instance. Import `{ withBlobs }` from "@noy-db/hub/blobs" and pass `withBlobs()` to `createNoydb({ blobStrategy: withBlobs() })`.'
343
+ );
344
+ }
345
+ };
346
+
347
+ // src/with-audit/consent/strategy.ts
348
+ var NO_CONSENT = {
349
+ async write() {
350
+ },
351
+ async read() {
352
+ return [];
353
+ }
354
+ };
355
+
356
+ // src/with-commit/crdt/strategy.ts
357
+ var NOT_ENABLED = new Error(
358
+ 'CRDT mode requires the CRDT strategy. Import `{ withCrdt }` from "@noy-db/hub/crdt" and pass it to `createNoydb({ crdtStrategy: withCrdt() })`.'
359
+ );
360
+ var NO_CRDT = {
361
+ buildLwwMapState() {
362
+ throw NOT_ENABLED;
363
+ },
364
+ buildRgaState() {
365
+ throw NOT_ENABLED;
366
+ },
367
+ mergeCrdtStates() {
368
+ throw NOT_ENABLED;
369
+ },
370
+ resolveCrdtSnapshot() {
371
+ throw NOT_ENABLED;
372
+ }
373
+ };
374
+
375
+ // src/with-commit/history/strategy.ts
376
+ function notEnabled(op) {
377
+ return new Error(
378
+ `${op} requires the history strategy. Import \`{ withHistory }\` from "@noy-db/hub/history" and pass it to \`createNoydb({ historyStrategy: withHistory() })\`.`
379
+ );
380
+ }
381
+ var NO_HISTORY = {
382
+ async saveHistory() {
383
+ },
384
+ async getHistoryEntries() {
385
+ throw notEnabled("collection.history()");
386
+ },
387
+ async getVersionEnvelope() {
388
+ throw notEnabled("collection.getVersion()");
389
+ },
390
+ async pruneHistory() {
391
+ return 0;
392
+ },
393
+ async clearHistory() {
394
+ return 0;
395
+ },
396
+ async tombstoneHistory() {
397
+ return 0;
398
+ },
399
+ async rewrapHistory() {
400
+ },
401
+ async envelopePayloadHash() {
402
+ return "";
403
+ },
404
+ computePatch() {
405
+ return [];
406
+ },
407
+ diff() {
408
+ throw notEnabled("collection.diff()");
409
+ },
410
+ buildLedger() {
411
+ return null;
412
+ },
413
+ buildVaultInstant() {
414
+ throw notEnabled("vault.at() / vault.timeMachine()");
415
+ }
416
+ };
417
+
418
+ // src/with-lookup/indexing/strategy.ts
419
+ var NO_INDEXING = {
420
+ createState() {
421
+ return DISABLED_STATE;
422
+ }
423
+ };
424
+ var DISABLED_STATE = {
425
+ isEnabled: false,
426
+ getEagerIndexes: () => null,
427
+ getPersistedIndexes: () => null
428
+ };
429
+
430
+ // src/with-audit/periods/strategy.ts
431
+ var NOT_ENABLED2 = new Error(
432
+ 'Accounting periods require the periods strategy. Import `{ withPeriods }` from "@noy-db/hub/periods" and pass it to `createNoydb({ periodsStrategy: withPeriods() })`.'
433
+ );
434
+ var NO_PERIODS = {
435
+ async loadPeriods() {
436
+ return [];
437
+ },
438
+ async chainAnchor() {
439
+ return { priorPeriodHash: "" };
440
+ },
441
+ assertTsWritable() {
442
+ },
443
+ validatePeriodName() {
444
+ throw NOT_ENABLED2;
445
+ },
446
+ async appendPeriodLedgerEntry() {
447
+ throw NOT_ENABLED2;
448
+ }
449
+ };
450
+
451
+ // src/with-party/session/strategy.ts
452
+ function notEnabled2(op) {
453
+ return new Error(
454
+ `${op} requires the session strategy. Import \`{ withSession }\` from "@noy-db/hub/session" and pass it to \`createNoydb({ sessionStrategy: withSession() })\`.`
455
+ );
456
+ }
457
+ var NO_SESSION = {
458
+ validateSessionPolicy() {
459
+ throw notEnabled2("sessionPolicy");
460
+ },
461
+ createEnforcer() {
462
+ throw notEnabled2("session policy enforcement");
463
+ },
464
+ revokeAllSessions() {
465
+ }
466
+ };
467
+
468
+ // src/with-fork/shadow/strategy.ts
469
+ var NOT_ENABLED3 = new Error(
470
+ 'VaultFrame requires the shadow strategy. Import `{ withShadow }` from "@noy-db/hub/shadow" and pass it to `createNoydb({ shadowStrategy: withShadow() })`.'
471
+ );
472
+ var NO_SHADOW = {
473
+ buildFrame() {
474
+ throw NOT_ENABLED3;
475
+ }
476
+ };
477
+
478
+ // src/with-fork/snapshots/strategy.ts
479
+ var NOT_ENABLED4 = new Error(
480
+ 'Snapshots require the snapshot strategy. Import `{ withSnapshots }` from "@noy-db/hub/snapshots" and pass it to `createNoydb({ snapshotStrategy: withSnapshots({ store }) })`.'
481
+ );
482
+ var NO_SNAPSHOTS = {
483
+ async snapshot() {
484
+ throw NOT_ENABLED4;
485
+ },
486
+ async listSnapshots() {
487
+ throw NOT_ENABLED4;
488
+ },
489
+ async restoreSnapshot() {
490
+ throw NOT_ENABLED4;
491
+ },
492
+ async autoSnapshot() {
493
+ throw NOT_ENABLED4;
494
+ }
495
+ };
496
+
497
+ // src/with-party/team/sync-strategy.ts
498
+ function notEnabled3(op) {
499
+ return new Error(
500
+ `${op} requires the sync strategy. Import \`{ withSync }\` from "@noy-db/hub/sync" and pass it to \`createNoydb({ syncStrategy: withSync() })\`.`
501
+ );
502
+ }
503
+ var NO_SYNC = {
504
+ buildSyncEngine() {
505
+ throw notEnabled3("SyncEngine");
506
+ },
507
+ buildSyncTransaction() {
508
+ throw notEnabled3("SyncTransaction");
509
+ },
510
+ buildPresence() {
511
+ throw notEnabled3("collection.presence()");
512
+ }
513
+ };
514
+
515
+ // src/with-commit/tx/strategy.ts
516
+ var NOT_ENABLED5 = new Error(
517
+ 'Multi-record transactions require the tx strategy. Import `{ withTransactions }` from "@noy-db/hub/tx" and pass it to `createNoydb({ txStrategy: withTransactions() })`.'
518
+ );
519
+ var NO_TX = {
520
+ async runTransaction(_db, _fn, _options, _txInvariants) {
521
+ throw NOT_ENABLED5;
522
+ },
523
+ async runDryRun() {
524
+ throw NOT_ENABLED5;
525
+ }
526
+ };
527
+
528
+ // src/port/with/archive-strategy.ts
529
+ var ARCHIVE_NOT_ENABLED = "vault.archive/restore/listArchived require `archiveStrategy: withArchive({ store })` in createNoydb";
530
+ var NO_ARCHIVE = {
531
+ get store() {
532
+ throw new Error(ARCHIVE_NOT_ENABLED);
533
+ }
534
+ };
535
+
536
+ // src/port/with/strategies.ts
537
+ var STRATEGY_DEFAULTS = {
538
+ aggregate: NO_AGGREGATE,
539
+ archive: NO_ARCHIVE,
540
+ attestation: NO_ATTESTATION,
541
+ blob: NO_BLOBS,
542
+ broker: NO_BROKER,
543
+ cargo: NO_CARGO,
544
+ classified: NO_CLASSIFIED,
545
+ consent: NO_CONSENT,
546
+ crdt: NO_CRDT,
547
+ custody: NO_CUSTODY,
548
+ forget: NO_FORGET,
549
+ history: NO_HISTORY,
550
+ i18n: NO_I18N,
551
+ index: NO_INDEXING,
552
+ lazy: IMPLICIT_LAZY,
553
+ periods: NO_PERIODS,
554
+ portability: NO_PORTABILITY,
555
+ sealedRecord: NO_SEALED_RECORD,
556
+ search: NO_SEARCH,
557
+ sequence: NO_SEQUENCE,
558
+ session: NO_SESSION,
559
+ shadow: NO_SHADOW,
560
+ snapshot: NO_SNAPSHOTS,
561
+ sync: NO_SYNC,
562
+ team: NO_TEAM,
563
+ tiers: NO_TIERS,
564
+ tx: NO_TX
565
+ };
566
+ var STRATEGY_KEYS = Object.keys(STRATEGY_DEFAULTS);
567
+ function resolveStrategies(options) {
568
+ const provided = options;
569
+ const resolved = { ...STRATEGY_DEFAULTS };
570
+ for (const key of STRATEGY_KEYS) {
571
+ const value = provided[`${key}Strategy`];
572
+ if (value !== void 0) resolved[key] = value;
573
+ }
574
+ return resolved;
575
+ }
295
576
 
296
577
  // src/port/by/default-provider.ts
297
578
  async function createDefaultCoordinationProvider(store) {
298
- const { StoreCoordinationProvider } = await import("./store-coordination-provider-3AELCZ4Y.js");
579
+ const { StoreCoordinationProvider } = await import("./store-coordination-provider-P3IU5JHD.js");
299
580
  return new StoreCoordinationProvider(store);
300
581
  }
301
582
 
@@ -964,61 +1245,6 @@ async function resolveTierSyncPrior(ctx, id, priorEnvelope) {
964
1245
  return await ctx.codec.decryptRecord(priorEnvelope, { skipValidation: true, id });
965
1246
  }
966
1247
 
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
- };
1009
-
1010
- // src/with-lookup/indexing/strategy.ts
1011
- var NO_INDEXING = {
1012
- createState() {
1013
- return DISABLED_STATE;
1014
- }
1015
- };
1016
- var DISABLED_STATE = {
1017
- isEnabled: false,
1018
- getEagerIndexes: () => null,
1019
- getPersistedIndexes: () => null
1020
- };
1021
-
1022
1248
  // src/with-lookup/search/serialize.ts
1023
1249
  function serializeIndex(idx) {
1024
1250
  return JSON.stringify(idx.toSnapshot());
@@ -1621,164 +1847,6 @@ function buildDescription(input) {
1621
1847
  };
1622
1848
  }
1623
1849
 
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
-
1672
- // src/with-formula/derivations/stale.ts
1673
- var _staleByRegistry = /* @__PURE__ */ new WeakMap();
1674
- var keyFor = (source, sourceId) => `${source}/${sourceId}`;
1675
- async function markStale(registry, strategy, sourceId) {
1676
- let map = _staleByRegistry.get(registry);
1677
- if (!map) {
1678
- map = /* @__PURE__ */ new Map();
1679
- _staleByRegistry.set(registry, map);
1680
- }
1681
- const k = keyFor(strategy.source, sourceId);
1682
- let set = map.get(k);
1683
- if (!set) {
1684
- set = /* @__PURE__ */ new Set();
1685
- map.set(k, set);
1686
- }
1687
- set.add(strategy);
1688
- }
1689
- async function resolveStaleOnRead(accessor, outputCollection, id) {
1690
- const registry = accessor.registry();
1691
- const producers = registry.strategiesProducingOutput(outputCollection);
1692
- if (producers.length === 0) return;
1693
- const map = _staleByRegistry.get(registry);
1694
- if (!map) return;
1695
- let DerivationExecutor = null;
1696
- for (const { spec, strategyHash } of producers) {
1697
- const k = keyFor(spec.source, id);
1698
- const pending = map.get(k);
1699
- if (!pending || !pending.has(spec)) continue;
1700
- const sourceColl = accessor.getCollection(spec.source);
1701
- const source = await sourceColl.get(id);
1702
- if (!source) {
1703
- pending.delete(spec);
1704
- continue;
1705
- }
1706
- const sourceWithId = { ...source, id };
1707
- if (DerivationExecutor === null) {
1708
- ({ DerivationExecutor } = await import("./executor-TEZYRDN3.js"));
1709
- }
1710
- const ctx = { vault: accessor.getReadOnlyFacade() };
1711
- const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx);
1712
- for (const key of Object.keys(spec.outputs)) {
1713
- const out = result.outputs[key];
1714
- if (!out) continue;
1715
- if (out.kind === "failed") {
1716
- const err = out.error;
1717
- if (spec.strict) {
1718
- throw err;
1719
- }
1720
- console.warn(
1721
- `[derivation] lazy output "${key}" for source "${spec.source}" id="${id}" failed:`,
1722
- err
1723
- );
1724
- continue;
1725
- }
1726
- if (out.kind === "array") {
1727
- console.warn(
1728
- `[derivation] unexpected array-shape output "${key}" in lazy resolve path; array-shape derivations require lifecycle: "eager".`
1729
- );
1730
- continue;
1731
- }
1732
- const outSpec = spec.outputs[key];
1733
- if (!outSpec) continue;
1734
- const outputColl = accessor.getCollection(outSpec.collection);
1735
- if (out.skipped === true) {
1736
- await outputColl._internalDelete(id, accessor.getActiveTxContext());
1737
- continue;
1738
- }
1739
- await outputColl.put(id, out.value);
1740
- }
1741
- pending.delete(spec);
1742
- }
1743
- }
1744
-
1745
- // src/with-commit/crdt/strategy.ts
1746
- var NOT_ENABLED = new Error(
1747
- 'CRDT mode requires the CRDT strategy. Import `{ withCrdt }` from "@noy-db/hub/crdt" and pass it to `createNoydb({ crdtStrategy: withCrdt() })`.'
1748
- );
1749
- var NO_CRDT = {
1750
- buildLwwMapState() {
1751
- throw NOT_ENABLED;
1752
- },
1753
- buildRgaState() {
1754
- throw NOT_ENABLED;
1755
- },
1756
- mergeCrdtStates() {
1757
- throw NOT_ENABLED;
1758
- },
1759
- resolveCrdtSnapshot() {
1760
- throw NOT_ENABLED;
1761
- }
1762
- };
1763
-
1764
- // src/with-party/team/sync-strategy.ts
1765
- function notEnabled2(op) {
1766
- return new Error(
1767
- `${op} requires the sync strategy. Import \`{ withSync }\` from "@noy-db/hub/sync" and pass it to \`createNoydb({ syncStrategy: withSync() })\`.`
1768
- );
1769
- }
1770
- var NO_SYNC = {
1771
- buildSyncEngine() {
1772
- throw notEnabled2("SyncEngine");
1773
- },
1774
- buildSyncTransaction() {
1775
- throw notEnabled2("SyncTransaction");
1776
- },
1777
- buildPresence() {
1778
- throw notEnabled2("collection.presence()");
1779
- }
1780
- };
1781
-
1782
1850
  // src/kernel/via/compose.ts
1783
1851
  function via(...descriptors) {
1784
1852
  if (descriptors.length === 0) {
@@ -1942,7 +2010,7 @@ function compileViaBindings(opts, classifiedGuardCtx, eraseCfgOut) {
1942
2010
  ...i18nFields !== void 0 ? { i18nFields } : {},
1943
2011
  ...dictKeyFields !== void 0 ? { dictKeyFields } : {},
1944
2012
  ...i18nDensifyFields !== void 0 ? { i18nDensifyFields } : {},
1945
- strategy: opts.i18nStrategy ?? NO_I18N,
2013
+ strategy: opts.strategies.i18n,
1946
2014
  ...opts.defaultLocale !== void 0 ? { defaultLocale: opts.defaultLocale } : {},
1947
2015
  ...opts.autoTranslateHook !== void 0 ? { autoTranslateHook: opts.autoTranslateHook } : {},
1948
2016
  ...opts.dictLabelResolver !== void 0 ? { dictLabelResolver: opts.dictLabelResolver } : {},
@@ -2177,14 +2245,9 @@ function resolveCollectionConfig(opts) {
2177
2245
  writeHooks: opts.writeHooks,
2178
2246
  subsystemBus: opts.subsystemBus,
2179
2247
  activeTxId: opts.activeTxId,
2180
- blobStrategy: opts.blobStrategy ?? NO_BLOBS,
2248
+ strategies: opts.strategies,
2181
2249
  objectStore: opts.objectStore,
2182
2250
  blobFields: opts.blobFields,
2183
- aggregateStrategy: opts.aggregateStrategy ?? NO_AGGREGATE,
2184
- crdtStrategy: opts.crdtStrategy ?? NO_CRDT,
2185
- historyStrategy: opts.historyStrategy ?? NO_HISTORY,
2186
- i18nStrategy: opts.i18nStrategy ?? NO_I18N,
2187
- syncStrategy: opts.syncStrategy ?? NO_SYNC,
2188
2251
  reconcileOnOpen: opts.reconcileOnOpen ?? "off",
2189
2252
  getDEK: opts.getDEK,
2190
2253
  onDirty: opts.onDirty,
@@ -2213,7 +2276,6 @@ function resolveCollectionConfig(opts) {
2213
2276
  moneyFields: effectiveViaFields.moneyFields,
2214
2277
  classified: resolvedClassified,
2215
2278
  classifiedGuardCtx,
2216
- classifiedStrategy: opts.classifiedStrategy ?? NO_CLASSIFIED,
2217
2279
  computed: mergedComputed,
2218
2280
  computedEdges,
2219
2281
  viaDepsEdges,
@@ -2235,8 +2297,6 @@ function resolveCollectionConfig(opts) {
2235
2297
  materializedViewSource: opts.materializedViewSource,
2236
2298
  graphDispatch: opts.graphDispatch,
2237
2299
  tiers: opts.tiers && opts.tiers.length > 0 ? new Set(opts.tiers) : null,
2238
- tiersStrategy: opts.tiersStrategy ?? NO_TIERS,
2239
- searchStrategy: opts.searchStrategy ?? NO_SEARCH,
2240
2300
  tierMode: opts.tierMode ?? "invisibility",
2241
2301
  blobTierPolicy: opts.blobTierPolicy ?? "isolate",
2242
2302
  onCrossTierAccess: opts.onCrossTierAccess,
@@ -2253,20 +2313,11 @@ function resolveCollectionConfig(opts) {
2253
2313
  // src/with-formula/computed/lazy.ts
2254
2314
  var fn = null;
2255
2315
  async function loadEvalComputedFields() {
2256
- fn ??= (await import("./computed-WZNKRLCY.js")).evalComputedFields;
2316
+ fn ??= (await import("./computed-33DRJDOC.js")).evalComputedFields;
2257
2317
  return fn;
2258
2318
  }
2259
2319
 
2260
2320
  // src/kernel/collection.ts
2261
- function selfWriteFieldEqual(a, b) {
2262
- if (a === b) return true;
2263
- if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
2264
- try {
2265
- return JSON.stringify(a) === JSON.stringify(b);
2266
- } catch {
2267
- return false;
2268
- }
2269
- }
2270
2321
  var fallbackWarned = /* @__PURE__ */ new Set();
2271
2322
  function warnOnceFallback(adapterName) {
2272
2323
  if (fallbackWarned.has(adapterName)) return;
@@ -2298,25 +2349,20 @@ var Collection = class {
2298
2349
  /** True when the caller explicitly provided a `historyConfig` option (vs. inheriting the vault default). */
2299
2350
  historyConfigExplicit;
2300
2351
  /**
2301
- * tree-shake seam — the strategy that backs `collection.blob(id)`.
2302
- * Defaults to `NO_BLOBS`, a ~10-line stub that throws with an actionable
2303
- * message. Consumers opt into real blob storage by importing
2304
- * `{ blobs }` from `@noy-db/hub/blobs` and passing the returned
2305
- * strategy to `createNoydb({ blobStrategy: blobs() })`. With the
2306
- * default stub, none of the BlobSet / chunk / MIME-magic machinery
2307
- * reaches the bundle.
2352
+ * Every opt-in service, resolved once by `createNoydb` (#838) and shared by
2353
+ * reference with the owning `Vault` and `Noydb`.
2354
+ *
2355
+ * Each entry is a tree-shake seam. An un-opted-in service resolves to its
2356
+ * `NO_*` stub — a tiny module that throws with an actionable message —
2357
+ * so, for example, none of the BlobSet / chunk / MIME-magic machinery
2358
+ * reaches the bundle unless the consumer imports `@noy-db/hub/blobs` and
2359
+ * passes `blobStrategy: blobs()` to `createNoydb`.
2308
2360
  */
2309
- blobStrategy;
2361
+ strategies;
2310
2362
  objectStore;
2311
2363
  blobFields;
2312
2364
  blobTierPolicy;
2313
2365
  // #724 T2/T3
2314
- aggregateStrategy;
2315
- crdtStrategy;
2316
- tiersStrategy;
2317
- searchStrategy;
2318
- historyStrategy;
2319
- syncStrategy;
2320
2366
  // In-memory cache of decrypted records (eager mode only). Lazy mode
2321
2367
  // uses `lru` instead. Both fields exist so a single Collection instance
2322
2368
  // doesn't need a runtime branch on every cache access.
@@ -2486,12 +2532,6 @@ var Collection = class {
2486
2532
  /** C-A/R10 memoization: marker declared-set lookup (undefined=unresolved) + classified-handle persist-once flag. */
2487
2533
  _markerDigestOnlyCache = void 0;
2488
2534
  _markerPersisted = false;
2489
- /**
2490
- * Tree-shake seam for `reveal()` — defaults to `NO_CLASSIFIED`, which
2491
- * throws `ClassifiedNotEnabledError`. Set via the `classifiedStrategy`
2492
- * `createNoydb()` option (opt in with `withClassified()`).
2493
- */
2494
- classifiedStrategy;
2495
2535
  /** Async callback provided by the Vault to open a dynamic dictionary handle (for label-map pre-computation in the search index). Only used in `resolveDictLabelMaps()`; static dicts bypass this entirely. Mutable, assign-once — see {@link _reconcileReadState} (#671 item 1). */
2496
2536
  getDictionary;
2497
2537
  /**
@@ -2640,16 +2680,10 @@ var Collection = class {
2640
2680
  this.writeHooks = cfg.writeHooks;
2641
2681
  this.subsystemBus = cfg.subsystemBus;
2642
2682
  this.activeTxId = cfg.activeTxId;
2643
- this.blobStrategy = cfg.blobStrategy;
2683
+ this.strategies = cfg.strategies;
2644
2684
  this.objectStore = cfg.objectStore;
2645
2685
  this.blobFields = cfg.blobFields;
2646
2686
  this.blobTierPolicy = cfg.blobTierPolicy ?? "isolate";
2647
- this.aggregateStrategy = cfg.aggregateStrategy;
2648
- this.crdtStrategy = cfg.crdtStrategy;
2649
- this.tiersStrategy = cfg.tiersStrategy;
2650
- this.searchStrategy = cfg.searchStrategy;
2651
- this.historyStrategy = cfg.historyStrategy;
2652
- this.syncStrategy = cfg.syncStrategy;
2653
2687
  this.reconcileOnOpen = cfg.reconcileOnOpen;
2654
2688
  this.getDEK = cfg.getDEK;
2655
2689
  this.onDirty = cfg.onDirty;
@@ -2676,7 +2710,6 @@ var Collection = class {
2676
2710
  this.classified = cfg.classified;
2677
2711
  this.classifiedGuardCtx = cfg.classifiedGuardCtx;
2678
2712
  this.vdigFields = cfg.vdigFields;
2679
- this.classifiedStrategy = cfg.classifiedStrategy;
2680
2713
  this.computed = cfg.computed;
2681
2714
  this.getDictionary = cfg.getDictionary;
2682
2715
  this.defaultLocale = cfg.defaultLocale;
@@ -2724,7 +2757,7 @@ var Collection = class {
2724
2757
  deterministicFields: this.deterministicFields,
2725
2758
  vdigFields: this.vdigFields,
2726
2759
  crdtMode: this.crdtMode,
2727
- crdtStrategy: this.crdtStrategy,
2760
+ crdtStrategy: this.strategies.crdt,
2728
2761
  schema: this.schema,
2729
2762
  getDEK: (collection) => this.getDEK(collection ?? this.name),
2730
2763
  cekCache: this.cekCache,
@@ -2742,7 +2775,7 @@ var Collection = class {
2742
2775
  const remoteJson = await this.codec.decryptJsonString(remote, id);
2743
2776
  if (localJson === null) return local;
2744
2777
  if (remoteJson === null) return remote;
2745
- const merged = this.crdtStrategy.mergeCrdtStates(JSON.parse(localJson), JSON.parse(remoteJson));
2778
+ const merged = this.strategies.crdt.mergeCrdtStates(JSON.parse(localJson), JSON.parse(remoteJson));
2746
2779
  const mergedVersion = Math.max(local._v, remote._v) + 1;
2747
2780
  const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
2748
2781
  return this.codec.encryptJsonString(JSON.stringify(merged), mergedVersion, cek);
@@ -2800,12 +2833,12 @@ var Collection = class {
2800
2833
  }
2801
2834
  this.lazy = opts.prefetch === false;
2802
2835
  if (this.lazy) {
2803
- this.lru = (opts.lazyStrategy ?? IMPLICIT_LAZY).createCache(this.name, opts.cache);
2836
+ this.lru = opts.strategies.lazy.createCache(this.name, opts.cache);
2804
2837
  this.hydrated = true;
2805
2838
  } else {
2806
2839
  this.lru = null;
2807
2840
  }
2808
- const strategy = opts.indexStrategy ?? NO_INDEXING;
2841
+ const strategy = opts.strategies.index;
2809
2842
  this.indexState = strategy.createState({
2810
2843
  defs: opts.indexes ?? [],
2811
2844
  lazy: this.lazy
@@ -2960,7 +2993,7 @@ var Collection = class {
2960
2993
  if (spec.storage === "digest-only") {
2961
2994
  throw new ClassifiedRevealError(this.name, field, `storage:'digest-only' \u2014 verify-only; nothing recoverable to reveal`);
2962
2995
  }
2963
- return this.classifiedStrategy.reveal({
2996
+ return this.strategies.classified.reveal({
2964
2997
  collection: this.name,
2965
2998
  spec,
2966
2999
  encrypted: this.storeCiphertext,
@@ -2980,7 +3013,7 @@ var Collection = class {
2980
3013
  throw new ClassifiedVerifyError(this.name, field, `storage:'never' \u2014 nothing is stored to verify against`);
2981
3014
  }
2982
3015
  const ctx = this._classifiedVerifyCtx(spec);
2983
- return spec.storage === "digest-only" ? this.classifiedStrategy.verify(ctx, id, field, candidate) : this.classifiedStrategy.verifyText(ctx, id, field, candidate);
3016
+ return spec.storage === "digest-only" ? this.strategies.classified.verify(ctx, id, field, candidate) : this.strategies.classified.verifyText(ctx, id, field, candidate);
2984
3017
  }
2985
3018
  /** k-of-n challenge over the collection's secretAnswer members. Requires withClassified(). */
2986
3019
  async verifyGroup(id, answers, opts) {
@@ -2989,7 +3022,7 @@ var Collection = class {
2989
3022
  throw new ClassifiedVerifyError(this.name, "*", "no groupable digest-only (secretAnswer) fields declared");
2990
3023
  }
2991
3024
  const ctx = { ...this._classifiedVerifyCtx(members[0].spec), groupMembers: members };
2992
- return this.classifiedStrategy.matchGroup(ctx, id, answers, opts);
3025
+ return this.strategies.classified.matchGroup(ctx, id, answers, opts);
2993
3026
  }
2994
3027
  _classifiedVerifyCtx(spec) {
2995
3028
  return {
@@ -3044,7 +3077,7 @@ var Collection = class {
3044
3077
  if (typeof candidate !== "string") {
3045
3078
  throw new ClassifiedVerifyError(this.name, "*", "candidate must be a string");
3046
3079
  }
3047
- const target = await this.classifiedStrategy.computeTarget(this._classifiedVerifyCtx(spec), field, candidate);
3080
+ const target = await this.strategies.classified.computeTarget(this._classifiedVerifyCtx(spec), field, candidate);
3048
3081
  const ids = await this.adapter.list(this.vault, this.name);
3049
3082
  const hits = [];
3050
3083
  const hitMap = /* @__PURE__ */ new Map();
@@ -3057,7 +3090,7 @@ var Collection = class {
3057
3090
  }
3058
3091
  await this.onAccess?.("find", "*");
3059
3092
  if (hits.length === 0) return [];
3060
- const { verifyDigestField } = await import("./verify-MXN66IIH.js");
3093
+ const { verifyDigestField } = await import("./verify-5X37OXRY.js");
3061
3094
  const policy = {
3062
3095
  normalize: spec.verifyNormalize ?? "password",
3063
3096
  notLastN: spec.notLastN ?? 0,
@@ -3131,7 +3164,7 @@ var Collection = class {
3131
3164
  id,
3132
3165
  version: scrubbed._v,
3133
3166
  actor: this.keyring.userId,
3134
- payloadHash: await this.historyStrategy.envelopePayloadHash(scrubbed),
3167
+ payloadHash: await this.strategies.history.envelopePayloadHash(scrubbed),
3135
3168
  reason: "classified:scrub-equatable-tags"
3136
3169
  });
3137
3170
  }
@@ -3263,7 +3296,7 @@ var Collection = class {
3263
3296
  }
3264
3297
  }
3265
3298
  if (this.materializedViewSource !== void 0) {
3266
- const { resolveStaleMVOnRead } = await import("./stale-4UNPHWOU.js");
3299
+ const { resolveStaleMVOnRead } = await import("./stale-NBROTA66.js");
3267
3300
  await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: "resolve-on-read" }));
3268
3301
  }
3269
3302
  let record;
@@ -3357,7 +3390,7 @@ var Collection = class {
3357
3390
  if (this.syncAdapter !== void 0) presenceOpts.syncAdapter = this.syncAdapter;
3358
3391
  if (opts?.staleMs !== void 0) presenceOpts.staleMs = opts.staleMs;
3359
3392
  if (opts?.pollIntervalMs !== void 0) presenceOpts.pollIntervalMs = opts.pollIntervalMs;
3360
- return this.syncStrategy.buildPresence(presenceOpts);
3393
+ return this.strategies.sync.buildPresence(presenceOpts);
3361
3394
  }
3362
3395
  /**
3363
3396
  * Create or update a record. Runs inside the hub's write-queue tracker
@@ -3519,6 +3552,103 @@ var Collection = class {
3519
3552
  return clone;
3520
3553
  }
3521
3554
  /** @internal Untracked put body — call {@link put}, not this. */
3555
+ /**
3556
+ * Decode a prior envelope's CRDT state, or `undefined` when there is no
3557
+ * usable prior: no envelope, a shredded body decrypting to `null`, or a
3558
+ * payload that is not a CRDT state. The `lww-map` and `rga` branches each
3559
+ * carried a copy, byte-identical apart from the cast (#842).
3560
+ */
3561
+ async #decodePriorCrdtState(envelope) {
3562
+ if (!envelope) return void 0;
3563
+ const prevJson = await this.codec.decryptJsonString(envelope);
3564
+ if (prevJson === null) return void 0;
3565
+ const prevParsed = JSON.parse(prevJson);
3566
+ if (prevParsed === null || typeof prevParsed !== "object" || !("_crdt" in prevParsed)) {
3567
+ return void 0;
3568
+ }
3569
+ return prevParsed;
3570
+ }
3571
+ /**
3572
+ * Record a write on the active transaction so a mid-batch failure rolls it
3573
+ * back. Four sites in the derivation/MV dispatch hand-built this literal (#842).
3574
+ */
3575
+ #trackPut(txCtx, collectionName, id, priorEnvelope) {
3576
+ txCtx._executed.push({
3577
+ op: { type: "put", vaultName: this.vault, collectionName, id },
3578
+ priorEnvelope
3579
+ });
3580
+ }
3581
+ /**
3582
+ * Snapshot the PRIOR version into history, emit, and prune.
3583
+ *
3584
+ * Deliberately does NOT carry `source` from the current write — a history
3585
+ * entry describes the version being replaced, not the one replacing it.
3586
+ *
3587
+ * Kept OUT of {@link #commitWriteTail} because the two paths call it at
3588
+ * different points: the normal path snapshots BEFORE `adapter.put` (so a
3589
+ * history failure leaves no write behind), while the CRDT path must merge
3590
+ * and persist first to resolve the prior record at all. Folding it into the
3591
+ * tail would silently reorder one of them (#842).
3592
+ */
3593
+ async #savePriorHistory(id, prior, cek, vdigCtx) {
3594
+ if (this.historyConfig.enabled === false) return;
3595
+ await this.strategies.history.saveHistory(
3596
+ this.adapter,
3597
+ this.vault,
3598
+ this.name,
3599
+ id,
3600
+ await this.codec.encryptRecord(prior.record, prior.version, cek, void 0, void 0, vdigCtx, id)
3601
+ );
3602
+ this.emitter.emit("history:save", { vault: this.vault, collection: this.name, id, version: prior.version });
3603
+ if (this.historyConfig.maxVersions) {
3604
+ await this.strategies.history.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
3605
+ }
3606
+ }
3607
+ /**
3608
+ * Everything both write paths do once the envelope is on the adapter:
3609
+ * classified marker, embedding sidecar, ledger append, cache/index
3610
+ * maintenance, and the mutation event that drives derivation dispatch.
3611
+ *
3612
+ * The CRDT branch used to re-implement all of it, and in doing so skipped
3613
+ * `_ensureClassifiedMarker`, the unique-constraint upsert and
3614
+ * `_toCacheableRecord` (#835). All three were unreachable — each blocked by
3615
+ * a config-time refusal on CRDT collections — but only by accident of what
3616
+ * that copy happened to omit. One tail makes the divergence unrepresentable
3617
+ * rather than merely unreachable; on a CRDT collection the extra steps are
3618
+ * provably no-ops (classified/unique + crdt are refused at construction, and
3619
+ * a CRDT body never produces a `_sealed` slot, so `_toCacheableRecord` is
3620
+ * the identity).
3621
+ */
3622
+ async #commitWriteTail(args) {
3623
+ const { id, envelope, version, indexed, event, prior, reason } = args;
3624
+ await this._ensureClassifiedMarker();
3625
+ if (this.embeddings) {
3626
+ await this.strategies.search.embedOnWrite(this.searchContext(), id, indexed, version);
3627
+ }
3628
+ if (this.ledger) {
3629
+ const appendInput = {
3630
+ op: "put",
3631
+ collection: this.name,
3632
+ id,
3633
+ version,
3634
+ actor: this.keyring.userId,
3635
+ payloadHash: await this.strategies.history.envelopePayloadHash(envelope)
3636
+ };
3637
+ if (prior) appendInput.delta = this.strategies.history.computePatch(indexed, prior.record);
3638
+ if (reason !== void 0) appendInput.reason = reason;
3639
+ await this.ledger.append(appendInput);
3640
+ }
3641
+ const cacheable = await this._toCacheableRecord(indexed, envelope, id);
3642
+ if (this.lazy && this.lru) {
3643
+ this.lru.set(id, { record: cacheable, version }, estimateRecordBytes(indexed));
3644
+ await this.maintainPersistedIndexesOnPut(id, indexed, prior ? prior.record : null, version);
3645
+ } else {
3646
+ this.cache.set(id, { record: cacheable, version });
3647
+ this.indexes?.upsert(id, indexed, prior ? prior.record : null);
3648
+ this.uniqueConstraints?.upsert(id, indexed, prior?.record);
3649
+ }
3650
+ await this._onRecordMutated(id, "put", "local-write", { record: event, version });
3651
+ }
3522
3652
  async _putInternal(id, record, options) {
3523
3653
  if (!hasWritePermission(this.keyring, this.name)) {
3524
3654
  throw new ReadOnlyError();
@@ -3567,29 +3697,11 @@ var Collection = class {
3567
3697
  const now = (/* @__PURE__ */ new Date()).toISOString();
3568
3698
  let crdtState;
3569
3699
  if (this.crdtMode === "lww-map") {
3570
- let existingState;
3571
- if (existingEnvelope) {
3572
- const prevJson = await this.codec.decryptJsonString(existingEnvelope);
3573
- if (prevJson !== null) {
3574
- const prevParsed = JSON.parse(prevJson);
3575
- if (prevParsed !== null && typeof prevParsed === "object" && "_crdt" in prevParsed) {
3576
- existingState = prevParsed;
3577
- }
3578
- }
3579
- }
3580
- crdtState = this.crdtStrategy.buildLwwMapState(record, existingState, now);
3700
+ const existingState = await this.#decodePriorCrdtState(existingEnvelope);
3701
+ crdtState = this.strategies.crdt.buildLwwMapState(record, existingState, now);
3581
3702
  } else if (this.crdtMode === "rga") {
3582
- let existingState;
3583
- if (existingEnvelope) {
3584
- const prevJson = await this.codec.decryptJsonString(existingEnvelope);
3585
- if (prevJson !== null) {
3586
- const prevParsed = JSON.parse(prevJson);
3587
- if (prevParsed !== null && typeof prevParsed === "object" && "_crdt" in prevParsed) {
3588
- existingState = prevParsed;
3589
- }
3590
- }
3591
- }
3592
- crdtState = this.crdtStrategy.buildRgaState(Array.isArray(record) ? record : [record], existingState, generateULID);
3703
+ const existingState = await this.#decodePriorCrdtState(existingEnvelope);
3704
+ crdtState = this.strategies.crdt.buildRgaState(Array.isArray(record) ? record : [record], existingState, generateULID);
3593
3705
  } else {
3594
3706
  crdtState = { _crdt: "yjs", update: record };
3595
3707
  }
@@ -3597,42 +3709,21 @@ var Collection = class {
3597
3709
  const cek2 = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
3598
3710
  const envelope2 = await this.codec.encryptJsonString(JSON.stringify(crdtState), version2, cek2, options?.source, options?.sourceTs);
3599
3711
  await this.adapter.put(this.vault, this.name, id, envelope2);
3600
- const resolvedRecord = this.crdtStrategy.resolveCrdtSnapshot(crdtState);
3712
+ const resolvedRecord = this.strategies.crdt.resolveCrdtSnapshot(crdtState);
3601
3713
  const existingResolvedRecord = existingEnvelope ? await this.codec.decryptRecord(existingEnvelope, { skipValidation: true }) : null;
3602
3714
  const existingResolved = existingResolvedRecord !== null ? { record: existingResolvedRecord, version: existingVersion } : void 0;
3603
- if (existingResolved && this.historyConfig.enabled !== false) {
3604
- 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));
3605
- this.emitter.emit("history:save", { vault: this.vault, collection: this.name, id, version: existingResolved.version });
3606
- if (this.historyConfig.maxVersions) {
3607
- await this.historyStrategy.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
3608
- }
3609
- }
3610
- if (this.ledger) {
3611
- const appendInput = {
3612
- op: "put",
3613
- collection: this.name,
3614
- id,
3615
- version: version2,
3616
- actor: this.keyring.userId,
3617
- payloadHash: await this.historyStrategy.envelopePayloadHash(envelope2)
3618
- };
3619
- if (existingResolved) appendInput.delta = this.historyStrategy.computePatch(resolvedRecord, existingResolved.record);
3620
- if (options?.reason !== void 0) appendInput.reason = options.reason;
3621
- await this.ledger.append(appendInput);
3622
- }
3623
- if (this.lazy && this.lru) {
3624
- this.lru.set(id, { record: resolvedRecord, version: version2 }, estimateRecordBytes(resolvedRecord));
3625
- await this.maintainPersistedIndexesOnPut(
3626
- id,
3627
- resolvedRecord,
3628
- existingResolved ? existingResolved.record : null,
3629
- version2
3630
- );
3631
- } else {
3632
- this.cache.set(id, { record: resolvedRecord, version: version2 });
3633
- this.indexes?.upsert(id, resolvedRecord, existingResolved ? existingResolved.record : null);
3715
+ if (existingResolved) {
3716
+ await this.#savePriorHistory(id, existingResolved, cek2, this.vdigFields !== null ? { id, prev: existingEnvelope } : void 0);
3634
3717
  }
3635
- await this._onRecordMutated(id, "put", "local-write", { record, version: version2 });
3718
+ await this.#commitWriteTail({
3719
+ id,
3720
+ envelope: envelope2,
3721
+ version: version2,
3722
+ indexed: resolvedRecord,
3723
+ event: record,
3724
+ prior: existingResolved,
3725
+ reason: options?.reason
3726
+ });
3636
3727
  return;
3637
3728
  }
3638
3729
  let existing;
@@ -3657,52 +3748,24 @@ var Collection = class {
3657
3748
  if (priorRaw === null && (this.markerIds.has(id) || this.tabCoordinated?.())) {
3658
3749
  priorRaw = await this.adapter.get(this.vault, this.name, id);
3659
3750
  }
3660
- if (priorRaw && isDeleteMarker(priorRaw)) version = priorRaw._v + 1;
3661
- }
3662
- this.uniqueConstraints?.check(id, record);
3663
- const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
3664
- const vdigCtx = this.vdigFields !== null ? { id, prev: await this.adapter.get(this.vault, this.name, id) } : void 0;
3665
- if (existing && this.historyConfig.enabled !== false) {
3666
- 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));
3667
- this.emitter.emit("history:save", {
3668
- vault: this.vault,
3669
- collection: this.name,
3670
- id,
3671
- version: existing.version
3672
- });
3673
- if (this.historyConfig.maxVersions) await this.historyStrategy.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
3674
- }
3675
- const envelope = await this.codec.encryptRecord(record, version, cek, options?.source, options?.sourceTs, vdigCtx, id);
3676
- await this.adapter.put(this.vault, this.name, id, envelope);
3677
- this.markerIds.delete(id);
3678
- await this._ensureClassifiedMarker();
3679
- if (this.embeddings) {
3680
- await this.searchStrategy.embedOnWrite(this.searchContext(), id, record, version);
3681
- }
3682
- if (this.ledger) {
3683
- const appendInput = {
3684
- op: "put",
3685
- collection: this.name,
3686
- id,
3687
- version,
3688
- actor: this.keyring.userId,
3689
- payloadHash: await this.historyStrategy.envelopePayloadHash(envelope)
3690
- };
3691
- if (existing) {
3692
- appendInput.delta = this.historyStrategy.computePatch(record, existing.record);
3693
- }
3694
- if (options?.reason !== void 0) appendInput.reason = options.reason;
3695
- await this.ledger.append(appendInput);
3696
- }
3697
- if (this.lazy && this.lru) {
3698
- this.lru.set(id, { record: await this._toCacheableRecord(record, envelope, id), version }, estimateRecordBytes(record));
3699
- await this.maintainPersistedIndexesOnPut(id, record, existing ? existing.record : null, version);
3700
- } else {
3701
- this.cache.set(id, { record: await this._toCacheableRecord(record, envelope, id), version });
3702
- this.indexes?.upsert(id, record, existing ? existing.record : null);
3703
- this.uniqueConstraints?.upsert(id, record, existing?.record);
3751
+ if (priorRaw && isDeleteMarker(priorRaw)) version = priorRaw._v + 1;
3704
3752
  }
3705
- await this._onRecordMutated(id, "put", "local-write", { record, version });
3753
+ this.uniqueConstraints?.check(id, record);
3754
+ const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
3755
+ const vdigCtx = this.vdigFields !== null ? { id, prev: await this.adapter.get(this.vault, this.name, id) } : void 0;
3756
+ if (existing) await this.#savePriorHistory(id, existing, cek, vdigCtx);
3757
+ const envelope = await this.codec.encryptRecord(record, version, cek, options?.source, options?.sourceTs, vdigCtx, id);
3758
+ await this.adapter.put(this.vault, this.name, id, envelope);
3759
+ this.markerIds.delete(id);
3760
+ await this.#commitWriteTail({
3761
+ id,
3762
+ envelope,
3763
+ version,
3764
+ indexed: record,
3765
+ event: record,
3766
+ prior: existing,
3767
+ reason: options?.reason
3768
+ });
3706
3769
  }
3707
3770
  /**
3708
3771
  * Fire registered MV strategies whose dependency set includes this
@@ -3719,34 +3782,8 @@ var Collection = class {
3719
3782
  */
3720
3783
  async dispatchMaterializedViews(id, record, wave) {
3721
3784
  if (this.materializedViewSource === void 0) return;
3722
- const incoming = record;
3723
- if (incoming && typeof incoming === "object" && "_materializedFrom" in incoming) return;
3724
- const registry = this.materializedViewSource.registry();
3725
- const mvs = registry.mvsForSource(this.name);
3726
- if (mvs.length === 0) return;
3727
- let executor = null;
3728
- let staleHelpers = null;
3729
- for (const reg of mvs) {
3730
- const mode = reg.spec.refresh;
3731
- if (mode === "eager") {
3732
- if (wave?.seen(`mv\0${reg.spec.name}`)) continue;
3733
- if (executor === null) {
3734
- ;
3735
- ({ MaterializedViewExecutor: executor } = await import("./executor-YORMIBWV.js"));
3736
- }
3737
- await executor.refresh(reg, {
3738
- getCollection: (name) => this.materializedViewSource.getCollection(name),
3739
- getActiveTxContext: () => this.materializedViewSource.getActiveTxContext(),
3740
- getQueryContext: () => this.materializedViewSource.getQueryContext(),
3741
- dispatchCtx: this.#dispatchCtx({ collection: this.name, id })
3742
- });
3743
- } else if (mode === "lazy") {
3744
- if (staleHelpers === null) {
3745
- staleHelpers = await import("./stale-4UNPHWOU.js");
3746
- }
3747
- staleHelpers.markMVStale(registry, reg.spec.name);
3748
- }
3749
- }
3785
+ const { dispatchMaterializedViews } = await import("./dispatch-SMXUO7W5.js");
3786
+ return dispatchMaterializedViews(this.#mvDispatchCtx(this.materializedViewSource), id, record, wave);
3750
3787
  }
3751
3788
  /**
3752
3789
  * Fire registered derivation strategies for this source collection.
@@ -3834,6 +3871,32 @@ var Collection = class {
3834
3871
  return out;
3835
3872
  }
3836
3873
  /** @internal — ctx for `putDerivedOutput`'s frozen-period skip+audit (#638 Task 5). */
3874
+ /** What `with-formula/materialized-views/dispatch.ts` needs from this collection (#842). */
3875
+ #mvDispatchCtx(materializedViewSource) {
3876
+ return {
3877
+ materializedViewSource,
3878
+ collectionName: this.name,
3879
+ dispatchCtx: (source) => this.#dispatchCtx(source)
3880
+ };
3881
+ }
3882
+ /**
3883
+ * What `with-formula/derivations/dispatch.ts` needs from this collection (#842).
3884
+ *
3885
+ * The return type is inferred, not annotated: importing `DerivationDeleteCtx`
3886
+ * would be a STATIC spine→service import, which `port-layering` rejects even
3887
+ * when it is type-only — the guard scans import statements, not their
3888
+ * erasure. The dynamic `import()` at the call site still types the argument.
3889
+ */
3890
+ #derivationDeleteCtx(derivationSource) {
3891
+ return {
3892
+ derivationSource,
3893
+ collectionName: this.name,
3894
+ adapter: this.adapter,
3895
+ vault: this.vault,
3896
+ getDEK: this.getDEK,
3897
+ storeCiphertext: this.storeCiphertext
3898
+ };
3899
+ }
3837
3900
  #dispatchCtx(source) {
3838
3901
  return { emit: (e, p) => this.emitter.emit(e, p), source, audit: ledgerAuditHook(this.ledger, this.keyring.userId) };
3839
3902
  }
@@ -3859,11 +3922,7 @@ var Collection = class {
3859
3922
  const patched = { ...base, [field]: newValue };
3860
3923
  const txCtx = this.derivationSource.getActiveTxContext();
3861
3924
  if (txCtx !== null) {
3862
- const prior = await this.adapter.get(this.vault, into, parentId);
3863
- txCtx._executed.push({
3864
- op: { type: "put", vaultName: this.vault, collectionName: into, id: parentId },
3865
- priorEnvelope: prior
3866
- });
3925
+ this.#trackPut(txCtx, into, parentId, await this.adapter.get(this.vault, into, parentId));
3867
3926
  }
3868
3927
  return putDerivedOutput(intoColl, parentId, patched, this.#dispatchCtx(source));
3869
3928
  }
@@ -3896,150 +3955,14 @@ var Collection = class {
3896
3955
  * dispatch wave's per-target dedup; `undefined` on the local-write path (byte-identical). */
3897
3956
  async dispatchDerivations(id, record, version, wave) {
3898
3957
  if (this.derivationSource === void 0) return;
3899
- const incoming = this.via ? this.via.canonicalizeStored(record) : record;
3900
- if (incoming && typeof incoming === "object" && "_derivedFrom" in incoming) return;
3901
- const registry = this.derivationSource.registry();
3902
- const strategies = registry.strategiesForSource(this.name);
3903
- if (strategies.length === 0) return;
3904
- let DerivationExecutor = null;
3905
- for (const { spec, strategyHash } of strategies) {
3906
- const mode = typeof spec.lifecycle === "string" ? spec.lifecycle : spec.lifecycle.mode;
3907
- if (spec.rollup) {
3908
- if (mode !== "eager") continue;
3909
- let parentId;
3910
- if (this.name === spec.rollup.from) {
3911
- const kv = incoming[spec.rollup.key];
3912
- parentId = typeof kv === "string" || typeof kv === "number" ? String(kv) : null;
3913
- } else {
3914
- parentId = id;
3915
- }
3916
- if (parentId !== null) await this.recomputeRollup(spec, parentId, { collection: this.name, id }, wave);
3917
- continue;
3918
- }
3919
- const isSource = spec.source === this.name;
3920
- const isSibling = !isSource && (spec.sources?.includes(this.name) ?? false);
3921
- const trigger = !isSource && !isSibling ? spec.triggerBy?.find((t) => t.collection === this.name) : void 0;
3922
- const runs = [];
3923
- if (isSource) {
3924
- runs.push({ input: { ...incoming, id }, base: incoming, runId: id, version });
3925
- } else if (isSibling) {
3926
- const p = await this.derivationSource.getCollection(spec.source).get(id);
3927
- if (p !== null && p !== void 0) {
3928
- const raw = await this.derivationSource.getCollection(spec.source)._getStoredRecord(id);
3929
- runs.push({ input: { ...p, id }, base: raw ?? p, runId: id, version: 0 });
3930
- }
3931
- } else if (trigger) {
3932
- const srcColl = this.derivationSource.getCollection(spec.source);
3933
- const ids = await srcColl._findMatchingIds(trigger.on, id);
3934
- if (trigger.maxFanout !== void 0 && ids.length > trigger.maxFanout) {
3935
- throw new DerivationCapExceededError(`triggerBy ${this.name}\u2192${spec.source}`, ids.length, trigger.maxFanout);
3936
- }
3937
- for (const sid of ids) {
3938
- const raw = await srcColl._getStoredRecord(sid);
3939
- if (raw === null) continue;
3940
- runs.push({ input: { ...raw, id: sid }, base: raw, runId: sid, version: 0 });
3941
- }
3942
- }
3943
- if (runs.length === 0) continue;
3944
- if (mode !== "eager") {
3945
- for (const run of runs) await markStale(registry, spec, run.runId);
3946
- continue;
3947
- }
3948
- if (DerivationExecutor === null) {
3949
- ({ DerivationExecutor } = await import("./executor-TEZYRDN3.js"));
3950
- }
3951
- for (const run of runs) {
3952
- const ctx = { vault: this.derivationSource.getReadOnlyFacade() };
3953
- const outCtx = this.#dispatchCtx({ collection: spec.source, id: run.runId });
3954
- const result = await DerivationExecutor.run(spec, run.input, run.version, strategyHash, ctx);
3955
- for (const key of Object.keys(spec.outputs)) {
3956
- const out = result.outputs[key];
3957
- if (!out) continue;
3958
- if (out.kind === "failed") {
3959
- const err = out.error;
3960
- if (spec.strict) throw err;
3961
- console.warn(`[derivation] output "${key}" for source "${spec.source}" id="${run.runId}" failed:`, err);
3962
- continue;
3963
- }
3964
- const outSpec = spec.outputs[key];
3965
- if (!outSpec) continue;
3966
- const outputCollection = this.derivationSource.getCollection(outSpec.collection);
3967
- const txCtx = this.derivationSource.getActiveTxContext();
3968
- if (out.kind === "array") {
3969
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-HJV3A7PM.js");
3970
- const prior = await loadFanoutSidecar(this.adapter, this.vault, spec.source, run.runId, key, this.getDEK, this.storeCiphertext);
3971
- const prevKeys = new Set(prior?.keys ?? []);
3972
- const newKeysList = out.entries.map((e) => e.key);
3973
- const newKeysSet = new Set(newKeysList);
3974
- for (const k of prevKeys) {
3975
- if (newKeysSet.has(k)) continue;
3976
- await outputCollection._internalDelete(k, txCtx);
3977
- }
3978
- for (const entry of out.entries) {
3979
- if (txCtx !== null) {
3980
- const priorEnvelope = await this.adapter.get(this.vault, outSpec.collection, entry.key);
3981
- txCtx._executed.push({
3982
- op: {
3983
- type: "put",
3984
- vaultName: this.vault,
3985
- collectionName: outSpec.collection,
3986
- id: entry.key
3987
- },
3988
- priorEnvelope
3989
- });
3990
- }
3991
- await putDerivedOutput(outputCollection, entry.key, entry.value, outCtx, { source: "derived" });
3992
- }
3993
- await saveFanoutSidecar(this.adapter, this.vault, {
3994
- source: spec.source,
3995
- sourceId: run.runId,
3996
- outputKey: key,
3997
- outputCollection: outSpec.collection,
3998
- keys: newKeysList
3999
- }, this.getDEK, this.storeCiphertext);
4000
- continue;
4001
- }
4002
- if (out.skipped === true) {
4003
- await outputCollection._internalDelete(run.runId, txCtx);
4004
- continue;
4005
- }
4006
- if (outSpec.shape === "record" && outSpec.denorm !== void 0 && outSpec.collection === spec.source) {
4007
- const value = out.value;
4008
- const patched = { ...run.base };
4009
- let changed = false;
4010
- for (const f of outSpec.denorm) {
4011
- if (!selfWriteFieldEqual(run.base[f], value[f])) {
4012
- patched[f] = value[f];
4013
- changed = true;
4014
- }
4015
- }
4016
- if (!changed) continue;
4017
- if (txCtx !== null) {
4018
- const prior = await this.adapter.get(this.vault, outSpec.collection, run.runId);
4019
- txCtx._executed.push({
4020
- op: { type: "put", vaultName: this.vault, collectionName: outSpec.collection, id: run.runId },
4021
- priorEnvelope: prior
4022
- });
4023
- }
4024
- await putDerivedOutput(outputCollection, run.runId, patched, outCtx, { source: "derived" });
4025
- continue;
4026
- }
4027
- if (txCtx !== null) {
4028
- const prior = await this.adapter.get(this.vault, outSpec.collection, run.runId);
4029
- txCtx._executed.push({
4030
- op: {
4031
- type: "put",
4032
- vaultName: this.vault,
4033
- collectionName: outSpec.collection,
4034
- id: run.runId
4035
- },
4036
- priorEnvelope: prior
4037
- });
4038
- }
4039
- await putDerivedOutput(outputCollection, run.runId, out.value, outCtx, { source: "derived" });
4040
- }
4041
- }
4042
- }
3958
+ const { dispatchDerivations } = await import("./dispatch-PKQQFDBT.js");
3959
+ return dispatchDerivations({
3960
+ ...this.#derivationDeleteCtx(this.derivationSource),
3961
+ via: this.via,
3962
+ recomputeRollup: (spec, parentId, source, w) => this.recomputeRollup(spec, parentId, source, w),
3963
+ dispatchCtx: (source) => this.#dispatchCtx(source),
3964
+ trackPut: (txCtx, collectionName, rid, prior) => this.#trackPut(txCtx, collectionName, rid, prior)
3965
+ }, id, record, version, wave);
4043
3966
  }
4044
3967
  /**
4045
3968
  * Delete a record by ID. Runs inside the hub's write-queue tracker
@@ -4208,10 +4131,10 @@ var Collection = class {
4208
4131
  if (existing && this.historyConfig.enabled !== false) {
4209
4132
  const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
4210
4133
  const prevForVdig = this.vdigFields !== null ? await this.adapter.get(this.vault, this.name, id) : null;
4211
- 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));
4134
+ await this.strategies.history.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));
4212
4135
  }
4213
4136
  const previousEnvelope = await this.adapter.get(this.vault, this.name, id);
4214
- const previousPayloadHash = await this.historyStrategy.envelopePayloadHash(previousEnvelope);
4137
+ const previousPayloadHash = await this.strategies.history.envelopePayloadHash(previousEnvelope);
4215
4138
  let markerVersion;
4216
4139
  if (this.onDirty) {
4217
4140
  const live = previousEnvelope;
@@ -4309,33 +4232,8 @@ var Collection = class {
4309
4232
  */
4310
4233
  async dispatchArrayDerivationsOnDelete(id, eraseRecordShapeToo = false) {
4311
4234
  if (this.derivationSource === void 0) return 0;
4312
- const registry = this.derivationSource.registry();
4313
- const strategies = registry.strategiesForSource(this.name);
4314
- if (strategies.length === 0) return 0;
4315
- let helpers = null;
4316
- const txCtx = this.derivationSource.getActiveTxContext();
4317
- let erased = 0;
4318
- for (const { spec } of strategies) {
4319
- for (const [outputKey, outSpec] of Object.entries(spec.outputs)) {
4320
- if (outSpec.shape === "record") {
4321
- if (eraseRecordShapeToo && spec.source === this.name && outSpec.collection !== this.name) {
4322
- if (await this.derivationSource.getCollection(outSpec.collection)._internalDelete(id, txCtx)) erased += 1;
4323
- }
4324
- continue;
4325
- }
4326
- if (helpers === null) {
4327
- helpers = await import("./fanout-sidecar-HJV3A7PM.js");
4328
- }
4329
- const sidecar = await helpers.loadFanoutSidecar(this.adapter, this.vault, spec.source, id, outputKey, this.getDEK, this.storeCiphertext);
4330
- if (!sidecar) continue;
4331
- const outputCollection = this.derivationSource.getCollection(outSpec.collection);
4332
- for (const derivedId of sidecar.keys) {
4333
- if (await outputCollection._internalDelete(derivedId, txCtx)) erased += 1;
4334
- }
4335
- await helpers.deleteFanoutSidecar(this.adapter, this.vault, spec.source, id, outputKey);
4336
- }
4337
- }
4338
- return erased;
4235
+ const { dispatchArrayDerivationsOnDelete } = await import("./dispatch-PKQQFDBT.js");
4236
+ return dispatchArrayDerivationsOnDelete(this.#derivationDeleteCtx(this.derivationSource), id, eraseRecordShapeToo);
4339
4237
  }
4340
4238
  /**
4341
4239
  * Mirror of {@link dispatchMaterializedViews} for the delete/forget path — no `_materializedFrom`
@@ -4348,41 +4246,8 @@ var Collection = class {
4348
4246
  */
4349
4247
  async dispatchMaterializedViewsOnDelete(id) {
4350
4248
  if (this.materializedViewSource === void 0) return { deleted: 0, residueUndecodable: [], residueDeclined: [] };
4351
- const registry = this.materializedViewSource.registry();
4352
- const mvs = registry.mvsForSource(this.name);
4353
- if (mvs.length === 0) return { deleted: 0, residueUndecodable: [], residueDeclined: [] };
4354
- let executor = null;
4355
- let staleHelpers = null;
4356
- let deleted = 0;
4357
- const residueUndecodable = [];
4358
- const residueDeclined = [];
4359
- for (const reg of mvs) {
4360
- const mode = reg.spec.refresh;
4361
- if (mode === "eager") {
4362
- if (executor === null) {
4363
- ;
4364
- ({ MaterializedViewExecutor: executor } = await import("./executor-YORMIBWV.js"));
4365
- }
4366
- const rr = await executor.refresh(reg, {
4367
- getCollection: (name) => this.materializedViewSource.getCollection(name),
4368
- getActiveTxContext: () => this.materializedViewSource.getActiveTxContext(),
4369
- getQueryContext: () => this.materializedViewSource.getQueryContext(),
4370
- dispatchCtx: this.#dispatchCtx({ collection: this.name, id })
4371
- });
4372
- deleted += rr.deleted;
4373
- residueUndecodable.push(...rr.residueUndecodable);
4374
- residueDeclined.push(...rr.residueDeclined);
4375
- } else {
4376
- if (staleHelpers === null) {
4377
- staleHelpers = await import("./stale-4UNPHWOU.js");
4378
- }
4379
- const inv = await staleHelpers.invalidateMVAtRest(this.materializedViewSource, reg, mode);
4380
- deleted += inv.deleted;
4381
- residueUndecodable.push(...inv.residueUndecodable.map((rid) => `${reg.outputCollection}:${rid}`));
4382
- residueDeclined.push(...inv.residueDeclined.map((rid) => `${reg.outputCollection}:${rid}`));
4383
- }
4384
- }
4385
- return { deleted, residueUndecodable, residueDeclined };
4249
+ const { dispatchMaterializedViewsOnDelete } = await import("./dispatch-SMXUO7W5.js");
4250
+ return dispatchMaterializedViewsOnDelete(this.#mvDispatchCtx(this.materializedViewSource), id);
4386
4251
  }
4387
4252
  /**
4388
4253
  * List all records in the collection.
@@ -4401,7 +4266,7 @@ var Collection = class {
4401
4266
  );
4402
4267
  }
4403
4268
  if (this.materializedViewSource !== void 0) {
4404
- const { resolveStaleMVOnRead } = await import("./stale-4UNPHWOU.js");
4269
+ const { resolveStaleMVOnRead } = await import("./stale-NBROTA66.js");
4405
4270
  await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: "resolve-on-read" }));
4406
4271
  }
4407
4272
  await this.ensureHydrated();
@@ -4422,28 +4287,28 @@ var Collection = class {
4422
4287
  * see `src/search/tokenize.ts` for the Thai/CJK caveat.
4423
4288
  */
4424
4289
  search(field, query, opts = {}) {
4425
- return this.searchStrategy.search(this.searchContext(), field, query, opts);
4290
+ return this.strategies.search.search(this.searchContext(), field, query, opts);
4426
4291
  }
4427
4292
  /** Force-persist the lexical index now — gated behind `searchStrategy: withSearch()`. */
4428
4293
  flushIndex() {
4429
- return this.searchStrategy.flushIndex(this.searchContext());
4294
+ return this.strategies.search.flushIndex(this.searchContext());
4430
4295
  }
4431
4296
  /** Pre-build the lexical index — gated behind `searchStrategy: withSearch()`. */
4432
4297
  warmIndex() {
4433
- return this.searchStrategy.warmIndex(this.searchContext());
4298
+ return this.strategies.search.warmIndex(this.searchContext());
4434
4299
  }
4435
4300
  /** Retrieval (lexical | semantic | hybrid) — gated behind `searchStrategy: withSearch()`. */
4436
4301
  retrieve(query, opts = {}) {
4437
- return this.searchStrategy.retrieve(this.searchContext(), query, opts);
4302
+ return this.strategies.search.retrieve(this.searchContext(), query, opts);
4438
4303
  }
4439
4304
  /** Raw-vector kNN — gated behind `searchStrategy: withSearch()`. */
4440
4305
  similarTo(vector, opts = {}) {
4441
- return this.searchStrategy.similarTo(this.searchContext(), vector, opts);
4306
+ return this.strategies.search.similarTo(this.searchContext(), vector, opts);
4442
4307
  }
4443
4308
  /** Opt-in bulk `_vec` re-derive (#788) — a plain collection has nothing to rebuild; gated behind `searchStrategy: withSearch()` otherwise. */
4444
4309
  rebuildEmbeddings() {
4445
4310
  if (!this.embeddings) return Promise.resolve({ rebuilt: 0, skipped: 0 });
4446
- return this.searchStrategy.rebuildEmbeddings(this.searchContext());
4311
+ return this.strategies.search.rebuildEmbeddings(this.searchContext());
4447
4312
  }
4448
4313
  /**
4449
4314
  * Bind the {@link SearchContext} the search/retrieval surface needs. The
@@ -4653,7 +4518,7 @@ var Collection = class {
4653
4518
  ...this.defaultLocale !== void 0 ? { defaultLocale: this.defaultLocale } : {},
4654
4519
  ...resolver.resolveDictSource ? { resolveDictSource: (field) => resolver.resolveDictSource(leftCollection, field) } : {}
4655
4520
  } : void 0;
4656
- return new Query(source, void 0, joinContext, this.aggregateStrategy);
4521
+ return new Query(source, void 0, joinContext, this.strategies.aggregate);
4657
4522
  }
4658
4523
  /**
4659
4524
  * Subscribe to every put/delete on this collection. Returns an
@@ -4767,7 +4632,7 @@ var Collection = class {
4767
4632
  // ─── History Methods ────────────────────────────────────────────
4768
4633
  /** Get version history for a record, newest first. */
4769
4634
  async history(id, options) {
4770
- const envelopes = await this.historyStrategy.getHistoryEntries(
4635
+ const envelopes = await this.strategies.history.getHistoryEntries(
4771
4636
  this.adapter,
4772
4637
  this.vault,
4773
4638
  this.name,
@@ -4799,7 +4664,7 @@ var Collection = class {
4799
4664
  * and re-put the records through the normal `put()` path.
4800
4665
  */
4801
4666
  async getVersion(id, version) {
4802
- const envelope = await this.historyStrategy.getVersionEnvelope(
4667
+ const envelope = await this.strategies.history.getVersionEnvelope(
4803
4668
  this.adapter,
4804
4669
  this.vault,
4805
4670
  this.name,
@@ -4824,7 +4689,7 @@ var Collection = class {
4824
4689
  */
4825
4690
  async diff(id, versionA, versionB) {
4826
4691
  const recordA = versionA === 0 ? null : await this.resolveVersion(id, versionA);
4827
- return this.historyStrategy.diff(recordA, versionB === void 0 || versionB === 0 ? versionB === 0 ? null : await this.resolveCurrentOrVersion(id) : await this.resolveVersion(id, versionB));
4692
+ return this.strategies.history.diff(recordA, versionB === void 0 || versionB === 0 ? versionB === 0 ? null : await this.resolveCurrentOrVersion(id) : await this.resolveVersion(id, versionB));
4828
4693
  }
4829
4694
  /** Resolve a version: try history first, then check if it's the current version. */
4830
4695
  async resolveVersion(id, version) {
@@ -4841,7 +4706,7 @@ var Collection = class {
4841
4706
  }
4842
4707
  /** Prune history entries for a record (or all records if id is undefined). */
4843
4708
  async pruneRecordHistory(id, options) {
4844
- const pruned = await this.historyStrategy.pruneHistory(
4709
+ const pruned = await this.strategies.history.pruneHistory(
4845
4710
  this.adapter,
4846
4711
  this.vault,
4847
4712
  this.name,
@@ -4860,7 +4725,7 @@ var Collection = class {
4860
4725
  }
4861
4726
  /** Clear all history for this collection (or a specific record). */
4862
4727
  async clearHistory(id) {
4863
- return this.historyStrategy.clearHistory(this.adapter, this.vault, this.name, id);
4728
+ return this.strategies.history.clearHistory(this.adapter, this.vault, this.name, id);
4864
4729
  }
4865
4730
  // ─── Core Methods ─────────────────────────────────────────────
4866
4731
  /**
@@ -5282,7 +5147,7 @@ var Collection = class {
5282
5147
  * vault-shared `_blob` DEK (enabling cross-collection deduplication).
5283
5148
  */
5284
5149
  blob(id) {
5285
- return this.blobStrategy.openSlot({
5150
+ return this.strategies.blob.openSlot({
5286
5151
  store: this.adapter,
5287
5152
  vault: this.vault,
5288
5153
  collection: this.name,
@@ -5554,14 +5419,14 @@ var Collection = class {
5554
5419
  /** C-A/R10: persist the classified marker once per classified handle (store I/O in config-drift.ts). */
5555
5420
  async _ensureClassifiedMarker() {
5556
5421
  if (this._markerPersisted || this.vdigFields === null) return;
5557
- const { persistClassifiedMarkerForFields } = await import("./classified-marker-7S5IEP6Q.js");
5422
+ const { persistClassifiedMarkerForFields } = await import("./classified-marker-52P3D72W.js");
5558
5423
  await persistClassifiedMarkerForFields(this.adapter, this.vault, this.name, this.vdigFields, await this.getDEK(this.name));
5559
5424
  this._markerPersisted = true;
5560
5425
  }
5561
5426
  /** C-A/R10 drift signal — the marker's declared digest-only set, memoized to one store read per handle (see config-drift.ts). */
5562
5427
  async _classifiedMarkerDigestOnly() {
5563
5428
  if (this._markerDigestOnlyCache !== void 0) return this._markerDigestOnlyCache;
5564
- const { readClassifiedMarkerDigestOnly } = await import("./classified-marker-7S5IEP6Q.js");
5429
+ const { readClassifiedMarkerDigestOnly } = await import("./classified-marker-52P3D72W.js");
5565
5430
  this._markerDigestOnlyCache = await readClassifiedMarkerDigestOnly(this.adapter, this.vault, this.name, await this.getDEK(this.name));
5566
5431
  return this._markerDigestOnlyCache;
5567
5432
  }
@@ -5603,23 +5468,23 @@ var Collection = class {
5603
5468
  // ─── Hierarchical Access ──────────────────────────
5604
5469
  /** tier-aware put — gated behind `tiersStrategy: withTiers()`. `searchResidue: true` = stuck search compensation (#774, mirroring #764's elevate/demote posture); the write itself always completes. */
5605
5470
  putAtTier(id, record, tier, opts) {
5606
- return this.tiersStrategy.putAtTier(this.tiersContext(), id, record, tier, opts);
5471
+ return this.strategies.tiers.putAtTier(this.tiersContext(), id, record, tier, opts);
5607
5472
  }
5608
5473
  /** tier-aware get — gated behind `tiersStrategy: withTiers()`. */
5609
5474
  getAtTier(id) {
5610
- return this.tiersStrategy.getAtTier(this.tiersContext(), id);
5475
+ return this.strategies.tiers.getAtTier(this.tiersContext(), id);
5611
5476
  }
5612
5477
  /** list ids grouped by the caller's readability — gated behind `withTiers()`. */
5613
5478
  listAtTier() {
5614
- return this.tiersStrategy.listAtTier(this.tiersContext());
5479
+ return this.strategies.tiers.listAtTier(this.tiersContext());
5615
5480
  }
5616
5481
  /** elevate a record to a higher tier — gated behind `withTiers()`. `searchResidue: true` = stuck search compensation (#764); the move itself always completes. */
5617
5482
  elevate(id, toTier) {
5618
- return this.tiersStrategy.elevate(this.tiersContext(), id, toTier);
5483
+ return this.strategies.tiers.elevate(this.tiersContext(), id, toTier);
5619
5484
  }
5620
5485
  /** demote a record to a lower tier — gated behind `withTiers()`. Same `searchResidue` posture as {@link elevate} (#764). */
5621
5486
  demote(id, toTier) {
5622
- return this.tiersStrategy.demote(this.tiersContext(), id, toTier);
5487
+ return this.strategies.tiers.demote(this.tiersContext(), id, toTier);
5623
5488
  }
5624
5489
  /**
5625
5490
  * 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.
@@ -5680,16 +5545,16 @@ var Collection = class {
5680
5545
  },
5681
5546
  syncIndexes: (id, rec, version, priorEnvelope) => syncTierIndexes(this.indexingContext(), id, rec, version, priorEnvelope),
5682
5547
  syncSearch: (id, rec, version) => syncTierSearch(this.searchContext(), id, rec, version),
5683
- syncHistory: async (id, fromDek, toDek) => this.historyStrategy.rewrapHistory(this.adapter, this.vault, this.name, id, fromDek, toDek, await this.getDEK(this.name)),
5548
+ syncHistory: async (id, fromDek, toDek) => this.strategies.history.rewrapHistory(this.adapter, this.vault, this.name, id, fromDek, toDek, await this.getDEK(this.name)),
5684
5549
  saveHistorySnapshot: async (id, envelope) => {
5685
5550
  if (this.historyConfig.enabled === false) return;
5686
- await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, envelope);
5551
+ await this.strategies.history.saveHistory(this.adapter, this.vault, this.name, id, envelope);
5687
5552
  this.emitter.emit("history:save", { vault: this.vault, collection: this.name, id, version: envelope._v });
5688
- if (this.historyConfig.maxVersions) await this.historyStrategy.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
5553
+ if (this.historyConfig.maxVersions) await this.strategies.history.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
5689
5554
  },
5690
- historyEnabled: this.historyConfig.enabled !== false && this.historyStrategy !== NO_HISTORY,
5555
+ historyEnabled: this.historyConfig.enabled !== false && this.strategies.history !== NO_HISTORY,
5691
5556
  // #728/#737: lets putAtTier skip decrypting `existing` when no real history strategy is wired
5692
- syncBlobs: (id, fromTier, toTier) => this.blobStrategy !== NO_BLOBS ? this.blob(id).syncTierMove(fromTier, toTier, this.blobTierPolicy) : Promise.resolve(),
5557
+ syncBlobs: (id, fromTier, toTier) => this.strategies.blob !== NO_BLOBS ? this.blob(id).syncTierMove(fromTier, toTier, this.blobTierPolicy) : Promise.resolve(),
5693
5558
  // #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
5694
5559
  syncLedger: async (id) => {
5695
5560
  await this.ledger?.purgeRecordDeltas(this.name, id);
@@ -6017,46 +5882,6 @@ var DeferredNumberingStore = class {
6017
5882
  }
6018
5883
  };
6019
5884
 
6020
- // src/with-fork/shadow/strategy.ts
6021
- var NOT_ENABLED2 = new Error(
6022
- 'VaultFrame requires the shadow strategy. Import `{ withShadow }` from "@noy-db/hub/shadow" and pass it to `createNoydb({ shadowStrategy: withShadow() })`.'
6023
- );
6024
- var NO_SHADOW = {
6025
- buildFrame() {
6026
- throw NOT_ENABLED2;
6027
- }
6028
- };
6029
-
6030
- // src/with-audit/consent/strategy.ts
6031
- var NO_CONSENT = {
6032
- async write() {
6033
- },
6034
- async read() {
6035
- return [];
6036
- }
6037
- };
6038
-
6039
- // src/with-audit/periods/strategy.ts
6040
- var NOT_ENABLED3 = new Error(
6041
- 'Accounting periods require the periods strategy. Import `{ withPeriods }` from "@noy-db/hub/periods" and pass it to `createNoydb({ periodsStrategy: withPeriods() })`.'
6042
- );
6043
- var NO_PERIODS = {
6044
- async loadPeriods() {
6045
- return [];
6046
- },
6047
- async chainAnchor() {
6048
- return { priorPeriodHash: "" };
6049
- },
6050
- assertTsWritable() {
6051
- },
6052
- validatePeriodName() {
6053
- throw NOT_ENABLED3;
6054
- },
6055
- async appendPeriodLedgerEntry() {
6056
- throw NOT_ENABLED3;
6057
- }
6058
- };
6059
-
6060
5885
  // src/with-audit/periods/vault-facade.ts
6061
5886
  var VaultPeriods = class {
6062
5887
  constructor(deps) {
@@ -6986,7 +6811,7 @@ var VaultLinks = class {
6986
6811
  // src/with-shape/links/lazy-handle.ts
6987
6812
  function makeLazyLinkSetHandle(d) {
6988
6813
  let engine = null;
6989
- const load = () => engine ??= import("./link-set-GNGGCFI4.js").then(
6814
+ const load = () => engine ??= import("./link-set-ZU4E5J5S.js").then(
6990
6815
  ({ LinkSet }) => new LinkSet(d.adapter, d.vault, d.name, d.spec, d.encrypted, d.getDEK, d.actor, d.emitter, d.endpointExists)
6991
6816
  );
6992
6817
  return {
@@ -7524,7 +7349,7 @@ function declareSatellite(ctx, collectionName, options, existingRegistry) {
7524
7349
  ctx.forEachSyncEngine((e) => e.remirrorPairResolvers([spec.base, spec.satellite]));
7525
7350
  const registry = reg;
7526
7351
  const baseSchema = ctx.getBaseSchema(spec.base);
7527
- void import("./post-register-A7HCFBP5.js").then((m) => m.postRegister(ctx.adapter, ctx.vaultName, spec, ctx.getDEK, baseSchema, registry)).catch(() => {
7352
+ void import("./post-register-XIAHB6KF.js").then((m) => m.postRegister(ctx.adapter, ctx.vaultName, spec, ctx.getDEK, baseSchema, registry)).catch(() => {
7528
7353
  });
7529
7354
  return reg;
7530
7355
  }
@@ -8041,6 +7866,43 @@ var VaultAttestation = class {
8041
7866
  };
8042
7867
 
8043
7868
  // src/kernel/vault.ts
7869
+ var COLLECTION_PASSTHROUGH_KEYS = [
7870
+ "indexes",
7871
+ "reconcileOnOpen",
7872
+ "prefetch",
7873
+ "cache",
7874
+ "schema",
7875
+ "conflictPolicy",
7876
+ "crdt",
7877
+ "deterministicFields",
7878
+ "acknowledgeDeterministicRisk",
7879
+ "acknowledgeEquatableRisk",
7880
+ "sensitive",
7881
+ "perRecordKeys",
7882
+ "provenance",
7883
+ "ramCiphertext",
7884
+ "tiers",
7885
+ "tierMode",
7886
+ "blobTierPolicy",
7887
+ "i18nFields",
7888
+ "embeddings",
7889
+ "textIndexes",
7890
+ "warmIndexOnOpen",
7891
+ "textIndexPersist",
7892
+ "moneyFields",
7893
+ "viaFields",
7894
+ "computed",
7895
+ "classifiedFields",
7896
+ "fieldMeta",
7897
+ "meta"
7898
+ ];
7899
+ function copyDefined(dst, src, keys) {
7900
+ if (src === void 0) return;
7901
+ for (const key of keys) {
7902
+ const value = src[key];
7903
+ if (value !== void 0) dst[key] = value;
7904
+ }
7905
+ }
8044
7906
  var Vault = class {
8045
7907
  adapter;
8046
7908
  /** The vault's name as passed to `openVault()`. Stable for the instance lifetime. */
@@ -8058,36 +7920,22 @@ var Vault = class {
8058
7920
  syncAdapter;
8059
7921
  getPurgeableTargets;
8060
7922
  historyConfig;
8061
- /** tree-shake seam for the optional blob service; `undefined` means "blobs are off for this
8062
- * vault" — every `collection.blob(id)` call throws with a pointer at `@noy-db/hub/blobs`. */
8063
- blobStrategy;
7923
+ /**
7924
+ * Every opt-in service, resolved once by `createNoydb` (#838). Shared by
7925
+ * reference with the owning `Noydb` and with every `Collection` this vault
7926
+ * opens, so all three always agree about which services are enabled.
7927
+ */
7928
+ strategies;
8064
7929
  objectStore;
8065
- /** Cold-storage archival strategy (the archive target store). */
8066
- archiveStrategy;
8067
7930
  /** Per-collection record archival policies. Indexed by collection name. */
8068
7931
  archiveRegistry = /* @__PURE__ */ new Map();
8069
- indexStrategy;
8070
- lazyStrategy;
8071
- aggregateStrategy;
8072
- crdtStrategy;
8073
- tiersStrategy;
8074
- searchStrategy;
8075
- /** Cargo (partition extraction) strategy — `NO_CARGO` (throwing) unless `withCargo()` was passed.
8076
- * Public so the `extractPartition` free function (which takes a `Vault`) routes through it. */
8077
- cargoStrategy;
8078
- brokerStrategy;
8079
- sealedRecordStrategy;
8080
- portabilityStrategy;
8081
- sequenceStrategy;
8082
- consentStrategy;
8083
7932
  periods;
8084
7933
  linksEnforcer;
8085
- shadowStrategy;
8086
- historyStrategy;
8087
- forgetStrategy;
8088
- i18nStrategy;
8089
- syncStrategy;
8090
- classifiedStrategy;
7934
+ /** Cargo (partition extraction) strategy — `NO_CARGO` (throwing) unless `withCargo()` was passed.
7935
+ * Public so the `extractPartition` free function (which takes a `Vault`) routes through it. */
7936
+ get cargoStrategy() {
7937
+ return this.strategies.cargo;
7938
+ }
8091
7939
  /** Per-vault guard registry; `null` until `_initGuards()` runs (or for vaults that never register
8092
7940
  * one) — the runtime class is dynamic-imported on demand to keep it out of the floor bundle. */
8093
7941
  guardRegistry = null;
@@ -8136,7 +7984,7 @@ var Vault = class {
8136
7984
  * @see docs/superpowers/specs/2026-06-17-fr6-deed-custodian-liberate-design.md
8137
7985
  */
8138
7986
  custody;
8139
- /** Re-derives an UnlockedKeyring from the adapter using the active user's passphrase; called by
7987
+ /** Re-derives an UnlockedKeyring from the adapter using the active user's secret; called by
8140
7988
  * `load()` after the on-disk keyring file has been replaced. Provided by Noydb at openVault()
8141
7989
  * time; `undefined` in tests that construct Vault directly (load() then skips the refresh). */
8142
7990
  reloadKeyring;
@@ -8269,23 +8117,10 @@ var Vault = class {
8269
8117
  this.onRegisterConflictResolver = opts.onRegisterConflictResolver;
8270
8118
  this.syncAdapter = opts.syncAdapter;
8271
8119
  this.getPurgeableTargets = opts.getPurgeableTargets ?? (() => []);
8272
- this.blobStrategy = opts.blobStrategy;
8120
+ this.strategies = opts.strategies;
8273
8121
  this.objectStore = opts.objectStore;
8274
- this.archiveStrategy = opts.archiveStrategy;
8275
- this.indexStrategy = opts.indexStrategy;
8276
- this.lazyStrategy = opts.lazyStrategy;
8277
- this.aggregateStrategy = opts.aggregateStrategy;
8278
- this.crdtStrategy = opts.crdtStrategy;
8279
- this.tiersStrategy = opts.tiersStrategy;
8280
- this.searchStrategy = opts.searchStrategy;
8281
- this.cargoStrategy = opts.cargoStrategy ?? NO_CARGO;
8282
- this.brokerStrategy = opts.brokerStrategy ?? NO_BROKER;
8283
- this.sealedRecordStrategy = opts.sealedRecordStrategy ?? NO_SEALED_RECORD;
8284
- this.portabilityStrategy = opts.portabilityStrategy ?? NO_PORTABILITY;
8285
- this.sequenceStrategy = opts.sequenceStrategy ?? NO_SEQUENCE;
8286
- this.consentStrategy = opts.consentStrategy ?? NO_CONSENT;
8287
8122
  this.periods = new VaultPeriods({
8288
- strategy: opts.periodsStrategy ?? NO_PERIODS,
8123
+ strategy: this.strategies.periods,
8289
8124
  adapter: this.adapter,
8290
8125
  vault: this.name,
8291
8126
  encrypted: this.encrypted,
@@ -8310,12 +8145,6 @@ var Vault = class {
8310
8145
  getActiveTxContext: () => this.noydb._activeTxContextOrNull,
8311
8146
  emitter: this.emitter
8312
8147
  });
8313
- this.shadowStrategy = opts.shadowStrategy ?? NO_SHADOW;
8314
- this.historyStrategy = opts.historyStrategy ?? NO_HISTORY;
8315
- this.forgetStrategy = opts.forgetStrategy ?? NO_FORGET;
8316
- this.i18nStrategy = opts.i18nStrategy ?? NO_I18N;
8317
- this.syncStrategy = opts.syncStrategy ?? NO_SYNC;
8318
- this.classifiedStrategy = opts.classifiedStrategy ?? NO_CLASSIFIED;
8319
8148
  this.graph = new ViaGraph();
8320
8149
  void opts.guardStrategies;
8321
8150
  this.historyConfig = opts.historyConfig ?? { enabled: true };
@@ -8330,19 +8159,19 @@ var Vault = class {
8330
8159
  getDEK: (collection) => this.getDEK(collection),
8331
8160
  role: () => this.keyring.role,
8332
8161
  getRawRecord: async (collection, recId) => await this.collection(collection).get(recId, { locale: "raw" })
8333
- }, opts.attestationStrategy ?? NO_ATTESTATION);
8162
+ }, this.strategies.attestation);
8334
8163
  this.user = this.noydb.userApiFactory({
8335
8164
  adapter: this.adapter,
8336
8165
  vaultName: this.name,
8337
8166
  writerKeyringId: this.keyring.userId,
8338
8167
  getDek: () => this.getDEK(USER_ENVELOPE_COLLECTION),
8339
8168
  checkGate: (gate, presented) => this.noydb.checkGate(this.name, gate, presented),
8340
- exportAccessible: (opts2) => this.portabilityStrategy.exportAccessibleData(this, opts2),
8341
- unilateralWithdraw: (opts2) => this.portabilityStrategy.withdrawAccessibleData(this, opts2),
8342
- requestWithdraw: (opts2) => this.portabilityStrategy.requestWithdrawal(this, opts2),
8343
- listWithdrawals: (opts2) => this.portabilityStrategy.listWithdrawalRequests(this, opts2),
8344
- approveWithdraw: (requestId, opts2) => this.portabilityStrategy.approveWithdrawal(this, requestId, opts2),
8345
- rejectWithdraw: (requestId, opts2) => this.portabilityStrategy.rejectWithdrawal(this, requestId, opts2)
8169
+ exportAccessible: (opts2) => this.strategies.portability.exportAccessibleData(this, opts2),
8170
+ unilateralWithdraw: (opts2) => this.strategies.portability.withdrawAccessibleData(this, opts2),
8171
+ requestWithdraw: (opts2) => this.strategies.portability.requestWithdrawal(this, opts2),
8172
+ listWithdrawals: (opts2) => this.strategies.portability.listWithdrawalRequests(this, opts2),
8173
+ approveWithdraw: (requestId, opts2) => this.strategies.portability.approveWithdrawal(this, requestId, opts2),
8174
+ rejectWithdraw: (requestId, opts2) => this.strategies.portability.rejectWithdrawal(this, requestId, opts2)
8346
8175
  });
8347
8176
  this.custody = new CustodyApi(
8348
8177
  (options, factors) => this.noydb.grantCustodian(this.name, options, factors),
@@ -8400,7 +8229,7 @@ var Vault = class {
8400
8229
  * dispatch reads/writes — from this vault's OWN privates, rather than passing `this` itself. */
8401
8230
  _viaReconcileCtx() {
8402
8231
  return {
8403
- i18nStrategy: this.i18nStrategy,
8232
+ i18nStrategy: this.strategies.i18n,
8404
8233
  locale: this.locale,
8405
8234
  translateText: this.translateText,
8406
8235
  i18nFieldRegistry: this.i18nFieldRegistry,
@@ -8441,7 +8270,7 @@ var Vault = class {
8441
8270
  this.satelliteRegistry = declareSatellite({
8442
8271
  adapter: this.adapter,
8443
8272
  vaultName: this.name,
8444
- forgetSubjects: this.forgetStrategy.subjects,
8273
+ forgetSubjects: this.strategies.forget.subjects,
8445
8274
  getDEK: this.getDEK,
8446
8275
  getBaseSchema: (base) => this.collectionCache.get(base)?.getSchema(),
8447
8276
  getBaseCrdt: (base) => this.collectionCache.get(base)?.getConfig()?.crdt,
@@ -8520,7 +8349,7 @@ var Vault = class {
8520
8349
  const strategies = options.schemaUpdate ?? [];
8521
8350
  const work = (async () => {
8522
8351
  const dek = await this.getDEK(collectionName);
8523
- const { persistSchemaIfNeeded } = await import("./register-YBMRLZLO.js");
8352
+ const { persistSchemaIfNeeded } = await import("./register-HB4TQZSV.js");
8524
8353
  const result = await persistSchemaIfNeeded({
8525
8354
  store: this.adapter,
8526
8355
  vault: this.name,
@@ -8561,22 +8390,9 @@ var Vault = class {
8561
8390
  // #693: re-create gate fallback
8562
8391
  historyConfig: effectiveHistoryConfig,
8563
8392
  historyConfigExplicit: options?.historyConfig !== void 0,
8564
- // thread the vault-wide blob strategy into every
8565
- // collection. `undefined` is intentionally preserved so the
8566
- // Collection constructor uses its NO_BLOBS default.
8567
- ...this.blobStrategy !== void 0 ? { blobStrategy: this.blobStrategy } : {},
8568
8393
  ...this.objectStore !== void 0 ? { objectStore: this.objectStore } : {},
8569
8394
  ...options?.blobFields !== void 0 ? { blobFields: options.blobFields } : {},
8570
- ...this.indexStrategy !== void 0 ? { indexStrategy: this.indexStrategy } : {},
8571
- ...this.lazyStrategy !== void 0 ? { lazyStrategy: this.lazyStrategy } : {},
8572
- ...this.aggregateStrategy !== void 0 ? { aggregateStrategy: this.aggregateStrategy } : {},
8573
- ...this.crdtStrategy !== void 0 ? { crdtStrategy: this.crdtStrategy } : {},
8574
- ...this.tiersStrategy !== void 0 ? { tiersStrategy: this.tiersStrategy } : {},
8575
- ...this.searchStrategy !== void 0 ? { searchStrategy: this.searchStrategy } : {},
8576
- historyStrategy: this.historyStrategy,
8577
- i18nStrategy: this.i18nStrategy,
8578
- syncStrategy: this.syncStrategy,
8579
- classifiedStrategy: this.classifiedStrategy,
8395
+ strategies: this.strategies,
8580
8396
  // Per-collection ledger opt-out: when this collection sets
8581
8397
  // `historyConfig.ledger: false`, withhold the ledger reference so all
8582
8398
  // four `if (this.ledger)` append sites in Collection no-op. The chain
@@ -8614,27 +8430,8 @@ var Vault = class {
8614
8430
  }
8615
8431
  } : {}
8616
8432
  };
8617
- if (options?.indexes !== void 0) collOpts.indexes = options.indexes;
8618
- if (options?.reconcileOnOpen !== void 0) collOpts.reconcileOnOpen = options.reconcileOnOpen;
8619
- if (options?.prefetch !== void 0) collOpts.prefetch = options.prefetch;
8620
- if (options?.cache !== void 0) collOpts.cache = options.cache;
8621
- if (options?.schema !== void 0) collOpts.schema = options.schema;
8622
- if (options?.conflictPolicy !== void 0) collOpts.conflictPolicy = options.conflictPolicy;
8623
- if (options?.crdt !== void 0) collOpts.crdt = options.crdt;
8624
- if (options?.deterministicFields !== void 0) {
8625
- collOpts.deterministicFields = options.deterministicFields;
8626
- }
8627
- if (options?.acknowledgeDeterministicRisk !== void 0) {
8628
- collOpts.acknowledgeDeterministicRisk = options.acknowledgeDeterministicRisk;
8629
- }
8630
- if (options?.acknowledgeEquatableRisk !== void 0) {
8631
- collOpts.acknowledgeEquatableRisk = options.acknowledgeEquatableRisk;
8632
- }
8633
- if (options?.sensitive !== void 0) {
8634
- collOpts.sensitive = options.sensitive;
8635
- }
8636
- if (options?.perRecordKeys !== void 0) collOpts.perRecordKeys = options.perRecordKeys;
8637
- const subjectKey = this.forgetStrategy.subjects[collectionName];
8433
+ copyDefined(collOpts, options, COLLECTION_PASSTHROUGH_KEYS);
8434
+ const subjectKey = this.strategies.forget.subjects[collectionName];
8638
8435
  if (subjectKey !== void 0) {
8639
8436
  if (options?.perRecordKeys === false) {
8640
8437
  console.warn(
@@ -8648,22 +8445,8 @@ var Vault = class {
8648
8445
  if (value !== void 0 && value !== null) await this._addSubjectRef(coerceSubjectId(value), { collection: collectionName, id });
8649
8446
  };
8650
8447
  }
8651
- if (options?.provenance !== void 0) collOpts.provenance = options.provenance;
8652
- if (options?.ramCiphertext !== void 0) collOpts.ramCiphertext = options.ramCiphertext;
8653
- if (options?.tiers !== void 0) collOpts.tiers = options.tiers;
8654
- if (options?.tierMode !== void 0) collOpts.tierMode = options.tierMode;
8655
- if (options?.blobTierPolicy !== void 0) collOpts.blobTierPolicy = options.blobTierPolicy;
8656
8448
  collOpts.onCrossTierAccess = (event) => this.emitCrossTier(event);
8657
8449
  if (this.syncAdapter !== void 0) collOpts.syncAdapter = this.syncAdapter;
8658
- if (options?.i18nFields !== void 0) collOpts.i18nFields = options.i18nFields;
8659
- if (options?.embeddings !== void 0) collOpts.embeddings = options.embeddings;
8660
- if (options?.textIndexes !== void 0) collOpts.textIndexes = options.textIndexes;
8661
- if (options?.warmIndexOnOpen !== void 0) collOpts.warmIndexOnOpen = options.warmIndexOnOpen;
8662
- if (options?.textIndexPersist !== void 0) collOpts.textIndexPersist = options.textIndexPersist;
8663
- if (options?.moneyFields !== void 0) collOpts.moneyFields = options.moneyFields;
8664
- if (options?.viaFields !== void 0) collOpts.viaFields = options.viaFields;
8665
- if (options?.computed !== void 0) collOpts.computed = options.computed;
8666
- if (options?.classifiedFields !== void 0) collOpts.classifiedFields = options.classifiedFields;
8667
8450
  if (effectiveViaFields.dictKeyFields !== void 0 || effectiveViaFields.lookupFields !== void 0) {
8668
8451
  collOpts.dictLabelResolver = async (dictName, key, locale, fallback) => {
8669
8452
  const stat = this.staticByName.get(dictName);
@@ -8697,10 +8480,6 @@ var Vault = class {
8697
8480
  if (effectiveViaFields.i18nFields !== void 0 && this.translateText) {
8698
8481
  collOpts.autoTranslateHook = this.translateText;
8699
8482
  }
8700
- if (options?.fieldMeta !== void 0) {
8701
- collOpts.fieldMeta = options.fieldMeta;
8702
- }
8703
- if (options?.meta !== void 0) collOpts.meta = options.meta;
8704
8483
  if (options?.refs !== void 0) {
8705
8484
  collOpts.declaredRefs = this.refRegistry.getOutbound(collectionName);
8706
8485
  }
@@ -8719,7 +8498,7 @@ var Vault = class {
8719
8498
  const work = (async () => {
8720
8499
  try {
8721
8500
  const dek = await this.getDEK(collectionName);
8722
- await (await import("./register-YBMRLZLO.js")).persistSchemaIfNeeded({
8501
+ await (await import("./register-HB4TQZSV.js")).persistSchemaIfNeeded({
8723
8502
  store: this.adapter,
8724
8503
  vault: this.name,
8725
8504
  collectionName,
@@ -9015,7 +8794,7 @@ var Vault = class {
9015
8794
  const values = getAtPath(obj, field);
9016
8795
  for (const value of values) {
9017
8796
  if (value === void 0 || value === null) continue;
9018
- this.i18nStrategy.validateI18nTextValue(value, field, descriptor);
8797
+ this.strategies.i18n.validateI18nTextValue(value, field, descriptor);
9019
8798
  }
9020
8799
  }
9021
8800
  }
@@ -9056,7 +8835,7 @@ var Vault = class {
9056
8835
  this.reservedLookupCollections.set(dictCollectionName(name), name);
9057
8836
  let handle = this.dictionaryCache.get(name);
9058
8837
  if (!handle) {
9059
- handle = this.i18nStrategy.buildDictionaryHandle({
8838
+ handle = this.strategies.i18n.buildDictionaryHandle({
9060
8839
  adapter: this.adapter,
9061
8840
  compartmentName: this.name,
9062
8841
  dictionaryName: name,
@@ -9217,7 +8996,7 @@ var Vault = class {
9217
8996
  * is re-keyed for distinct recipients.
9218
8997
  *
9219
8998
  * Each recipient becomes its own `KeyringFile` sealed with that
9220
- * recipient's passphrase. The DEKs wrapped into each slot are
8999
+ * recipient's secret. The DEKs wrapped into each slot are
9221
9000
  * exactly those the recipient's role + permissions justify, and
9222
9001
  * never wider than the source keyring's own DEK set
9223
9002
  * (privilege-escalation check).
@@ -9269,7 +9048,7 @@ var Vault = class {
9269
9048
  };
9270
9049
  }
9271
9050
  if (!this.sequenceStore) {
9272
- this.sequenceStore = this.sequenceStrategy.createStore({
9051
+ this.sequenceStore = this.strategies.sequence.createStore({
9273
9052
  adapter: this.adapter,
9274
9053
  vault: this.name,
9275
9054
  encrypted: this.encrypted,
@@ -9367,7 +9146,7 @@ var Vault = class {
9367
9146
  return runListArchived(this._archiveContext(), collection);
9368
9147
  }
9369
9148
  _archiveContext() {
9370
- const strategy = this.archiveStrategy;
9149
+ const strategy = this.strategies.archive;
9371
9150
  if (!strategy) {
9372
9151
  throw new Error(
9373
9152
  "vault.archive/restore/listArchived require `archiveStrategy: withArchive({ store })` in createNoydb"
@@ -9534,7 +9313,7 @@ var Vault = class {
9534
9313
  */
9535
9314
  getLedgerOrNull() {
9536
9315
  if (!this.ledgerStore) {
9537
- this.ledgerStore = this.historyStrategy.buildLedger({
9316
+ this.ledgerStore = this.strategies.history.buildLedger({
9538
9317
  adapter: this.adapter,
9539
9318
  vault: this.name,
9540
9319
  encrypted: this.encrypted,
@@ -9559,7 +9338,7 @@ var Vault = class {
9559
9338
  * number of distinct subjects re-indexed.
9560
9339
  */
9561
9340
  async rebuildSubjectIndex() {
9562
- if (Object.keys(this.forgetStrategy.subjects).length === 0) {
9341
+ if (Object.keys(this.strategies.forget.subjects).length === 0) {
9563
9342
  throw new ForgetStrategyNotConfiguredError();
9564
9343
  }
9565
9344
  return rebuildSubjectIndex(
@@ -9567,7 +9346,7 @@ var Vault = class {
9567
9346
  this.name,
9568
9347
  this.getDEK,
9569
9348
  this.encrypted,
9570
- this.forgetStrategy.subjects,
9349
+ this.strategies.forget.subjects,
9571
9350
  async (collectionName, id, env) => {
9572
9351
  const coll = this.collection(collectionName);
9573
9352
  return coll._decodeEnvelope(env, id);
@@ -9592,7 +9371,7 @@ var Vault = class {
9592
9371
  * @throws ForgetStrategyNotConfiguredError when no `withForgetCascade` was set.
9593
9372
  */
9594
9373
  async forget(subjectId) {
9595
- if (Object.keys(this.forgetStrategy.subjects).length === 0) {
9374
+ if (Object.keys(this.strategies.forget.subjects).length === 0) {
9596
9375
  throw new ForgetStrategyNotConfiguredError();
9597
9376
  }
9598
9377
  const ledger = this.getLedgerOrNull();
@@ -9614,17 +9393,17 @@ var Vault = class {
9614
9393
  const sealedResidue = [];
9615
9394
  const indexResidue = [];
9616
9395
  const ledgerDeltaResidue = [];
9617
- const blobsEnabled = this.blobStrategy !== void 0;
9396
+ const blobsEnabled = this.strategies.blob !== NO_BLOBS;
9618
9397
  const actor = this.keyring.userId;
9619
9398
  const fanoutStats = { recordsErased: 0, aggregatesRecomputed: 0, residueFrozen: [], lookupReferencesCascaded: 0, lookupReferencesNullified: 0, lookupReferencesResidue: [], derivedResidueUndecodable: [], derivedResidueDeclined: [] };
9620
9399
  const { partitionSealedCekKeys, shouldSkipBlobScan, bumpResidueCount, residueNoticesFromMap } = await import("./purge-scope-FGNNLWHD.js");
9621
- const scopedPurge = this.forgetStrategy.scopedPurge === true;
9400
+ const scopedPurge = this.strategies.forget.scopedPurge === true;
9622
9401
  const sealedCekScopedSkipped = /* @__PURE__ */ new Map();
9623
9402
  const blobScopedSkipped = /* @__PURE__ */ new Map();
9624
9403
  for (const ref2 of allRefs) {
9625
9404
  const coll = this.collection(ref2.collection);
9626
9405
  const satelliteOf = ref2.satelliteOf;
9627
- const perRecordKeys = this.forgetStrategy.subjects[satelliteOf ?? ref2.collection] !== void 0;
9406
+ const perRecordKeys = this.strategies.forget.subjects[satelliteOf ?? ref2.collection] !== void 0;
9628
9407
  const lookupCompareKeys = await this.linksEnforcer.checkLookupRefsRestrict(this.graph, ref2.collection, ref2.collection, ref2.id);
9629
9408
  const live = await this.adapter.get(this.name, ref2.collection, ref2.id);
9630
9409
  if (perRecordKeys && live && live._data && !hasPerRecordKey(live)) {
@@ -9684,7 +9463,7 @@ var Vault = class {
9684
9463
  collections.add(ref2.collection);
9685
9464
  await forgetDerivedFanout(this, { collection: ref2.collection, id: ref2.id }, live, fanoutStats, lookupCompareKeys);
9686
9465
  }
9687
- historyVersionsShredded += await this.historyStrategy.tombstoneHistory(
9466
+ historyVersionsShredded += await this.strategies.history.tombstoneHistory(
9688
9467
  this.adapter,
9689
9468
  this.name,
9690
9469
  ref2.collection,
@@ -9814,7 +9593,7 @@ var Vault = class {
9814
9593
  * `<collection>/<id>/<pid>` key the delivery envelope was written under.
9815
9594
  */
9816
9595
  async sealRecordToHost(collection, id, hostSealer, opts) {
9817
- return this.sealedRecordStrategy.sealRecordToHost(this._sealingContext(), collection, id, hostSealer, opts);
9596
+ return this.strategies.sealedRecord.sealRecordToHost(this._sealingContext(), collection, id, hostSealer, opts);
9818
9597
  }
9819
9598
  /**
9820
9599
  * Revoke a sealed-CEK grant. **Default is SOFT**: deletes the `pid` delivery
@@ -9824,7 +9603,7 @@ var Vault = class {
9824
9603
  * longer open the record. See `revokeSealedRecord` in `record-keys/sealing.ts`.
9825
9604
  */
9826
9605
  async revokeSealedRecord(collection, id, pid, opts) {
9827
- return this.sealedRecordStrategy.revokeSealedRecord(this._sealingContext(), collection, id, pid, opts);
9606
+ return this.strategies.sealedRecord.revokeSealedRecord(this._sealingContext(), collection, id, pid, opts);
9828
9607
  }
9829
9608
  /**
9830
9609
  * HARD-rotate a record's CEK: decrypt the live body under the old CEK,
@@ -9844,7 +9623,7 @@ var Vault = class {
9844
9623
  * @throws {@link RecordCekNotFoundError} if the record is missing or has no `_cek`.
9845
9624
  */
9846
9625
  async rotateRecordCek(collection, id) {
9847
- return this.sealedRecordStrategy.rotateRecordCek(this._sealingContext(), collection, id);
9626
+ return this.strategies.sealedRecord.rotateRecordCek(this._sealingContext(), collection, id);
9848
9627
  }
9849
9628
  /**
9850
9629
  * Build the {@link SealingContext} the record-keys grantor functions need:
@@ -9906,7 +9685,7 @@ var Vault = class {
9906
9685
  async _initDerivations(handles) {
9907
9686
  if (handles.length === 0) return;
9908
9687
  const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
9909
- import("./registry-ZULMLCJK.js"),
9688
+ import("./registry-JOFO7RAH.js"),
9910
9689
  import("./read-only-facade-CHCKSEPD.js")
9911
9690
  ]);
9912
9691
  const registry = new DerivationRegistry();
@@ -9938,7 +9717,7 @@ var Vault = class {
9938
9717
  */
9939
9718
  async _initMaterializedViews(handles) {
9940
9719
  if (handles.length === 0) return;
9941
- const { MaterializedViewRegistry } = await import("./registry-4V4YQCXJ.js");
9720
+ const { MaterializedViewRegistry } = await import("./registry-6BMBFEXT.js");
9942
9721
  const registry = new MaterializedViewRegistry();
9943
9722
  this.materializedViewRegistry = registry;
9944
9723
  const db = this;
@@ -9963,7 +9742,7 @@ var Vault = class {
9963
9742
  */
9964
9743
  async _initOverlayedViews(handles) {
9965
9744
  if (handles.length === 0) return;
9966
- const { OverlayedViewRegistry } = await import("./registry-3LXKNXWI.js");
9745
+ const { OverlayedViewRegistry } = await import("./registry-7CZWF3EQ.js");
9967
9746
  const registry = new OverlayedViewRegistry();
9968
9747
  const mvRegistry = this.materializedViewRegistry;
9969
9748
  const overlayNames = /* @__PURE__ */ new Set();
@@ -10010,14 +9789,14 @@ var Vault = class {
10010
9789
  if (!reg) {
10011
9790
  throw new Error(`refreshView: no MV registered with name "${name}"`);
10012
9791
  }
10013
- const { MaterializedViewExecutor } = await import("./executor-YORMIBWV.js");
9792
+ const { MaterializedViewExecutor } = await import("./executor-SHYLIBOM.js");
10014
9793
  const result = await MaterializedViewExecutor.refresh(reg, {
10015
9794
  getCollection: (n) => this.collection(n),
10016
9795
  getActiveTxContext: () => this.noydb._activeTxContextOrNull,
10017
9796
  getQueryContext: () => this,
10018
9797
  dispatchCtx: this._dispatchCtx({ collection: name, id: "refreshView" })
10019
9798
  });
10020
- const { clearMVStaleFully } = await import("./stale-4UNPHWOU.js");
9799
+ const { clearMVStaleFully } = await import("./stale-NBROTA66.js");
10021
9800
  await clearMVStaleFully(this.adapter, this.name, registry, name);
10022
9801
  return result;
10023
9802
  }
@@ -10030,7 +9809,7 @@ var Vault = class {
10030
9809
  if (registry === null) return { derived: 0, failed: 0, skippedFrozen: 0 };
10031
9810
  const strategies = registry.strategiesForSource(sourceCollection);
10032
9811
  if (strategies.length === 0) return { derived: 0, failed: 0, skippedFrozen: 0 };
10033
- const { DerivationExecutor } = await import("./executor-TEZYRDN3.js");
9812
+ const { DerivationExecutor } = await import("./executor-FCJEH3FU.js");
10034
9813
  const sourceColl = this.collection(sourceCollection);
10035
9814
  const records = await sourceColl.list();
10036
9815
  const ctx = { vault: this.derivationFacade ?? new (await import("./read-only-facade-CHCKSEPD.js")).ReadOnlyVaultFacade(this, "derivation") };
@@ -10057,7 +9836,7 @@ var Vault = class {
10057
9836
  if (!outSpec) continue;
10058
9837
  const outputColl = this.collection(outSpec.collection);
10059
9838
  if (out.kind === "array") {
10060
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-HJV3A7PM.js");
9839
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-WWXVHHUH.js");
10061
9840
  const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key, this.getDEK, this.encrypted);
10062
9841
  const prevKeys = new Set(prior?.keys ?? []);
10063
9842
  const newKeysList = out.entries.map((e) => e.key);
@@ -10151,7 +9930,7 @@ var Vault = class {
10151
9930
  */
10152
9931
  at(timestamp) {
10153
9932
  const iso = timestamp instanceof Date ? timestamp.toISOString() : timestamp;
10154
- return this.historyStrategy.buildVaultInstant(
9933
+ return this.strategies.history.buildVaultInstant(
10155
9934
  {
10156
9935
  adapter: this.adapter,
10157
9936
  name: this.name,
@@ -10183,11 +9962,11 @@ var Vault = class {
10183
9962
  *.
10184
9963
  */
10185
9964
  frame() {
10186
- return this.shadowStrategy.buildFrame(this);
9965
+ return this.strategies.shadow.buildFrame(this);
10187
9966
  }
10188
9967
  /** Credential-broker handle (#479); `NO_BROKER` throws unless `brokerStrategy: withBroker(config)` was passed to createNoydb(). */
10189
9968
  broker() {
10190
- return buildCredentialBrokerHandle(this.brokerStrategy, this.adapter, this.name, () => this.keyring);
9969
+ return buildCredentialBrokerHandle(this.strategies.broker, this.adapter, this.name, () => this.keyring);
10191
9970
  }
10192
9971
  /**
10193
9972
  * Run `fn` under a consent scope. Every `get` / `put` / `delete`
@@ -10229,7 +10008,7 @@ var Vault = class {
10229
10008
  *.
10230
10009
  */
10231
10010
  async consentAudit(filter = {}) {
10232
- return this.consentStrategy.read(this.adapter, this.name, this.encrypted, this.getDEK, filter);
10011
+ return this.strategies.consent.read(this.adapter, this.name, this.encrypted, this.getDEK, filter);
10233
10012
  }
10234
10013
  /**
10235
10014
  * Called by Collection after every access when a consent scope is
@@ -10240,7 +10019,7 @@ var Vault = class {
10240
10019
  async _logConsent(op, collection, recordId) {
10241
10020
  const ctx = this.consentContext;
10242
10021
  if (!ctx) return;
10243
- await this.consentStrategy.write(
10022
+ await this.strategies.consent.write(
10244
10023
  this.adapter,
10245
10024
  this.name,
10246
10025
  this.encrypted,
@@ -10284,10 +10063,10 @@ var Vault = class {
10284
10063
  * collection.
10285
10064
  */
10286
10065
  async delegate(opts) {
10287
- const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-UT76AQIG.js");
10066
+ const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-WWZPEDK2.js");
10288
10067
  if (!this.keyring.kek) {
10289
10068
  throw new ValidationError(
10290
- "issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (passphrase) first."
10069
+ "issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (secret) first."
10291
10070
  );
10292
10071
  }
10293
10072
  const targetKek = this.keyring.kek;
@@ -10306,7 +10085,7 @@ var Vault = class {
10306
10085
  * if the id does not exist.
10307
10086
  */
10308
10087
  async revokeDelegation(id) {
10309
- const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-UT76AQIG.js");
10088
+ const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-WWZPEDK2.js");
10310
10089
  await revokeDelegation(this.adapter, this.name, id);
10311
10090
  void DELEGATIONS_COLLECTION;
10312
10091
  }
@@ -10554,7 +10333,7 @@ var Vault = class {
10554
10333
  * @see docs/superpowers/specs/2026-05-22-schema-dump-design.md
10555
10334
  */
10556
10335
  async dumpSchema(opts = {}) {
10557
- const { dumpVaultSchema } = await import("./walk-H4YE52S2.js");
10336
+ const { dumpVaultSchema } = await import("./walk-E3OVLBFR.js");
10558
10337
  return dumpVaultSchema(this, opts);
10559
10338
  }
10560
10339
  /**
@@ -10689,7 +10468,7 @@ var Vault = class {
10689
10468
  * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md
10690
10469
  */
10691
10470
  async getCover(opts = {}) {
10692
- const { readCover } = await import("./cover-B5MY43CK.js");
10471
+ const { readCover } = await import("./cover-5BSNJREH.js");
10693
10472
  return readCover(this.adapter, this.name, opts);
10694
10473
  }
10695
10474
  /**
@@ -10704,7 +10483,7 @@ var Vault = class {
10704
10483
  * both modes round-trip cleanly.
10705
10484
  */
10706
10485
  async dump() {
10707
- const { dumpVault } = await import("./backup-JL2GOTYQ.js");
10486
+ const { dumpVault } = await import("./backup-YCHAC575.js");
10708
10487
  return dumpVault(this.backupContext());
10709
10488
  }
10710
10489
  /**
@@ -10719,7 +10498,7 @@ var Vault = class {
10719
10498
  vault: this.name,
10720
10499
  userId: () => this.keyring.userId,
10721
10500
  getLedgerOrNull: () => this.getLedgerOrNull(),
10722
- envelopePayloadHash: (envelope) => this.historyStrategy.envelopePayloadHash(envelope),
10501
+ envelopePayloadHash: (envelope) => this.strategies.history.envelopePayloadHash(envelope),
10723
10502
  reloadKeyringAndRebuildDEK: async () => {
10724
10503
  if (this.reloadKeyring) {
10725
10504
  this.keyring = await this.reloadKeyring();
@@ -10756,7 +10535,7 @@ var Vault = class {
10756
10535
  * — there's no chain to verify against.
10757
10536
  */
10758
10537
  async load(backupJson) {
10759
- const { loadVault } = await import("./backup-JL2GOTYQ.js");
10538
+ const { loadVault } = await import("./backup-YCHAC575.js");
10760
10539
  return loadVault(this.backupContext(), backupJson);
10761
10540
  }
10762
10541
  /**
@@ -10788,7 +10567,7 @@ var Vault = class {
10788
10567
  * way to detect tampering of an in-place vault.
10789
10568
  */
10790
10569
  async verifyBackupIntegrity() {
10791
- const { verifyBackupIntegrity } = await import("./backup-JL2GOTYQ.js");
10570
+ const { verifyBackupIntegrity } = await import("./backup-YCHAC575.js");
10792
10571
  return verifyBackupIntegrity(this.backupContext());
10793
10572
  }
10794
10573
  /**
@@ -11006,7 +10785,7 @@ var Vault = class {
11006
10785
  * is the live validator object, not a serialization of it).
11007
10786
  */
11008
10787
  async exportJSON(opts = {}) {
11009
- const { exportVaultJSON } = await import("./backup-JL2GOTYQ.js");
10788
+ const { exportVaultJSON } = await import("./backup-YCHAC575.js");
11010
10789
  return exportVaultJSON(this.backupContext(), opts);
11011
10790
  }
11012
10791
  };
@@ -11404,25 +11183,6 @@ var QuickUnlockStore = class {
11404
11183
  }
11405
11184
  };
11406
11185
 
11407
- // src/with-fork/snapshots/strategy.ts
11408
- var NOT_ENABLED4 = new Error(
11409
- 'Snapshots require the snapshot strategy. Import `{ withSnapshots }` from "@noy-db/hub/snapshots" and pass it to `createNoydb({ snapshotStrategy: withSnapshots({ store }) })`.'
11410
- );
11411
- var NO_SNAPSHOTS = {
11412
- async snapshot() {
11413
- throw NOT_ENABLED4;
11414
- },
11415
- async listSnapshots() {
11416
- throw NOT_ENABLED4;
11417
- },
11418
- async restoreSnapshot() {
11419
- throw NOT_ENABLED4;
11420
- },
11421
- async autoSnapshot() {
11422
- throw NOT_ENABLED4;
11423
- }
11424
- };
11425
-
11426
11186
  // src/with-fork/snapshots/scheduler.ts
11427
11187
  var SnapshotScheduler = class {
11428
11188
  policy;
@@ -11623,19 +11383,6 @@ var NoydbSnapshots = class {
11623
11383
  }
11624
11384
  };
11625
11385
 
11626
- // src/with-commit/tx/strategy.ts
11627
- var NOT_ENABLED5 = new Error(
11628
- 'Multi-record transactions require the tx strategy. Import `{ withTransactions }` from "@noy-db/hub/tx" and pass it to `createNoydb({ txStrategy: withTransactions() })`.'
11629
- );
11630
- var NO_TX = {
11631
- async runTransaction(_db, _fn, _options, _txInvariants) {
11632
- throw NOT_ENABLED5;
11633
- },
11634
- async runDryRun() {
11635
- throw NOT_ENABLED5;
11636
- }
11637
- };
11638
-
11639
11386
  // src/kernel/memory-store.ts
11640
11387
  function memoryStore() {
11641
11388
  const store = /* @__PURE__ */ new Map();
@@ -11719,23 +11466,6 @@ function memoryStore() {
11719
11466
  };
11720
11467
  }
11721
11468
 
11722
- // src/with-party/session/strategy.ts
11723
- function notEnabled3(op) {
11724
- return new Error(
11725
- `${op} requires the session strategy. Import \`{ withSession }\` from "@noy-db/hub/session" and pass it to \`createNoydb({ sessionStrategy: withSession() })\`.`
11726
- );
11727
- }
11728
- var NO_SESSION = {
11729
- validateSessionPolicy() {
11730
- throw notEnabled3("sessionPolicy");
11731
- },
11732
- createEnforcer() {
11733
- throw notEnabled3("session policy enforcement");
11734
- },
11735
- revokeAllSessions() {
11736
- }
11737
- };
11738
-
11739
11469
  // src/with-party/auth-introspection/index.ts
11740
11470
  async function describeAuthConfig(store, vault) {
11741
11471
  const policy = await loadVaultPolicy(store, vault) ?? defaultPolicySnapshot();
@@ -11743,8 +11473,8 @@ async function describeAuthConfig(store, vault) {
11743
11473
  const lines = [];
11744
11474
  lines.push(`Vault "${vault}" \u2014 three-tier authentication`);
11745
11475
  lines.push("");
11746
- lines.push("Tier 1 \u2014 Passphrase (master)");
11747
- lines.push(` Phrase format: ${policy.passphrase?.minWords ?? 6}+ words, lowercase letters, \u2265${policy.passphrase?.minWordLength ?? 3} chars/word`);
11476
+ lines.push("Tier 1 \u2014 Secret (master)");
11477
+ lines.push(` Phrase format: ${policy.secret?.minWords ?? 6}+ words, lowercase letters, \u2265${policy.secret?.minWordLength ?? 3} chars/word`);
11748
11478
  lines.push(" Strength validator: enforced (override available for tests only)");
11749
11479
  lines.push("");
11750
11480
  lines.push("Tier 2 \u2014 Authenticate (routine login)");
@@ -11755,7 +11485,7 @@ async function describeAuthConfig(store, vault) {
11755
11485
  lines.push(" Method: PIN (per-app configurable)");
11756
11486
  lines.push("");
11757
11487
  lines.push(`Recovery profiles enrolled: ${recoveryProfiles.length === 0 ? "none" : recoveryProfiles.join(", ")}`);
11758
- lines.push("Managed-passphrase mode: off (post-1.0)");
11488
+ lines.push("Managed-secret mode: off (post-1.0)");
11759
11489
  lines.push("");
11760
11490
  lines.push("Sensitive-action gates:");
11761
11491
  for (const [gate, gp] of Object.entries(policy.gates)) {
@@ -11768,7 +11498,7 @@ async function diagramAuthConfig(store, vault) {
11768
11498
  const lines = [];
11769
11499
  lines.push("flowchart TB");
11770
11500
  lines.push(` vault["Vault: ${escapeMermaid(vault)}"]`);
11771
- lines.push(' tier1["Tier 1<br/>Passphrase"]');
11501
+ lines.push(' tier1["Tier 1<br/>Secret"]');
11772
11502
  lines.push(' tier2["Tier 2<br/>Multi-slot Authenticate"]');
11773
11503
  lines.push(' tier3["Tier 3<br/>PIN / Quick-resume"]');
11774
11504
  lines.push(" vault --> tier1");
@@ -11842,7 +11572,7 @@ function describeGatePolicy(gp) {
11842
11572
  }
11843
11573
  function defaultPolicySnapshot() {
11844
11574
  return {
11845
- passphrase: { minWords: 6, minWordLength: 3, rejectRepeatedAdjacent: true },
11575
+ secret: { minWords: 6, minWordLength: 3, rejectRepeatedAdjacent: true },
11846
11576
  gates: {}
11847
11577
  };
11848
11578
  }
@@ -11992,7 +11722,7 @@ var TeamFacade = class {
11992
11722
  * ```ts
11993
11723
  * import { enrollWebAuthn } from '@noy-db/on-webauthn'
11994
11724
  *
11995
- * await db.enrollWebAuthn('demo', async (keyring) => {
11725
+ * await db.team.enrollWebAuthn('demo', async (keyring) => {
11996
11726
  * const e = await enrollWebAuthn(keyring, 'demo', { rp: {...} })
11997
11727
  * return {
11998
11728
  * id: `webauthn-${e.credentialId.slice(0, 8)}`,
@@ -12021,7 +11751,7 @@ var TeamFacade = class {
12021
11751
  const slotOptions = await ceremony(keyring);
12022
11752
  if (slotOptions.method !== "webauthn") {
12023
11753
  throw new ValidationError(
12024
- `enrollWebAuthn: ceremony returned method "${slotOptions.method}"; expected "webauthn". Use db.enrollAuthenticator() for non-webauthn methods.`
11754
+ `enrollWebAuthn: ceremony returned method "${slotOptions.method}"; expected "webauthn". Use db.team.enrollAuthenticator() for non-webauthn methods.`
12025
11755
  );
12026
11756
  }
12027
11757
  const credentialId = slotOptions.meta.credentialId;
@@ -12099,44 +11829,44 @@ var TeamFacade = class {
12099
11829
  }
12100
11830
  // ─── Tier-1 change flows ────────────────────────────────────────
12101
11831
  /**
12102
- * Rotate the user's passphrase (user remembers old). Validates the
12103
- * new phrase against the configured `passphrase` policy, runs the
12104
- * `rotate-passphrase` gate, then re-derives + re-wraps every DEK.
11832
+ * Rotate the user's secret (user remembers old). Validates the
11833
+ * new phrase against the configured `secret` policy, runs the
11834
+ * `rotate-secret` gate, then re-derives + re-wraps every DEK.
12105
11835
  *
12106
11836
  * Tier-2 authenticator slots are dropped — each slot wraps the old
12107
11837
  * KEK and would need its derivation key to be re-presented. Re-enrol
12108
11838
  * via `db.enrollAuthenticator` after rotation.
12109
11839
  *
12110
- * @throws `WeakPassphraseError` on a weak new phrase.
11840
+ * @throws `WeakSecretError` on a weak new phrase.
12111
11841
  * @throws `PolicyDeniedError` when the gate denies (missing factor, …).
12112
- * @throws `InvalidKeyError` when `oldPassphrase` is wrong.
11842
+ * @throws `InvalidKeyError` when `oldSecret` is wrong.
12113
11843
  */
12114
- async rotatePassphrase(vault, input, factors) {
12115
- if (this.deps.options.passphraseMode === "managed") {
11844
+ async rotateSecret(vault, input, factors) {
11845
+ if (this.deps.options.secretMode === "managed") {
12116
11846
  throw new PolicyDeniedError(
12117
- "rotate-passphrase",
11847
+ "rotate-secret",
12118
11848
  "disabled",
12119
11849
  { minTier: 1, enabled: false },
12120
- "Managed-passphrase mode (#14): the passphrase is hub-generated and sealed under the SealingKeyProvider \u2014 there is no plaintext to rotate. Use the recovery flow (follow-up issue) to mint a fresh sealed passphrase."
11850
+ "Managed-secret mode (#14): the secret is hub-generated and sealed under the SealingKeyProvider \u2014 there is no plaintext to rotate. Use the recovery flow (follow-up issue) to mint a fresh sealed secret."
12121
11851
  );
12122
11852
  }
12123
- await this.deps.checkGate(vault, "rotate-passphrase", factors);
11853
+ await this.deps.checkGate(vault, "rotate-secret", factors);
12124
11854
  const userId = this.deps.options.user;
12125
- const next = await rotatePassphrase(this.deps.options.store, vault, userId, input);
11855
+ const next = await rotateSecret(this.deps.options.store, vault, userId, input);
12126
11856
  this.deps.keyringCache.set(vault, next);
12127
11857
  }
12128
11858
  /**
12129
- * Reset the passphrase using a recovery proof (user forgot the old).
11859
+ * Reset the secret using a recovery proof (user forgot the old).
12130
11860
  * Currently supports the `'paper'` profile end-to-end; the
12131
11861
  * other profiles throw {@link RecoveryProfileNotImplementedError}.
12132
11862
  *
12133
11863
  * Burns the used recovery entry on success.
12134
11864
  */
12135
- async recoverPassphrase(vault, input, factors) {
12136
- await this.deps.checkGate(vault, "recover-passphrase", factors);
11865
+ async recoverSecret(vault, input, factors) {
11866
+ await this.deps.checkGate(vault, "recover-secret", factors);
12137
11867
  const userId = this.deps.options.user;
12138
11868
  const entriesBeforeRecovery = await loadPaperRecoveryEntries(this.deps.options.store, vault);
12139
- const next = await recoverPassphrase(this.deps.options.shamirRecovery, this.deps.options.store, vault, userId, input);
11869
+ const next = await recoverSecret(this.deps.options.shamirRecovery, this.deps.options.store, vault, userId, input);
12140
11870
  this.deps.keyringCache.set(vault, next);
12141
11871
  const rotateRemaining = input.rotateRemainingCodes ?? true;
12142
11872
  const remainingAfterBurn = Math.max(0, entriesBeforeRecovery.length - 1);
@@ -12158,15 +11888,15 @@ var TeamFacade = class {
12158
11888
  }
12159
11889
  /**
12160
11890
  * Deliberate paper-recovery-code regeneration. User knows their
12161
- * passphrase but wants a fresh sheet — they lost the printout or
11891
+ * secret but wants a fresh sheet — they lost the printout or
12162
11892
  * suspect compromise of the off-site copy.
12163
11893
  *
12164
- * Symmetric to {@link rotatePassphrase} for the recovery profile:
11894
+ * Symmetric to {@link rotateSecret} for the recovery profile:
12165
11895
  * gated, audit-trackable, ergonomic. Replaces (not appends) the
12166
11896
  * paper sheet under `_meta/recovery-paper` in a single envelope `put`.
12167
11897
  *
12168
11898
  * Gated by the `rotate-recovery` policy gate:
12169
- * - PERSONAL_POLICY: `{ minTier: 1 }` — knowing the passphrase
11899
+ * - PERSONAL_POLICY: `{ minTier: 1 }` — knowing the secret
12170
11900
  * suffices, matching the lower-level flow's bar.
12171
11901
  * - STRICT_POLICY: `{ minTier: 1, factors: [{ anyOf: ['totp',
12172
11902
  * 'email-otp', 'webauthn-roaming'] }] }` — rotation is an
@@ -12186,13 +11916,13 @@ var TeamFacade = class {
12186
11916
  *
12187
11917
  * @example Default count + show-once UI
12188
11918
  * ```ts
12189
- * const { newCodes } = await db.rotateRecovery('acme', { profile: 'paper' })
11919
+ * const { newCodes } = await db.team.rotateRecovery('acme', { profile: 'paper' })
12190
11920
  * showCodesToUser(newCodes)
12191
11921
  * ```
12192
11922
  *
12193
11923
  * @example STRICT-policy site with TOTP factor proof
12194
11924
  * ```ts
12195
- * await db.rotateRecovery(
11925
+ * await db.team.rotateRecovery(
12196
11926
  * 'acme',
12197
11927
  * { profile: 'paper', count: 10 },
12198
11928
  * { factors: [{ kind: 'totp', proof: '123456' }] },
@@ -12216,7 +11946,7 @@ var TeamFacade = class {
12216
11946
  const existing = await loadPaperRecoveryEntries(this.deps.options.store, vault);
12217
11947
  if (existing.length === 0) {
12218
11948
  throw new Error(
12219
- `db.rotateRecovery: no recovery codes are enrolled for vault "${vault}". Call db.enrollRecovery({ profile: 'paper', entries }) first; rotateRecovery replaces an existing sheet rather than minting one from scratch.`
11949
+ `db.rotateRecovery: no recovery codes are enrolled for vault "${vault}". Call db.team.enrollRecovery({ profile: 'paper', entries }) first; rotateRecovery replaces an existing sheet rather than minting one from scratch.`
12220
11950
  );
12221
11951
  }
12222
11952
  const keyring = await this.getKeyring(vault);
@@ -12238,7 +11968,7 @@ var TeamFacade = class {
12238
11968
  const existing = await loadShamirRecoveryEntries(this.deps.options.store, vault);
12239
11969
  if (existing.length === 0) {
12240
11970
  throw new Error(
12241
- `db.rotateRecovery: no Shamir recovery entry is enrolled for vault "${vault}". Call db.enrollRecovery({ profile: 'shamir', k, n }) first; rotateRecovery replaces an existing entry rather than minting one from scratch.`
11971
+ `db.rotateRecovery: no Shamir recovery entry is enrolled for vault "${vault}". Call db.team.enrollRecovery({ profile: 'shamir', k, n }) first; rotateRecovery replaces an existing entry rather than minting one from scratch.`
12242
11972
  );
12243
11973
  }
12244
11974
  let targetEntryId;
@@ -12275,7 +12005,7 @@ var TeamFacade = class {
12275
12005
  * **Atomic create-and-enroll for managed-mode vaults.**
12276
12006
  *
12277
12007
  * Bootstraps a managed-mode vault and enrolls strong recovery in
12278
- * a single ceremony. Under `passphraseMode: 'managed'`, every
12008
+ * a single ceremony. Under `secretMode: 'managed'`, every
12279
12009
  * `openVault` call requires a strong recovery profile (Shamir
12280
12010
  * today) to be enrolled — otherwise it throws
12281
12011
  * {@link ManagedRecoveryNotEnrolledError}. This method bypasses
@@ -12294,11 +12024,11 @@ var TeamFacade = class {
12294
12024
  * ```ts
12295
12025
  * const db = await createNoydb({
12296
12026
  * store, user: 'alice',
12297
- * passphraseMode: 'managed',
12027
+ * secretMode: 'managed',
12298
12028
  * sealingKey: macosKeychainSealingProvider({ ... }),
12299
12029
  * })
12300
12030
  *
12301
- * const { vault, recoveryEnrollments } = await db.openVaultAndEnrollRecovery('acme', {
12031
+ * const { vault, recoveryEnrollments } = await db.team.openVaultAndEnrollRecovery('acme', {
12302
12032
  * recovery: [{ profile: 'shamir', k: 2, n: 3 }],
12303
12033
  * })
12304
12034
  * for (const r of recoveryEnrollments) {
@@ -12315,11 +12045,11 @@ var TeamFacade = class {
12315
12045
  "openVaultAndEnrollRecovery: at least one recovery enrollment is required."
12316
12046
  );
12317
12047
  }
12318
- if (this.deps.options.passphraseMode === "managed") {
12048
+ if (this.deps.options.secretMode === "managed") {
12319
12049
  const hasStrong = opts.recovery.some((r) => r.profile === "shamir");
12320
12050
  if (!hasStrong) {
12321
12051
  throw new ValidationError(
12322
- 'openVaultAndEnrollRecovery: managed-mode vaults require at least one strong recovery profile in the `recovery` array. Paper alone is not strong under managed mode (no user passphrase to fall back on). Include { profile: "shamir", k, n } in `recovery`.'
12052
+ 'openVaultAndEnrollRecovery: managed-mode vaults require at least one strong recovery profile in the `recovery` array. Paper alone is not strong under managed mode (no user secret to fall back on). Include { profile: "shamir", k, n } in `recovery`.'
12323
12053
  );
12324
12054
  }
12325
12055
  }
@@ -12334,7 +12064,7 @@ var TeamFacade = class {
12334
12064
  for (const enrollment of opts.recovery) {
12335
12065
  recoveryEnrollments.push(await this.enrollRecovery(vault, enrollment));
12336
12066
  }
12337
- if (this.deps.options.passphraseMode === "managed") {
12067
+ if (this.deps.options.secretMode === "managed") {
12338
12068
  const policy = this.deps.policyCache.get(vault);
12339
12069
  if (policy) {
12340
12070
  await this.deps.assertRecoveryEnrolled(vault, policy);
@@ -12343,20 +12073,20 @@ var TeamFacade = class {
12343
12073
  return { vault: vaultHandle, recoveryEnrollments };
12344
12074
  }
12345
12075
  /**
12346
- * **Recovery flow under managed-passphrase mode.**
12076
+ * **Recovery flow under managed-secret mode.**
12347
12077
  *
12348
- * Replaces the sealed passphrase of a managed-mode vault with a
12078
+ * Replaces the sealed secret of a managed-mode vault with a
12349
12079
  * fresh 256-bit random, sealed under the configured
12350
- * `SealingKeyProvider`. The user never sees the new passphrase.
12080
+ * `SealingKeyProvider`. The user never sees the new secret.
12351
12081
  *
12352
12082
  * Internally:
12353
12083
  * 1. Verify the recovery proof (Shamir today) and unwrap the
12354
12084
  * DEK set.
12355
- * 2. Mint a fresh 256-bit random as the new effective passphrase.
12085
+ * 2. Mint a fresh 256-bit random as the new effective secret.
12356
12086
  * 3. Rewrap the DEK set under a fresh KEK derived from the new
12357
- * passphrase (via the existing `recoverPassphrase` path).
12087
+ * secret (via the existing `recoverSecret` path).
12358
12088
  * 4. Seal the random bytes under the provider and overwrite
12359
- * `_meta/sealed-passphrase`.
12089
+ * `_meta/sealed-secret`.
12360
12090
  * 5. Drop the keyring cache so the next operation re-derives.
12361
12091
  *
12362
12092
  * The vault's strong-recovery enrollment is preserved across
@@ -12364,40 +12094,40 @@ var TeamFacade = class {
12364
12094
  *
12365
12095
  * @throws ValidationError if the Noydb instance is not in managed mode.
12366
12096
  */
12367
- async recoverManagedPassphrase(vault, options) {
12368
- if (this.deps.options.passphraseMode !== "managed") {
12097
+ async recoverManagedSecret(vault, options) {
12098
+ if (this.deps.options.secretMode !== "managed") {
12369
12099
  throw new ValidationError(
12370
- "recoverManagedPassphrase: this method only applies to vaults opened in managed-passphrase mode. For standard mode, use db.recoverPassphrase."
12100
+ "recoverManagedSecret: this method only applies to vaults opened in managed-secret mode. For standard mode, use db.recoverSecret."
12371
12101
  );
12372
12102
  }
12373
12103
  const provider = this.deps.options.sealingKey;
12374
12104
  if (!provider) {
12375
12105
  throw new ValidationError(
12376
- 'recoverManagedPassphrase: createNoydb({ passphraseMode: "managed" }) requires `sealingKey` to be supplied; without it the new sealed passphrase cannot be persisted.'
12106
+ 'recoverManagedSecret: createNoydb({ secretMode: "managed" }) requires `sealingKey` to be supplied; without it the new sealed secret cannot be persisted.'
12377
12107
  );
12378
12108
  }
12379
12109
  const randomBytes = new Uint8Array(32);
12380
12110
  globalThis.crypto.getRandomValues(randomBytes);
12381
12111
  let binary = "";
12382
12112
  for (let i = 0; i < randomBytes.length; i++) binary += String.fromCharCode(randomBytes[i]);
12383
- const newPassphrase = btoa(binary);
12113
+ const newSecret = btoa(binary);
12384
12114
  try {
12385
12115
  const sealed = await provider.seal(randomBytes);
12386
- await recoverPassphrase(
12116
+ await recoverSecret(
12387
12117
  this.deps.options.shamirRecovery,
12388
12118
  this.deps.options.store,
12389
12119
  vault,
12390
12120
  this.deps.options.user,
12391
12121
  {
12392
- newPassphrase,
12122
+ newSecret,
12393
12123
  recoveryProof: options.recoveryProof,
12394
- // The new passphrase IS 256 bits of random; policy gates on
12124
+ // The new secret IS 256 bits of random; policy gates on
12395
12125
  // length/entropy don't apply.
12396
- allowWeakPassphrase: true,
12397
- ...options.passphrasePolicy !== void 0 ? { passphrasePolicy: options.passphrasePolicy } : {}
12126
+ allowWeakSecret: true,
12127
+ ...options.secretPolicy !== void 0 ? { secretPolicy: options.secretPolicy } : {}
12398
12128
  }
12399
12129
  );
12400
- await saveSealedPassphrase(this.deps.options.store, vault, {
12130
+ await saveSealedSecret(this.deps.options.store, vault, {
12401
12131
  providerId: provider.id,
12402
12132
  sealed
12403
12133
  });
@@ -12408,7 +12138,7 @@ var TeamFacade = class {
12408
12138
  }
12409
12139
  /**
12410
12140
  * Atomic peer-recovery — re-wraps an EXISTING user's keyring under
12411
- * a fresh temp passphrase in a single store write. Closes the
12141
+ * a fresh temp secret in a single store write. Closes the
12412
12142
  * partial-failure window (the previous compose-from-primitives
12413
12143
  * pattern was `db.revoke + db.grant`, two writes — if the issuer
12414
12144
  * cancelled between them the target was locked out entirely).
@@ -12427,17 +12157,17 @@ var TeamFacade = class {
12427
12157
  * recovery / TOTP / email-OTP factor proof at the moment of
12428
12158
  * recovery, so the issuer affirmatively re-asserts identity.
12429
12159
  *
12430
- * The recipient should call `db.rotatePassphrase` on first session
12160
+ * The recipient should call `db.rotateSecret` on first session
12431
12161
  * to choose their own phrase — the temp acts as a single-use
12432
12162
  * bridge.
12433
12163
  *
12434
12164
  * ```ts
12435
- * await db.recoverUser('acme', {
12165
+ * await db.team.recoverUser('acme', {
12436
12166
  * userId: 'bob',
12437
- * passphrase: 'temporary-correct-horse-battery-staple-printer',
12167
+ * secret: 'temporary-correct-horse-battery-staple-printer',
12438
12168
  * }, { factors: [{ kind: 'recovery' }] })
12439
12169
  * // Bob opens createNoydb({ user: 'bob', secret: tempPhrase })
12440
- * // and immediately calls db.rotatePassphrase to set his own.
12170
+ * // and immediately calls db.rotateSecret to set his own.
12441
12171
  * ```
12442
12172
  *
12443
12173
  * @throws `NoAccessError` when no keyring exists for the target.
@@ -12463,17 +12193,17 @@ var TeamFacade = class {
12463
12193
  * The hub wraps the user's DEK set (not the KEK) under a code-derived
12464
12194
  * AES-GCM key — see `team/recovery.ts` for the rationale. The mint
12465
12195
  * helper {@link mintPaperRecoveryEntry} is the canonical primitive;
12466
- * pair it with `db.getKeyring(vault)` to obtain the live DEK set:
12196
+ * pair it with `db.team.getKeyring(vault)` to obtain the live DEK set:
12467
12197
  *
12468
12198
  * ```ts
12469
12199
  * import { mintPaperRecoveryEntry } from '@noy-db/hub'
12470
12200
  *
12471
- * const keyring = await db.getKeyring('acme')
12201
+ * const keyring = await db.team.getKeyring('acme')
12472
12202
  * const codes: string[] = ['CORRECT-HORSE-1', 'BATTERY-STAPLE-2', ...]
12473
12203
  * const entries = await Promise.all(
12474
12204
  * codes.map((code, i) => mintPaperRecoveryEntry(keyring.deks, code, `code-${i}`)),
12475
12205
  * )
12476
- * await db.enrollRecovery('acme', { profile: 'paper', entries })
12206
+ * await db.team.enrollRecovery('acme', { profile: 'paper', entries })
12477
12207
  * showCodesToUser(codes)
12478
12208
  * ```
12479
12209
  *
@@ -12484,7 +12214,7 @@ var TeamFacade = class {
12484
12214
  * ```ts
12485
12215
  * import { generateRecoveryCodeSet } from '@noy-db/on-recovery'
12486
12216
  * const { codes, entries } = await generateRecoveryCodeSet({ deks: keyring.deks, count: 8 })
12487
- * await db.enrollRecovery('acme', { profile: 'paper', entries })
12217
+ * await db.team.enrollRecovery('acme', { profile: 'paper', entries })
12488
12218
  * ```
12489
12219
  */
12490
12220
  async enrollRecovery(vault, enrollment) {
@@ -12584,7 +12314,7 @@ var TeamFacade = class {
12584
12314
  * and no `secret` / `getKeyring` is configured.
12585
12315
  *
12586
12316
  * ```ts
12587
- * const keyring = await db.getKeyring('acme')
12317
+ * const keyring = await db.team.getKeyring('acme')
12588
12318
  * // keyring.deks: Map<collection, CryptoKey>
12589
12319
  * // keyring.kek: CryptoKey | null (null for tier-3 / wrap-DEKs sessions)
12590
12320
  * // keyring.role / .permissions / .authenticators
@@ -12661,7 +12391,7 @@ var Noydb = class {
12661
12391
  keyringCache = /* @__PURE__ */ new Map();
12662
12392
  syncEngines = /* @__PURE__ */ new Map();
12663
12393
  /**
12664
- * Per-vault active session tier — defaults to `1` after a passphrase
12394
+ * Per-vault active session tier — defaults to `1` after a secret
12665
12395
  * unlock; tier-2 / tier-3 unlocks downgrade it. Used by
12666
12396
  * {@link checkGate} to evaluate `gate.minTier`.
12667
12397
  */
@@ -12689,26 +12419,43 @@ var Noydb = class {
12689
12419
  writeRelay;
12690
12420
  /** Per-vault policy enforcers. */
12691
12421
  policyEnforcers = /* @__PURE__ */ new Map();
12692
- txStrategy;
12693
- forgetStrategy;
12694
12422
  /**
12695
- * Opt-in sovereign-custody (FR-6) strategy — `NO_CUSTODY` (throwing) unless
12696
- * `withCustody()` was passed. Public so `Vault` routes `vault.custody.liberate`
12697
- * through it; grant/revoke route through it from this class. @internal
12423
+ * Every opt-in service, resolved once (#838). Shared by reference with each
12424
+ * `Vault` this instance opens and, through them, every `Collection` — so
12425
+ * there is exactly one resolution and no construction path can disagree
12426
+ * about which services are enabled (the #834 bug class).
12698
12427
  */
12699
- custodyStrategy;
12428
+ strategies;
12700
12429
  /**
12701
- * Opt-in multi-user team strategy (#267 keyring-grant → team split) —
12702
- * `NO_TEAM` (throwing) unless `withTeam()` was passed; the keyring
12703
- * engines are linked only by the active strategy, not by this file. */
12704
- teamStrategy;
12705
- sessionStrategy;
12706
- syncStrategy;
12430
+ * Opt-in sovereign-custody (FR-6) strategy — `NO_CUSTODY` (throwing) unless
12431
+ * `withCustody()` was passed. Kept as a public accessor because `Vault`
12432
+ * routes `vault.custody.liberate` through `this.noydb.custodyStrategy`.
12433
+ * @internal
12434
+ */
12435
+ get custodyStrategy() {
12436
+ return this.strategies.custody;
12437
+ }
12707
12438
  snapshots;
12708
12439
  policyManager;
12709
12440
  /** Pre-resolved policy-gate engine function (mirrors `coordinationProvider`/`userApiFactory` above). */
12710
12441
  policyCheckGate;
12711
- team;
12442
+ /**
12443
+ * Credential and multi-user operations — enrolment, secret rotation,
12444
+ * recovery, quick-unlock (#846).
12445
+ *
12446
+ * Public because 23 methods on this class did nothing but restate a
12447
+ * TeamFacade signature and forward to it, so every signature had to be
12448
+ * hand-kept in sync with its counterpart. `db.team.rotateSecret(…)`
12449
+ * reads the same and has one source of truth.
12450
+ *
12451
+ * A getter, not a field, so it appears in the prototype-based kernel API
12452
+ * manifest — an instance field is invisible to it (the same reason
12453
+ * `custodyStrategy` became one in #838).
12454
+ */
12455
+ get team() {
12456
+ return this.#team;
12457
+ }
12458
+ #team;
12712
12459
  /**
12713
12460
  * Currently-running multi-record transaction, set by
12714
12461
  * `runTransaction` at the start of Phase 2 (commit) and cleared in
@@ -12747,14 +12494,9 @@ var Noydb = class {
12747
12494
  this.userApiFactory = options.userApiFactory;
12748
12495
  if (!options.policyFactory || !options.policyCheckGateFn) throw new ValidationError("Noydb must be constructed via createNoydb(), which resolves the default policy service.");
12749
12496
  this.policyCheckGate = options.policyCheckGateFn;
12750
- this.txStrategy = options.txStrategy ?? NO_TX;
12751
- this.forgetStrategy = options.forgetStrategy ?? NO_FORGET;
12752
- this.custodyStrategy = options.custodyStrategy ?? NO_CUSTODY;
12753
- this.teamStrategy = options.teamStrategy ?? NO_TEAM;
12754
- this.sessionStrategy = options.sessionStrategy ?? NO_SESSION;
12755
- this.syncStrategy = options.syncStrategy ?? NO_SYNC;
12497
+ this.strategies = resolveStrategies(options);
12756
12498
  this.snapshots = new NoydbSnapshots({
12757
- strategy: options.snapshotStrategy ?? NO_SNAPSHOTS,
12499
+ strategy: this.strategies.snapshot,
12758
12500
  user: options.user,
12759
12501
  isClosed: () => this.closed,
12760
12502
  getVault: (name) => this.vaultCache.get(name),
@@ -12775,7 +12517,7 @@ var Noydb = class {
12775
12517
  this.vaultCache.delete(vault);
12776
12518
  }
12777
12519
  });
12778
- this.team = new TeamFacade({
12520
+ this.#team = new TeamFacade({
12779
12521
  options: this.options,
12780
12522
  keyringCache: this.keyringCache,
12781
12523
  activeTier: this.activeTier,
@@ -12791,7 +12533,7 @@ var Noydb = class {
12791
12533
  }
12792
12534
  });
12793
12535
  if (options.sessionPolicy) {
12794
- this.sessionStrategy.validateSessionPolicy(options.sessionPolicy);
12536
+ this.strategies.session.validateSessionPolicy(options.sessionPolicy);
12795
12537
  }
12796
12538
  this.#registerGuardGate();
12797
12539
  this.#registerPeriodGate();
@@ -12800,7 +12542,7 @@ var Noydb = class {
12800
12542
  }
12801
12543
  /** @internal — resolved forget strategy (NO_FORGET when not configured). */
12802
12544
  get _forgetStrategy() {
12803
- return this.forgetStrategy;
12545
+ return this.strategies.forget;
12804
12546
  }
12805
12547
  // GDPR subject-index maintenance. When `withForgetCascade` declares
12806
12548
  // any subject fields, keep the encrypted `_subject_index` in lock-step with
@@ -12813,7 +12555,7 @@ var Noydb = class {
12813
12555
  // does NOT) — drop the ref so a deleted record never lingers in the
12814
12556
  // index (RISK #2). Without it, forget() would try to shred a ghost.
12815
12557
  #registerForgetHooks() {
12816
- const subjects = this.forgetStrategy.subjects;
12558
+ const subjects = this.strategies.forget.subjects;
12817
12559
  if (Object.keys(subjects).length === 0) return;
12818
12560
  const subjectFieldFor = (collection) => subjects[collection];
12819
12561
  this.writeHooks.onAfterWrite(async (event) => {
@@ -12877,7 +12619,7 @@ var Noydb = class {
12877
12619
  if (!facade) return;
12878
12620
  const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
12879
12621
  await registry.runChecks(e.collection, incoming, ctx);
12880
- const { GuardExecutor } = await import("./executor-WQQRU6DO.js");
12622
+ const { GuardExecutor } = await import("./executor-OHET7TF7.js");
12881
12623
  for (const g of guards) {
12882
12624
  await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming, e.computedFieldNames);
12883
12625
  }
@@ -13002,7 +12744,7 @@ var Noydb = class {
13002
12744
  if (targets.length > 0) {
13003
12745
  const primary = targets.find((t) => t.role === "sync-peer") ?? targets[0];
13004
12746
  const effectivePolicy = this.options.syncPolicy ?? primary.policy ?? INDEXED_STORE_POLICY;
13005
- syncEngine = this.syncStrategy.buildSyncEngine({
12747
+ syncEngine = this.strategies.sync.buildSyncEngine({
13006
12748
  local: this.options.store,
13007
12749
  remote: primary.store,
13008
12750
  vault: name,
@@ -13016,7 +12758,7 @@ var Noydb = class {
13016
12758
  for (const target of targets) {
13017
12759
  if (target === primary) continue;
13018
12760
  const targetPolicy = target.policy ?? this.options.syncPolicy ?? INDEXED_STORE_POLICY;
13019
- const engine = this.syncStrategy.buildSyncEngine({
12761
+ const engine = this.strategies.sync.buildSyncEngine({
13020
12762
  local: this.options.store,
13021
12763
  remote: target.store,
13022
12764
  vault: name,
@@ -13049,31 +12791,14 @@ var Noydb = class {
13049
12791
  syncAdapter: targets.length > 0 ? targets[0].store : void 0,
13050
12792
  getPurgeableTargets: () => targets.filter((t) => t.role === "backup" || t.role === "archive").map((t) => ({ store: t.store, role: t.role, ...t.label !== void 0 ? { label: t.label } : {} })),
13051
12793
  historyConfig: this.options.history,
13052
- ...this.options.blobStrategy !== void 0 ? { blobStrategy: this.options.blobStrategy } : {},
12794
+ // #838 — the 21 conditional strategy spreads that used to live here are
12795
+ // one shared reference. This block is where #834's drift happened: a
12796
+ // copy of it silently omitted six strategies, and there was nothing to
12797
+ // catch that. There is no longer a per-service line to omit.
12798
+ strategies: this.strategies,
13053
12799
  ...this.options.objectStore !== void 0 ? { objectStore: this.options.objectStore } : {},
13054
- ...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
13055
- ...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
13056
- ...this.options.lazyStrategy !== void 0 ? { lazyStrategy: this.options.lazyStrategy } : {},
13057
- ...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
13058
- ...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
13059
- ...this.options.tiersStrategy !== void 0 ? { tiersStrategy: this.options.tiersStrategy } : {},
13060
- ...this.options.searchStrategy !== void 0 ? { searchStrategy: this.options.searchStrategy } : {},
13061
- ...this.options.cargoStrategy !== void 0 ? { cargoStrategy: this.options.cargoStrategy } : {},
13062
- ...this.options.brokerStrategy !== void 0 ? { brokerStrategy: this.options.brokerStrategy } : {},
13063
- ...this.options.consentStrategy !== void 0 ? { consentStrategy: this.options.consentStrategy } : {},
13064
- ...this.options.periodsStrategy !== void 0 ? { periodsStrategy: this.options.periodsStrategy } : {},
13065
- ...this.options.shadowStrategy !== void 0 ? { shadowStrategy: this.options.shadowStrategy } : {},
13066
- ...this.options.historyStrategy !== void 0 ? { historyStrategy: this.options.historyStrategy } : {},
13067
- ...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
13068
- ...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
13069
12800
  ...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
13070
12801
  ...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
13071
- forgetStrategy: this.forgetStrategy,
13072
- ...this.options.attestationStrategy !== void 0 ? { attestationStrategy: this.options.attestationStrategy } : {},
13073
- ...this.options.classifiedStrategy !== void 0 ? { classifiedStrategy: this.options.classifiedStrategy } : {},
13074
- ...this.options.sealedRecordStrategy !== void 0 ? { sealedRecordStrategy: this.options.sealedRecordStrategy } : {},
13075
- ...this.options.portabilityStrategy !== void 0 ? { portabilityStrategy: this.options.portabilityStrategy } : {},
13076
- ...this.options.sequenceStrategy !== void 0 ? { sequenceStrategy: this.options.sequenceStrategy } : {},
13077
12802
  locale: opts?.locale,
13078
12803
  ...opts?.meta !== void 0 ? { meta: opts.meta } : {},
13079
12804
  // Thread the translator hook so Collection.put() can invoke it
@@ -13142,7 +12867,7 @@ var Noydb = class {
13142
12867
  * Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
13143
12868
  */
13144
12869
  async grant(vault, options, factors) {
13145
- return this.teamStrategy.grant(this.team, vault, options, factors);
12870
+ return this.strategies.team.grant(this.team, vault, options, factors);
13146
12871
  }
13147
12872
  /**
13148
12873
  * Revoke a user's access to a vault.
@@ -13155,7 +12880,7 @@ var Noydb = class {
13155
12880
  * Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
13156
12881
  */
13157
12882
  async revoke(vault, options, factors) {
13158
- return this.teamStrategy.revoke(this.team, vault, options, factors);
12883
+ return this.strategies.team.revoke(this.team, vault, options, factors);
13159
12884
  }
13160
12885
  /**
13161
12886
  * Grant the FR-6 `custodian` role to a user (owner-only custody API).
@@ -13168,7 +12893,7 @@ var Noydb = class {
13168
12893
  * owner-only invariant even if a host mis-configures the gate.
13169
12894
  */
13170
12895
  async grantCustodian(vault, options, factors) {
13171
- return this.custodyStrategy.grantCustodian(this, vault, options, factors);
12896
+ return this.strategies.custody.grantCustodian(this, vault, options, factors);
13172
12897
  }
13173
12898
  /** @internal — grant-custodian engine, reached only via withCustody(); the
13174
12899
  * keyring engine arrives as an argument so the floor never carries it (#267). */
@@ -13187,7 +12912,7 @@ var Noydb = class {
13187
12912
  * 'owner'` check, so an admin cannot unwind a custodianship.
13188
12913
  */
13189
12914
  async revokeCustodian(vault, options, factors) {
13190
- return this.custodyStrategy.revokeCustodian(this, vault, options, factors);
12915
+ return this.strategies.custody.revokeCustodian(this, vault, options, factors);
13191
12916
  }
13192
12917
  /** @internal — revoke-custodian engine, reached only via withCustody().
13193
12918
  * Mirrors `_grantCustodianImpl` (#267: engine passed in). */
@@ -13266,7 +12991,7 @@ var Noydb = class {
13266
12991
  * Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
13267
12992
  */
13268
12993
  async rotate(vault, collections) {
13269
- return this.teamStrategy.rotate(this.team, vault, collections);
12994
+ return this.strategies.team.rotate(this.team, vault, collections);
13270
12995
  }
13271
12996
  /** List all users with access to a vault. */
13272
12997
  async listUsers(vault) {
@@ -13279,9 +13004,9 @@ var Noydb = class {
13279
13004
  *
13280
13005
  * The walk is a two-step pipeline: first ask the adapter for the
13281
13006
  * universe of compartments it stores, then for each one attempt to
13282
- * load the calling user's keyring with the in-memory passphrase.
13007
+ * load the calling user's keyring with the in-memory secret.
13283
13008
  * Compartments where the user has no keyring file (`NoAccessError`)
13284
- * or where the passphrase doesn't unwrap (`InvalidKeyError`) are
13009
+ * or where the secret doesn't unwrap (`InvalidKeyError`) are
13285
13010
  * silently dropped from the result — the existence of those
13286
13011
  * compartments is **not** confirmed in the return value.
13287
13012
  *
@@ -13302,15 +13027,15 @@ var Noydb = class {
13302
13027
  * **Known edge case.** A vault whose keyring file
13303
13028
  * happens to have an empty wrapped-DEKs map (because the owner
13304
13029
  * granted access before any collection was created) will pass the
13305
- * `loadKeyring` probe with *any* passphrase — there are no DEKs to
13030
+ * `loadKeyring` probe with *any* secret — there are no DEKs to
13306
13031
  * unwrap, so the integrity-checked unwrap that normally rejects
13307
- * wrong passphrases never runs. The result is that an unrelated
13032
+ * wrong secrets never runs. The result is that an unrelated
13308
13033
  * principal who happens to know the user-id and the vault
13309
13034
  * name can show up in `listAccessibleVaults()` as having
13310
13035
  * access to that empty vault. They cannot read any actual
13311
13036
  * data (their DEK set is empty), so this is a metadata leak
13312
13037
  * (vault name + user-id), not a content leak. Hardening this
13313
- * via a passphrase canary in the keyring file is a deferred
13038
+ * via a secret canary in the keyring file is a deferred
13314
13039
  * follow-up.
13315
13040
  *
13316
13041
  * **Cost.** O(compartments × keyring-load) — one `loadKeyring`
@@ -13351,7 +13076,7 @@ var Noydb = class {
13351
13076
  }
13352
13077
  if (!this.options.secret) {
13353
13078
  throw new ValidationError(
13354
- "Noydb.listAccessibleVaults(): a secret (passphrase) is required when encryption is enabled."
13079
+ "Noydb.listAccessibleVaults(): a secret (secret) is required when encryption is enabled."
13355
13080
  );
13356
13081
  }
13357
13082
  const minRank = ROLE_RANK[options.minRole ?? "client"];
@@ -13490,21 +13215,21 @@ var Noydb = class {
13490
13215
  return store.resolveBackend ? store.resolveBackend(vaultId) : this.options.store;
13491
13216
  }
13492
13217
  /**
13493
- * Change the current user's passphrase for a vault.
13218
+ * Change the current user's secret for a vault.
13494
13219
  *
13495
- * Validates the new passphrase against the strength rules. Pass
13496
- * `{ allowWeakPassphrase: true }` to skip — typically only useful for
13497
- * fixtures and migrations. Pass a `PassphrasePolicy` to override the
13220
+ * Validates the new secret against the strength rules. Pass
13221
+ * `{ allowWeakSecret: true }` to skip — typically only useful for
13222
+ * fixtures and migrations. Pass a `SecretPolicy` to override the
13498
13223
  * default rules (e.g. consumer-tunable `pattern` / `customValidator`).
13499
13224
  */
13500
- async changeSecret(vault, newPassphrase, options) {
13225
+ async changeSecret(vault, newSecret, options) {
13501
13226
  this.checkPolicyOperation(vault, "changeSecret");
13502
13227
  const keyring = await this._getKeyringInternal(vault);
13503
13228
  const updated = await changeSecret(
13504
13229
  this.options.store,
13505
13230
  vault,
13506
13231
  keyring,
13507
- newPassphrase,
13232
+ newSecret,
13508
13233
  options
13509
13234
  );
13510
13235
  this.keyringCache.set(vault, updated);
@@ -13556,7 +13281,7 @@ var Noydb = class {
13556
13281
  }
13557
13282
  transaction(arg, maybeFn) {
13558
13283
  if (typeof arg === "function") {
13559
- return this.txStrategy.runTransaction(this, arg);
13284
+ return this.strategies.tx.runTransaction(this, arg);
13560
13285
  }
13561
13286
  if (typeof arg === "object" && arg !== null && arg.dryRun === true) {
13562
13287
  if (typeof maybeFn !== "function") {
@@ -13564,7 +13289,7 @@ var Noydb = class {
13564
13289
  "db.transaction({ dryRun: true }, fn) requires the callback as the second argument."
13565
13290
  );
13566
13291
  }
13567
- return this.txStrategy.runDryRun(this, maybeFn);
13292
+ return this.strategies.tx.runDryRun(this, maybeFn);
13568
13293
  }
13569
13294
  if (typeof arg === "object" && arg !== null && arg.amendment === true) {
13570
13295
  if (typeof maybeFn !== "function") {
@@ -13572,7 +13297,7 @@ var Noydb = class {
13572
13297
  "db.transaction({ amendment: true }, fn) requires the callback as the second argument."
13573
13298
  );
13574
13299
  }
13575
- return this.txStrategy.runTransaction(this, maybeFn, arg);
13300
+ return this.strategies.tx.runTransaction(this, maybeFn, arg);
13576
13301
  }
13577
13302
  const vault = arg;
13578
13303
  const comp = this.vaultCache.get(vault);
@@ -13582,7 +13307,7 @@ var Noydb = class {
13582
13307
  );
13583
13308
  }
13584
13309
  const engine = this.getSyncEngine(vault);
13585
- return this.syncStrategy.buildSyncTransaction(comp, engine);
13310
+ return this.strategies.sync.buildSyncTransaction(comp, engine);
13586
13311
  }
13587
13312
  /**
13588
13313
  * Internal accessor for the primary store — used by the tx
@@ -13863,7 +13588,7 @@ var Noydb = class {
13863
13588
  enforcer.destroy();
13864
13589
  }
13865
13590
  this.policyEnforcers.clear();
13866
- this.sessionStrategy.revokeAllSessions();
13591
+ this.strategies.session.revokeAllSessions();
13867
13592
  for (const engine of this.syncEngines.values()) {
13868
13593
  engine.stopAutoSync();
13869
13594
  }
@@ -13985,7 +13710,7 @@ var Noydb = class {
13985
13710
  * denial; resolves with `void` on success.
13986
13711
  *
13987
13712
  * @param vault The vault whose policy applies.
13988
- * @param gate Gate name — built-in (e.g. `'rotate-passphrase'`)
13713
+ * @param gate Gate name — built-in (e.g. `'rotate-secret'`)
13989
13714
  * or app-defined (`app:*`).
13990
13715
  * @param presented Caller-supplied factor proofs.
13991
13716
  */
@@ -14010,12 +13735,12 @@ var Noydb = class {
14010
13735
  * Two enforcement modes:
14011
13736
  *
14012
13737
  * 1. **Managed-mode mandatory strong-recovery.** When
14013
- * `passphraseMode === 'managed'`, the vault MUST have at least
13738
+ * `secretMode === 'managed'`, the vault MUST have at least
14014
13739
  * one **strong** recovery profile (Shamir today). Paper alone is
14015
13740
  * rejected because under managed mode the user has no memorized
14016
- * passphrase, so losing the paper sheet = losing every record.
13741
+ * secret, so losing the paper sheet = losing every record.
14017
13742
  * This check is unconditional — independent of `requireRecovery`
14018
- * and the `recover-passphrase` gate.
13743
+ * and the `recover-secret` gate.
14019
13744
  *
14020
13745
  * 2. **Opt-in strict mandatory-recovery.** When
14021
13746
  * `requireRecovery: true` is set on createNoydb (and the gate is
@@ -14029,14 +13754,14 @@ var Noydb = class {
14029
13754
  */
14030
13755
  async assertRecoveryEnrolled(vault, policy, opts) {
14031
13756
  const skipManaged = (opts?.skipManagedCheck ?? false) || this._skipNextManagedRecoveryCheck;
14032
- if (this.options.passphraseMode === "managed" && !skipManaged) {
13757
+ if (this.options.secretMode === "managed" && !skipManaged) {
14033
13758
  const enrolled2 = await hasStrongRecoveryEnrolled(this.options.store, vault);
14034
13759
  if (!enrolled2) {
14035
13760
  throw new ManagedRecoveryNotEnrolledError(vault);
14036
13761
  }
14037
13762
  }
14038
13763
  if (this.options.requireRecovery !== true) return;
14039
- const gate = policy.gates["recover-passphrase"];
13764
+ const gate = policy.gates["recover-secret"];
14040
13765
  if (gate?.enabled === false) return;
14041
13766
  const enrolled = await hasRecoveryEnrolled(this.options.store, vault);
14042
13767
  if (enrolled) return;
@@ -14051,34 +13776,6 @@ var Noydb = class {
14051
13776
  this.activeTier.set(vault, tier);
14052
13777
  }
14053
13778
  // ─── Tier-2 enroll / remove ─────────────────────────────────────
14054
- /** Add a tier-2 authenticator slot — see {@link TeamFacade.enrollAuthenticator}. */
14055
- async enrollAuthenticator(vault, options, factors) {
14056
- return this.team.enrollAuthenticator(vault, options, factors);
14057
- }
14058
- /** Remove a tier-2 authenticator slot — see {@link TeamFacade.removeAuthenticator}. */
14059
- async removeAuthenticator(vault, slotId, factors) {
14060
- return this.team.removeAuthenticator(vault, slotId, factors);
14061
- }
14062
- /** Read the slot list for a vault — see {@link TeamFacade.listAuthenticators}. */
14063
- async listAuthenticators(vault) {
14064
- return this.team.listAuthenticators(vault);
14065
- }
14066
- /** Mutate an authenticator slot's `meta` — see {@link TeamFacade.updateAuthenticator}. */
14067
- async updateAuthenticator(vault, slotId, options, factors) {
14068
- return this.team.updateAuthenticator(vault, slotId, options, factors);
14069
- }
14070
- /** Native WebAuthn enrollment — see {@link TeamFacade.enrollWebAuthn}. */
14071
- async enrollWebAuthn(vault, ceremony, factors) {
14072
- return this.team.enrollWebAuthn(vault, ceremony, factors);
14073
- }
14074
- /** List webauthn-method slots — see {@link TeamFacade.listWebAuthnSlots}. */
14075
- async listWebAuthnSlots(vault) {
14076
- return this.team.listWebAuthnSlots(vault);
14077
- }
14078
- /** Unlock via a tier-2 authenticator slot — see {@link TeamFacade.unlockViaAuthenticator}. */
14079
- async unlockViaAuthenticator(vault, slotId, verify) {
14080
- return this.team.unlockViaAuthenticator(vault, slotId, verify);
14081
- }
14082
13779
  // ─── Cover (https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md) ──────
14083
13780
  /**
14084
13781
  * Set the owner-curated cover for a vault. Throws
@@ -14102,7 +13799,7 @@ var Noydb = class {
14102
13799
  "setCover: the cover feature is not enabled. Pass `cover: true` (or a schema object) to `createNoydb`."
14103
13800
  );
14104
13801
  }
14105
- const { loadCover, saveCover, resolveSchema, validateCoverInput, mergeCustom, validateCoverSize } = await import("./cover-B5MY43CK.js");
13802
+ const { loadCover, saveCover, resolveSchema, validateCoverInput, mergeCustom, validateCoverSize } = await import("./cover-5BSNJREH.js");
14106
13803
  const schema = resolveSchema(coverOption);
14107
13804
  validateCoverInput(input, schema);
14108
13805
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -14134,76 +13831,12 @@ var Noydb = class {
14134
13831
  * regardless).
14135
13832
  */
14136
13833
  async getCover(vault, opts = {}) {
14137
- const { readCover } = await import("./cover-B5MY43CK.js");
13834
+ const { readCover } = await import("./cover-5BSNJREH.js");
14138
13835
  return readCover(this.options.store, vault, opts);
14139
13836
  }
14140
13837
  // ─── Auth introspection ─────────────────────────────────────────
14141
- /** English summary of the configured auth model — see {@link TeamFacade.describeAuthConfig}. */
14142
- async describeAuthConfig(vault) {
14143
- return this.team.describeAuthConfig(vault);
14144
- }
14145
- /** Mermaid `flowchart TB` source for the auth graph — see {@link TeamFacade.diagramAuthConfig}. */
14146
- async diagramAuthConfig(vault) {
14147
- return this.team.diagramAuthConfig(vault);
14148
- }
14149
- /** Per-user enrollment summary — see {@link TeamFacade.describeUserAuth}. */
14150
- async describeUserAuth(vault, userId, factors) {
14151
- return this.team.describeUserAuth(vault, userId, factors);
14152
- }
14153
- /** Bulk per-user enrollment summary — see {@link TeamFacade.describeAllUsersAuth}. */
14154
- async describeAllUsersAuth(vault, factors) {
14155
- return this.team.describeAllUsersAuth(vault, factors);
14156
- }
14157
13838
  // ─── Tier-1 change flows ────────────────────────────────────────
14158
- /** Rotate the user's passphrase (user remembers old) — see {@link TeamFacade.rotatePassphrase}. */
14159
- async rotatePassphrase(vault, input, factors) {
14160
- return this.team.rotatePassphrase(vault, input, factors);
14161
- }
14162
- /** Reset the passphrase using a recovery proof — see {@link TeamFacade.recoverPassphrase}. */
14163
- async recoverPassphrase(vault, input, factors) {
14164
- return this.team.recoverPassphrase(vault, input, factors);
14165
- }
14166
- /** Deliberate paper/Shamir recovery-code regeneration — see {@link TeamFacade.rotateRecovery}. */
14167
- async rotateRecovery(vault, options, factors) {
14168
- return this.team.rotateRecovery(vault, options, factors);
14169
- }
14170
- /** Atomic create-and-enroll for managed-mode vaults — see {@link TeamFacade.openVaultAndEnrollRecovery}. */
14171
- async openVaultAndEnrollRecovery(vault, opts) {
14172
- return this.team.openVaultAndEnrollRecovery(vault, opts);
14173
- }
14174
- /** Recovery flow under managed-passphrase mode — see {@link TeamFacade.recoverManagedPassphrase}. */
14175
- async recoverManagedPassphrase(vault, options) {
14176
- return this.team.recoverManagedPassphrase(vault, options);
14177
- }
14178
- /** Atomic peer-recovery of an existing user's keyring — see {@link TeamFacade.recoverUser}. */
14179
- async recoverUser(vault, options, factors) {
14180
- return this.team.recoverUser(vault, options, factors);
14181
- }
14182
- /** Persist a recovery enrollment (paper or Shamir) — see {@link TeamFacade.enrollRecovery}. */
14183
- async enrollRecovery(vault, enrollment) {
14184
- return this.team.enrollRecovery(vault, enrollment);
14185
- }
14186
- /** Read the persisted recovery entries (paper + Shamir) — see {@link TeamFacade.listRecoveryEntries}. */
14187
- async listRecoveryEntries(vault) {
14188
- return this.team.listRecoveryEntries(vault);
14189
- }
14190
13839
  // ─── Tier-3 enroll / unlock ─────────────────────────────────────
14191
- /** Register a tier-3 quick-unlock state — see {@link TeamFacade.enrollUnlock}. */
14192
- async enrollUnlock(vault, state, factors) {
14193
- return this.team.enrollUnlock(vault, state, factors);
14194
- }
14195
- /** Resume a session via the registered tier-3 state — see {@link TeamFacade.unlockViaPin}. */
14196
- async unlockViaPin(vault, resume) {
14197
- return this.team.unlockViaPin(vault, resume);
14198
- }
14199
- /** Drop the tier-3 state for a vault — see {@link TeamFacade.clearQuickUnlock}. */
14200
- clearQuickUnlock(vault) {
14201
- this.team.clearQuickUnlock(vault);
14202
- }
14203
- /** Public defensive-copy accessor for the unlocked keyring — see {@link TeamFacade.getKeyring}. */
14204
- async getKeyring(vault) {
14205
- return this.team.getKeyring(vault);
14206
- }
14207
13840
  /**
14208
13841
  * Live-reference variant used by the hub's own code paths. Internal
14209
13842
  * mutations on `deks` (e.g. {@link ensureCollectionDEK} adding a
@@ -14224,7 +13857,7 @@ var Noydb = class {
14224
13857
  }
14225
13858
  await assertKeyringOpenAllowed(this.options.store, vault, this.options.user, opts.create);
14226
13859
  let effectiveSecret;
14227
- if (this.options.passphraseMode === "managed") {
13860
+ if (this.options.secretMode === "managed") {
14228
13861
  effectiveSecret = await resolveManagedSecret(
14229
13862
  this.options.store,
14230
13863
  vault,
@@ -14234,7 +13867,7 @@ var Noydb = class {
14234
13867
  effectiveSecret = this.options.secret;
14235
13868
  }
14236
13869
  if (!effectiveSecret) {
14237
- throw new ValidationError("A secret (passphrase) or getKeyring callback is required when encryption is enabled");
13870
+ throw new ValidationError("A secret (secret) or getKeyring callback is required when encryption is enabled");
14238
13871
  }
14239
13872
  let keyring;
14240
13873
  try {
@@ -14248,10 +13881,10 @@ var Noydb = class {
14248
13881
  effectiveSecret,
14249
13882
  {
14250
13883
  // Managed mode generates 256-bit base64 strings that don't satisfy
14251
- // the human-passphrase strength rules (no spaces, no "words").
13884
+ // the human-secret strength rules (no spaces, no "words").
14252
13885
  // Skip validation in managed mode — the entropy floor is already
14253
13886
  // 256 bits by construction.
14254
- validate: this.options.passphraseMode === "managed" ? false : this.options.validatePassphrase === true
13887
+ validate: this.options.secretMode === "managed" ? false : this.options.validateSecret === true
14255
13888
  }
14256
13889
  );
14257
13890
  } else if (err instanceof InvalidKeyError && this.options.onInvalidKey === "reset") {
@@ -14262,7 +13895,7 @@ var Noydb = class {
14262
13895
  this.options.user,
14263
13896
  effectiveSecret,
14264
13897
  {
14265
- validate: this.options.passphraseMode === "managed" ? false : this.options.validatePassphrase === true
13898
+ validate: this.options.secretMode === "managed" ? false : this.options.validateSecret === true
14266
13899
  }
14267
13900
  );
14268
13901
  } else {
@@ -14300,34 +13933,34 @@ var Noydb = class {
14300
13933
  async function createNoydb(options) {
14301
13934
  if (!options.store) options = { ...options, store: memoryStore() };
14302
13935
  const encrypted = options.encrypt !== false;
14303
- const managed = options.passphraseMode === "managed";
13936
+ const managed = options.secretMode === "managed";
14304
13937
  if (options.secret && options.getKeyring) {
14305
13938
  throw new ValidationError("Provide either `secret` or `getKeyring`, not both");
14306
13939
  }
14307
13940
  if (managed) {
14308
13941
  if (options.secret) {
14309
13942
  throw new ValidationError(
14310
- '`passphraseMode: "managed"` is mutually exclusive with `secret` \u2014 managed mode generates the passphrase itself. Drop `secret`.'
13943
+ '`secretMode: "managed"` is mutually exclusive with `secret` \u2014 managed mode generates the secret itself. Drop `secret`.'
14311
13944
  );
14312
13945
  }
14313
13946
  if (options.getKeyring) {
14314
13947
  throw new ValidationError(
14315
- '`passphraseMode: "managed"` is mutually exclusive with `getKeyring` \u2014 a custom unlock callback would bypass the sealing flow. Drop `getKeyring`.'
13948
+ '`secretMode: "managed"` is mutually exclusive with `getKeyring` \u2014 a custom unlock callback would bypass the sealing flow. Drop `getKeyring`.'
14316
13949
  );
14317
13950
  }
14318
13951
  if (!options.sealingKey) {
14319
13952
  throw new ValidationError(
14320
- '`passphraseMode: "managed"` requires `sealingKey: SealingKeyProvider` (see @noy-db/seal-macos-keychain / @noy-db/seal-aws-kms / etc.).'
13953
+ '`secretMode: "managed"` requires `sealingKey: SealingKeyProvider` (see @noy-db/seal-macos-keychain / @noy-db/seal-aws-kms / etc.).'
14321
13954
  );
14322
13955
  }
14323
13956
  }
14324
13957
  if (encrypted && !managed && !options.secret && !options.getKeyring) {
14325
- throw new ValidationError("A secret (passphrase) or getKeyring callback is required when encryption is enabled");
13958
+ throw new ValidationError("A secret (secret) or getKeyring callback is required when encryption is enabled");
14326
13959
  }
14327
13960
  if (!options.coordinationStrategy) options = { ...options, coordinationStrategy: await createDefaultCoordinationProvider(options.store) };
14328
- if (!options.userApiFactory) options = { ...options, userApiFactory: (await import("./api-UPAT2O3M.js")).createUserApi };
13961
+ if (!options.userApiFactory) options = { ...options, userApiFactory: (await import("./api-22ES33N3.js")).createUserApi };
14329
13962
  if (!options.policyFactory) {
14330
- const policyModule = await import("./policy-EAXSJNOT.js");
13963
+ const policyModule = await import("./policy-IY2YEA3A.js");
14331
13964
  options = { ...options, policyFactory: policyModule.createNoydbPolicy, policyCheckGateFn: policyModule.checkGate };
14332
13965
  }
14333
13966
  return new Noydb(options);
@@ -14364,4 +13997,4 @@ export {
14364
13997
  Noydb,
14365
13998
  createNoydb
14366
13999
  };
14367
- //# sourceMappingURL=chunk-LUH2MPEF.js.map
14000
+ //# sourceMappingURL=chunk-EEZCB74X.js.map