@noy-db/hub 0.3.0-pre.2 → 0.3.0-pre.4

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 (383) hide show
  1. package/dist/adapter/index.d.ts +2 -2
  2. package/dist/adapter/index.js +1 -1
  3. package/dist/aggregate/index.d.ts +3 -3
  4. package/dist/aggregate/index.js +4 -4
  5. package/dist/api-JOXUNSKP.js +20 -0
  6. package/dist/as/index.d.ts +4 -4
  7. package/dist/as/index.js +12 -6
  8. package/dist/at/index.d.ts +2 -2
  9. package/dist/attestation/index.d.ts +3 -3
  10. package/dist/attestation/index.js +19 -13
  11. package/dist/attestation/index.js.map +1 -1
  12. package/dist/{backup-KMJQ66MF.js → backup-MOB27UUN.js} +12 -6
  13. package/dist/{backup-KMJQ66MF.js.map → backup-MOB27UUN.js.map} +1 -1
  14. package/dist/blobs/index.d.ts +4 -4
  15. package/dist/blobs/index.js +11 -5
  16. package/dist/blobs/index.js.map +1 -1
  17. package/dist/bundle/index.d.ts +5 -5
  18. package/dist/bundle/index.js +21 -15
  19. package/dist/bundle/index.js.map +1 -1
  20. package/dist/{bundle-PwBGkhpe.d.ts → bundle-Bs13EZtX.d.ts} +1 -1
  21. package/dist/by/index.js +2 -2
  22. package/dist/cargo/index.d.ts +4 -4
  23. package/dist/cargo/index.js +23 -17
  24. package/dist/{chunk-SMXWYP24.js → chunk-3QRQOBS7.js} +3 -3
  25. package/dist/{chunk-QHJW5EXU.js → chunk-3Y4QLJ6K.js} +2 -2
  26. package/dist/{chunk-NF5JWERG.js → chunk-43ISXURO.js} +2 -2
  27. package/dist/{chunk-5LUY7UTV.js → chunk-4K3MQ5S3.js} +2 -2
  28. package/dist/{chunk-QZISFCVG.js → chunk-5CY35H55.js} +11 -9
  29. package/dist/{chunk-QZISFCVG.js.map → chunk-5CY35H55.js.map} +1 -1
  30. package/dist/chunk-5EWYUR5P.js +37 -0
  31. package/dist/chunk-5EWYUR5P.js.map +1 -0
  32. package/dist/{chunk-Y22T3KQE.js → chunk-5MRE3C4Q.js} +5 -5
  33. package/dist/{chunk-M6OST55S.js → chunk-5W7AOFWA.js} +2 -2
  34. package/dist/{chunk-AXRXJTE2.js → chunk-6HNKCKFZ.js} +7 -7
  35. package/dist/{chunk-UAG5KWVA.js → chunk-6RXPSMKR.js} +3 -3
  36. package/dist/{chunk-TJYQIGAP.js → chunk-7J7JRYXW.js} +9 -5
  37. package/dist/chunk-7J7JRYXW.js.map +1 -0
  38. package/dist/{chunk-UDRIWL7A.js → chunk-A5DYVMDR.js} +3 -3
  39. package/dist/chunk-AF5ZRTZ4.js +108 -0
  40. package/dist/chunk-AF5ZRTZ4.js.map +1 -0
  41. package/dist/{chunk-I3TIKTJO.js → chunk-BKGIWGCX.js} +2 -2
  42. package/dist/{chunk-IO6GRPT6.js → chunk-BMQOH7MM.js} +2 -2
  43. package/dist/{chunk-26LGBE4T.js → chunk-CPXPHQGX.js} +6 -4
  44. package/dist/{chunk-26LGBE4T.js.map → chunk-CPXPHQGX.js.map} +1 -1
  45. package/dist/{chunk-FISN7WE4.js → chunk-EWR7HL3K.js} +4 -4
  46. package/dist/{chunk-AQTBSL7R.js → chunk-FH52CDEW.js} +5 -5
  47. package/dist/chunk-G4MGYGSS.js +130 -0
  48. package/dist/chunk-G4MGYGSS.js.map +1 -0
  49. package/dist/{chunk-UV5MFVO3.js → chunk-G7RDYYTE.js} +2 -2
  50. package/dist/{chunk-UIU2THRG.js → chunk-GBTUANXF.js} +16 -297
  51. package/dist/chunk-GBTUANXF.js.map +1 -0
  52. package/dist/{chunk-TEILUWOI.js → chunk-GOUNIHFA.js} +10 -10
  53. package/dist/{chunk-LXQT4WMP.js → chunk-GQOT6QJR.js} +8 -6
  54. package/dist/{chunk-LXQT4WMP.js.map → chunk-GQOT6QJR.js.map} +1 -1
  55. package/dist/{chunk-RUEKROOS.js → chunk-GXGK22QU.js} +2 -2
  56. package/dist/{chunk-IELYAOGG.js → chunk-GZZL5R73.js} +4 -4
  57. package/dist/{chunk-JNUWZ6D3.js → chunk-H5XRIJX3.js} +7 -5
  58. package/dist/{chunk-JNUWZ6D3.js.map → chunk-H5XRIJX3.js.map} +1 -1
  59. package/dist/{chunk-CWPPNPOH.js → chunk-H7RYPVMJ.js} +2 -2
  60. package/dist/{chunk-5N6CZTCY.js → chunk-HBKDR7R3.js} +3 -3
  61. package/dist/{chunk-KXGNJJXB.js → chunk-HLUKZ36Q.js} +9 -9
  62. package/dist/{chunk-LMTH2RM6.js → chunk-HMXLN43G.js} +2 -2
  63. package/dist/{chunk-BG3SPSR4.js → chunk-HY6ZGGEC.js} +2 -2
  64. package/dist/{chunk-UPJNJGGA.js → chunk-K5P46KB3.js} +27 -10
  65. package/dist/chunk-K5P46KB3.js.map +1 -0
  66. package/dist/chunk-KYY7L72M.js +106 -0
  67. package/dist/chunk-KYY7L72M.js.map +1 -0
  68. package/dist/{chunk-62QYRORB.js → chunk-LIP6JWYK.js} +3 -3
  69. package/dist/{chunk-5TDJ56JE.js → chunk-LN22XH4B.js} +1 -1
  70. package/dist/chunk-LN22XH4B.js.map +1 -0
  71. package/dist/chunk-LP7BEXCT.js +32 -0
  72. package/dist/chunk-LP7BEXCT.js.map +1 -0
  73. package/dist/{chunk-IGUYVGGI.js → chunk-LPRPVCNY.js} +5 -5
  74. package/dist/{chunk-AIWULCUO.js → chunk-M66NAZA4.js} +5 -3
  75. package/dist/{chunk-AIWULCUO.js.map → chunk-M66NAZA4.js.map} +1 -1
  76. package/dist/{chunk-KVOXU4T5.js → chunk-N5YVZHCB.js} +2 -2
  77. package/dist/{chunk-76722EBH.js → chunk-NB47TXGP.js} +14 -12
  78. package/dist/{chunk-76722EBH.js.map → chunk-NB47TXGP.js.map} +1 -1
  79. package/dist/chunk-NO272T7Q.js +194 -0
  80. package/dist/chunk-NO272T7Q.js.map +1 -0
  81. package/dist/{chunk-SRB2XEWB.js → chunk-O2DB4C3M.js} +8 -6
  82. package/dist/{chunk-SRB2XEWB.js.map → chunk-O2DB4C3M.js.map} +1 -1
  83. package/dist/{chunk-IUEN57TV.js → chunk-OFBFAVLI.js} +6 -6
  84. package/dist/{chunk-MTMJVJ5W.js → chunk-OPTFANOX.js} +5 -3
  85. package/dist/chunk-OPTFANOX.js.map +1 -0
  86. package/dist/{chunk-5O3AOPDT.js → chunk-OVO2RZAE.js} +212 -439
  87. package/dist/chunk-OVO2RZAE.js.map +1 -0
  88. package/dist/{chunk-GYGWYIOZ.js → chunk-P27Z66EB.js} +7 -5
  89. package/dist/{chunk-GYGWYIOZ.js.map → chunk-P27Z66EB.js.map} +1 -1
  90. package/dist/{chunk-HCIPRAGS.js → chunk-P2LDXRGP.js} +2 -2
  91. package/dist/chunk-P3NGV5RV.js +41 -0
  92. package/dist/chunk-P3NGV5RV.js.map +1 -0
  93. package/dist/{chunk-5R3ERCDH.js → chunk-P3V7JTB6.js} +25 -9
  94. package/dist/{chunk-5R3ERCDH.js.map → chunk-P3V7JTB6.js.map} +1 -1
  95. package/dist/{chunk-LV7M27WM.js → chunk-P5WXDYMD.js} +8 -197
  96. package/dist/chunk-P5WXDYMD.js.map +1 -0
  97. package/dist/chunk-PGFY7IRW.js +95 -0
  98. package/dist/chunk-PGFY7IRW.js.map +1 -0
  99. package/dist/chunk-QKVILR7N.js +25 -0
  100. package/dist/chunk-QKVILR7N.js.map +1 -0
  101. package/dist/{chunk-V7RWQRG7.js → chunk-QNTEDPWP.js} +3 -3
  102. package/dist/{chunk-Q7SS3IME.js → chunk-RDHAGBEB.js} +3 -3
  103. package/dist/{chunk-EIZUR2XW.js → chunk-RTS23VIJ.js} +2 -2
  104. package/dist/{chunk-LFLXAY2W.js → chunk-SEQ2JI3Y.js} +9 -7
  105. package/dist/{chunk-LFLXAY2W.js.map → chunk-SEQ2JI3Y.js.map} +1 -1
  106. package/dist/{chunk-AZAOEIKW.js → chunk-SW56GSYC.js} +2 -2
  107. package/dist/{chunk-TA66UMI4.js → chunk-T2EGAXPM.js} +2 -2
  108. package/dist/{chunk-SM3AVUHC.js → chunk-T45LAT2Y.js} +2 -2
  109. package/dist/{chunk-SKF73JOP.js → chunk-T65UZXR6.js} +3 -3
  110. package/dist/{chunk-ITNUCOXM.js → chunk-TB5RNNJ4.js} +7 -5
  111. package/dist/{chunk-ITNUCOXM.js.map → chunk-TB5RNNJ4.js.map} +1 -1
  112. package/dist/chunk-TCIUO62Z.js +29 -0
  113. package/dist/chunk-TCIUO62Z.js.map +1 -0
  114. package/dist/chunk-THNJ3IKU.js +17 -0
  115. package/dist/chunk-THNJ3IKU.js.map +1 -0
  116. package/dist/chunk-TLJOJBZD.js +404 -0
  117. package/dist/chunk-TLJOJBZD.js.map +1 -0
  118. package/dist/chunk-TQ3REHVF.js +95 -0
  119. package/dist/chunk-TQ3REHVF.js.map +1 -0
  120. package/dist/{chunk-DGDI2D4M.js → chunk-TVRQ3RYH.js} +28 -7
  121. package/dist/chunk-TVRQ3RYH.js.map +1 -0
  122. package/dist/{chunk-PSMV73A5.js → chunk-TYGW5TOR.js} +7 -7
  123. package/dist/{chunk-ZYUC53LT.js → chunk-U23JUUPX.js} +58 -2
  124. package/dist/{chunk-ZYUC53LT.js.map → chunk-U23JUUPX.js.map} +1 -1
  125. package/dist/{chunk-3YFXJ3ZP.js → chunk-U24XHXNK.js} +2 -2
  126. package/dist/chunk-ULIHDPKL.js +94 -0
  127. package/dist/chunk-ULIHDPKL.js.map +1 -0
  128. package/dist/chunk-UOEWDCUX.js +69 -0
  129. package/dist/chunk-UOEWDCUX.js.map +1 -0
  130. package/dist/{chunk-WWGT2MDV.js → chunk-VAWY44JW.js} +8 -8
  131. package/dist/{chunk-WWGT2MDV.js.map → chunk-VAWY44JW.js.map} +1 -1
  132. package/dist/chunk-VFRNWE5P.js +239 -0
  133. package/dist/chunk-VFRNWE5P.js.map +1 -0
  134. package/dist/{chunk-IPB7FTQX.js → chunk-VMJ5URU7.js} +10 -8
  135. package/dist/chunk-VMJ5URU7.js.map +1 -0
  136. package/dist/{chunk-VFQGRQIH.js → chunk-VPCMJ5Z4.js} +7 -5
  137. package/dist/{chunk-VFQGRQIH.js.map → chunk-VPCMJ5Z4.js.map} +1 -1
  138. package/dist/{chunk-VCTFO5CO.js → chunk-VRPBEOWU.js} +2 -2
  139. package/dist/{chunk-ZCGAHGUS.js → chunk-VWGCJUTV.js} +2 -2
  140. package/dist/{chunk-XXYIOFUB.js → chunk-XJR3COJO.js} +5 -5
  141. package/dist/{chunk-PKHL44ER.js → chunk-XYYW64LB.js} +2 -2
  142. package/dist/{chunk-IAGBDSCS.js → chunk-YFF2RP3X.js} +2 -2
  143. package/dist/{chunk-MD3Y6J3L.js → chunk-Z3FZC5GV.js} +7 -5
  144. package/dist/{chunk-MD3Y6J3L.js.map → chunk-Z3FZC5GV.js.map} +1 -1
  145. package/dist/{chunk-DFEMTNPJ.js → chunk-Z5PIUYNB.js} +10 -8
  146. package/dist/{chunk-DFEMTNPJ.js.map → chunk-Z5PIUYNB.js.map} +1 -1
  147. package/dist/{chunk-WYSO2NIH.js → chunk-Z7KI4WHR.js} +2 -2
  148. package/dist/chunk-ZKF6HH7V.js +120 -0
  149. package/dist/chunk-ZKF6HH7V.js.map +1 -0
  150. package/dist/{chunk-I2NOIW44.js → chunk-ZKYMKF2S.js} +8 -6
  151. package/dist/{chunk-I2NOIW44.js.map → chunk-ZKYMKF2S.js.map} +1 -1
  152. package/dist/{chunk-PSHOXR6C.js → chunk-ZPHDGUZZ.js} +737 -1082
  153. package/dist/chunk-ZPHDGUZZ.js.map +1 -0
  154. package/dist/{chunk-CMGR4ZEW.js → chunk-ZROMNP7Q.js} +2 -2
  155. package/dist/classified/index.d.ts +17 -0
  156. package/dist/classified/index.js +38 -0
  157. package/dist/collection-facade-MKEBZDWW.js +39 -0
  158. package/dist/computed-BMMEFRFJ.js +11 -0
  159. package/dist/config-drift-KGM7ZRW4.js +24 -0
  160. package/dist/config-drift-KGM7ZRW4.js.map +1 -0
  161. package/dist/consent/index.d.ts +3 -3
  162. package/dist/consent/index.js +10 -4
  163. package/dist/consent/index.js.map +1 -1
  164. package/dist/crdt/index.d.ts +3 -3
  165. package/dist/delegation-BQNIEHZE.js +25 -0
  166. package/dist/derivations/index.d.ts +4 -4
  167. package/dist/derivations/index.js +12 -6
  168. package/dist/describe/index.d.ts +1 -1
  169. package/dist/{describe-Ccd1hS7a.d.ts → describe-C6iHNlqJ.d.ts} +19 -0
  170. package/dist/{dev-unlock-h0K-UZTk.d.ts → dev-unlock-Cqd5Xv5J.d.ts} +1 -1
  171. package/dist/{enclave-UL5LW66V.js → enclave-YN6223OG.js} +47 -18
  172. package/dist/executor-CBTNU5VZ.js +9 -0
  173. package/dist/executor-DJHNSTIR.js +9 -0
  174. package/dist/executor-FGISLQIN.js +21 -0
  175. package/dist/export-accessible-P7SLRLK3.js +23 -0
  176. package/dist/extract-partition-RNVSFHAB.js +36 -0
  177. package/dist/{fanout-sidecar-GF3DJ6KR.js → fanout-sidecar-WS22Q5WH.js} +17 -14
  178. package/dist/fanout-sidecar-WS22Q5WH.js.map +1 -0
  179. package/dist/fence-watcher-DHQ775JB.js +69 -0
  180. package/dist/fence-watcher-DHQ775JB.js.map +1 -0
  181. package/dist/find-RNBG7LBY.js +11 -0
  182. package/dist/forget/index.js +10 -4
  183. package/dist/forget/index.js.map +1 -1
  184. package/dist/guards/index.d.ts +4 -4
  185. package/dist/guards/index.js +3 -3
  186. package/dist/{hash-CdSr06sm.d.ts → hash-D8Q5MJLA.d.ts} +7 -2
  187. package/dist/history/index.d.ts +4 -4
  188. package/dist/history/index.js +12 -6
  189. package/dist/history/index.js.map +1 -1
  190. package/dist/i18n/index.d.ts +3 -3
  191. package/dist/i18n/index.js +14 -8
  192. package/dist/i18n/index.js.map +1 -1
  193. package/dist/in/index.d.ts +2 -2
  194. package/dist/{index-_6At2_9_.d.ts → index-D4GQe1Rx.d.ts} +1058 -49
  195. package/dist/{index-CGLLRtFc.d.ts → index-DRxk8q_7.d.ts} +3 -3
  196. package/dist/index.d.ts +60 -15
  197. package/dist/index.js +1081 -121
  198. package/dist/index.js.map +1 -1
  199. package/dist/indexing/index.d.ts +3 -3
  200. package/dist/indexing/index.js +4 -4
  201. package/dist/issue-W5QG53B5.js +19 -0
  202. package/dist/json-schema-I22JCYCG.js +44 -0
  203. package/dist/json-schema-I22JCYCG.js.map +1 -0
  204. package/dist/kernel/index.d.ts +3 -3
  205. package/dist/kernel/index.js +13 -7
  206. package/dist/lazy/index.d.ts +21 -0
  207. package/dist/lazy/index.js +12 -0
  208. package/dist/{ledger-RYI35CDS.js → ledger-KZWBKAG5.js} +12 -6
  209. package/dist/liberate-GMGCHIND.js +24 -0
  210. package/dist/link-set-UQEIYQAM.js +31 -0
  211. package/dist/materialized-views/index.d.ts +4 -4
  212. package/dist/materialized-views/index.js +16 -10
  213. package/dist/{mime-magic-B4RoFj3B.d.ts → mime-magic-DmwT7OzZ.d.ts} +1 -1
  214. package/dist/noydb-KS2O2MRI.js +60 -0
  215. package/dist/on/index.d.ts +2 -2
  216. package/dist/on/index.js +10 -4
  217. package/dist/overlay-views/index.d.ts +4 -4
  218. package/dist/overlay-views/index.js +4 -4
  219. package/dist/periods/index.d.ts +3 -3
  220. package/dist/periods/index.js +13 -7
  221. package/dist/pod/index.d.ts +3 -3
  222. package/dist/pod/index.js +12 -6
  223. package/dist/{policy-IXK4FVXP.js → policy-YIKUH4AD.js} +5 -5
  224. package/dist/portability/index.d.ts +3 -3
  225. package/dist/portability/index.js +8 -8
  226. package/dist/{public-envelope-JHDQCPSX.js → public-envelope-MRN5YYZZ.js} +4 -4
  227. package/dist/query/index.d.ts +2 -2
  228. package/dist/query/index.js +6 -6
  229. package/dist/register-K6DDSIXN.js +21 -0
  230. package/dist/registry-IMNMHWTM.js +17 -0
  231. package/dist/registry-K6VUQXKV.js +19 -0
  232. package/dist/registry-ZVO3T4M5.js +9 -0
  233. package/dist/registry-ZVO3T4M5.js.map +1 -0
  234. package/dist/request-withdrawal-EHALV66Y.js +31 -0
  235. package/dist/request-withdrawal-EHALV66Y.js.map +1 -0
  236. package/dist/reveal-TBLTFWQ2.js +38 -0
  237. package/dist/reveal-TBLTFWQ2.js.map +1 -0
  238. package/dist/revoke-MHAUAESM.js +24 -0
  239. package/dist/revoke-MHAUAESM.js.map +1 -0
  240. package/dist/sealed-record/index.d.ts +3 -3
  241. package/dist/sealed-record/index.js +13 -7
  242. package/dist/sealed-record/index.js.map +1 -1
  243. package/dist/session/index.d.ts +4 -4
  244. package/dist/session/index.js +10 -4
  245. package/dist/session/index.js.map +1 -1
  246. package/dist/shadow/index.d.ts +3 -3
  247. package/dist/shadow/index.js +2 -2
  248. package/dist/signer-PQ74YXRY.js +25 -0
  249. package/dist/signer-PQ74YXRY.js.map +1 -0
  250. package/dist/snapshots/index.d.ts +3 -3
  251. package/dist/snapshots/index.js +11 -5
  252. package/dist/snapshots/index.js.map +1 -1
  253. package/dist/{stale-3JWHNDIY.js → stale-7Q62KVI3.js} +2 -2
  254. package/dist/stale-7Q62KVI3.js.map +1 -0
  255. package/dist/storage-5E6YB2JY.js +21 -0
  256. package/dist/storage-5E6YB2JY.js.map +1 -0
  257. package/dist/{store-coordination-provider-3I7XWZZK.js → store-coordination-provider-JJCEMTAE.js} +3 -3
  258. package/dist/sync/index.d.ts +2 -2
  259. package/dist/sync/index.js +10 -4
  260. package/dist/sync/index.js.map +1 -1
  261. package/dist/team/index.d.ts +18 -4
  262. package/dist/team/index.js +24 -11
  263. package/dist/tiers/index.d.ts +2 -2
  264. package/dist/tiers/index.js +11 -5
  265. package/dist/to/index.d.ts +2 -2
  266. package/dist/to/index.js +1 -1
  267. package/dist/{transition-guard-DqodPNKw.d.ts → transition-guard-C4hvR-Ac.d.ts} +1 -1
  268. package/dist/tx/index.d.ts +3 -3
  269. package/dist/tx/index.js +3 -3
  270. package/dist/ui/index.d.ts +1 -1
  271. package/dist/util/index.js +1 -1
  272. package/dist/validators-Ctgkj5qd.d.ts +101 -0
  273. package/dist/{vault-diff-BtpiBvic.d.ts → vault-diff-B1Ir6EGs.d.ts} +1 -1
  274. package/dist/verify-YB5LQHNA.js +139 -0
  275. package/dist/verify-YB5LQHNA.js.map +1 -0
  276. package/dist/walk-5C3GPKT2.js +241 -0
  277. package/dist/walk-5C3GPKT2.js.map +1 -0
  278. package/dist/with/index.d.ts +3 -3
  279. package/dist/with/index.js +12 -6
  280. package/dist/{with-materialized-view-DMmWtYfJ.d.ts → with-materialized-view-Bp65kKdQ.d.ts} +1 -1
  281. package/dist/{with-overlayed-view-D_IB2nkM.d.ts → with-overlayed-view-BRhdQNrK.d.ts} +1 -1
  282. package/dist/{with-rollup-em2wxoHP.d.ts → with-rollup-bQRPc3y1.d.ts} +1 -1
  283. package/dist/withdraw-accessible-JMX2TCPX.js +28 -0
  284. package/dist/withdraw-accessible-JMX2TCPX.js.map +1 -0
  285. package/package.json +11 -3
  286. package/dist/api-RW3KP7WU.js +0 -14
  287. package/dist/chunk-5O3AOPDT.js.map +0 -1
  288. package/dist/chunk-5TDJ56JE.js.map +0 -1
  289. package/dist/chunk-DGDI2D4M.js.map +0 -1
  290. package/dist/chunk-IPB7FTQX.js.map +0 -1
  291. package/dist/chunk-LV7M27WM.js.map +0 -1
  292. package/dist/chunk-M2YKN37S.js +0 -524
  293. package/dist/chunk-M2YKN37S.js.map +0 -1
  294. package/dist/chunk-MTMJVJ5W.js.map +0 -1
  295. package/dist/chunk-PSHOXR6C.js.map +0 -1
  296. package/dist/chunk-TJYQIGAP.js.map +0 -1
  297. package/dist/chunk-UIU2THRG.js.map +0 -1
  298. package/dist/chunk-UPJNJGGA.js.map +0 -1
  299. package/dist/collection-facade-GQAOGJP2.js +0 -33
  300. package/dist/delegation-UL5HKLER.js +0 -19
  301. package/dist/executor-2FWQRLMG.js +0 -15
  302. package/dist/executor-QZ7BXICW.js +0 -9
  303. package/dist/executor-Z5ZLJVTV.js +0 -9
  304. package/dist/export-accessible-KRV5W4GH.js +0 -17
  305. package/dist/extract-partition-GLKBOXFQ.js +0 -30
  306. package/dist/fanout-sidecar-GF3DJ6KR.js.map +0 -1
  307. package/dist/issue-Y6UVIR43.js +0 -13
  308. package/dist/liberate-CRPZEV7O.js +0 -18
  309. package/dist/noydb-LDEBLNHY.js +0 -50
  310. package/dist/registry-45RJNWGU.js +0 -9
  311. package/dist/registry-5GRV5VXI.js +0 -13
  312. package/dist/registry-WEUCHBO4.js +0 -11
  313. package/dist/request-withdrawal-GBPH2FDY.js +0 -25
  314. package/dist/revoke-TUFRGI6S.js +0 -18
  315. package/dist/signer-PNKTBVF7.js +0 -19
  316. package/dist/withdraw-accessible-FFS46EOD.js +0 -22
  317. /package/dist/{api-RW3KP7WU.js.map → api-JOXUNSKP.js.map} +0 -0
  318. /package/dist/{chunk-SMXWYP24.js.map → chunk-3QRQOBS7.js.map} +0 -0
  319. /package/dist/{chunk-QHJW5EXU.js.map → chunk-3Y4QLJ6K.js.map} +0 -0
  320. /package/dist/{chunk-NF5JWERG.js.map → chunk-43ISXURO.js.map} +0 -0
  321. /package/dist/{chunk-5LUY7UTV.js.map → chunk-4K3MQ5S3.js.map} +0 -0
  322. /package/dist/{chunk-Y22T3KQE.js.map → chunk-5MRE3C4Q.js.map} +0 -0
  323. /package/dist/{chunk-M6OST55S.js.map → chunk-5W7AOFWA.js.map} +0 -0
  324. /package/dist/{chunk-AXRXJTE2.js.map → chunk-6HNKCKFZ.js.map} +0 -0
  325. /package/dist/{chunk-UAG5KWVA.js.map → chunk-6RXPSMKR.js.map} +0 -0
  326. /package/dist/{chunk-UDRIWL7A.js.map → chunk-A5DYVMDR.js.map} +0 -0
  327. /package/dist/{chunk-I3TIKTJO.js.map → chunk-BKGIWGCX.js.map} +0 -0
  328. /package/dist/{chunk-IO6GRPT6.js.map → chunk-BMQOH7MM.js.map} +0 -0
  329. /package/dist/{chunk-FISN7WE4.js.map → chunk-EWR7HL3K.js.map} +0 -0
  330. /package/dist/{chunk-AQTBSL7R.js.map → chunk-FH52CDEW.js.map} +0 -0
  331. /package/dist/{chunk-UV5MFVO3.js.map → chunk-G7RDYYTE.js.map} +0 -0
  332. /package/dist/{chunk-TEILUWOI.js.map → chunk-GOUNIHFA.js.map} +0 -0
  333. /package/dist/{chunk-RUEKROOS.js.map → chunk-GXGK22QU.js.map} +0 -0
  334. /package/dist/{chunk-IELYAOGG.js.map → chunk-GZZL5R73.js.map} +0 -0
  335. /package/dist/{chunk-CWPPNPOH.js.map → chunk-H7RYPVMJ.js.map} +0 -0
  336. /package/dist/{chunk-5N6CZTCY.js.map → chunk-HBKDR7R3.js.map} +0 -0
  337. /package/dist/{chunk-KXGNJJXB.js.map → chunk-HLUKZ36Q.js.map} +0 -0
  338. /package/dist/{chunk-LMTH2RM6.js.map → chunk-HMXLN43G.js.map} +0 -0
  339. /package/dist/{chunk-BG3SPSR4.js.map → chunk-HY6ZGGEC.js.map} +0 -0
  340. /package/dist/{chunk-62QYRORB.js.map → chunk-LIP6JWYK.js.map} +0 -0
  341. /package/dist/{chunk-IGUYVGGI.js.map → chunk-LPRPVCNY.js.map} +0 -0
  342. /package/dist/{chunk-KVOXU4T5.js.map → chunk-N5YVZHCB.js.map} +0 -0
  343. /package/dist/{chunk-IUEN57TV.js.map → chunk-OFBFAVLI.js.map} +0 -0
  344. /package/dist/{chunk-HCIPRAGS.js.map → chunk-P2LDXRGP.js.map} +0 -0
  345. /package/dist/{chunk-V7RWQRG7.js.map → chunk-QNTEDPWP.js.map} +0 -0
  346. /package/dist/{chunk-Q7SS3IME.js.map → chunk-RDHAGBEB.js.map} +0 -0
  347. /package/dist/{chunk-EIZUR2XW.js.map → chunk-RTS23VIJ.js.map} +0 -0
  348. /package/dist/{chunk-AZAOEIKW.js.map → chunk-SW56GSYC.js.map} +0 -0
  349. /package/dist/{chunk-TA66UMI4.js.map → chunk-T2EGAXPM.js.map} +0 -0
  350. /package/dist/{chunk-SM3AVUHC.js.map → chunk-T45LAT2Y.js.map} +0 -0
  351. /package/dist/{chunk-SKF73JOP.js.map → chunk-T65UZXR6.js.map} +0 -0
  352. /package/dist/{chunk-PSMV73A5.js.map → chunk-TYGW5TOR.js.map} +0 -0
  353. /package/dist/{chunk-3YFXJ3ZP.js.map → chunk-U24XHXNK.js.map} +0 -0
  354. /package/dist/{chunk-VCTFO5CO.js.map → chunk-VRPBEOWU.js.map} +0 -0
  355. /package/dist/{chunk-ZCGAHGUS.js.map → chunk-VWGCJUTV.js.map} +0 -0
  356. /package/dist/{chunk-XXYIOFUB.js.map → chunk-XJR3COJO.js.map} +0 -0
  357. /package/dist/{chunk-PKHL44ER.js.map → chunk-XYYW64LB.js.map} +0 -0
  358. /package/dist/{chunk-IAGBDSCS.js.map → chunk-YFF2RP3X.js.map} +0 -0
  359. /package/dist/{chunk-WYSO2NIH.js.map → chunk-Z7KI4WHR.js.map} +0 -0
  360. /package/dist/{chunk-CMGR4ZEW.js.map → chunk-ZROMNP7Q.js.map} +0 -0
  361. /package/dist/{collection-facade-GQAOGJP2.js.map → classified/index.js.map} +0 -0
  362. /package/dist/{delegation-UL5HKLER.js.map → collection-facade-MKEBZDWW.js.map} +0 -0
  363. /package/dist/{enclave-UL5LW66V.js.map → computed-BMMEFRFJ.js.map} +0 -0
  364. /package/dist/{executor-2FWQRLMG.js.map → delegation-BQNIEHZE.js.map} +0 -0
  365. /package/dist/{executor-QZ7BXICW.js.map → enclave-YN6223OG.js.map} +0 -0
  366. /package/dist/{executor-Z5ZLJVTV.js.map → executor-CBTNU5VZ.js.map} +0 -0
  367. /package/dist/{export-accessible-KRV5W4GH.js.map → executor-DJHNSTIR.js.map} +0 -0
  368. /package/dist/{extract-partition-GLKBOXFQ.js.map → executor-FGISLQIN.js.map} +0 -0
  369. /package/dist/{issue-Y6UVIR43.js.map → export-accessible-P7SLRLK3.js.map} +0 -0
  370. /package/dist/{ledger-RYI35CDS.js.map → extract-partition-RNVSFHAB.js.map} +0 -0
  371. /package/dist/{liberate-CRPZEV7O.js.map → find-RNBG7LBY.js.map} +0 -0
  372. /package/dist/{noydb-LDEBLNHY.js.map → issue-W5QG53B5.js.map} +0 -0
  373. /package/dist/{policy-IXK4FVXP.js.map → lazy/index.js.map} +0 -0
  374. /package/dist/{public-envelope-JHDQCPSX.js.map → ledger-KZWBKAG5.js.map} +0 -0
  375. /package/dist/{registry-45RJNWGU.js.map → liberate-GMGCHIND.js.map} +0 -0
  376. /package/dist/{registry-5GRV5VXI.js.map → link-set-UQEIYQAM.js.map} +0 -0
  377. /package/dist/{registry-WEUCHBO4.js.map → noydb-KS2O2MRI.js.map} +0 -0
  378. /package/dist/{request-withdrawal-GBPH2FDY.js.map → policy-YIKUH4AD.js.map} +0 -0
  379. /package/dist/{revoke-TUFRGI6S.js.map → public-envelope-MRN5YYZZ.js.map} +0 -0
  380. /package/dist/{signer-PNKTBVF7.js.map → register-K6DDSIXN.js.map} +0 -0
  381. /package/dist/{stale-3JWHNDIY.js.map → registry-IMNMHWTM.js.map} +0 -0
  382. /package/dist/{withdraw-accessible-FFS46EOD.js.map → registry-K6VUQXKV.js.map} +0 -0
  383. /package/dist/{store-coordination-provider-3I7XWZZK.js.map → store-coordination-provider-JJCEMTAE.js.map} +0 -0
@@ -1,22 +1,35 @@
1
1
  import {
2
- loadVaultPolicy
3
- } from "./chunk-SM3AVUHC.js";
2
+ jsonSchemaToFields
3
+ } from "./chunk-TQ3REHVF.js";
4
4
  import {
5
5
  NO_SEQUENCE,
6
6
  SEQUENCE_COLLECTION,
7
7
  compileSequenceFormat,
8
8
  resolveSequenceKey
9
- } from "./chunk-GYGWYIOZ.js";
9
+ } from "./chunk-P27Z66EB.js";
10
+ import {
11
+ loadVaultPolicy
12
+ } from "./chunk-T45LAT2Y.js";
13
+ import {
14
+ LinkIntegrityError,
15
+ isLinkCollectionName,
16
+ linkCollectionName,
17
+ linkRowKey
18
+ } from "./chunk-P3NGV5RV.js";
19
+ import {
20
+ derivePersistedSchema,
21
+ isZod4Schema
22
+ } from "./chunk-ULIHDPKL.js";
10
23
  import {
11
24
  loadFence
12
- } from "./chunk-IAGBDSCS.js";
25
+ } from "./chunk-YFF2RP3X.js";
13
26
  import {
14
27
  InvertedIndex,
15
28
  MemoryIndexStore,
16
29
  NO_SEARCH,
17
30
  VectorSet,
18
31
  buildPersistedIndexCallbacks
19
- } from "./chunk-TEILUWOI.js";
32
+ } from "./chunk-GOUNIHFA.js";
20
33
  import {
21
34
  ServiceBus,
22
35
  WriteHookRegistry,
@@ -24,58 +37,65 @@ import {
24
37
  assertCanImport,
25
38
  canExport,
26
39
  canImport
27
- } from "./chunk-5R3ERCDH.js";
40
+ } from "./chunk-P3V7JTB6.js";
28
41
  import {
29
42
  NO_ATTESTATION
30
- } from "./chunk-WYSO2NIH.js";
43
+ } from "./chunk-Z7KI4WHR.js";
44
+ import {
45
+ NO_CLASSIFIED,
46
+ enforceClassifiedWrite,
47
+ resolveClassifiedFields
48
+ } from "./chunk-AF5ZRTZ4.js";
31
49
  import {
32
50
  NO_TIERS,
33
51
  classifySealedShred
34
- } from "./chunk-IPB7FTQX.js";
52
+ } from "./chunk-VMJ5URU7.js";
35
53
  import {
36
54
  NO_PORTABILITY
37
- } from "./chunk-KVOXU4T5.js";
55
+ } from "./chunk-N5YVZHCB.js";
38
56
  import {
39
57
  CustodyApi,
40
58
  NO_CARGO,
41
59
  NO_CUSTODY
42
- } from "./chunk-TJYQIGAP.js";
60
+ } from "./chunk-7J7JRYXW.js";
43
61
  import {
44
62
  runDrainBarrier
45
- } from "./chunk-QHJW5EXU.js";
63
+ } from "./chunk-3Y4QLJ6K.js";
64
+ import {
65
+ PERIODS_COLLECTION
66
+ } from "./chunk-GZZL5R73.js";
46
67
  import {
47
68
  TxContext,
48
69
  revertExecuted
49
- } from "./chunk-SKF73JOP.js";
70
+ } from "./chunk-T65UZXR6.js";
50
71
  import {
51
72
  OverlayedCollection
52
- } from "./chunk-CMGR4ZEW.js";
73
+ } from "./chunk-ZROMNP7Q.js";
53
74
  import {
54
75
  EXPORT_AUDIT_COLLECTION,
55
76
  createExportBlobsHandle,
56
77
  runCompaction
57
- } from "./chunk-Y22T3KQE.js";
78
+ } from "./chunk-5MRE3C4Q.js";
58
79
  import {
59
80
  LazyQuery,
60
81
  decodeIdxId,
61
82
  encodeIdxId
62
- } from "./chunk-V7RWQRG7.js";
83
+ } from "./chunk-QNTEDPWP.js";
63
84
  import {
64
- loadPersistedSchema,
65
- savePersistedSchema
66
- } from "./chunk-26LGBE4T.js";
85
+ IMPLICIT_LAZY,
86
+ Lru,
87
+ estimateRecordBytes
88
+ } from "./chunk-NO272T7Q.js";
67
89
  import {
68
90
  resolveManagedSecret,
69
91
  saveSealedPassphrase
70
- } from "./chunk-ZCGAHGUS.js";
71
- import {
72
- PERIODS_COLLECTION
73
- } from "./chunk-IELYAOGG.js";
92
+ } from "./chunk-VWGCJUTV.js";
74
93
  import {
75
94
  isDictCollectionName,
76
95
  isStaticDictDescriptor
77
- } from "./chunk-LFLXAY2W.js";
96
+ } from "./chunk-SEQ2JI3Y.js";
78
97
  import {
98
+ NO_TEAM,
79
99
  enrollAuthenticator,
80
100
  findAuthenticator,
81
101
  recoverPassphrase,
@@ -84,7 +104,7 @@ import {
84
104
  rotatePassphrase,
85
105
  updateAuthenticator,
86
106
  writeMagicLinkGrant
87
- } from "./chunk-UPJNJGGA.js";
107
+ } from "./chunk-K5P46KB3.js";
88
108
  import {
89
109
  hasRecoveryEnrolled,
90
110
  hasStrongRecoveryEnrolled,
@@ -94,7 +114,7 @@ import {
94
114
  mintShamirRecoveryEntry,
95
115
  savePaperRecoveryEntries,
96
116
  saveShamirRecoveryEntries
97
- } from "./chunk-IGUYVGGI.js";
117
+ } from "./chunk-LPRPVCNY.js";
98
118
  import {
99
119
  INDEXED_STORE_POLICY
100
120
  } from "./chunk-VQNJ7UZL.js";
@@ -104,25 +124,22 @@ import {
104
124
  changeSecret,
105
125
  createOwnerKeyring,
106
126
  ensureCollectionDEK,
107
- grant,
108
127
  hasAccess,
109
128
  hasWritePermission,
110
129
  listUsers,
111
130
  loadKeyring,
112
- revoke,
113
- rotateKeys,
114
131
  updateKeyringIdentity
115
- } from "./chunk-WWGT2MDV.js";
132
+ } from "./chunk-VAWY44JW.js";
116
133
  import {
117
134
  persistDirectoryConfig,
118
135
  readDirectoryConfig
119
- } from "./chunk-ITNUCOXM.js";
136
+ } from "./chunk-TB5RNNJ4.js";
120
137
  import {
121
138
  generateULID
122
139
  } from "./chunk-ZJADGNYF.js";
123
140
  import {
124
- sha256Hex as sha256Hex2
125
- } from "./chunk-AIWULCUO.js";
141
+ sha256Hex
142
+ } from "./chunk-M66NAZA4.js";
126
143
  import {
127
144
  NO_FORGET,
128
145
  addSubjectRef,
@@ -131,52 +148,54 @@ import {
131
148
  readDottedPath,
132
149
  rebuildSubjectIndex,
133
150
  removeSubjectRef
134
- } from "./chunk-SRB2XEWB.js";
151
+ } from "./chunk-O2DB4C3M.js";
135
152
  import {
136
153
  NO_SEALED_RECORD
137
- } from "./chunk-UV5MFVO3.js";
154
+ } from "./chunk-G7RDYYTE.js";
138
155
  import {
139
156
  RecordCodec,
140
157
  SEALED_CEK_NS,
141
- buildTombstone,
142
- encrypt,
143
158
  findByDet,
144
159
  hasPerRecordKey,
145
- isTombstone,
146
160
  openEnvelopeJson,
147
161
  queryByDet,
148
162
  resolveStableCek,
149
- sha256Hex,
150
163
  validateSchemaInput
151
- } from "./chunk-5O3AOPDT.js";
164
+ } from "./chunk-OVO2RZAE.js";
165
+ import {
166
+ buildTombstone,
167
+ isTombstone
168
+ } from "./chunk-QKVILR7N.js";
152
169
  import {
153
170
  NOYDB_FORMAT_VERSION
154
- } from "./chunk-5TDJ56JE.js";
171
+ } from "./chunk-LN22XH4B.js";
172
+ import {
173
+ encrypt
174
+ } from "./chunk-TLJOJBZD.js";
155
175
  import {
156
176
  NO_AGGREGATE,
157
177
  Query,
158
- ScanBuilder,
159
- canonicalizeIncomingMoney,
160
- canonicalizeStoredMoney,
161
- decodeMoneyFields,
162
- quantizeMoneyFields,
163
- validateMoneyFieldPaths
164
- } from "./chunk-UIU2THRG.js";
178
+ ScanBuilder
179
+ } from "./chunk-GBTUANXF.js";
165
180
  import {
166
181
  canonicalGroupKey
167
- } from "./chunk-LV7M27WM.js";
182
+ } from "./chunk-P5WXDYMD.js";
168
183
  import {
184
+ moneyRuntime,
169
185
  readPath
170
- } from "./chunk-M2YKN37S.js";
186
+ } from "./chunk-ZKF6HH7V.js";
171
187
  import {
172
188
  getAtPath,
173
189
  resolvePolicy,
174
190
  setAtPathInPlace,
175
191
  stripI18nFilled
176
- } from "./chunk-5LUY7UTV.js";
192
+ } from "./chunk-4K3MQ5S3.js";
177
193
  import {
178
194
  AlreadyElevatedError,
179
195
  AttestationError,
196
+ ClassifiedConfigError,
197
+ ClassifiedRevealError,
198
+ ClassifiedVerifyError,
180
199
  ConflictError,
181
200
  DebugPlaintextError,
182
201
  DerivationCapExceededError,
@@ -207,40 +226,79 @@ import {
207
226
  UnknownDictCodeError,
208
227
  UnsupportedIndexOptionError,
209
228
  ValidationError
210
- } from "./chunk-ZYUC53LT.js";
229
+ } from "./chunk-U23JUUPX.js";
211
230
 
212
231
  // src/port/by/default-provider.ts
213
232
  async function createDefaultCoordinationProvider(store) {
214
- const { StoreCoordinationProvider } = await import("./store-coordination-provider-3I7XWZZK.js");
233
+ const { StoreCoordinationProvider } = await import("./store-coordination-provider-JJCEMTAE.js");
215
234
  return new StoreCoordinationProvider(store);
216
235
  }
217
236
 
218
- // src/with-formula/computed/index.ts
219
- var ComputedFieldError = class extends NoydbError {
220
- constructor(field, id, cause) {
221
- super(
222
- "COMPUTED_FIELD",
223
- `computed field "${field}" threw for record "${id}": ` + (cause instanceof Error ? cause.message : String(cause))
237
+ // src/with-shape/classified/guards.ts
238
+ function guardClassifiedCompat(collection, byField, ctx) {
239
+ const digestOnly = Object.entries(byField).filter(([, s]) => s.storage === "digest-only");
240
+ const protectedForms = Object.values(byField).filter((s) => s.storage === "digest-only" || s.storage === "recoverable");
241
+ if (protectedForms.length > 0 && (ctx.crdt || ctx.hasConflictPolicy)) {
242
+ throw new ClassifiedConfigError(
243
+ collection,
244
+ "digest-only/recoverable classified fields cannot combine with a crdt mode or a conflictPolicy resolver \u2014 merge paths bypass write enforcement (R2)"
224
245
  );
225
- this.field = field;
226
- this.id = id;
227
- this.cause = cause;
228
- this.name = "ComputedFieldError";
229
246
  }
230
- field;
231
- id;
232
- cause;
233
- };
234
- function evalComputedFields(record, computed, id) {
235
- const out = { ...record };
236
- for (const [field, fn] of Object.entries(computed)) {
237
- try {
238
- out[field] = fn(out);
239
- } catch (cause) {
240
- throw new ComputedFieldError(field, id, cause);
247
+ for (const [f, spec] of Object.entries(byField)) {
248
+ if (spec.equatable === true && spec.storage !== "digest-only") {
249
+ throw new ClassifiedConfigError(
250
+ collection,
251
+ `field "${f}" declares equatable but storage is '${spec.storage}' \u2014 equatable is a digest-only knob; recoverable equality is _det's job (R7)`
252
+ );
253
+ }
254
+ }
255
+ const hasEquatable = Object.values(byField).some((s) => s.equatable === true);
256
+ if (hasEquatable && ctx.acknowledgeEquatableRisk !== true) {
257
+ throw new ClassifiedConfigError(
258
+ collection,
259
+ `classified equatable fields require \`acknowledgeEquatableRisk: true\` \u2014 equal values produce equal store-visible index tags (a partition leak a DEK holder can offline-dictionary at the PBKDF2 floor); the door is the real control for low-entropy fields (R8)`
260
+ );
261
+ }
262
+ if (digestOnly.length === 0) return;
263
+ if (!ctx.storeCiphertext) {
264
+ throw new ClassifiedConfigError(
265
+ collection,
266
+ `storage:'digest-only' requires an encrypted collection \u2014 with encrypt: false the write path skips the digest slot entirely and the secret would persist as raw plaintext`
267
+ );
268
+ }
269
+ if (!ctx.perRecordKeys) {
270
+ throw new ClassifiedConfigError(
271
+ collection,
272
+ `storage:'digest-only' requires perRecordKeys: true \u2014 vdig keys derive from the per-record CEK so forget() shreds them (R1)`
273
+ );
274
+ }
275
+ for (const [f, spec] of digestOnly) {
276
+ const n = spec.notLastN ?? 0;
277
+ if (!Number.isInteger(n) || n < 0 || n > 8) {
278
+ throw new ClassifiedConfigError(
279
+ collection,
280
+ `digest-only field "${f}" declares notLastN ${n} \u2014 must be an integer 0..8 (write cost is n \xD7 600K PBKDF2; ring blast radius is documented)`
281
+ );
282
+ }
283
+ if (ctx.bareSensitiveFields.has(f)) {
284
+ throw new ClassifiedConfigError(
285
+ collection,
286
+ `field "${f}" is digest-only AND listed in sensitive[] \u2014 storage forms are mutually exclusive per field (R5)`
287
+ );
288
+ }
289
+ if (ctx.deterministicFields?.has(f)) {
290
+ throw new ClassifiedConfigError(
291
+ collection,
292
+ `digest-only field "${f}" cannot be deterministic \u2014 equality-correlatable ciphertext defeats per-write salts (R3)`
293
+ );
294
+ }
295
+ if (ctx.indexedFields.has(f) || ctx.textIndexFields.has(f) || ctx.vectorSourceFields.has(f) || ctx.subjectKeyField === f) {
296
+ throw new ClassifiedConfigError(
297
+ collection,
298
+ `digest-only field "${f}" cannot be indexed, text-indexed, embedded, or a forget-subject key (R4)`
299
+ );
241
300
  }
242
301
  }
243
- return out;
244
302
  }
245
303
 
246
304
  // src/with-lookup/indexing/collection-facade.ts
@@ -497,89 +555,6 @@ async function purgePersistedIndexes(ctx, id) {
497
555
  return { purged, residue };
498
556
  }
499
557
 
500
- // src/with-shape/persisted-schemas/canonicalize.ts
501
- function canonicalize(value) {
502
- if (value === null || typeof value !== "object") {
503
- return JSON.stringify(value);
504
- }
505
- if (Array.isArray(value)) {
506
- return "[" + value.map(canonicalize).join(",") + "]";
507
- }
508
- const obj = value;
509
- const keys = Object.keys(obj).sort();
510
- const parts = keys.map((k) => JSON.stringify(k) + ":" + canonicalize(obj[k]));
511
- return "{" + parts.join(",") + "}";
512
- }
513
-
514
- // src/with-shape/persisted-schemas/derive.ts
515
- function isZodSchema(value) {
516
- if (value === null || typeof value !== "object") return false;
517
- const std = value["~standard"];
518
- if (std && typeof std === "object" && std.vendor === "zod") return true;
519
- const def = value._def;
520
- if (!def || typeof def !== "object") return false;
521
- return typeof def.typeName === "string" && def.typeName.startsWith("Zod");
522
- }
523
- function detectKind(validator) {
524
- if (isZodSchema(validator)) return "Zod";
525
- return "Unknown";
526
- }
527
- function isZod4Schema(value) {
528
- if (value === null || typeof value !== "object") return false;
529
- return "_zod" in value;
530
- }
531
- async function loadZodToJsonSchemaConverter() {
532
- try {
533
- const mod = await import("zod-to-json-schema");
534
- if (!mod.zodToJsonSchema) {
535
- throw new Error("zod-to-json-schema export missing");
536
- }
537
- return mod.zodToJsonSchema;
538
- } catch (err) {
539
- throw new Error(
540
- `persistJsonSchema requires the optional peer-dep \`zod-to-json-schema\`. Install it: \`pnpm add zod-to-json-schema\` (or npm/yarn equivalent). Original error: ${err instanceof Error ? err.message : String(err)}`
541
- );
542
- }
543
- }
544
- async function loadZodV4Converter() {
545
- try {
546
- const mod = await import("./zod-HAJM7LMS.js");
547
- if (typeof mod.toJSONSchema !== "function") {
548
- throw new Error("zod.toJSONSchema not available (zod v4 required)");
549
- }
550
- return mod.toJSONSchema;
551
- } catch (err) {
552
- throw new Error(
553
- `persistJsonSchema with a Zod v4 schema requires zod@4 with toJSONSchema. Original error: ${err instanceof Error ? err.message : String(err)}`
554
- );
555
- }
556
- }
557
- async function derivePersistedSchema(validator) {
558
- const kind = detectKind(validator);
559
- const derivedAt = (/* @__PURE__ */ new Date()).toISOString();
560
- if (kind === "Zod") {
561
- let jsonSchema;
562
- if (isZod4Schema(validator)) {
563
- const convert = await loadZodV4Converter();
564
- jsonSchema = convert(validator);
565
- } else {
566
- const convert = await loadZodToJsonSchemaConverter();
567
- jsonSchema = convert(validator);
568
- }
569
- const canonical = canonicalize(jsonSchema);
570
- const hash = await sha256Hex(new TextEncoder().encode(canonical));
571
- return { _noydb_schema: 1, kind, jsonSchema, hash, derivedAt };
572
- }
573
- return {
574
- _noydb_schema: 1,
575
- kind,
576
- jsonSchema: null,
577
- hash: null,
578
- reason: `derivation not yet supported for kind=${kind} (v0 supports Zod only)`,
579
- derivedAt
580
- };
581
- }
582
-
583
558
  // src/with-lookup/indexing/strategy.ts
584
559
  var NO_INDEXING = {
585
560
  createState() {
@@ -825,97 +800,6 @@ function resolveFieldMeta(key, inputs) {
825
800
  };
826
801
  }
827
802
 
828
- // src/with-shape/introspection/fields.ts
829
- function jsonSchemaType(node) {
830
- if (Array.isArray(node.type)) {
831
- const non = node.type.filter((t) => t !== "null");
832
- return non[0] ?? "opaque";
833
- }
834
- if (node.enum && Array.isArray(node.enum)) return "enum";
835
- if (node.const !== void 0) return "enum";
836
- if (typeof node.type === "string") return node.type;
837
- return "opaque";
838
- }
839
- function constraintsFor(node) {
840
- const out = {};
841
- if (node.enum) out.values = node.enum;
842
- if (node.const !== void 0) out.values = [node.const];
843
- if (node.minLength !== void 0) out.minLength = node.minLength;
844
- if (node.maxLength !== void 0) out.maxLength = node.maxLength;
845
- if (node.pattern !== void 0) out.pattern = node.pattern;
846
- if (node.format !== void 0) out.format = node.format;
847
- if (node.minimum !== void 0) out.minimum = node.minimum;
848
- if (node.maximum !== void 0) out.maximum = node.maximum;
849
- if (node.exclusiveMinimum !== void 0) out.gt = node.exclusiveMinimum;
850
- if (node.exclusiveMaximum !== void 0) out.lt = node.exclusiveMaximum;
851
- return Object.keys(out).length === 0 ? void 0 : out;
852
- }
853
- function extractObjectFields(obj, source, refs) {
854
- const required = new Set(Array.isArray(obj.required) ? obj.required : []);
855
- const fields = {};
856
- if (!obj.properties || typeof obj.properties !== "object") return { fields, required };
857
- for (const [name, node] of Object.entries(obj.properties)) {
858
- const descriptor = {
859
- type: jsonSchemaType(node),
860
- source,
861
- ...required.has(name) ? {} : { optional: true },
862
- ...refs?.[name] ? { references: `${refs[name].target}.id` } : {}
863
- };
864
- const constraints = constraintsFor(node);
865
- if (constraints) descriptor.constraints = constraints;
866
- fields[name] = descriptor;
867
- }
868
- return { fields, required };
869
- }
870
- function mergeUnionMembers(members, source, refs) {
871
- if (members.length === 0) return {};
872
- const extracted = members.filter((m) => m.properties && typeof m.properties === "object").map((m) => extractObjectFields(m, source, refs));
873
- if (extracted.length === 0) return {};
874
- const allNames = /* @__PURE__ */ new Set();
875
- for (const { fields } of extracted) {
876
- for (const name of Object.keys(fields)) allNames.add(name);
877
- }
878
- const memberCount = extracted.length;
879
- const out = {};
880
- for (const name of allNames) {
881
- const presentIn = extracted.filter(({ fields }) => name in fields);
882
- const requiredInAll = presentIn.length === memberCount && presentIn.every(({ required }) => required.has(name));
883
- const base = presentIn[0].fields[name];
884
- const allValues = [];
885
- for (const { fields } of presentIn) {
886
- const fd = fields[name];
887
- if (fd?.constraints?.values && Array.isArray(fd.constraints.values)) {
888
- for (const v of fd.constraints.values) {
889
- if (!allValues.includes(v)) allValues.push(v);
890
- }
891
- }
892
- }
893
- const mergedConstraints = allValues.length > 0 ? { ...base.constraints ?? {}, values: allValues } : base.constraints;
894
- const descriptor = {
895
- type: base.type,
896
- source,
897
- ...requiredInAll ? {} : { optional: true },
898
- ...base.references ? { references: base.references } : {}
899
- };
900
- if (mergedConstraints) {
901
- descriptor.constraints = mergedConstraints;
902
- }
903
- out[name] = descriptor;
904
- }
905
- return out;
906
- }
907
- function jsonSchemaToFields(jsonSchema, source, refs) {
908
- if (!jsonSchema || typeof jsonSchema !== "object") return {};
909
- const root = jsonSchema;
910
- const unionMembers = root.anyOf ?? root.oneOf;
911
- if (Array.isArray(unionMembers) && unionMembers.length > 0) {
912
- return mergeUnionMembers(unionMembers, source, refs);
913
- }
914
- if (!root.properties || typeof root.properties !== "object") return {};
915
- const { fields } = extractObjectFields(root, source, refs);
916
- return fields;
917
- }
918
-
919
803
  // src/with-shape/introspection/describe.ts
920
804
  var ZOD_META_KEYS = /* @__PURE__ */ new Set([
921
805
  "label",
@@ -985,7 +869,7 @@ function deriveWidget(opts) {
985
869
  return "text";
986
870
  }
987
871
  function buildDescription(input) {
988
- const { collection, fieldMeta, moneyFields, dictKeyFields, computed, refs, zodFields, dictLabels, meta, i18nFields } = input;
872
+ const { collection, fieldMeta, moneyFields, dictKeyFields, computed, refs, zodFields, dictLabels, meta, i18nFields, classified } = input;
989
873
  if (zodFields !== void 0 && Object.keys(zodFields).length > 0 && fieldMeta !== void 0) {
990
874
  const knownFields = /* @__PURE__ */ new Set([
991
875
  ...Object.keys(moneyFields ?? {}),
@@ -1004,7 +888,8 @@ function buildDescription(input) {
1004
888
  ...Object.keys(computed ?? {}),
1005
889
  ...Object.keys(fieldMeta ?? {}),
1006
890
  ...Object.keys(zodFields ?? {}),
1007
- ...Object.keys(i18nFields ?? {})
891
+ ...Object.keys(i18nFields ?? {}),
892
+ ...Object.keys(classified ?? {})
1008
893
  ]);
1009
894
  const fields = [];
1010
895
  for (const key of [...allKeys].sort()) {
@@ -1014,6 +899,7 @@ function buildDescription(input) {
1014
899
  const refDesc = refs[key];
1015
900
  const isComputed = computed !== void 0 && key in computed;
1016
901
  const i18nDesc = i18nFields?.[key];
902
+ const cls = classified?.[key];
1017
903
  let type = zod?.type ?? "unknown";
1018
904
  const inferred = {};
1019
905
  let moneyBlock;
@@ -1069,6 +955,7 @@ function buildDescription(input) {
1069
955
  type = "string";
1070
956
  } else if (isComputed) {
1071
957
  }
958
+ if (cls !== void 0) inferred.sensitivity = cls.sensitivity;
1072
959
  const channelEntry = fieldMeta?.[key];
1073
960
  const zodMeta = zod?.meta;
1074
961
  const resolved = resolveFieldMeta(key, {
@@ -1096,6 +983,7 @@ function buildDescription(input) {
1096
983
  key,
1097
984
  type,
1098
985
  optional: zod?.optional ?? false,
986
+ ...zod?.constraints !== void 0 ? { constraints: zod.constraints } : {},
1099
987
  label: resolved.label,
1100
988
  ...resolved.description !== void 0 ? { description: resolved.description } : {},
1101
989
  ...resolved.group !== void 0 ? { group: resolved.group } : {},
@@ -1112,7 +1000,15 @@ function buildDescription(input) {
1112
1000
  ...isComputed ? { computed: true } : {},
1113
1001
  ...i18nBlock !== void 0 ? { i18n: i18nBlock } : {},
1114
1002
  widget,
1115
- editable
1003
+ editable,
1004
+ ...cls !== void 0 ? {
1005
+ classified: {
1006
+ preset: cls.preset,
1007
+ storage: cls.storage,
1008
+ list: cls.list.kind === "omit" ? "omit" : cls.list.kind === "mask" ? { mask: cls.list.pattern } : { rider: cls.list.rider },
1009
+ ...cls.equatable === true ? { equatable: true } : {}
1010
+ }
1011
+ } : {}
1116
1012
  };
1117
1013
  fields.push(field);
1118
1014
  }
@@ -1127,203 +1023,6 @@ function buildDescription(input) {
1127
1023
  };
1128
1024
  }
1129
1025
 
1130
- // src/with-shape/introspection/json-schema.ts
1131
- function jsonType(t) {
1132
- switch (t) {
1133
- case "number":
1134
- return "number";
1135
- case "boolean":
1136
- return "boolean";
1137
- case "array":
1138
- return "array";
1139
- case "object":
1140
- return "object";
1141
- default:
1142
- return "string";
1143
- }
1144
- }
1145
- function buildJsonSchema(desc, base) {
1146
- const baseProps = base?.["properties"] ?? {};
1147
- const properties = {};
1148
- for (const f of desc.fields) {
1149
- const prop = { ...baseProps[f.key] ?? { type: jsonType(f.type) } };
1150
- prop["x-label"] = f.label;
1151
- if (f.unit !== void 0) prop["x-unit"] = f.unit;
1152
- if (f.semanticType !== void 0) prop["x-semanticType"] = f.semanticType;
1153
- if (f.sensitivity !== void 0) prop["x-sensitivity"] = f.sensitivity;
1154
- if (f.widget !== void 0) prop["x-widget"] = f.widget;
1155
- if (f.editable === false) prop["x-readonly"] = true;
1156
- if (f.money !== void 0) prop["x-money"] = f.money;
1157
- if (f.ref !== void 0) prop["x-ref"] = f.ref.target;
1158
- if (f.dict?.values) {
1159
- const labels = {};
1160
- for (const v of f.dict.values) if (v.label !== void 0) labels[v.value] = v.label;
1161
- if (Object.keys(labels).length) prop["x-enumLabels"] = labels;
1162
- }
1163
- properties[f.key] = prop;
1164
- }
1165
- return base != null && typeof base === "object" ? { ...base, properties } : { type: "object", properties };
1166
- }
1167
-
1168
- // src/kernel/cache/lru.ts
1169
- var Lru = class {
1170
- entries = /* @__PURE__ */ new Map();
1171
- maxRecords;
1172
- maxBytes;
1173
- currentBytes = 0;
1174
- hits = 0;
1175
- misses = 0;
1176
- evictions = 0;
1177
- constructor(options) {
1178
- if (options.maxRecords === void 0 && options.maxBytes === void 0) {
1179
- throw new Error("Lru: must specify maxRecords, maxBytes, or both");
1180
- }
1181
- this.maxRecords = options.maxRecords;
1182
- this.maxBytes = options.maxBytes;
1183
- }
1184
- /**
1185
- * Look up a key. Hits promote the entry to most-recently-used; misses
1186
- * return undefined. Both update the running stats counters.
1187
- */
1188
- get(key) {
1189
- const entry = this.entries.get(key);
1190
- if (!entry) {
1191
- this.misses++;
1192
- return void 0;
1193
- }
1194
- this.entries.delete(key);
1195
- this.entries.set(key, entry);
1196
- this.hits++;
1197
- return entry.value;
1198
- }
1199
- /**
1200
- * Insert or update a key. If the key already exists, its size is
1201
- * accounted for and the entry is promoted to MRU. After insertion,
1202
- * eviction runs to maintain both budgets.
1203
- */
1204
- set(key, value, size) {
1205
- const existing = this.entries.get(key);
1206
- if (existing) {
1207
- this.currentBytes -= existing.size;
1208
- this.entries.delete(key);
1209
- }
1210
- this.entries.set(key, { value, size });
1211
- this.currentBytes += size;
1212
- this.evictUntilUnderBudget();
1213
- }
1214
- /**
1215
- * Remove a key without affecting hit/miss stats. Used by `Collection.delete()`.
1216
- * Returns true if the key was present.
1217
- */
1218
- remove(key) {
1219
- const existing = this.entries.get(key);
1220
- if (!existing) return false;
1221
- this.currentBytes -= existing.size;
1222
- this.entries.delete(key);
1223
- return true;
1224
- }
1225
- /** True if the cache currently holds an entry for the given key. */
1226
- has(key) {
1227
- return this.entries.has(key);
1228
- }
1229
- /**
1230
- * Drop every entry. Stats counters survive — call `resetStats()` if you
1231
- * want a clean slate. Used by `Collection.invalidate()` on key rotation.
1232
- */
1233
- clear() {
1234
- this.entries.clear();
1235
- this.currentBytes = 0;
1236
- }
1237
- /** Reset hit/miss/eviction counters to zero. Does NOT touch entries. */
1238
- resetStats() {
1239
- this.hits = 0;
1240
- this.misses = 0;
1241
- this.evictions = 0;
1242
- }
1243
- /** Snapshot of current cache statistics. Cheap — no copying. */
1244
- stats() {
1245
- return {
1246
- hits: this.hits,
1247
- misses: this.misses,
1248
- evictions: this.evictions,
1249
- size: this.entries.size,
1250
- bytes: this.currentBytes
1251
- };
1252
- }
1253
- /**
1254
- * Iterate over all currently-cached values. Order is least-recently-used
1255
- * first. Used by tests and devtools — production callers should use
1256
- * `Collection.scan()` instead.
1257
- */
1258
- *values() {
1259
- for (const entry of this.entries.values()) yield entry.value;
1260
- }
1261
- /**
1262
- * Walk the cache from the LRU end and drop entries until both budgets
1263
- * are satisfied. Called after every `set()`. Single pass — entries are
1264
- * never re-promoted during eviction.
1265
- */
1266
- evictUntilUnderBudget() {
1267
- while (this.overBudget()) {
1268
- const oldest = this.entries.keys().next();
1269
- if (oldest.done) return;
1270
- const key = oldest.value;
1271
- const entry = this.entries.get(key);
1272
- if (entry) this.currentBytes -= entry.size;
1273
- this.entries.delete(key);
1274
- this.evictions++;
1275
- }
1276
- }
1277
- overBudget() {
1278
- if (this.maxRecords !== void 0 && this.entries.size > this.maxRecords) return true;
1279
- if (this.maxBytes !== void 0 && this.currentBytes > this.maxBytes) return true;
1280
- return false;
1281
- }
1282
- };
1283
-
1284
- // src/kernel/cache/policy.ts
1285
- var UNITS = {
1286
- "": 1,
1287
- "B": 1,
1288
- "KB": 1024,
1289
- "MB": 1024 * 1024,
1290
- "GB": 1024 * 1024 * 1024
1291
- // 'TB' deliberately not supported — if you need it, you're not using NOYDB.
1292
- };
1293
- function parseBytes(input) {
1294
- if (typeof input === "number") {
1295
- if (!Number.isFinite(input) || input <= 0) {
1296
- throw new Error(`parseBytes: numeric input must be a positive finite number, got ${String(input)}`);
1297
- }
1298
- return Math.floor(input);
1299
- }
1300
- const trimmed = input.trim();
1301
- if (trimmed === "") {
1302
- throw new Error("parseBytes: empty string is not a valid byte budget");
1303
- }
1304
- const match = /^([0-9]+(?:\.[0-9]+)?)\s*([A-Za-z]*)$/.exec(trimmed);
1305
- if (!match) {
1306
- throw new Error(`parseBytes: invalid byte budget "${input}". Expected format: "1024", "50KB", "50MB", "1GB"`);
1307
- }
1308
- const value = parseFloat(match[1]);
1309
- const unit = (match[2] ?? "").toUpperCase();
1310
- if (!(unit in UNITS)) {
1311
- throw new Error(`parseBytes: unknown unit "${match[2]}" in "${input}". Supported: B, KB, MB, GB`);
1312
- }
1313
- const bytes = Math.floor(value * UNITS[unit]);
1314
- if (bytes <= 0) {
1315
- throw new Error(`parseBytes: byte budget must be > 0, got ${bytes} from "${input}"`);
1316
- }
1317
- return bytes;
1318
- }
1319
- function estimateRecordBytes(record) {
1320
- try {
1321
- return JSON.stringify(record).length;
1322
- } catch {
1323
- return 0;
1324
- }
1325
- }
1326
-
1327
1026
  // src/with-formula/derivations/stale.ts
1328
1027
  var _staleByRegistry = /* @__PURE__ */ new WeakMap();
1329
1028
  var keyFor = (source, sourceId) => `${source}/${sourceId}`;
@@ -1360,7 +1059,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
1360
1059
  }
1361
1060
  const sourceWithId = { ...source, id };
1362
1061
  if (DerivationExecutor === null) {
1363
- ({ DerivationExecutor } = await import("./executor-Z5ZLJVTV.js"));
1062
+ ({ DerivationExecutor } = await import("./executor-CBTNU5VZ.js"));
1364
1063
  }
1365
1064
  const ctx = { vault: accessor.getReadOnlyFacade() };
1366
1065
  const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx);
@@ -1517,7 +1216,17 @@ function resolveCollectionConfig(opts) {
1517
1216
  `Collection "${opts.name}": embeddings are not supported on CRDT collections (L2). Use a non-CRDT collection for semantic search.`
1518
1217
  );
1519
1218
  }
1520
- if (opts.moneyFields) validateMoneyFieldPaths(opts.moneyFields);
1219
+ if (opts.moneyFields) moneyRuntime().validateMoneyFieldPaths(opts.moneyFields);
1220
+ const resolvedClassified = opts.classifiedFields !== void 0 ? resolveClassifiedFields(opts.name, opts.classifiedFields) : void 0;
1221
+ let mergedComputed = opts.computed;
1222
+ if (resolvedClassified !== void 0) {
1223
+ for (const key of Object.keys(opts.computed ?? {})) {
1224
+ if (resolvedClassified.riderComputed[key] !== void 0) {
1225
+ throw new ClassifiedConfigError(opts.name, `computed field "${key}" collides with a rider companion`);
1226
+ }
1227
+ }
1228
+ mergedComputed = { ...resolvedClassified.riderComputed, ...opts.computed ?? {} };
1229
+ }
1521
1230
  let deterministicFields;
1522
1231
  if (opts.deterministicFields && opts.deterministicFields.length > 0) {
1523
1232
  if (opts.acknowledgeDeterministicRisk !== true) {
@@ -1533,7 +1242,39 @@ function resolveCollectionConfig(opts) {
1533
1242
  Object.entries(opts.i18nFields).filter(([, d]) => d.options.densifyOnWrite === true)
1534
1243
  ) : {};
1535
1244
  const i18nDensifyFields = Object.keys(densifyFields).length > 0 ? densifyFields : void 0;
1536
- const sensitiveFields = opts.sensitive && opts.sensitive.length > 0 ? Object.freeze(new Set(opts.sensitive)) : Object.freeze(/* @__PURE__ */ new Set());
1245
+ const guardIndexedFields = /* @__PURE__ */ new Set();
1246
+ for (const ix of opts.indexes ?? []) {
1247
+ if (typeof ix === "string") guardIndexedFields.add(ix);
1248
+ else if (Array.isArray(ix)) for (const f of ix) guardIndexedFields.add(f);
1249
+ else for (const f of ix.fields) guardIndexedFields.add(f);
1250
+ }
1251
+ const embeddingSources = opts.embeddings === void 0 ? [] : typeof opts.embeddings.source === "string" ? [opts.embeddings.source] : [...opts.embeddings.source];
1252
+ const classifiedGuardCtx = {
1253
+ perRecordKeys: opts.perRecordKeys === true,
1254
+ crdt: opts.crdt !== void 0,
1255
+ hasConflictPolicy: opts.conflictPolicy !== void 0,
1256
+ storeCiphertext: opts.encrypted,
1257
+ deterministicFields,
1258
+ indexedFields: guardIndexedFields,
1259
+ textIndexFields: new Set(opts.textIndexes ?? []),
1260
+ vectorSourceFields: new Set(embeddingSources),
1261
+ subjectKeyField: opts.subjectKeyField,
1262
+ bareSensitiveFields: new Set(opts.sensitive ?? []),
1263
+ acknowledgeEquatableRisk: opts.acknowledgeEquatableRisk === true
1264
+ };
1265
+ if (resolvedClassified !== void 0) {
1266
+ guardClassifiedCompat(opts.name, resolvedClassified.byField, classifiedGuardCtx);
1267
+ }
1268
+ const classifiedSensitive = resolvedClassified === void 0 ? [] : Object.entries(resolvedClassified.byField).filter(([, s]) => s.storage === "recoverable").map(([f]) => f);
1269
+ const sensitiveList = [...opts.sensitive ?? [], ...classifiedSensitive];
1270
+ const sensitiveFields = sensitiveList.length > 0 ? Object.freeze(new Set(sensitiveList)) : Object.freeze(/* @__PURE__ */ new Set());
1271
+ const vdigEntries = resolvedClassified === void 0 ? [] : Object.entries(resolvedClassified.byField).filter(([, s]) => s.storage === "digest-only").map(([f, s]) => [f, {
1272
+ normalize: s.verifyNormalize ?? "password",
1273
+ notLastN: s.notLastN ?? 0,
1274
+ equatable: s.equatable === true,
1275
+ ...s.rotateDays !== void 0 ? { rotateDays: s.rotateDays } : {}
1276
+ }]);
1277
+ const vdigFields = vdigEntries.length > 0 ? new Map(vdigEntries) : null;
1537
1278
  const perRecordCek = opts.perRecordKeys === true;
1538
1279
  const cekCache = perRecordCek ? new Lru({ maxRecords: 4096 }) : null;
1539
1280
  return {
@@ -1577,7 +1318,10 @@ function resolveCollectionConfig(opts) {
1577
1318
  meta: opts.meta,
1578
1319
  _refs: opts.declaredRefs ?? {},
1579
1320
  moneyFields: opts.moneyFields,
1580
- computed: opts.computed,
1321
+ classified: resolvedClassified,
1322
+ classifiedGuardCtx,
1323
+ classifiedStrategy: opts.classifiedStrategy ?? NO_CLASSIFIED,
1324
+ computed: mergedComputed,
1581
1325
  dictLabelResolver: opts.dictLabelResolver,
1582
1326
  getDictionary: opts.getDictionary,
1583
1327
  i18nPutValidator: opts.i18nPutValidator,
@@ -1595,12 +1339,20 @@ function resolveCollectionConfig(opts) {
1595
1339
  onCrossTierAccess: opts.onCrossTierAccess,
1596
1340
  deterministicFields,
1597
1341
  sensitiveFields,
1342
+ vdigFields,
1598
1343
  perRecordCek,
1599
1344
  cekCache,
1600
1345
  provenance: opts.provenance === true
1601
1346
  };
1602
1347
  }
1603
1348
 
1349
+ // src/with-formula/computed/lazy.ts
1350
+ var fn = null;
1351
+ async function loadEvalComputedFields() {
1352
+ fn ??= (await import("./computed-BMMEFRFJ.js")).evalComputedFields;
1353
+ return fn;
1354
+ }
1355
+
1604
1356
  // src/kernel/collection.ts
1605
1357
  function selfWriteFieldEqual(a, b) {
1606
1358
  if (a === b) return true;
@@ -1827,6 +1579,35 @@ var Collection = class {
1827
1579
  * the same MV-pre-creation reconcile as {@link moneyFields}.
1828
1580
  */
1829
1581
  computed;
1582
+ /**
1583
+ * Resolved classified() sensitive-field descriptors, declared via the
1584
+ * `classifiedFields` collection option. Mutable so {@link _applyClassifiedFields}
1585
+ * can attach a declaration to a collection MV-analysis pre-created.
1586
+ */
1587
+ classified;
1588
+ /**
1589
+ * Frozen construction-time facts the refusal matrix (R1-R5) checks against.
1590
+ * Stored so {@link _applyClassifiedFields} — door 2, the reconcile seam —
1591
+ * can re-run the SAME guard the config resolver ran at door 1 (C5's lesson:
1592
+ * crdt/conflictPolicy/perRecordKeys are construction-only but
1593
+ * classifiedFields can attach later).
1594
+ */
1595
+ classifiedGuardCtx;
1596
+ /**
1597
+ * Digest-only classified fields (`storage: 'digest-only'`), keyed by field
1598
+ * name — the enclave-consumable policy map the codec's write path carries
1599
+ * `_vdig` forward under (C6). `null` when the collection declares none.
1600
+ */
1601
+ vdigFields;
1602
+ /** C-A/R10 memoization: marker declared-set lookup (undefined=unresolved) + classified-handle persist-once flag. */
1603
+ _markerDigestOnlyCache = void 0;
1604
+ _markerPersisted = false;
1605
+ /**
1606
+ * Tree-shake seam for `reveal()` — defaults to `NO_CLASSIFIED`, which
1607
+ * throws `ClassifiedNotEnabledError`. Set via the `classifiedStrategy`
1608
+ * `createNoydb()` option (opt in with `withClassified()`).
1609
+ */
1610
+ classifiedStrategy;
1830
1611
  /**
1831
1612
  * Async callback provided by the Vault that resolves a dict key
1832
1613
  * to its label for a given locale. Used by the locale-read path for
@@ -2031,6 +1812,10 @@ var Collection = class {
2031
1812
  this.meta = cfg.meta;
2032
1813
  this._refs = cfg._refs;
2033
1814
  this.moneyFields = cfg.moneyFields;
1815
+ this.classified = cfg.classified;
1816
+ this.classifiedGuardCtx = cfg.classifiedGuardCtx;
1817
+ this.vdigFields = cfg.vdigFields;
1818
+ this.classifiedStrategy = cfg.classifiedStrategy;
2034
1819
  this.computed = cfg.computed;
2035
1820
  this.dictLabelResolver = cfg.dictLabelResolver;
2036
1821
  this.getDictionary = cfg.getDictionary;
@@ -2077,11 +1862,13 @@ var Collection = class {
2077
1862
  provenance: this.provenance,
2078
1863
  sensitiveFields: this.sensitiveFields,
2079
1864
  deterministicFields: this.deterministicFields,
1865
+ vdigFields: this.vdigFields,
2080
1866
  crdtMode: this.crdtMode,
2081
1867
  crdtStrategy: this.crdtStrategy,
2082
1868
  schema: this.schema,
2083
1869
  getDEK: () => this.getDEK(this.name),
2084
- cekCache: this.cekCache
1870
+ cekCache: this.cekCache,
1871
+ classifiedMarkerDigestOnly: () => this._classifiedMarkerDigestOnly()
2085
1872
  });
2086
1873
  if (opts.crdt && opts.onRegisterConflictResolver) {
2087
1874
  const crdtMode = opts.crdt;
@@ -2153,15 +1940,7 @@ var Collection = class {
2153
1940
  }
2154
1941
  this.lazy = opts.prefetch === false;
2155
1942
  if (this.lazy) {
2156
- if (!opts.cache || opts.cache.maxRecords === void 0 && opts.cache.maxBytes === void 0) {
2157
- throw new Error(
2158
- `Collection "${this.name}": lazy mode (prefetch: false) requires a cache option with maxRecords and/or maxBytes. An unbounded lazy cache defeats the purpose.`
2159
- );
2160
- }
2161
- const lruOptions = {};
2162
- if (opts.cache.maxRecords !== void 0) lruOptions.maxRecords = opts.cache.maxRecords;
2163
- if (opts.cache.maxBytes !== void 0) lruOptions.maxBytes = parseBytes(opts.cache.maxBytes);
2164
- this.lru = new Lru(lruOptions);
1943
+ this.lru = (opts.lazyStrategy ?? IMPLICIT_LAZY).createCache(this.name, opts.cache);
2165
1944
  this.hydrated = true;
2166
1945
  } else {
2167
1946
  this.lru = null;
@@ -2248,7 +2027,8 @@ var Collection = class {
2248
2027
  refs: this._refs,
2249
2028
  zodFields: void 0,
2250
2029
  ...this.meta !== void 0 ? { meta: this.meta } : {},
2251
- ...this.i18nFields !== void 0 ? { i18nFields: this.i18nFields } : {}
2030
+ ...this.i18nFields !== void 0 ? { i18nFields: this.i18nFields } : {},
2031
+ ...this.classified !== void 0 ? { classified: this.classified.byField } : {}
2252
2032
  });
2253
2033
  }
2254
2034
  /**
@@ -2285,11 +2065,13 @@ var Collection = class {
2285
2065
  zodFields,
2286
2066
  ...dictLabels !== void 0 ? { dictLabels } : {},
2287
2067
  ...this.meta !== void 0 ? { meta: this.meta } : {},
2288
- ...this.i18nFields !== void 0 ? { i18nFields: this.i18nFields } : {}
2068
+ ...this.i18nFields !== void 0 ? { i18nFields: this.i18nFields } : {},
2069
+ ...this.classified !== void 0 ? { classified: this.classified.byField } : {}
2289
2070
  });
2290
2071
  }
2291
2072
  /** JSON Schema for this collection with describe() metadata as x- extensions. */
2292
2073
  async toJSONSchema() {
2074
+ const { buildJsonSchema } = await import("./json-schema-I22JCYCG.js");
2293
2075
  const desc = await this.describe({});
2294
2076
  let base = null;
2295
2077
  if (this.schema !== void 0) {
@@ -2298,6 +2080,195 @@ var Collection = class {
2298
2080
  }
2299
2081
  return buildJsonSchema(desc, base);
2300
2082
  }
2083
+ /** Single-point audited reveal of one classified field. Requires withClassified(). */
2084
+ async reveal(id, field) {
2085
+ const spec = this.classified?.byField[field];
2086
+ if (spec === void 0) throw new ClassifiedRevealError(this.name, field, "field is not classified");
2087
+ if (spec.storage === "never") {
2088
+ throw new ClassifiedRevealError(this.name, field, `storage:'never' \u2014 nothing is stored to reveal`);
2089
+ }
2090
+ if (spec.storage === "digest-only") {
2091
+ throw new ClassifiedRevealError(this.name, field, `storage:'digest-only' \u2014 verify-only; nothing recoverable to reveal`);
2092
+ }
2093
+ return this.classifiedStrategy.reveal({
2094
+ collection: this.name,
2095
+ spec,
2096
+ encrypted: this.storeCiphertext,
2097
+ getEnvelope: (rid) => this.adapter.get(this.vault, this.name, rid),
2098
+ resolveCek: (env) => this.codec.resolveEnvelopeCek(env),
2099
+ getDEK: () => this.getDEK(this.name),
2100
+ ...this.onAccess !== void 0 ? { onAccess: async (_op, rid) => {
2101
+ await this.onAccess("reveal", rid);
2102
+ } } : {}
2103
+ }, id, field);
2104
+ }
2105
+ /** Verify-without-reveal: verdict-only oracle for one classified field. Requires withClassified(). */
2106
+ async verify(id, field, candidate) {
2107
+ const spec = this.classified?.byField[field];
2108
+ if (spec === void 0) throw new ClassifiedVerifyError(this.name, field, "field is not classified");
2109
+ if (spec.storage === "never") {
2110
+ throw new ClassifiedVerifyError(this.name, field, `storage:'never' \u2014 nothing is stored to verify against`);
2111
+ }
2112
+ const ctx = this._classifiedVerifyCtx(spec);
2113
+ return spec.storage === "digest-only" ? this.classifiedStrategy.verify(ctx, id, field, candidate) : this.classifiedStrategy.verifyText(ctx, id, field, candidate);
2114
+ }
2115
+ /** k-of-n challenge over the collection's secretAnswer members. Requires withClassified(). */
2116
+ async verifyGroup(id, answers, opts) {
2117
+ const members = Object.entries(this.classified?.byField ?? {}).filter(([, s]) => s.storage === "digest-only" && s.verifyGroupMember === true).map(([field, spec]) => ({ field, spec }));
2118
+ if (members.length === 0) {
2119
+ throw new ClassifiedVerifyError(this.name, "*", "no groupable digest-only (secretAnswer) fields declared");
2120
+ }
2121
+ const ctx = { ...this._classifiedVerifyCtx(members[0].spec), groupMembers: members };
2122
+ return this.classifiedStrategy.matchGroup(ctx, id, answers, opts);
2123
+ }
2124
+ _classifiedVerifyCtx(spec) {
2125
+ return {
2126
+ collection: this.name,
2127
+ spec,
2128
+ getEnvelope: (rid) => this.adapter.get(this.vault, this.name, rid),
2129
+ resolveCek: (env) => this.codec.resolveEnvelopeCek(env),
2130
+ getDEK: () => this.getDEK(this.name),
2131
+ now: () => Date.now(),
2132
+ // Q7: injected here; engine tests inject their own
2133
+ ...this.onAccess !== void 0 ? { onAccess: async (_op, rid) => {
2134
+ await this.onAccess("verify", rid);
2135
+ } } : {}
2136
+ };
2137
+ }
2138
+ /**
2139
+ * Equatable blind-index lookup: the ids whose classified digest-only
2140
+ * `equatable` field carries a `_bidx` tag matching `candidate` AND whose
2141
+ * `_vdig` payload confirms it. Requires the field to be declared
2142
+ * `classified.password({ equatable: true })` (or `secretAnswer`) and the
2143
+ * collection to have opened its `acknowledgeEquatableRisk` door.
2144
+ *
2145
+ * The algorithm order is load-bearing (spec §3):
2146
+ * 1. Caller-bug refusals thrown at ~0 elapsed, BEFORE any PBKDF2 (R9 /
2147
+ * Oracle #6): the three field mis-declarations share ONE constant,
2148
+ * field-name-free message so the refusal text cannot enumerate which
2149
+ * fields are classified / digest-only / equatable.
2150
+ * 2. Derive the ONE blind-index target UNCONDITIONALLY (I-1 / F1): an empty
2151
+ * collection still pays exactly one 600K PBKDF2, so wall-time can never
2152
+ * distinguish "no records" from "no match". No early return may precede
2153
+ * this line.
2154
+ * 3. Scan `list + one get` per id, string-comparing the stored `_bidx` tag —
2155
+ * decrypting NOTHING — and retain each hit's already-fetched envelope.
2156
+ * 4. Emit the single sweep consent op (`onAccess('find', '*')`) now — after
2157
+ * the scan, before confirm (Oracle #5) — fixing its store-write timestamp
2158
+ * independent of hit count.
2159
+ * 5. Confirm-by-verify against the ALREADY-FETCHED envelope (C-B): run the
2160
+ * enclave `verifyDigestField` on an in-memory `getEnvelope` closure so the
2161
+ * confirm reads ZERO additional envelopes. A tag-hit whose `_vdig` fails
2162
+ * to confirm is dropped silently (a splice is indistinguishable from a
2163
+ * stale tag). Store-shape law: the only store calls are `list + N get`.
2164
+ */
2165
+ async findByDigest(field, candidate) {
2166
+ const spec = this.classified?.byField[field];
2167
+ if (spec === void 0 || spec.storage !== "digest-only" || spec.equatable !== true) {
2168
+ throw new ClassifiedVerifyError(
2169
+ this.name,
2170
+ "*",
2171
+ "not a declared equatable digest-only classified field"
2172
+ );
2173
+ }
2174
+ if (typeof candidate !== "string") {
2175
+ throw new ClassifiedVerifyError(this.name, "*", "candidate must be a string");
2176
+ }
2177
+ const target = await this.classifiedStrategy.computeTarget(this._classifiedVerifyCtx(spec), field, candidate);
2178
+ const ids = await this.adapter.list(this.vault, this.name);
2179
+ const hits = [];
2180
+ const hitMap = /* @__PURE__ */ new Map();
2181
+ for (const id of ids) {
2182
+ const env = await this.adapter.get(this.vault, this.name, id);
2183
+ if (target !== null && env?._bidx?.[field] === target) {
2184
+ hits.push(id);
2185
+ hitMap.set(id, env);
2186
+ }
2187
+ }
2188
+ await this.onAccess?.("find", "*");
2189
+ if (hits.length === 0) return [];
2190
+ const { verifyDigestField } = await import("./verify-YB5LQHNA.js");
2191
+ const policy = {
2192
+ normalize: spec.verifyNormalize ?? "password",
2193
+ notLastN: spec.notLastN ?? 0,
2194
+ equatable: true,
2195
+ ...spec.rotateDays !== void 0 ? { rotateDays: spec.rotateDays } : {}
2196
+ };
2197
+ const confirmCtx = {
2198
+ collection: this.name,
2199
+ getEnvelope: async (rid) => hitMap.get(rid) ?? null,
2200
+ // in-memory: zero extra store.get
2201
+ resolveCek: (env) => this.codec.resolveEnvelopeCek(env),
2202
+ getDEK: () => this.getDEK(this.name),
2203
+ now: () => Date.now()
2204
+ };
2205
+ const confirmed = [];
2206
+ for (const id of hits) {
2207
+ const verdict = await verifyDigestField(confirmCtx, id, field, candidate, policy);
2208
+ if (verdict.ok === true) confirmed.push(id);
2209
+ }
2210
+ return confirmed;
2211
+ }
2212
+ /**
2213
+ * Retire a field's equatable blind-index (`_bidx`) coverage across every
2214
+ * live record — the SOLE lazy-write-independent drop-path for a still-live
2215
+ * record's tag (besides clear / `forget()` / DEK-rotation). For each envelope
2216
+ * carrying `_bidx[field]`, rewrite it WITHOUT that slot (dropping the whole
2217
+ * `_bidx` map when it becomes empty), leaving `_vdig[field]` and everything
2218
+ * else INTACT — the field stays `digest-only`, only the index coverage is
2219
+ * retired. NO crypto, NO re-mint, NO re-encrypt: a targeted envelope rewrite.
2220
+ * Returns the count of records scrubbed.
2221
+ *
2222
+ * This is a maintenance write, not a read-egress: it emits NO `'find'` op and
2223
+ * no consent. The field is validated to a declared equatable digest-only
2224
+ * classified field (only such a field ever carries `_bidx`).
2225
+ *
2226
+ * **Ledger consistency**: dropping `_bidx[field]` changes the envelope's
2227
+ * payload hash (`_bidx` is bound into `envelopeBodyForHash`), so a raw
2228
+ * `adapter.put` of the scrubbed envelope WITHOUT a matching ledger entry would
2229
+ * desync the chain and make a future integrity cross-check flag false
2230
+ * tampering. After each rewrite we therefore append an `op:'migration'` entry
2231
+ * recording the NEW payloadHash at the SAME version — this is index retirement,
2232
+ * not a new record version, so `_v` is NOT bumped; the migration op is
2233
+ * reverse-delta-inert (`ledger.reconstruct` skips non-put/delete ops) yet
2234
+ * keeps the hash chain and the record's latest recorded payloadHash correct.
2235
+ */
2236
+ async scrubEquatableTags(field) {
2237
+ const spec = this.classified?.byField[field];
2238
+ if (spec === void 0 || spec.storage !== "digest-only" || spec.equatable !== true) {
2239
+ throw new ClassifiedVerifyError(
2240
+ this.name,
2241
+ "*",
2242
+ "not a declared equatable digest-only classified field"
2243
+ );
2244
+ }
2245
+ const ids = await this.adapter.list(this.vault, this.name);
2246
+ let count = 0;
2247
+ for (const id of ids) {
2248
+ const env = await this.adapter.get(this.vault, this.name, id);
2249
+ if (env?._bidx?.[field] === void 0) continue;
2250
+ const nextBidx = { ...env._bidx };
2251
+ delete nextBidx[field];
2252
+ const scrubbedRaw = { ...env };
2253
+ delete scrubbedRaw._bidx;
2254
+ if (Object.keys(nextBidx).length > 0) scrubbedRaw._bidx = nextBidx;
2255
+ const scrubbed = scrubbedRaw;
2256
+ await this.adapter.put(this.vault, this.name, id, scrubbed);
2257
+ if (this.ledger) {
2258
+ await this.ledger.append({
2259
+ op: "migration",
2260
+ collection: this.name,
2261
+ id,
2262
+ version: scrubbed._v,
2263
+ actor: this.keyring.userId,
2264
+ payloadHash: await this.historyStrategy.envelopePayloadHash(scrubbed),
2265
+ reason: "classified:scrub-equatable-tags"
2266
+ });
2267
+ }
2268
+ count++;
2269
+ }
2270
+ return count;
2271
+ }
2301
2272
  /**
2302
2273
  * @internal — attach money descriptors post-construction. MV dependency
2303
2274
  * analysis auto-creates a source collection (without options) during
@@ -2306,7 +2277,7 @@ var Collection = class {
2306
2277
  */
2307
2278
  _applyMoneyFields(moneyFields) {
2308
2279
  if (this.moneyFields !== void 0) return;
2309
- validateMoneyFieldPaths(moneyFields);
2280
+ moneyRuntime().validateMoneyFieldPaths(moneyFields);
2310
2281
  this.moneyFields = moneyFields;
2311
2282
  }
2312
2283
  /** @internal — attach computed fields post-construction. See {@link _applyMoneyFields}. */
@@ -2321,6 +2292,52 @@ var Collection = class {
2321
2292
  _applyMeta(meta) {
2322
2293
  if (this.meta === void 0) this.meta = meta;
2323
2294
  }
2295
+ /**
2296
+ * @internal — attach classified fields post-construction. See {@link _applyMoneyFields}.
2297
+ * First-wins. Note: unlike money/computed/meta, this cannot retro-seal a
2298
+ * collection that was already auto-created — `sensitiveFields` is frozen at
2299
+ * construction time. A reconciled declaration is only accepted when none of
2300
+ * its members are `storage: 'recoverable'` (those require sealing at first
2301
+ * open); otherwise this throws rather than silently persisting the value as
2302
+ * inline plaintext while `describe()` advertises protection.
2303
+ */
2304
+ _applyClassifiedFields(classifiedFields) {
2305
+ const resolved = resolveClassifiedFields(this.name, classifiedFields);
2306
+ if (this.classified !== void 0) {
2307
+ for (const [field, spec] of Object.entries(resolved.byField)) {
2308
+ const prior = this.classified.byField[field];
2309
+ if (prior !== void 0 && prior.storage !== spec.storage) {
2310
+ throw new ClassifiedConfigError(
2311
+ this.name,
2312
+ `field "${field}" was already declared storage:'${prior.storage}' \u2014 storage-form transitions are refused (R6); migrate explicitly`
2313
+ );
2314
+ }
2315
+ }
2316
+ return;
2317
+ }
2318
+ guardClassifiedCompat(this.name, resolved.byField, this.classifiedGuardCtx);
2319
+ for (const key of Object.keys(resolved.riderComputed)) {
2320
+ if (this.computed?.[key] !== void 0) {
2321
+ throw new ClassifiedConfigError(this.name, `rider companion "${key}" collides with a declared field`);
2322
+ }
2323
+ }
2324
+ const retroDigest = Object.entries(resolved.byField).filter(([, spec]) => spec.storage === "digest-only").map(([field]) => field);
2325
+ if (retroDigest.length > 0) {
2326
+ throw new ClassifiedConfigError(
2327
+ this.name,
2328
+ `digest-only classified field(s) ${retroDigest.map((f) => `"${f}"`).join(", ")} were declared after the collection was first opened without them \u2014 the digest write path is fixed at first open, so these values would persist recoverably in _data. Declare classifiedFields at the collection's first vault.collection() call.`
2329
+ );
2330
+ }
2331
+ const unsealable = Object.entries(resolved.byField).filter(([field, spec]) => spec.storage === "recoverable" && !this.sensitiveFields.has(field)).map(([field]) => field);
2332
+ if (unsealable.length > 0) {
2333
+ throw new ClassifiedConfigError(
2334
+ this.name,
2335
+ `recoverable classified field(s) ${unsealable.map((f) => `"${f}"`).join(", ")} were declared after the collection was first opened without them \u2014 sealing is fixed at first open, so these values would persist as inline plaintext. Declare classifiedFields at the collection's first vault.collection() call (for materialized-view sources this means recoverable classified fields are not supported in stage 1).`
2336
+ );
2337
+ }
2338
+ this.classified = resolved;
2339
+ this.computed = { ...resolved.riderComputed, ...this.computed ?? {} };
2340
+ }
2324
2341
  /** @internal — used only in tests; do not read in production code. */
2325
2342
  get _ramCiphertext() {
2326
2343
  return this.ramCiphertext;
@@ -2346,7 +2363,7 @@ var Collection = class {
2346
2363
  }
2347
2364
  }
2348
2365
  if (this.materializedViewSource !== void 0) {
2349
- const { resolveStaleMVOnRead } = await import("./stale-3JWHNDIY.js");
2366
+ const { resolveStaleMVOnRead } = await import("./stale-7Q62KVI3.js");
2350
2367
  await resolveStaleMVOnRead(this.materializedViewSource, this.name);
2351
2368
  }
2352
2369
  let record;
@@ -2578,29 +2595,47 @@ var Collection = class {
2578
2595
  const cached = this.cache.get(id);
2579
2596
  return cached ? { record: cached.record, version: cached.version } : void 0;
2580
2597
  }
2598
+ /** Resolves the prior envelope/record for a gate event; elides the read (#267) when no handler at `point` needs it (`elided: true`, `env`/`record` null). */
2599
+ async resolveGatePrior(point, id) {
2600
+ if (!this.subsystemBus.gateNeedsPrior(point)) return { env: null, record: null, elided: true };
2601
+ const env = await this.adapter.get(this.vault, this.name, id);
2602
+ if (!env) return { env: null, record: null, elided: false };
2603
+ try {
2604
+ return { env, record: await this.codec.decryptRecord(env, { skipValidation: true }), elided: false };
2605
+ } catch {
2606
+ return { env, record: null, elided: false };
2607
+ }
2608
+ }
2609
+ /**
2610
+ * Wraps {@link RecordCodec.toCacheRecord} with an additional strip for
2611
+ * digest-only classified fields: the codec already omits them from `_data`
2612
+ * on write, but the write path caches the pre-encrypt `record` object
2613
+ * directly (to skip a redundant decrypt) — without this, a vdig field's
2614
+ * plaintext would sit in the working-set cache and `get()` would leak it
2615
+ * right back out, defeating C6.
2616
+ */
2617
+ async _toCacheableRecord(record, envelope, id) {
2618
+ const base = await this.codec.toCacheRecord(record, envelope, id);
2619
+ if (this.vdigFields === null) return base;
2620
+ const clone = { ...base };
2621
+ for (const field of this.vdigFields.keys()) delete clone[field];
2622
+ return clone;
2623
+ }
2581
2624
  /** @internal Untracked put body — call {@link put}, not this. */
2582
2625
  async _putInternal(id, record, options) {
2583
2626
  if (!hasWritePermission(this.keyring, this.name)) {
2584
2627
  throw new ReadOnlyError();
2585
2628
  }
2586
- record = canonicalizeIncomingMoney(record, this.moneyFields);
2629
+ if (this.moneyFields) record = moneyRuntime().canonicalizeIncomingMoney(record, this.moneyFields);
2587
2630
  if (this.subsystemBus?.hasGateHandlers("beforePut")) {
2588
- const existingEnv = await this.adapter.get(this.vault, this.name, id);
2589
- let existingRecord = null;
2590
- if (existingEnv) {
2591
- try {
2592
- existingRecord = await this.codec.decryptRecord(existingEnv, { skipValidation: true });
2593
- } catch {
2594
- existingRecord = null;
2595
- }
2596
- }
2631
+ const { env: existingEnv, record: existingRecord } = await this.resolveGatePrior("beforePut", id);
2597
2632
  const gateEvent = {
2598
2633
  op: existingEnv ? "update" : "create",
2599
2634
  vault: this.vault,
2600
2635
  collection: this.name,
2601
2636
  docId: id,
2602
2637
  incoming: record,
2603
- existing: canonicalizeStoredMoney(existingRecord, this.moneyFields),
2638
+ existing: this.moneyFields ? moneyRuntime().canonicalizeStoredMoney(existingRecord, this.moneyFields) : existingRecord,
2604
2639
  existingVersion: existingEnv?._v ?? 0,
2605
2640
  existingTs: existingEnv?._ts,
2606
2641
  userId: this.keyring.userId,
@@ -2609,14 +2644,17 @@ var Collection = class {
2609
2644
  };
2610
2645
  await this.subsystemBus.dispatchGate("beforePut", gateEvent);
2611
2646
  }
2647
+ if (this.classified !== void 0) {
2648
+ enforceClassifiedWrite(record, this.classified.byField, this.name);
2649
+ }
2612
2650
  if (this.computed !== void 0) {
2613
- record = evalComputedFields(record, this.computed, id);
2651
+ record = (await loadEvalComputedFields())(record, this.computed, id);
2614
2652
  }
2615
2653
  if (this.schema !== void 0) {
2616
2654
  record = await validateSchemaInput(this.schema, record, `put(${id})`);
2617
2655
  }
2618
2656
  if (this.moneyFields) {
2619
- record = quantizeMoneyFields(record, this.moneyFields);
2657
+ record = moneyRuntime().quantizeMoneyFields(record, this.moneyFields);
2620
2658
  }
2621
2659
  if (this.i18nFields) {
2622
2660
  const obj = record;
@@ -2744,7 +2782,8 @@ var Collection = class {
2744
2782
  const existingResolvedRecord = existingEnvelope ? await this.codec.decryptRecord(existingEnvelope, { skipValidation: true }) : null;
2745
2783
  const existingResolved = existingResolvedRecord !== null ? { record: existingResolvedRecord, version: existingVersion } : void 0;
2746
2784
  if (existingResolved && this.historyConfig.enabled !== false) {
2747
- const histEnvelope = await this.codec.encryptRecord(existingResolved.record, existingResolved.version, cek2);
2785
+ const vdigCtx2 = this.vdigFields !== null ? { id, prev: existingEnvelope } : void 0;
2786
+ const histEnvelope = await this.codec.encryptRecord(existingResolved.record, existingResolved.version, cek2, void 0, void 0, vdigCtx2);
2748
2787
  await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, histEnvelope);
2749
2788
  this.emitter.emit("history:save", { vault: this.vault, collection: this.name, id, version: existingResolved.version });
2750
2789
  if (this.historyConfig.maxVersions) {
@@ -2803,8 +2842,9 @@ var Collection = class {
2803
2842
  const version = existing ? existing.version + 1 : 1;
2804
2843
  this.uniqueConstraints?.check(id, record);
2805
2844
  const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
2845
+ const vdigCtx = this.vdigFields !== null ? { id, prev: await this.adapter.get(this.vault, this.name, id) } : void 0;
2806
2846
  if (existing && this.historyConfig.enabled !== false) {
2807
- const historyEnvelope = await this.codec.encryptRecord(existing.record, existing.version, cek);
2847
+ const historyEnvelope = await this.codec.encryptRecord(existing.record, existing.version, cek, void 0, void 0, vdigCtx);
2808
2848
  await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, historyEnvelope);
2809
2849
  this.emitter.emit("history:save", {
2810
2850
  vault: this.vault,
@@ -2818,8 +2858,9 @@ var Collection = class {
2818
2858
  });
2819
2859
  }
2820
2860
  }
2821
- const envelope = await this.codec.encryptRecord(record, version, cek, options?.source, options?.sourceTs);
2861
+ const envelope = await this.codec.encryptRecord(record, version, cek, options?.source, options?.sourceTs, vdigCtx);
2822
2862
  await this.adapter.put(this.vault, this.name, id, envelope);
2863
+ await this._ensureClassifiedMarker();
2823
2864
  if (this.embeddings) {
2824
2865
  await this.searchStrategy.embedOnWrite(this.searchContext(), id, record, version);
2825
2866
  }
@@ -2839,10 +2880,10 @@ var Collection = class {
2839
2880
  await this.ledger.append(appendInput);
2840
2881
  }
2841
2882
  if (this.lazy && this.lru) {
2842
- this.lru.set(id, { record: await this.codec.toCacheRecord(record, envelope, id), version }, estimateRecordBytes(record));
2883
+ this.lru.set(id, { record: await this._toCacheableRecord(record, envelope, id), version }, estimateRecordBytes(record));
2843
2884
  await this.maintainPersistedIndexesOnPut(id, record, existing ? existing.record : null, version);
2844
2885
  } else {
2845
- this.cache.set(id, { record: await this.codec.toCacheRecord(record, envelope, id), version });
2886
+ this.cache.set(id, { record: await this._toCacheableRecord(record, envelope, id), version });
2846
2887
  this.indexes?.upsert(id, record, existing ? existing.record : null);
2847
2888
  this.uniqueConstraints?.upsert(id, record, existing?.record);
2848
2889
  }
@@ -2885,7 +2926,7 @@ var Collection = class {
2885
2926
  if (mode === "eager") {
2886
2927
  if (executor === null) {
2887
2928
  ;
2888
- ({ MaterializedViewExecutor: executor } = await import("./executor-2FWQRLMG.js"));
2929
+ ({ MaterializedViewExecutor: executor } = await import("./executor-FGISLQIN.js"));
2889
2930
  }
2890
2931
  await executor.refresh(reg, {
2891
2932
  getCollection: (name) => this.materializedViewSource.getCollection(name),
@@ -2894,7 +2935,7 @@ var Collection = class {
2894
2935
  });
2895
2936
  } else if (mode === "lazy") {
2896
2937
  if (staleHelpers === null) {
2897
- staleHelpers = await import("./stale-3JWHNDIY.js");
2938
+ staleHelpers = await import("./stale-7Q62KVI3.js");
2898
2939
  }
2899
2940
  staleHelpers.markMVStale(registry, reg.spec.name);
2900
2941
  }
@@ -2946,7 +2987,7 @@ var Collection = class {
2946
2987
  raw = (await this.resolvePriorValues(id))?.record ?? null;
2947
2988
  }
2948
2989
  if (raw === null) return null;
2949
- return canonicalizeStoredMoney(raw, this.moneyFields);
2990
+ return this.moneyFields ? moneyRuntime().canonicalizeStoredMoney(raw, this.moneyFields) : raw;
2950
2991
  }
2951
2992
  /**
2952
2993
  * @internal Ids of records whose top-level `field` equals `value`.
@@ -3029,7 +3070,7 @@ var Collection = class {
3029
3070
  }
3030
3071
  async dispatchDerivations(id, record, version) {
3031
3072
  if (this.derivationSource === void 0) return;
3032
- const incoming = canonicalizeStoredMoney(record, this.moneyFields);
3073
+ const incoming = this.moneyFields ? moneyRuntime().canonicalizeStoredMoney(record, this.moneyFields) : record;
3033
3074
  if (incoming && typeof incoming === "object" && "_derivedFrom" in incoming) return;
3034
3075
  const registry = this.derivationSource.registry();
3035
3076
  const strategies = registry.strategiesForSource(this.name);
@@ -3079,7 +3120,7 @@ var Collection = class {
3079
3120
  continue;
3080
3121
  }
3081
3122
  if (DerivationExecutor === null) {
3082
- ({ DerivationExecutor } = await import("./executor-Z5ZLJVTV.js"));
3123
+ ({ DerivationExecutor } = await import("./executor-CBTNU5VZ.js"));
3083
3124
  }
3084
3125
  for (const run of runs) {
3085
3126
  const ctx = { vault: this.derivationSource.getReadOnlyFacade() };
@@ -3098,7 +3139,7 @@ var Collection = class {
3098
3139
  const outputCollection = this.derivationSource.getCollection(outSpec.collection);
3099
3140
  const txCtx = this.derivationSource.getActiveTxContext();
3100
3141
  if (out.kind === "array") {
3101
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-GF3DJ6KR.js");
3142
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-WS22Q5WH.js");
3102
3143
  const prior = await loadFanoutSidecar(this.adapter, this.vault, spec.source, run.runId, key, this.getDEK, this.storeCiphertext);
3103
3144
  const prevKeys = new Set(prior?.keys ?? []);
3104
3145
  const newKeysList = out.entries.map((e) => e.key);
@@ -3225,7 +3266,7 @@ var Collection = class {
3225
3266
  const next = transform(record);
3226
3267
  const nextVersion = (env._v ?? 0) + 1;
3227
3268
  const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
3228
- const newEnv = await this.codec.encryptRecord(next, nextVersion, cek);
3269
+ const newEnv = await this.codec.encryptRecord(next, nextVersion, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: env } : void 0);
3229
3270
  await this.adapter.put(this.vault, this.name, id, newEnv);
3230
3271
  await this._invalidateCacheEntry(id);
3231
3272
  if (this.ledger) {
@@ -3306,21 +3347,15 @@ var Collection = class {
3306
3347
  throw new ReadOnlyError();
3307
3348
  }
3308
3349
  if (this.subsystemBus?.hasGateHandlers("beforeDelete")) {
3309
- const existingEnv = await this.adapter.get(this.vault, this.name, id);
3310
- if (existingEnv) {
3311
- let existingRecord = null;
3312
- try {
3313
- existingRecord = await this.codec.decryptRecord(existingEnv, { skipValidation: true });
3314
- } catch {
3315
- existingRecord = null;
3316
- }
3350
+ const { env: existingEnv, record: existingRecord, elided } = await this.resolveGatePrior("beforeDelete", id);
3351
+ if (existingEnv || elided) {
3317
3352
  await this.subsystemBus.dispatchGate("beforeDelete", {
3318
3353
  vault: this.vault,
3319
3354
  collection: this.name,
3320
3355
  docId: id,
3321
- existing: canonicalizeStoredMoney(existingRecord, this.moneyFields),
3322
- existingVersion: existingEnv._v,
3323
- existingTs: existingEnv._ts,
3356
+ existing: this.moneyFields ? moneyRuntime().canonicalizeStoredMoney(existingRecord, this.moneyFields) : existingRecord,
3357
+ existingVersion: existingEnv?._v ?? 0,
3358
+ existingTs: existingEnv?._ts,
3324
3359
  internal,
3325
3360
  userId: this.keyring.userId,
3326
3361
  role: this.keyring.role
@@ -3347,7 +3382,8 @@ var Collection = class {
3347
3382
  }
3348
3383
  if (existing && this.historyConfig.enabled !== false) {
3349
3384
  const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
3350
- const historyEnvelope = await this.codec.encryptRecord(existing.record, existing.version, cek);
3385
+ const prevForVdig = this.vdigFields !== null ? await this.adapter.get(this.vault, this.name, id) : null;
3386
+ const historyEnvelope = await this.codec.encryptRecord(existing.record, existing.version, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: prevForVdig } : void 0);
3351
3387
  await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, historyEnvelope);
3352
3388
  }
3353
3389
  const previousEnvelope = await this.adapter.get(this.vault, this.name, id);
@@ -3456,7 +3492,7 @@ var Collection = class {
3456
3492
  for (const [outputKey, outSpec] of Object.entries(spec.outputs)) {
3457
3493
  if (outSpec.shape !== "array") continue;
3458
3494
  if (helpers === null) {
3459
- helpers = await import("./fanout-sidecar-GF3DJ6KR.js");
3495
+ helpers = await import("./fanout-sidecar-WS22Q5WH.js");
3460
3496
  }
3461
3497
  const sidecar = await helpers.loadFanoutSidecar(this.adapter, this.vault, spec.source, id, outputKey, this.getDEK, this.storeCiphertext);
3462
3498
  if (!sidecar) continue;
@@ -3490,7 +3526,7 @@ var Collection = class {
3490
3526
  if (mode === "eager") {
3491
3527
  if (executor === null) {
3492
3528
  ;
3493
- ({ MaterializedViewExecutor: executor } = await import("./executor-2FWQRLMG.js"));
3529
+ ({ MaterializedViewExecutor: executor } = await import("./executor-FGISLQIN.js"));
3494
3530
  }
3495
3531
  await executor.refresh(reg, {
3496
3532
  getCollection: (name) => this.materializedViewSource.getCollection(name),
@@ -3499,7 +3535,7 @@ var Collection = class {
3499
3535
  });
3500
3536
  } else if (mode === "lazy") {
3501
3537
  if (staleHelpers === null) {
3502
- staleHelpers = await import("./stale-3JWHNDIY.js");
3538
+ staleHelpers = await import("./stale-7Q62KVI3.js");
3503
3539
  }
3504
3540
  staleHelpers.markMVStale(registry, reg.spec.name);
3505
3541
  }
@@ -3522,7 +3558,7 @@ var Collection = class {
3522
3558
  );
3523
3559
  }
3524
3560
  if (this.materializedViewSource !== void 0) {
3525
- const { resolveStaleMVOnRead } = await import("./stale-3JWHNDIY.js");
3561
+ const { resolveStaleMVOnRead } = await import("./stale-7Q62KVI3.js");
3526
3562
  await resolveStaleMVOnRead(this.materializedViewSource, this.name);
3527
3563
  }
3528
3564
  await this.ensureHydrated();
@@ -4351,7 +4387,8 @@ var Collection = class {
4351
4387
  const result = {};
4352
4388
  for (const [id, entry] of this.cache) {
4353
4389
  const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
4354
- result[id] = await this.codec.encryptRecord(entry.record, entry.version, cek);
4390
+ const prevForVdig = this.vdigFields !== null ? await this.adapter.get(this.vault, this.name, id) : null;
4391
+ result[id] = await this.codec.encryptRecord(entry.record, entry.version, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: prevForVdig } : void 0);
4355
4392
  }
4356
4393
  return result;
4357
4394
  }
@@ -4377,7 +4414,7 @@ var Collection = class {
4377
4414
  const locale = localeOpts?.locale ?? this.defaultLocale;
4378
4415
  let result = record;
4379
4416
  if (hasMoney && this.moneyFields) {
4380
- result = decodeMoneyFields(result, this.moneyFields, typeof locale === "string" ? locale : void 0);
4417
+ result = moneyRuntime().decodeMoneyFields(result, this.moneyFields, typeof locale === "string" ? locale : void 0);
4381
4418
  }
4382
4419
  const hasStaticDisplay = hasDict && this.dictKeyFields !== void 0 && Object.values(this.dictKeyFields).some(
4383
4420
  (d) => isStaticDictDescriptor(d) && d.displayLocale !== void 0
@@ -4663,6 +4700,20 @@ var Collection = class {
4663
4700
  id
4664
4701
  );
4665
4702
  }
4703
+ /** C-A/R10: persist the classified marker once per classified handle (store I/O in config-drift.ts). */
4704
+ async _ensureClassifiedMarker() {
4705
+ if (this._markerPersisted || this.vdigFields === null) return;
4706
+ const { persistClassifiedMarkerForFields } = await import("./config-drift-KGM7ZRW4.js");
4707
+ await persistClassifiedMarkerForFields(this.adapter, this.vault, this.name, this.vdigFields, await this.getDEK(this.name));
4708
+ this._markerPersisted = true;
4709
+ }
4710
+ /** C-A/R10 drift signal — the marker's declared digest-only set, memoized to one store read per handle (see config-drift.ts). */
4711
+ async _classifiedMarkerDigestOnly() {
4712
+ if (this._markerDigestOnlyCache !== void 0) return this._markerDigestOnlyCache;
4713
+ const { readClassifiedMarkerDigestOnly } = await import("./config-drift-KGM7ZRW4.js");
4714
+ this._markerDigestOnlyCache = await readClassifiedMarkerDigestOnly(this.adapter, this.vault, this.name, await this.getDEK(this.name));
4715
+ return this._markerDigestOnlyCache;
4716
+ }
4666
4717
  /**
4667
4718
  * find the first record whose deterministic field matches
4668
4719
  * the given plaintext. Returns `null` when no match exists.
@@ -5384,141 +5435,6 @@ var RefRegistry = class {
5384
5435
  }
5385
5436
  };
5386
5437
 
5387
- // src/with-shape/links/link-set.ts
5388
- var LINK_COLLECTION_PREFIX = "_links_";
5389
- function linkCollectionName(name) {
5390
- return `${LINK_COLLECTION_PREFIX}${name}`;
5391
- }
5392
- function isLinkCollectionName(name) {
5393
- return name.startsWith(LINK_COLLECTION_PREFIX);
5394
- }
5395
- function linkRowKey(aId, bId) {
5396
- return `${encodeURIComponent(aId)}|${encodeURIComponent(bId)}`;
5397
- }
5398
- var LinkSet = class {
5399
- constructor(adapter, vault, name, spec, encrypted, getDEK, actor, emitter, endpointExists) {
5400
- this.adapter = adapter;
5401
- this.vault = vault;
5402
- this.name = name;
5403
- this.spec = spec;
5404
- this.encrypted = encrypted;
5405
- this.getDEK = getDEK;
5406
- this.actor = actor;
5407
- this.emitter = emitter;
5408
- this.endpointExists = endpointExists;
5409
- this.collName = linkCollectionName(name);
5410
- }
5411
- adapter;
5412
- vault;
5413
- name;
5414
- spec;
5415
- encrypted;
5416
- getDEK;
5417
- actor;
5418
- emitter;
5419
- endpointExists;
5420
- collName;
5421
- dekPromise = null;
5422
- dek() {
5423
- if (!this.dekPromise) this.dekPromise = this.getDEK(this.collName);
5424
- return this.dekPromise;
5425
- }
5426
- async encryptEntry(entry, version) {
5427
- const json = JSON.stringify(entry);
5428
- const base = { _noydb: NOYDB_FORMAT_VERSION, _v: version, _ts: (/* @__PURE__ */ new Date()).toISOString(), _by: this.actor };
5429
- if (!this.encrypted) return { ...base, _iv: "", _data: json };
5430
- const { iv, data } = await encrypt(json, await this.dek());
5431
- return { ...base, _iv: iv, _data: data };
5432
- }
5433
- async decryptEntry(env) {
5434
- const json = this.encrypted ? await openEnvelopeJson(env, await this.dek()) : env._data;
5435
- return JSON.parse(json);
5436
- }
5437
- async connect(aId, bId, meta) {
5438
- if (!await this.endpointExists(this.spec.a, aId)) {
5439
- throw new LinkEndpointError(this.name, this.spec.a, aId);
5440
- }
5441
- if (!await this.endpointExists(this.spec.b, bId)) {
5442
- throw new LinkEndpointError(this.name, this.spec.b, bId);
5443
- }
5444
- const key = linkRowKey(aId, bId);
5445
- const entry = meta !== void 0 ? { a: aId, b: bId, meta } : { a: aId, b: bId };
5446
- const existing = await this.adapter.get(this.vault, this.collName, key);
5447
- const env = await this.encryptEntry(entry, (existing?._v ?? 0) + 1);
5448
- await this.adapter.put(this.vault, this.collName, key, env, existing?._v);
5449
- this.emitter.emit("change", { vault: this.vault, collection: this.collName, id: key, action: "put" });
5450
- }
5451
- async disconnect(aId, bId) {
5452
- const key = linkRowKey(aId, bId);
5453
- const existing = await this.adapter.get(this.vault, this.collName, key);
5454
- if (!existing) return;
5455
- await this.adapter.delete(this.vault, this.collName, key);
5456
- this.emitter.emit("change", { vault: this.vault, collection: this.collName, id: key, action: "delete" });
5457
- }
5458
- async has(aId, bId) {
5459
- return await this.adapter.get(this.vault, this.collName, linkRowKey(aId, bId)) !== null;
5460
- }
5461
- async of(id) {
5462
- const rows = await this.list();
5463
- return rows.filter((r) => r.a === id || r.b === id);
5464
- }
5465
- async list() {
5466
- const keys = await this.adapter.list(this.vault, this.collName);
5467
- const out = [];
5468
- for (const key of keys) {
5469
- const env = await this.adapter.get(this.vault, this.collName, key);
5470
- if (!env) continue;
5471
- const e = await this.decryptEntry(env);
5472
- out.push(e.meta !== void 0 ? { a: e.a, b: e.b, meta: e.meta } : { a: e.a, b: e.b });
5473
- }
5474
- return out;
5475
- }
5476
- // ── Vault-internal cascade helpers ──────────────────────────────────
5477
- /** @internal — rows where the deleted endpoint id matches the relevant slot. */
5478
- async _rowsTouchingEndpoint(collection, id) {
5479
- const rows = await this.list();
5480
- return rows.filter(
5481
- (r) => this.spec.a === collection && r.a === id || this.spec.b === collection && r.b === id
5482
- );
5483
- }
5484
- /** @internal — the storage collection name (for tx pre-image capture). */
5485
- get _collectionName() {
5486
- return this.collName;
5487
- }
5488
- };
5489
- var LinkEndpointError = class extends NoydbError {
5490
- link;
5491
- endpoint;
5492
- missingId;
5493
- constructor(link, endpoint, missingId) {
5494
- super(
5495
- "LINK_ENDPOINT",
5496
- `link("${link}").connect: endpoint "${endpoint}" has no record "${missingId}".`
5497
- );
5498
- this.name = "LinkEndpointError";
5499
- this.link = link;
5500
- this.endpoint = endpoint;
5501
- this.missingId = missingId;
5502
- }
5503
- };
5504
- var LinkIntegrityError = class extends NoydbError {
5505
- link;
5506
- endpoint;
5507
- id;
5508
- count;
5509
- constructor(link, endpoint, id, count) {
5510
- super(
5511
- "LINK_INTEGRITY",
5512
- `Cannot delete "${endpoint}"/"${id}": ${count} link(s) in "${link}" still reference it (onDelete: 'strict').`
5513
- );
5514
- this.name = "LinkIntegrityError";
5515
- this.link = link;
5516
- this.endpoint = endpoint;
5517
- this.id = id;
5518
- this.count = count;
5519
- }
5520
- };
5521
-
5522
5438
  // src/with-shape/links/vault-facade.ts
5523
5439
  var VaultLinks = class {
5524
5440
  constructor(deps) {
@@ -5838,74 +5754,21 @@ var VaultLinks = class {
5838
5754
  }
5839
5755
  };
5840
5756
 
5841
- // src/with-shape/schema-update/delta.ts
5842
- function computeSchemaDelta(stored, fresh, collection) {
5843
- const a = stored;
5844
- const b = fresh;
5845
- const aProps = a.properties ?? {};
5846
- const bProps = b.properties ?? {};
5847
- const aReq = new Set(a.required ?? []);
5848
- const bReq = new Set(b.required ?? []);
5849
- const aKeys = Object.keys(aProps);
5850
- const bKeys = Object.keys(bProps);
5851
- const added = bKeys.filter((k) => !(k in aProps));
5852
- const removed = aKeys.filter((k) => !(k in bProps));
5853
- const changed = [];
5854
- for (const k of bKeys) {
5855
- if (!(k in aProps)) continue;
5856
- const shapeChanged = canonicalize(aProps[k]) !== canonicalize(bProps[k]);
5857
- const requiredChanged = aReq.has(k) !== bReq.has(k);
5858
- if (shapeChanged || requiredChanged) {
5859
- changed.push({ field: k, requiredChanged, shapeChanged });
5860
- }
5861
- }
5862
- let kind;
5863
- if (added.length === 0 && removed.length === 0 && changed.length === 0) {
5864
- kind = "none";
5865
- } else if (removed.length === 0 && changed.length === 0 && added.every((k) => !bReq.has(k))) {
5866
- kind = "additive";
5867
- } else {
5868
- kind = "non-additive";
5869
- }
5870
- return { collection, kind, added, removed, changed };
5871
- }
5872
-
5873
- // src/with-shape/schema-update/dispatch.ts
5874
- async function evaluateStrategies(delta, strategies, ctx) {
5875
- for (const strategy of strategies) {
5876
- const decision = await strategy.onSchemaDelta(delta, ctx);
5877
- if (decision.action !== "allow") return decision;
5878
- }
5879
- return { action: "allow" };
5880
- }
5881
-
5882
- // src/with-shape/persisted-schemas/register.ts
5883
- async function persistSchemaIfNeeded(opts) {
5884
- const fresh = await derivePersistedSchema(opts.validator);
5885
- const stored = await loadPersistedSchema(opts.store, opts.vault, opts.collectionName, opts.dek);
5886
- if (stored && isEquivalent(stored, fresh)) {
5887
- return { written: false, skipped: true, envelope: stored, decision: { action: "allow" } };
5888
- }
5889
- let decision = { action: "allow" };
5890
- const strategies = opts.strategies ?? [];
5891
- if (stored && strategies.length > 0 && stored.kind === fresh.kind && isPlainObject(stored.jsonSchema) && isPlainObject(fresh.jsonSchema)) {
5892
- const delta = computeSchemaDelta(stored.jsonSchema, fresh.jsonSchema, opts.collectionName);
5893
- decision = await evaluateStrategies(delta, strategies, { collection: opts.collectionName });
5894
- }
5895
- if (decision.action !== "allow") {
5896
- return { written: false, skipped: false, envelope: stored ?? fresh, decision };
5897
- }
5898
- await savePersistedSchema(opts.store, opts.vault, opts.collectionName, opts.dek, fresh);
5899
- return { written: true, skipped: false, envelope: fresh, decision };
5900
- }
5901
- function isPlainObject(v) {
5902
- return typeof v === "object" && v !== null && !Array.isArray(v);
5903
- }
5904
- function isEquivalent(a, b) {
5905
- if (a.kind !== b.kind) return false;
5906
- if (a.hash && b.hash) return a.hash === b.hash;
5907
- if (a.hash === null && b.hash === null) return true;
5908
- return false;
5757
+ // src/with-shape/links/lazy-handle.ts
5758
+ function makeLazyLinkSetHandle(d) {
5759
+ let engine = null;
5760
+ const load = () => engine ??= import("./link-set-UQEIYQAM.js").then(
5761
+ ({ LinkSet }) => new LinkSet(d.adapter, d.vault, d.name, d.spec, d.encrypted, d.getDEK, d.actor, d.emitter, d.endpointExists)
5762
+ );
5763
+ return {
5764
+ _collectionName: linkCollectionName(d.name),
5765
+ connect: async (aId, bId, meta) => (await load()).connect(aId, bId, meta),
5766
+ disconnect: async (aId, bId) => (await load()).disconnect(aId, bId),
5767
+ has: async (aId, bId) => (await load()).has(aId, bId),
5768
+ of: async (id) => (await load()).of(id),
5769
+ list: async () => (await load()).list(),
5770
+ _rowsTouchingEndpoint: async (collection, id) => (await load())._rowsTouchingEndpoint(collection, id)
5771
+ };
5909
5772
  }
5910
5773
 
5911
5774
  // src/with-shape/schema-update/gate.ts
@@ -6021,70 +5884,6 @@ var SchemaFenceController = class {
6021
5884
  }
6022
5885
  };
6023
5886
 
6024
- // src/with-shape/schema-update/fence-watcher.ts
6025
- var FenceWatcher = class {
6026
- #coordination;
6027
- #vault;
6028
- #writerId;
6029
- #sessionId;
6030
- #onFlush;
6031
- #now;
6032
- #emit;
6033
- #lastState = null;
6034
- #quiescedAtVersion = null;
6035
- #timer;
6036
- constructor(opts) {
6037
- this.#coordination = opts.coordination;
6038
- this.#vault = opts.vault;
6039
- this.#writerId = opts.clientId;
6040
- this.#sessionId = opts.sessionId ?? opts.clientId;
6041
- this.#onFlush = opts.onFlush;
6042
- this.#now = opts.now ?? (() => Date.now());
6043
- this.#emit = opts.emit ?? (() => {
6044
- });
6045
- }
6046
- /** Publish liveness (and the current ack) without changing quiesce state. */
6047
- async beat() {
6048
- await this.#coordination.reportPresence(this.#vault, {
6049
- writerId: this.#writerId,
6050
- sessionId: this.#sessionId,
6051
- lastSeen: this.#now(),
6052
- quiescedAtVersion: this.#quiescedAtVersion
6053
- });
6054
- }
6055
- /** Poll the fence; quiesce on draining; emit on transitions. */
6056
- async check() {
6057
- const fence = await this.#coordination.readFence(this.#vault);
6058
- if (fence.fenceState !== this.#lastState) {
6059
- this.#lastState = fence.fenceState;
6060
- this.#emit({ currentSchemaVersion: fence.currentSchemaVersion, fenceState: fence.fenceState });
6061
- }
6062
- if (fence.fenceState === "draining" && this.#quiescedAtVersion !== fence.currentSchemaVersion) {
6063
- await this.#onFlush();
6064
- this.#quiescedAtVersion = fence.currentSchemaVersion;
6065
- await this.beat();
6066
- }
6067
- if (fence.fenceState === "normal") {
6068
- this.#quiescedAtVersion = null;
6069
- }
6070
- }
6071
- start(intervalMs) {
6072
- if (this.#timer) return;
6073
- this.#timer = setInterval(() => {
6074
- void this.beat();
6075
- void this.check();
6076
- }, intervalMs);
6077
- const timer = this.#timer;
6078
- if (typeof timer.unref === "function") timer.unref();
6079
- }
6080
- stop() {
6081
- if (this.#timer) {
6082
- clearInterval(this.#timer);
6083
- this.#timer = void 0;
6084
- }
6085
- }
6086
- };
6087
-
6088
5887
  // src/with-audit/attestation/vault-facade.ts
6089
5888
  var VaultAttestation = class {
6090
5889
  constructor(deps, strategy) {
@@ -6157,224 +5956,6 @@ var VaultAttestation = class {
6157
5956
  }
6158
5957
  };
6159
5958
 
6160
- // src/with-shape/introspection/walk.ts
6161
- var INTERNAL_PREFIX = "_";
6162
- var KNOWN_INTERNAL_NAMES = ["_keyring", "_ledger", "_meta", "_schemas", "_deltas"];
6163
- async function dumpVaultSchema(vault, opts) {
6164
- const state = vault._introspectState();
6165
- const sampleSize = opts.sampleSize ?? 50;
6166
- const withStats = opts.withStats === true;
6167
- const cacheNames = [...state.collectionCache.keys()];
6168
- const storageNames = (await safeListAllCollections(state.adapter, state.name)).filter((n) => !n.startsWith(INTERNAL_PREFIX));
6169
- const allNames = Array.from(/* @__PURE__ */ new Set([...cacheNames, ...storageNames])).sort();
6170
- const collections = {};
6171
- for (const name of allNames) {
6172
- collections[name] = await describeCollection(state, name, sampleSize, withStats);
6173
- }
6174
- const materializedViews = describeMVs(state.mvRegistry);
6175
- const overlayViews = describeOverlays(state.overlayRegistry);
6176
- const derivations = describeDerivations(state.derivationRegistry);
6177
- let internal;
6178
- if (withStats) {
6179
- internal = {};
6180
- for (const name of KNOWN_INTERNAL_NAMES) {
6181
- const stats = await statsForCollection(state.adapter, state.name, name);
6182
- if (stats.records > 0) {
6183
- internal[name] = { records: stats.records, bytes: stats.bytes };
6184
- }
6185
- }
6186
- }
6187
- const snap = {
6188
- _noydb_snapshot: 1,
6189
- vault: state.name,
6190
- emittedAt: (/* @__PURE__ */ new Date()).toISOString(),
6191
- subsystems: state.subsystems,
6192
- ...state.vaultMeta !== void 0 ? { meta: state.vaultMeta } : {},
6193
- collections,
6194
- materializedViews,
6195
- overlayViews,
6196
- derivations,
6197
- ...internal !== void 0 ? { internal } : {}
6198
- };
6199
- return snap;
6200
- }
6201
- async function safeListAllCollections(adapter, vault) {
6202
- try {
6203
- const snap = await adapter.loadAll(vault);
6204
- return Object.keys(snap);
6205
- } catch {
6206
- return [];
6207
- }
6208
- }
6209
- async function describeCollection(state, collectionName, sampleSize, withStats) {
6210
- let fields = {};
6211
- let validator;
6212
- const refsRaw = state.refRegistry.getOutbound(collectionName);
6213
- const refs = {};
6214
- for (const [name, desc] of Object.entries(refsRaw)) {
6215
- refs[name] = { target: desc.target, mode: desc.mode };
6216
- }
6217
- try {
6218
- const dek = await state.getDEK(collectionName);
6219
- const persisted = await loadPersistedSchema(state.adapter, state.name, collectionName, dek);
6220
- if (persisted) {
6221
- validator = { kind: persisted.kind, source: "persisted" };
6222
- if (persisted.jsonSchema) {
6223
- fields = jsonSchemaToFields(persisted.jsonSchema, "persisted", refsRaw);
6224
- }
6225
- }
6226
- } catch {
6227
- }
6228
- const liveColl = state.collectionCache.get(collectionName);
6229
- if (!validator) {
6230
- const schema = liveColl?.getSchema();
6231
- if (schema) {
6232
- try {
6233
- const derived = await derivePersistedSchema(schema);
6234
- validator = { kind: derived.kind, source: "live-validator" };
6235
- if (derived.jsonSchema) {
6236
- fields = jsonSchemaToFields(derived.jsonSchema, "live-validator", refsRaw);
6237
- }
6238
- } catch {
6239
- }
6240
- }
6241
- }
6242
- if (Object.keys(fields).length === 0 && sampleSize > 0) {
6243
- }
6244
- const collMeta = liveColl?.getMeta();
6245
- const collConfig = liveColl?.getConfig();
6246
- const archivePresent = state.hasCollectionArchive?.(collectionName) === true;
6247
- const schemaUpdateNames = state.getCollectionSchemaUpdateNames?.(collectionName);
6248
- const hasSchemaUpdate = schemaUpdateNames !== void 0 && schemaUpdateNames.length > 0;
6249
- let mergedConfig;
6250
- if (collConfig !== void 0 || archivePresent || hasSchemaUpdate) {
6251
- mergedConfig = {
6252
- ...collConfig ?? {},
6253
- ...archivePresent ? { archive: true } : {},
6254
- ...hasSchemaUpdate ? { schemaUpdate: schemaUpdateNames } : {}
6255
- };
6256
- }
6257
- const descriptor = {
6258
- fields,
6259
- indexes: [],
6260
- refs,
6261
- ...validator ? { validator } : {},
6262
- ...collMeta !== void 0 ? { meta: collMeta } : {},
6263
- ...mergedConfig !== void 0 ? { config: mergedConfig } : {}
6264
- };
6265
- if (withStats) {
6266
- const stats = await statsForCollection(state.adapter, state.name, collectionName);
6267
- descriptor.stats = stats;
6268
- }
6269
- return descriptor;
6270
- }
6271
- async function statsForCollection(adapter, vault, collection) {
6272
- const ids = await adapter.list(vault, collection);
6273
- if (ids.length === 0) {
6274
- return { records: 0, bytes: 0, bytesAvg: 0, bytesMin: 0, bytesMax: 0, oldest: "", newest: "" };
6275
- }
6276
- let total = 0;
6277
- let min = Number.POSITIVE_INFINITY;
6278
- let max = 0;
6279
- let oldest = "\uFFFF";
6280
- let newest = "";
6281
- for (const id of ids) {
6282
- const env = await adapter.get(vault, collection, id);
6283
- if (!env) continue;
6284
- const size = env._data.length;
6285
- total += size;
6286
- if (size < min) min = size;
6287
- if (size > max) max = size;
6288
- if (env._ts < oldest) oldest = env._ts;
6289
- if (env._ts > newest) newest = env._ts;
6290
- }
6291
- return {
6292
- records: ids.length,
6293
- bytes: total,
6294
- bytesAvg: Math.round(total / ids.length),
6295
- bytesMin: min === Number.POSITIVE_INFINITY ? 0 : min,
6296
- bytesMax: max,
6297
- oldest: oldest === "\uFFFF" ? "" : oldest,
6298
- newest
6299
- };
6300
- }
6301
- function describeMVs(registry) {
6302
- if (!registry || typeof registry !== "object") return {};
6303
- const items = listFromRegistry(registry);
6304
- const out = {};
6305
- for (const item of items) {
6306
- const reg = item;
6307
- const spec = reg.spec;
6308
- if (!spec?.name) continue;
6309
- const sources = spec.unionSources ? spec.unionSources.map((u) => u.collection) : reg.dependencies ? [...reg.dependencies].sort() : [];
6310
- const groupBy = spec.groupBy ? Array.isArray(spec.groupBy) ? [...spec.groupBy] : [spec.groupBy] : void 0;
6311
- const aggregate = spec.aggregate ? Object.fromEntries(
6312
- Object.entries(spec.aggregate).map(([k, v]) => [k, summariseAggregateOp(v)])
6313
- ) : void 0;
6314
- out[spec.name] = {
6315
- sources,
6316
- ...groupBy ? { groupBy } : {},
6317
- ...aggregate ? { aggregate } : {},
6318
- refresh: spec.refresh ?? "eager"
6319
- };
6320
- }
6321
- return out;
6322
- }
6323
- function describeOverlays(registry) {
6324
- if (!registry || typeof registry !== "object") return {};
6325
- const specs = listFromRegistry(registry);
6326
- const out = {};
6327
- for (const spec of specs) {
6328
- const s = spec;
6329
- if (!s.name || !s.base || !s.overlay) continue;
6330
- out[s.name] = { base: s.base, overlay: s.overlay };
6331
- }
6332
- return out;
6333
- }
6334
- function describeDerivations(registry) {
6335
- if (!registry || typeof registry !== "object") return {};
6336
- const items = listFromRegistry(registry);
6337
- const out = {};
6338
- for (const item of items) {
6339
- const reg = item;
6340
- const s = reg.spec ?? reg;
6341
- if (!s.source) continue;
6342
- const outputCollections = s.outputs ? Object.values(s.outputs).map((o) => o.collection) : [];
6343
- const key = outputCollections.length > 0 ? [...outputCollections].sort().join("+") : s.source;
6344
- out[key] = {
6345
- source: s.source,
6346
- outputs: outputCollections
6347
- };
6348
- }
6349
- return out;
6350
- }
6351
- function listFromRegistry(reg) {
6352
- for (const method of ["all", "list", "specs", "values"]) {
6353
- const fn = reg[method];
6354
- if (typeof fn === "function") {
6355
- try {
6356
- const out = fn.call(reg);
6357
- if (Array.isArray(out)) return out;
6358
- if (out && typeof out.values === "function") {
6359
- return [...out.values()];
6360
- }
6361
- } catch {
6362
- continue;
6363
- }
6364
- }
6365
- }
6366
- return [];
6367
- }
6368
- function summariseAggregateOp(value) {
6369
- if (value && typeof value === "object") {
6370
- const op = value.op ?? value.kind;
6371
- const field = value.field;
6372
- if (op && field) return `${op}(${field})`;
6373
- if (op) return op;
6374
- }
6375
- return String(value);
6376
- }
6377
-
6378
5959
  // src/kernel/vault.ts
6379
5960
  function resolveLabelFromMap(labels, locale, fallback) {
6380
5961
  if (labels[locale] !== void 0) return labels[locale];
@@ -6427,6 +6008,7 @@ var Vault = class {
6427
6008
  /** Per-collection record archival policies. Indexed by collection name. */
6428
6009
  archiveRegistry = /* @__PURE__ */ new Map();
6429
6010
  indexStrategy;
6011
+ lazyStrategy;
6430
6012
  aggregateStrategy;
6431
6013
  crdtStrategy;
6432
6014
  tiersStrategy;
@@ -6448,6 +6030,7 @@ var Vault = class {
6448
6030
  forgetStrategy;
6449
6031
  i18nStrategy;
6450
6032
  syncStrategy;
6033
+ classifiedStrategy;
6451
6034
  /**
6452
6035
  * Per-vault guard registry. `null` until `_initGuards()` runs; stays
6453
6036
  * `null` for vaults that never register any guard strategy. The
@@ -6645,7 +6228,7 @@ var Vault = class {
6645
6228
  dictionaryCache = /* @__PURE__ */ new Map();
6646
6229
  /** Registered link specs, keyed by link name; set by `vault.link()`. */
6647
6230
  linkRegistry = /* @__PURE__ */ new Map();
6648
- /** Cache of LinkSet handles, one per link name. */
6231
+ /** Cache of link-set handles, one per link name (lazy -- see links()). */
6649
6232
  linkSetCache = /* @__PURE__ */ new Map();
6650
6233
  /** — subscribers for cross-tier access events. */
6651
6234
  crossTierSubs = /* @__PURE__ */ new Set();
@@ -6679,6 +6262,7 @@ var Vault = class {
6679
6262
  this.objectStore = opts.objectStore;
6680
6263
  this.archiveStrategy = opts.archiveStrategy;
6681
6264
  this.indexStrategy = opts.indexStrategy;
6265
+ this.lazyStrategy = opts.lazyStrategy;
6682
6266
  this.aggregateStrategy = opts.aggregateStrategy;
6683
6267
  this.crdtStrategy = opts.crdtStrategy;
6684
6268
  this.tiersStrategy = opts.tiersStrategy;
@@ -6713,6 +6297,7 @@ var Vault = class {
6713
6297
  this.forgetStrategy = opts.forgetStrategy ?? NO_FORGET;
6714
6298
  this.i18nStrategy = opts.i18nStrategy ?? NO_I18N;
6715
6299
  this.syncStrategy = opts.syncStrategy ?? NO_SYNC;
6300
+ this.classifiedStrategy = opts.classifiedStrategy ?? NO_CLASSIFIED;
6716
6301
  void opts.guardStrategies;
6717
6302
  this.historyConfig = opts.historyConfig ?? { enabled: true };
6718
6303
  this.reloadKeyring = opts.reloadKeyring;
@@ -6825,6 +6410,9 @@ var Vault = class {
6825
6410
  if (coll && options?.meta) {
6826
6411
  coll._applyMeta(options.meta);
6827
6412
  }
6413
+ if (coll && options?.classifiedFields) {
6414
+ coll._applyClassifiedFields(options.classifiedFields);
6415
+ }
6828
6416
  if (!coll) {
6829
6417
  if (options?.refs) {
6830
6418
  this.refRegistry.register(collectionName, options.refs);
@@ -6869,6 +6457,7 @@ var Vault = class {
6869
6457
  const strategies = options.schemaUpdate ?? [];
6870
6458
  const work = (async () => {
6871
6459
  const dek = await this.getDEK(collectionName);
6460
+ const { persistSchemaIfNeeded } = await import("./register-K6DDSIXN.js");
6872
6461
  const result = await persistSchemaIfNeeded({
6873
6462
  store: this.adapter,
6874
6463
  vault: this.name,
@@ -6880,7 +6469,7 @@ var Vault = class {
6880
6469
  const decision = result.decision ?? { action: "allow" };
6881
6470
  if (decision.action === "cutover") {
6882
6471
  this.schemaFence.registerPendingCutover(collectionName, decision.transform);
6883
- this._ensureFenceCoordination();
6472
+ await this._ensureFenceCoordination();
6884
6473
  }
6885
6474
  return decision;
6886
6475
  })();
@@ -6914,6 +6503,7 @@ var Vault = class {
6914
6503
  ...this.objectStore !== void 0 ? { objectStore: this.objectStore } : {},
6915
6504
  ...options?.blobFields !== void 0 ? { blobFields: options.blobFields } : {},
6916
6505
  ...this.indexStrategy !== void 0 ? { indexStrategy: this.indexStrategy } : {},
6506
+ ...this.lazyStrategy !== void 0 ? { lazyStrategy: this.lazyStrategy } : {},
6917
6507
  ...this.aggregateStrategy !== void 0 ? { aggregateStrategy: this.aggregateStrategy } : {},
6918
6508
  ...this.crdtStrategy !== void 0 ? { crdtStrategy: this.crdtStrategy } : {},
6919
6509
  ...this.tiersStrategy !== void 0 ? { tiersStrategy: this.tiersStrategy } : {},
@@ -6921,6 +6511,7 @@ var Vault = class {
6921
6511
  historyStrategy: this.historyStrategy,
6922
6512
  i18nStrategy: this.i18nStrategy,
6923
6513
  syncStrategy: this.syncStrategy,
6514
+ classifiedStrategy: this.classifiedStrategy,
6924
6515
  // Per-collection ledger opt-out: when this collection sets
6925
6516
  // `historyConfig.ledger: false`, withhold the ledger reference so all
6926
6517
  // four `if (this.ledger)` append sites in Collection no-op. The chain
@@ -6970,19 +6561,24 @@ var Vault = class {
6970
6561
  if (options?.acknowledgeDeterministicRisk !== void 0) {
6971
6562
  collOpts.acknowledgeDeterministicRisk = options.acknowledgeDeterministicRisk;
6972
6563
  }
6564
+ if (options?.acknowledgeEquatableRisk !== void 0) {
6565
+ collOpts.acknowledgeEquatableRisk = options.acknowledgeEquatableRisk;
6566
+ }
6973
6567
  if (options?.sensitive !== void 0) {
6974
6568
  collOpts.sensitive = options.sensitive;
6975
6569
  }
6976
6570
  if (options?.perRecordKeys !== void 0) {
6977
6571
  collOpts.perRecordKeys = options.perRecordKeys;
6978
6572
  }
6979
- if (this.forgetStrategy.subjects[collectionName] !== void 0) {
6573
+ const subjectKey = this.forgetStrategy.subjects[collectionName];
6574
+ if (subjectKey !== void 0) {
6980
6575
  if (options?.perRecordKeys === false) {
6981
6576
  console.warn(
6982
6577
  `[noy-db] Collection "${collectionName}" is declared in withForgetCascade but opened with perRecordKeys: false. Forcing perRecordKeys: true \u2014 GDPR crypto-shred requires per-record CEKs.`
6983
6578
  );
6984
6579
  }
6985
6580
  collOpts.perRecordKeys = true;
6581
+ collOpts.subjectKeyField = subjectKey;
6986
6582
  }
6987
6583
  if (options?.provenance !== void 0) collOpts.provenance = options.provenance;
6988
6584
  if (options?.ramCiphertext !== void 0) collOpts.ramCiphertext = options.ramCiphertext;
@@ -6997,6 +6593,7 @@ var Vault = class {
6997
6593
  if (options?.textIndexPersist !== void 0) collOpts.textIndexPersist = options.textIndexPersist;
6998
6594
  if (options?.moneyFields !== void 0) collOpts.moneyFields = options.moneyFields;
6999
6595
  if (options?.computed !== void 0) collOpts.computed = options.computed;
6596
+ if (options?.classifiedFields !== void 0) collOpts.classifiedFields = options.classifiedFields;
7000
6597
  if (options?.dictKeyFields !== void 0) {
7001
6598
  collOpts.dictLabelResolver = async (dictName, key, locale, fallback) => {
7002
6599
  const stat = this.staticByName.get(dictName);
@@ -7039,7 +6636,7 @@ var Vault = class {
7039
6636
  const work = (async () => {
7040
6637
  try {
7041
6638
  const dek = await this.getDEK(collectionName);
7042
- await persistSchemaIfNeeded({
6639
+ await (await import("./register-K6DDSIXN.js")).persistSchemaIfNeeded({
7043
6640
  store: this.adapter,
7044
6641
  vault: this.name,
7045
6642
  collectionName,
@@ -7123,10 +6720,12 @@ var Vault = class {
7123
6720
  async schemaFenceState() {
7124
6721
  return loadFence(this.adapter, this.name);
7125
6722
  }
7126
- /** @internal Start the per-client heartbeat + fence watcher once a cutover is registered. */
7127
- _ensureFenceCoordination() {
6723
+ /** @internal Start heartbeat + fence watcher once a cutover is registered. Async since #553: FenceWatcher dynamic-imports on demand. */
6724
+ async _ensureFenceCoordination() {
7128
6725
  if (this.#fenceCoordinationStarted) return;
7129
6726
  this.#fenceCoordinationStarted = true;
6727
+ const { FenceWatcher } = await import("./fence-watcher-DHQ775JB.js");
6728
+ if (!this.#fenceCoordinationStarted) return;
7130
6729
  this.#fenceWatcher = new FenceWatcher({
7131
6730
  coordination: this.noydb.coordination,
7132
6731
  vault: this.name,
@@ -7155,7 +6754,7 @@ var Vault = class {
7155
6754
  }
7156
6755
  /** @internal Drive one heartbeat + watch cycle deterministically (tests). */
7157
6756
  async _fenceTick() {
7158
- this._ensureFenceCoordination();
6757
+ await this._ensureFenceCoordination();
7159
6758
  await this.#fenceWatcher.beat();
7160
6759
  await this.#fenceWatcher.check();
7161
6760
  }
@@ -7367,17 +6966,17 @@ var Vault = class {
7367
6966
  if (!spec) {
7368
6967
  throw new ValidationError(`vault.links("${name}"): not declared. Call vault.link("${name}", { a, b }) first.`);
7369
6968
  }
7370
- handle = new LinkSet(
7371
- this.adapter,
7372
- this.name,
6969
+ handle = makeLazyLinkSetHandle({
6970
+ adapter: this.adapter,
6971
+ vault: this.name,
7373
6972
  name,
7374
6973
  spec,
7375
- this.encrypted,
7376
- this.getDEK,
7377
- this.keyring.userId,
7378
- this.emitter,
7379
- async (collection, id) => await this.collection(collection).get(id) !== null
7380
- );
6974
+ encrypted: this.encrypted,
6975
+ getDEK: this.getDEK,
6976
+ actor: this.keyring.userId,
6977
+ emitter: this.emitter,
6978
+ endpointExists: async (collection, id) => await this.collection(collection).get(id) !== null
6979
+ });
7381
6980
  this.linkSetCache.set(name, handle);
7382
6981
  }
7383
6982
  return handle;
@@ -7886,8 +7485,14 @@ var Vault = class {
7886
7485
  if (live?._sealed !== void 0) {
7887
7486
  try {
7888
7487
  const cls = await coll._classifySealedShred(live);
7889
- sealedFieldsShredded += cls.shreddable.length;
7890
- for (const field of cls.dekResidue) sealedResidue.push(`${ref2.collection}:${ref2.id}:${field}`);
7488
+ for (const slot of cls.slots) {
7489
+ if (slot.class === "shreddable" || slot.class === "live-shreddable+dekResidue-in-backups") {
7490
+ sealedFieldsShredded += 1;
7491
+ }
7492
+ if (slot.class === "dekResidue" || slot.class === "live-shreddable+dekResidue-in-backups") {
7493
+ sealedResidue.push(`${ref2.collection}:${ref2.id}:${slot.field}`);
7494
+ }
7495
+ }
7891
7496
  } catch {
7892
7497
  for (const field of Object.keys(live._sealed)) sealedResidue.push(`${ref2.collection}:${ref2.id}:${field}`);
7893
7498
  }
@@ -7946,7 +7551,7 @@ var Vault = class {
7946
7551
  indexResidue.push(`${collName}:_ftindex`);
7947
7552
  }
7948
7553
  }
7949
- const subjectHash = await sha256Hex2(subjectId);
7554
+ const subjectHash = await sha256Hex(subjectId);
7950
7555
  const ledger = this.getLedgerOrNull();
7951
7556
  if (!ledger) {
7952
7557
  throw new Error(
@@ -8114,7 +7719,7 @@ var Vault = class {
8114
7719
  async _initDerivations(handles) {
8115
7720
  if (handles.length === 0) return;
8116
7721
  const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
8117
- import("./registry-WEUCHBO4.js"),
7722
+ import("./registry-IMNMHWTM.js"),
8118
7723
  import("./read-only-facade-5ADRJVTM.js")
8119
7724
  ]);
8120
7725
  const registry = new DerivationRegistry();
@@ -8145,7 +7750,7 @@ var Vault = class {
8145
7750
  */
8146
7751
  async _initMaterializedViews(handles) {
8147
7752
  if (handles.length === 0) return;
8148
- const { MaterializedViewRegistry } = await import("./registry-5GRV5VXI.js");
7753
+ const { MaterializedViewRegistry } = await import("./registry-K6VUQXKV.js");
8149
7754
  const registry = new MaterializedViewRegistry();
8150
7755
  this.materializedViewRegistry = registry;
8151
7756
  const db = this;
@@ -8169,7 +7774,7 @@ var Vault = class {
8169
7774
  */
8170
7775
  async _initOverlayedViews(handles) {
8171
7776
  if (handles.length === 0) return;
8172
- const { OverlayedViewRegistry } = await import("./registry-45RJNWGU.js");
7777
+ const { OverlayedViewRegistry } = await import("./registry-ZVO3T4M5.js");
8173
7778
  const registry = new OverlayedViewRegistry();
8174
7779
  const mvRegistry = this.materializedViewRegistry;
8175
7780
  const overlayNames = /* @__PURE__ */ new Set();
@@ -8216,13 +7821,13 @@ var Vault = class {
8216
7821
  if (!reg) {
8217
7822
  throw new Error(`refreshView: no MV registered with name "${name}"`);
8218
7823
  }
8219
- const { MaterializedViewExecutor } = await import("./executor-2FWQRLMG.js");
7824
+ const { MaterializedViewExecutor } = await import("./executor-FGISLQIN.js");
8220
7825
  const result = await MaterializedViewExecutor.refresh(reg, {
8221
7826
  getCollection: (n) => this.collection(n),
8222
7827
  getActiveTxContext: () => this.noydb._activeTxContextOrNull,
8223
7828
  getQueryContext: () => this
8224
7829
  });
8225
- const { clearMVStale } = await import("./stale-3JWHNDIY.js");
7830
+ const { clearMVStale } = await import("./stale-7Q62KVI3.js");
8226
7831
  clearMVStale(registry, name);
8227
7832
  return result;
8228
7833
  }
@@ -8238,7 +7843,7 @@ var Vault = class {
8238
7843
  if (registry === null) return { derived: 0, failed: 0 };
8239
7844
  const strategies = registry.strategiesForSource(sourceCollection);
8240
7845
  if (strategies.length === 0) return { derived: 0, failed: 0 };
8241
- const { DerivationExecutor } = await import("./executor-Z5ZLJVTV.js");
7846
+ const { DerivationExecutor } = await import("./executor-CBTNU5VZ.js");
8242
7847
  const sourceColl = this.collection(sourceCollection);
8243
7848
  const records = await sourceColl.list();
8244
7849
  const ctx = { vault: this.derivationFacade ?? new (await import("./read-only-facade-5ADRJVTM.js")).ReadOnlyVaultFacade(this, "derivation") };
@@ -8263,7 +7868,7 @@ var Vault = class {
8263
7868
  if (!outSpec) continue;
8264
7869
  const outputColl = this.collection(outSpec.collection);
8265
7870
  if (out.kind === "array") {
8266
- const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-GF3DJ6KR.js");
7871
+ const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-WS22Q5WH.js");
8267
7872
  const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key, this.getDEK, this.encrypted);
8268
7873
  const prevKeys = new Set(prior?.keys ?? []);
8269
7874
  const newKeysList = out.entries.map((e) => e.key);
@@ -8413,11 +8018,11 @@ var Vault = class {
8413
8018
  *
8414
8019
  *.
8415
8020
  */
8416
- async withConsent(ctx, fn) {
8021
+ async withConsent(ctx, fn2) {
8417
8022
  const prior = this.consentContext;
8418
8023
  this.consentContext = ctx;
8419
8024
  try {
8420
- return await fn();
8025
+ return await fn2();
8421
8026
  } finally {
8422
8027
  this.consentContext = prior;
8423
8028
  }
@@ -8485,7 +8090,7 @@ var Vault = class {
8485
8090
  * collection.
8486
8091
  */
8487
8092
  async delegate(opts) {
8488
- const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-UL5HKLER.js");
8093
+ const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-BQNIEHZE.js");
8489
8094
  if (!this.keyring.kek) {
8490
8095
  throw new ValidationError(
8491
8096
  "issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (passphrase) first."
@@ -8507,7 +8112,7 @@ var Vault = class {
8507
8112
  * if the id does not exist.
8508
8113
  */
8509
8114
  async revokeDelegation(id) {
8510
- const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-UL5HKLER.js");
8115
+ const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-BQNIEHZE.js");
8511
8116
  await revokeDelegation(this.adapter, this.name, id);
8512
8117
  void DELEGATIONS_COLLECTION;
8513
8118
  }
@@ -8723,6 +8328,7 @@ var Vault = class {
8723
8328
  * @see docs/superpowers/specs/2026-05-22-schema-dump-design.md
8724
8329
  */
8725
8330
  async dumpSchema(opts = {}) {
8331
+ const { dumpVaultSchema } = await import("./walk-5C3GPKT2.js");
8726
8332
  return dumpVaultSchema(this, opts);
8727
8333
  }
8728
8334
  /**
@@ -8857,7 +8463,7 @@ var Vault = class {
8857
8463
  * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md
8858
8464
  */
8859
8465
  async getPublicEnvelope(opts = {}) {
8860
- const { readPublicEnvelope } = await import("./public-envelope-JHDQCPSX.js");
8466
+ const { readPublicEnvelope } = await import("./public-envelope-MRN5YYZZ.js");
8861
8467
  return readPublicEnvelope(this.adapter, this.name, opts);
8862
8468
  }
8863
8469
  /**
@@ -8872,7 +8478,7 @@ var Vault = class {
8872
8478
  * both modes round-trip cleanly.
8873
8479
  */
8874
8480
  async dump() {
8875
- const { dumpVault } = await import("./backup-KMJQ66MF.js");
8481
+ const { dumpVault } = await import("./backup-MOB27UUN.js");
8876
8482
  return dumpVault(this.backupContext());
8877
8483
  }
8878
8484
  /**
@@ -8924,7 +8530,7 @@ var Vault = class {
8924
8530
  * — there's no chain to verify against.
8925
8531
  */
8926
8532
  async load(backupJson) {
8927
- const { loadVault } = await import("./backup-KMJQ66MF.js");
8533
+ const { loadVault } = await import("./backup-MOB27UUN.js");
8928
8534
  return loadVault(this.backupContext(), backupJson);
8929
8535
  }
8930
8536
  /**
@@ -8956,7 +8562,7 @@ var Vault = class {
8956
8562
  * way to detect tampering of an in-place vault.
8957
8563
  */
8958
8564
  async verifyBackupIntegrity() {
8959
- const { verifyBackupIntegrity } = await import("./backup-KMJQ66MF.js");
8565
+ const { verifyBackupIntegrity } = await import("./backup-MOB27UUN.js");
8960
8566
  return verifyBackupIntegrity(this.backupContext());
8961
8567
  }
8962
8568
  /**
@@ -9174,7 +8780,7 @@ var Vault = class {
9174
8780
  * is the live validator object, not a serialization of it).
9175
8781
  */
9176
8782
  async exportJSON(opts = {}) {
9177
- const { exportVaultJSON } = await import("./backup-KMJQ66MF.js");
8783
+ const { exportVaultJSON } = await import("./backup-MOB27UUN.js");
9178
8784
  return exportVaultJSON(this.backupContext(), opts);
9179
8785
  }
9180
8786
  };
@@ -9251,10 +8857,10 @@ var WriteQueueTracker = class {
9251
8857
  * (success or failure). The fn's resolved value is returned; a thrown
9252
8858
  * error is re-thrown after the queue is decremented.
9253
8859
  */
9254
- async track(fn) {
8860
+ async track(fn2) {
9255
8861
  this.begin();
9256
8862
  try {
9257
- const value = await fn();
8863
+ const value = await fn2();
9258
8864
  this.settle();
9259
8865
  return value;
9260
8866
  } catch (error) {
@@ -9339,13 +8945,13 @@ var TabCoordinator = class {
9339
8945
  const out = [self, ...[...this.#peers.values()].filter((p) => p.lastSeen >= cutoff)];
9340
8946
  return out.sort((a, b) => a.tabId.localeCompare(b.tabId));
9341
8947
  }
9342
- onTabRoleChange(fn) {
9343
- this.#roleHandlers.add(fn);
9344
- return () => this.#roleHandlers.delete(fn);
8948
+ onTabRoleChange(fn2) {
8949
+ this.#roleHandlers.add(fn2);
8950
+ return () => this.#roleHandlers.delete(fn2);
9345
8951
  }
9346
- onActiveTabsChange(fn) {
9347
- this.#tabsHandlers.add(fn);
9348
- return () => this.#tabsHandlers.delete(fn);
8952
+ onActiveTabsChange(fn2) {
8953
+ this.#tabsHandlers.add(fn2);
8954
+ return () => this.#tabsHandlers.delete(fn2);
9349
8955
  }
9350
8956
  dispose() {
9351
8957
  if (this.#disposed) return;
@@ -10042,6 +9648,35 @@ var TeamFacade = class {
10042
9648
  }
10043
9649
  return p;
10044
9650
  }
9651
+ // ─── Multi-user grant / revoke / rotate runners (#267 team split) ──
9652
+ //
9653
+ // The kernel's `db.grant` / `db.revoke` / `db.rotate` route through the
9654
+ // TeamStrategy seam, which calls back here with the keyring ENGINE as an
9655
+ // argument (statically linked in `active.ts`, i.e. only in the
9656
+ // `@noy-db/hub/team` subpath bundle). These runners own the policy-gate +
9657
+ // keyring plumbing so the kernel keeps single-line delegators and the
9658
+ // engines stay off the single-user floor.
9659
+ /** Gate + run a `grant` engine. See `Noydb.grant` for the public contract. */
9660
+ async runGrant(engine, vault, options, factors) {
9661
+ this.deps.checkPolicyOperation(vault, "grant");
9662
+ await this.deps.checkGate(vault, "enroll-user", factors);
9663
+ const keyring = await this.deps.getKeyringInternal(vault);
9664
+ await engine(this.deps.options.store, vault, keyring, options);
9665
+ }
9666
+ /** Gate + run a `revoke` engine. See `Noydb.revoke` for the public contract. */
9667
+ async runRevoke(engine, vault, options, factors) {
9668
+ this.deps.checkPolicyOperation(vault, "revoke");
9669
+ await this.deps.checkGate(vault, "revoke-user", factors);
9670
+ const keyring = await this.deps.getKeyringInternal(vault);
9671
+ await engine(this.deps.options.store, vault, keyring, options);
9672
+ }
9673
+ /** Gate + run a `rotateKeys` engine. See `Noydb.rotate` for the public contract. */
9674
+ async runRotate(engine, vault, collections) {
9675
+ this.deps.checkPolicyOperation(vault, "rotate");
9676
+ const keyring = await this.deps.getKeyringInternal(vault);
9677
+ await engine(this.deps.options.store, vault, keyring, collections);
9678
+ this.deps.keyringCache.set(vault, keyring);
9679
+ }
10045
9680
  // ─── Tier-2 enroll / remove ─────────────────────────────────────
10046
9681
  /**
10047
9682
  * Add a tier-2 authenticator slot to the calling user's keyring.
@@ -10787,6 +10422,15 @@ var Noydb = class {
10787
10422
  /** Pre-resolved `vault.user` API factory (mirrors `coordinationProvider` above). Public so `Vault` can call it. */
10788
10423
  userApiFactory;
10789
10424
  vaultCache = /* @__PURE__ */ new Map();
10425
+ /**
10426
+ * In-flight `openVault` promise per name — concurrent opens of the same
10427
+ * vault must converge on ONE Vault instance. Without this, two callers
10428
+ * racing past the `vaultCache` miss each construct a Vault (and later two
10429
+ * Collections with independent DEKs for the same store slice), so a record
10430
+ * written through one fails decryption through the other with a spurious
10431
+ * `TamperedError` (#564).
10432
+ */
10433
+ vaultOpening = /* @__PURE__ */ new Map();
10790
10434
  keyringCache = /* @__PURE__ */ new Map();
10791
10435
  syncEngines = /* @__PURE__ */ new Map();
10792
10436
  /**
@@ -10826,6 +10470,11 @@ var Noydb = class {
10826
10470
  * through it; grant/revoke route through it from this class. @internal
10827
10471
  */
10828
10472
  custodyStrategy;
10473
+ /**
10474
+ * Opt-in multi-user team strategy (#267 keyring-grant → team split) —
10475
+ * `NO_TEAM` (throwing) unless `withTeam()` was passed; the keyring
10476
+ * engines are linked only by the active strategy, not by this file. */
10477
+ teamStrategy;
10829
10478
  sessionStrategy;
10830
10479
  syncStrategy;
10831
10480
  snapshots;
@@ -10876,6 +10525,7 @@ var Noydb = class {
10876
10525
  this.txStrategy = options.txStrategy ?? NO_TX;
10877
10526
  this.forgetStrategy = options.forgetStrategy ?? NO_FORGET;
10878
10527
  this.custodyStrategy = options.custodyStrategy ?? NO_CUSTODY;
10528
+ this.teamStrategy = options.teamStrategy ?? NO_TEAM;
10879
10529
  this.sessionStrategy = options.sessionStrategy ?? NO_SESSION;
10880
10530
  this.syncStrategy = options.syncStrategy ?? NO_SYNC;
10881
10531
  this.snapshots = new NoydbSnapshots({
@@ -10907,6 +10557,7 @@ var Noydb = class {
10907
10557
  quickUnlock: this.quickUnlock,
10908
10558
  policyCache: this.policyCache,
10909
10559
  checkGate: (vault, gate, factors) => this.checkGate(vault, gate, factors),
10560
+ checkPolicyOperation: (vault, op) => this.checkPolicyOperation(vault, op),
10910
10561
  getKeyringInternal: (vault, opts) => this._getKeyringInternal(vault, opts),
10911
10562
  assertRecoveryEnrolled: (vault, policy, opts) => this.assertRecoveryEnrolled(vault, policy, opts),
10912
10563
  openVault: (vault, opts) => this.openVault(vault, opts),
@@ -11001,7 +10652,7 @@ var Noydb = class {
11001
10652
  if (!facade) return;
11002
10653
  const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
11003
10654
  await registry.runChecks(e.collection, incoming, ctx);
11004
- const { GuardExecutor } = await import("./executor-QZ7BXICW.js");
10655
+ const { GuardExecutor } = await import("./executor-DJHNSTIR.js");
11005
10656
  for (const g of guards) {
11006
10657
  await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming, e.computedFieldNames);
11007
10658
  }
@@ -11096,12 +10747,26 @@ var Noydb = class {
11096
10747
  if (this.closed) throw new ValidationError("Instance is closed");
11097
10748
  this.touchPolicy(name);
11098
10749
  let comp = this.vaultCache.get(name);
10750
+ if (!comp) {
10751
+ const pending = this.vaultOpening.get(name);
10752
+ if (pending) comp = await pending;
10753
+ }
11099
10754
  if (comp) {
11100
10755
  if (opts?.locale !== void 0) {
11101
10756
  comp.setLocale(opts.locale);
11102
10757
  }
11103
10758
  return comp;
11104
10759
  }
10760
+ const opening = this.#openVaultFresh(name, opts);
10761
+ this.vaultOpening.set(name, opening);
10762
+ try {
10763
+ return await opening;
10764
+ } finally {
10765
+ this.vaultOpening.delete(name);
10766
+ }
10767
+ }
10768
+ /** Uncached single-flight body of {@link openVault} — see `vaultOpening`. */
10769
+ async #openVaultFresh(name, opts) {
11105
10770
  const keyring = await this._getKeyringInternal(name, { create: opts?.create !== false });
11106
10771
  if (!this.activeTier.has(name)) {
11107
10772
  this.activeTier.set(name, 1);
@@ -11142,7 +10807,7 @@ var Noydb = class {
11142
10807
  this.syncEngines.set(key, engine);
11143
10808
  }
11144
10809
  }
11145
- comp = new Vault({
10810
+ const comp = new Vault({
11146
10811
  adapter: this.options.store,
11147
10812
  name,
11148
10813
  noydb: this,
@@ -11163,6 +10828,7 @@ var Noydb = class {
11163
10828
  ...this.options.objectStore !== void 0 ? { objectStore: this.options.objectStore } : {},
11164
10829
  ...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
11165
10830
  ...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
10831
+ ...this.options.lazyStrategy !== void 0 ? { lazyStrategy: this.options.lazyStrategy } : {},
11166
10832
  ...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
11167
10833
  ...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
11168
10834
  ...this.options.tiersStrategy !== void 0 ? { tiersStrategy: this.options.tiersStrategy } : {},
@@ -11178,6 +10844,7 @@ var Noydb = class {
11178
10844
  ...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
11179
10845
  forgetStrategy: this.forgetStrategy,
11180
10846
  ...this.options.attestationStrategy !== void 0 ? { attestationStrategy: this.options.attestationStrategy } : {},
10847
+ ...this.options.classifiedStrategy !== void 0 ? { classifiedStrategy: this.options.classifiedStrategy } : {},
11181
10848
  ...this.options.sealedRecordStrategy !== void 0 ? { sealedRecordStrategy: this.options.sealedRecordStrategy } : {},
11182
10849
  ...this.options.portabilityStrategy !== void 0 ? { portabilityStrategy: this.options.portabilityStrategy } : {},
11183
10850
  ...this.options.sequenceStrategy !== void 0 ? { sequenceStrategy: this.options.sequenceStrategy } : {},
@@ -11228,6 +10895,7 @@ var Noydb = class {
11228
10895
  ...this.options.objectStore !== void 0 ? { objectStore: this.options.objectStore } : {},
11229
10896
  ...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
11230
10897
  ...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
10898
+ ...this.options.lazyStrategy !== void 0 ? { lazyStrategy: this.options.lazyStrategy } : {},
11231
10899
  ...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
11232
10900
  ...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
11233
10901
  ...this.options.tiersStrategy !== void 0 ? { tiersStrategy: this.options.tiersStrategy } : {},
@@ -11243,6 +10911,7 @@ var Noydb = class {
11243
10911
  ...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
11244
10912
  forgetStrategy: this.forgetStrategy,
11245
10913
  ...this.options.attestationStrategy !== void 0 ? { attestationStrategy: this.options.attestationStrategy } : {},
10914
+ ...this.options.classifiedStrategy !== void 0 ? { classifiedStrategy: this.options.classifiedStrategy } : {},
11246
10915
  ...this.options.sealedRecordStrategy !== void 0 ? { sealedRecordStrategy: this.options.sealedRecordStrategy } : {},
11247
10916
  ...this.options.portabilityStrategy !== void 0 ? { portabilityStrategy: this.options.portabilityStrategy } : {},
11248
10917
  ...this.options.sequenceStrategy !== void 0 ? { sequenceStrategy: this.options.sequenceStrategy } : {}
@@ -11267,6 +10936,7 @@ var Noydb = class {
11267
10936
  ...this.options.objectStore !== void 0 ? { objectStore: this.options.objectStore } : {},
11268
10937
  ...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
11269
10938
  ...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
10939
+ ...this.options.lazyStrategy !== void 0 ? { lazyStrategy: this.options.lazyStrategy } : {},
11270
10940
  ...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
11271
10941
  ...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
11272
10942
  ...this.options.tiersStrategy !== void 0 ? { tiersStrategy: this.options.tiersStrategy } : {},
@@ -11294,12 +10964,10 @@ var Noydb = class {
11294
10964
  *
11295
10965
  * The legacy `requireReAuthFor: ['grant']` session-policy check still
11296
10966
  * fires on top — both are independent opt-ins.
10967
+ * Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
11297
10968
  */
11298
10969
  async grant(vault, options, factors) {
11299
- this.checkPolicyOperation(vault, "grant");
11300
- await this.checkGate(vault, "enroll-user", factors);
11301
- const keyring = await this._getKeyringInternal(vault);
11302
- await grant(this.options.store, vault, keyring, options);
10970
+ return this.teamStrategy.grant(this.team, vault, options, factors);
11303
10971
  }
11304
10972
  /**
11305
10973
  * Revoke a user's access to a vault.
@@ -11309,12 +10977,10 @@ var Noydb = class {
11309
10977
  *
11310
10978
  * The legacy `requireReAuthFor: ['revoke']` session-policy check still
11311
10979
  * fires on top — both are independent opt-ins.
10980
+ * Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
11312
10981
  */
11313
10982
  async revoke(vault, options, factors) {
11314
- this.checkPolicyOperation(vault, "revoke");
11315
- await this.checkGate(vault, "revoke-user", factors);
11316
- const keyring = await this._getKeyringInternal(vault);
11317
- await revoke(this.options.store, vault, keyring, options);
10983
+ return this.teamStrategy.revoke(this.team, vault, options, factors);
11318
10984
  }
11319
10985
  /**
11320
10986
  * Grant the FR-6 `custodian` role to a user (owner-only custody API).
@@ -11329,13 +10995,14 @@ var Noydb = class {
11329
10995
  async grantCustodian(vault, options, factors) {
11330
10996
  return this.custodyStrategy.grantCustodian(this, vault, options, factors);
11331
10997
  }
11332
- /** @internal — the grant-custodian engine, reached only when withCustody() is opted in. */
11333
- async _grantCustodianImpl(vault, options, factors) {
10998
+ /** @internal — grant-custodian engine, reached only via withCustody(); the
10999
+ * keyring engine arrives as an argument so the floor never carries it (#267). */
11000
+ async _grantCustodianImpl(engine, vault, options, factors) {
11334
11001
  this.checkPolicyOperation(vault, "grant");
11335
11002
  await this.checkGate(vault, "grant-custodian", factors);
11336
11003
  const keyring = await this._getKeyringInternal(vault);
11337
11004
  if (keyring.role !== "owner") throw new PermissionDeniedError("only the Deed owner can grant a custodian");
11338
- await grant(this.options.store, vault, keyring, { ...options, role: "custodian" });
11005
+ await engine(this.options.store, vault, keyring, { ...options, role: "custodian" });
11339
11006
  }
11340
11007
  /**
11341
11008
  * Revoke a custodian (owner-only custody API).
@@ -11347,13 +11014,14 @@ var Noydb = class {
11347
11014
  async revokeCustodian(vault, options, factors) {
11348
11015
  return this.custodyStrategy.revokeCustodian(this, vault, options, factors);
11349
11016
  }
11350
- /** @internal — the revoke-custodian engine, reached only when withCustody() is opted in. */
11351
- async _revokeCustodianImpl(vault, options, factors) {
11017
+ /** @internal — revoke-custodian engine, reached only via withCustody().
11018
+ * Mirrors `_grantCustodianImpl` (#267: engine passed in). */
11019
+ async _revokeCustodianImpl(engine, vault, options, factors) {
11352
11020
  this.checkPolicyOperation(vault, "revoke");
11353
11021
  await this.checkGate(vault, "revoke-user", factors);
11354
11022
  const keyring = await this._getKeyringInternal(vault);
11355
11023
  if (keyring.role !== "owner") throw new PermissionDeniedError("only the Deed owner can revoke a custodian");
11356
- await revoke(this.options.store, vault, keyring, options);
11024
+ await engine(this.options.store, vault, keyring, options);
11357
11025
  }
11358
11026
  /**
11359
11027
  * Mutate post-grant identity fields on an existing keyring — `role`,
@@ -11420,12 +11088,10 @@ var Noydb = class {
11420
11088
  * Exposed on Noydb (rather than only on the lower-level keyring
11421
11089
  * module) so CLI and admin tooling can trigger rotation without
11422
11090
  * reaching into internals. See `noy-db rotate` for the CLI wrapper.
11091
+ * Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
11423
11092
  */
11424
11093
  async rotate(vault, collections) {
11425
- this.checkPolicyOperation(vault, "rotate");
11426
- const keyring = await this._getKeyringInternal(vault);
11427
- await rotateKeys(this.options.store, vault, keyring, collections);
11428
- this.keyringCache.set(vault, keyring);
11094
+ return this.teamStrategy.rotate(this.team, vault, collections);
11429
11095
  }
11430
11096
  /** List all users with access to a vault. */
11431
11097
  async listUsers(vault) {
@@ -11585,7 +11251,7 @@ var Noydb = class {
11585
11251
  * })
11586
11252
  * ```
11587
11253
  */
11588
- async queryAcross(vaultIds, fn, options = {}) {
11254
+ async queryAcross(vaultIds, fn2, options = {}) {
11589
11255
  if (this.closed) throw new ValidationError("Instance is closed");
11590
11256
  this.resetSessionTimer();
11591
11257
  const concurrency = Math.max(1, options.concurrency ?? 1);
@@ -11599,7 +11265,7 @@ var Noydb = class {
11599
11265
  const task = (async () => {
11600
11266
  try {
11601
11267
  const comp = await this.openVault(vaultId, { create: options.create !== false });
11602
- const result = await fn(comp);
11268
+ const result = await fn2(comp);
11603
11269
  results[idx] = { vault: vaultId, result };
11604
11270
  } catch (err) {
11605
11271
  results[idx] = {
@@ -11859,9 +11525,9 @@ var Noydb = class {
11859
11525
  return this.writeHooks.onAfterWrite(handler);
11860
11526
  }
11861
11527
  /** Subscribe to cross-tab write conflicts. Returns an unsubscribe. */
11862
- onWriteConflict(fn) {
11863
- this.on("write:conflict", fn);
11864
- return () => this.off("write:conflict", fn);
11528
+ onWriteConflict(fn2) {
11529
+ this.on("write:conflict", fn2);
11530
+ return () => this.off("write:conflict", fn2);
11865
11531
  }
11866
11532
  /**
11867
11533
  * Enable same-device multi-tab coordination: primary/secondary
@@ -11935,12 +11601,12 @@ var Noydb = class {
11935
11601
  activeTabs() {
11936
11602
  return this.tabCoordinator?.activeTabs() ?? [];
11937
11603
  }
11938
- onTabRoleChange(fn) {
11939
- return this.tabCoordinator?.onTabRoleChange(fn) ?? (() => {
11604
+ onTabRoleChange(fn2) {
11605
+ return this.tabCoordinator?.onTabRoleChange(fn2) ?? (() => {
11940
11606
  });
11941
11607
  }
11942
- onActiveTabsChange(fn) {
11943
- return this.tabCoordinator?.onActiveTabsChange(fn) ?? (() => {
11608
+ onActiveTabsChange(fn2) {
11609
+ return this.tabCoordinator?.onActiveTabsChange(fn2) ?? (() => {
11944
11610
  });
11945
11611
  }
11946
11612
  /** @internal The write-hook registry, threaded into each Collection. */
@@ -12239,7 +11905,7 @@ var Noydb = class {
12239
11905
  "setPublicEnvelope: the public-envelope feature is not enabled. Pass `publicEnvelope: true` (or a schema object) to `createNoydb`."
12240
11906
  );
12241
11907
  }
12242
- const { loadPublicEnvelope, savePublicEnvelope, resolveSchema, validatePublicEnvelopeInput } = await import("./public-envelope-JHDQCPSX.js");
11908
+ const { loadPublicEnvelope, savePublicEnvelope, resolveSchema, validatePublicEnvelopeInput } = await import("./public-envelope-MRN5YYZZ.js");
12243
11909
  const schema = resolveSchema(this.options.publicEnvelope);
12244
11910
  validatePublicEnvelopeInput(input, schema);
12245
11911
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -12268,7 +11934,7 @@ var Noydb = class {
12268
11934
  * regardless).
12269
11935
  */
12270
11936
  async getPublicEnvelope(vault, opts = {}) {
12271
- const { readPublicEnvelope } = await import("./public-envelope-JHDQCPSX.js");
11937
+ const { readPublicEnvelope } = await import("./public-envelope-MRN5YYZZ.js");
12272
11938
  return readPublicEnvelope(this.options.store, vault, opts);
12273
11939
  }
12274
11940
  // ─── Auth introspection ─────────────────────────────────────────
@@ -12459,9 +12125,9 @@ async function createNoydb(options) {
12459
12125
  throw new ValidationError("A secret (passphrase) or getKeyring callback is required when encryption is enabled");
12460
12126
  }
12461
12127
  if (!options.coordinationStrategy) options = { ...options, coordinationStrategy: await createDefaultCoordinationProvider(options.store) };
12462
- if (!options.userApiFactory) options = { ...options, userApiFactory: (await import("./api-RW3KP7WU.js")).createUserApi };
12128
+ if (!options.userApiFactory) options = { ...options, userApiFactory: (await import("./api-JOXUNSKP.js")).createUserApi };
12463
12129
  if (!options.policyFactory) {
12464
- const policyModule = await import("./policy-IXK4FVXP.js");
12130
+ const policyModule = await import("./policy-YIKUH4AD.js");
12465
12131
  options = { ...options, policyFactory: policyModule.createNoydbPolicy, policyCheckGateFn: policyModule.checkGate };
12466
12132
  }
12467
12133
  return new Noydb(options);
@@ -12478,13 +12144,6 @@ function normalizeSyncTargets(sync) {
12478
12144
  export {
12479
12145
  memoryStore,
12480
12146
  withArchive,
12481
- ComputedFieldError,
12482
- evalComputedFields,
12483
- isZodSchema,
12484
- derivePersistedSchema,
12485
- Lru,
12486
- parseBytes,
12487
- estimateRecordBytes,
12488
12147
  Collection,
12489
12148
  ELEVATION_AUDIT_COLLECTION,
12490
12149
  ElevatedHandle,
@@ -12494,10 +12153,6 @@ export {
12494
12153
  ref,
12495
12154
  refArray,
12496
12155
  RefRegistry,
12497
- isLinkCollectionName,
12498
- LinkEndpointError,
12499
- LinkIntegrityError,
12500
- persistSchemaIfNeeded,
12501
12156
  Vault,
12502
12157
  QuickUnlockStore,
12503
12158
  describeAuthConfig,
@@ -12507,4 +12162,4 @@ export {
12507
12162
  Noydb,
12508
12163
  createNoydb
12509
12164
  };
12510
- //# sourceMappingURL=chunk-PSHOXR6C.js.map
12165
+ //# sourceMappingURL=chunk-ZPHDGUZZ.js.map