@noy-db/hub 0.7.0-pre.8 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (447) hide show
  1. package/CHANGELOG.md +1379 -0
  2. package/README.md +7 -6
  3. package/dist/api-TXFOVOXX.js +19 -0
  4. package/dist/as/index.js +14 -14
  5. package/dist/at/index.js +9 -10
  6. package/dist/attestation/index.js +18 -19
  7. package/dist/attestation/index.js.map +1 -1
  8. package/dist/{backup-SZBDQQSL.js → backup-IJTB4S4M.js} +14 -15
  9. package/dist/{backup-SZBDQQSL.js.map → backup-IJTB4S4M.js.map} +1 -1
  10. package/dist/blobs/index.js +13 -14
  11. package/dist/blobs/index.js.map +1 -1
  12. package/dist/broker/index.js +12 -13
  13. package/dist/broker/index.js.map +1 -1
  14. package/dist/by/index.js +2 -3
  15. package/dist/cargo/index.js +33 -34
  16. package/dist/{chunk-X6TBQKHW.js → chunk-2577DKXB.js} +2 -2
  17. package/dist/chunk-2C3AQB46.js +1652 -0
  18. package/dist/chunk-2C3AQB46.js.map +1 -0
  19. package/dist/{chunk-L3FHEWA3.js → chunk-2N4GY74U.js} +6 -6
  20. package/dist/{chunk-626TSARM.js → chunk-2Y4IMKA6.js} +4 -4
  21. package/dist/{chunk-7CWII4BL.js → chunk-3RCJJBNR.js} +10 -10
  22. package/dist/{chunk-M7UC2QPT.js → chunk-453F654R.js} +2 -2
  23. package/dist/{chunk-2QNKXGUS.js → chunk-4GVM6QZA.js} +2 -2
  24. package/dist/{chunk-AB5P32RE.js → chunk-4OZNXTO4.js} +2 -2
  25. package/dist/{chunk-L3HDEHGM.js → chunk-5VCRVKOZ.js} +4 -4
  26. package/dist/{chunk-6AQIFBSP.js → chunk-5WDXHNSW.js} +5 -5
  27. package/dist/chunk-66TQOPFM.js +37 -0
  28. package/dist/chunk-66TQOPFM.js.map +1 -0
  29. package/dist/{chunk-BOFRKAUS.js → chunk-6GMZ7HEE.js} +6 -6
  30. package/dist/{chunk-PRHCMEUK.js → chunk-6GOE5PGN.js} +168 -1328
  31. package/dist/chunk-6GOE5PGN.js.map +1 -0
  32. package/dist/{chunk-XBFEKTIY.js → chunk-6I2RQCET.js} +4 -4
  33. package/dist/{chunk-PUJTKLPL.js → chunk-6X6SEMEE.js} +6 -4
  34. package/dist/{chunk-PUJTKLPL.js.map → chunk-6X6SEMEE.js.map} +1 -1
  35. package/dist/{chunk-UCUALOSM.js → chunk-6YXCPL4T.js} +2 -2
  36. package/dist/{chunk-BYBB4ABD.js → chunk-77K4PG6P.js} +8 -8
  37. package/dist/{chunk-S2VG3ABP.js → chunk-7MG2LHO5.js} +3 -3
  38. package/dist/{chunk-GU3LQYW2.js → chunk-7MG7SJT7.js} +1 -1
  39. package/dist/chunk-7MG7SJT7.js.map +1 -0
  40. package/dist/{chunk-JBIV4FLR.js → chunk-7O3Y4PPD.js} +5 -1
  41. package/dist/chunk-7O3Y4PPD.js.map +1 -0
  42. package/dist/{chunk-EO2KGKEJ.js → chunk-7V4TP3AF.js} +4 -4
  43. package/dist/{chunk-LFDMKZIP.js → chunk-ANATMFIO.js} +5 -5
  44. package/dist/{chunk-T3PHCEN4.js → chunk-ANSIZYEG.js} +3 -3
  45. package/dist/{chunk-ZKRRBRSZ.js → chunk-AO42KJO6.js} +7 -7
  46. package/dist/{chunk-VFIWDPXZ.js → chunk-BLN54W3L.js} +3 -3
  47. package/dist/{chunk-ZQ2UUHSL.js → chunk-BM5TWITZ.js} +7 -7
  48. package/dist/{chunk-WLFABTZ6.js → chunk-BOET4NA4.js} +3 -3
  49. package/dist/{chunk-FOG7YEJP.js → chunk-BOWNCWZT.js} +3 -3
  50. package/dist/{chunk-7XODKGTW.js → chunk-BSFNRLK2.js} +5 -5
  51. package/dist/{chunk-YPSOHDNC.js → chunk-BUE2D7PX.js} +26 -3
  52. package/dist/chunk-BUE2D7PX.js.map +1 -0
  53. package/dist/{chunk-J4MN6XIU.js → chunk-BZ3534YM.js} +2 -2
  54. package/dist/chunk-CARABLSQ.js +176 -0
  55. package/dist/chunk-CARABLSQ.js.map +1 -0
  56. package/dist/{chunk-4MZEZ37W.js → chunk-CHJBLCOG.js} +10 -8
  57. package/dist/{chunk-4MZEZ37W.js.map → chunk-CHJBLCOG.js.map} +1 -1
  58. package/dist/{chunk-IF56DYJK.js → chunk-CPWQB3N5.js} +7 -7
  59. package/dist/{chunk-SHILAQH5.js → chunk-DGOZ4UZD.js} +2 -2
  60. package/dist/{chunk-BWWUXE3L.js → chunk-ELNXJMGB.js} +6 -6
  61. package/dist/{chunk-44C2URL7.js → chunk-EQEYOJBM.js} +3 -3
  62. package/dist/{chunk-Y3XWRDAM.js → chunk-EYBQEIUY.js} +3 -3
  63. package/dist/{chunk-Z7ZXZL6Y.js → chunk-FAHMLERK.js} +2 -2
  64. package/dist/chunk-FFWI7UH7.js +53 -0
  65. package/dist/chunk-FFWI7UH7.js.map +1 -0
  66. package/dist/{chunk-EXDIHWFO.js → chunk-FMZY5Q6L.js} +3 -3
  67. package/dist/{chunk-H6WXKZL7.js → chunk-FXBIP2WD.js} +6 -6
  68. package/dist/{chunk-ZTYG36DH.js → chunk-G56KBWFY.js} +67 -22
  69. package/dist/chunk-G56KBWFY.js.map +1 -0
  70. package/dist/{chunk-672U6STZ.js → chunk-GPEQUXHL.js} +4 -4
  71. package/dist/{chunk-Z2PWOSCJ.js → chunk-GY4WYNNG.js} +2 -2
  72. package/dist/{chunk-RDHUZ674.js → chunk-HDOU6I2Y.js} +80 -8
  73. package/dist/chunk-HDOU6I2Y.js.map +1 -0
  74. package/dist/{chunk-OMHHGOG4.js → chunk-J6FXAEUG.js} +15 -13
  75. package/dist/chunk-J6FXAEUG.js.map +1 -0
  76. package/dist/{chunk-4A4TYISP.js → chunk-JBDFMYKQ.js} +2 -2
  77. package/dist/{chunk-POS53FG6.js → chunk-JMGDHKQF.js} +2 -2
  78. package/dist/{chunk-Q7GEDVHC.js → chunk-K6LHRFBL.js} +7 -7
  79. package/dist/{chunk-4JDIRUTT.js → chunk-K7NTTA6P.js} +2 -2
  80. package/dist/{chunk-26W5VETY.js → chunk-KG7TZKZG.js} +5 -5
  81. package/dist/{chunk-RJ7RIIX6.js → chunk-KJIMGIWO.js} +8 -8
  82. package/dist/{chunk-F7ZFRPGQ.js → chunk-KTFRCC5C.js} +2 -2
  83. package/dist/{chunk-HSGEIMJS.js → chunk-KUJDV5QH.js} +5 -5
  84. package/dist/{chunk-XWNLKG6R.js → chunk-KUX3OB6D.js} +7 -5
  85. package/dist/{chunk-XWNLKG6R.js.map → chunk-KUX3OB6D.js.map} +1 -1
  86. package/dist/{chunk-UPJMBMCR.js → chunk-L742JPKZ.js} +6 -6
  87. package/dist/{chunk-4TZUFNXL.js → chunk-L7CIOOBW.js} +2 -2
  88. package/dist/{chunk-7LYUJNU3.js → chunk-LWBCUYZW.js} +2 -2
  89. package/dist/{chunk-JHLJQUXU.js → chunk-MUM7IANK.js} +3 -3
  90. package/dist/{chunk-2GXEQUEX.js → chunk-MVMXZYXT.js} +2 -2
  91. package/dist/{chunk-XLPXGN66.js → chunk-NA2NIJZI.js} +8 -8
  92. package/dist/{chunk-S6YB5ZRP.js → chunk-NKHRDYOR.js} +4 -4
  93. package/dist/{chunk-XJ3FEKEY.js → chunk-NQKIUNW5.js} +2 -2
  94. package/dist/{chunk-6NRVFD55.js → chunk-PT43Y56J.js} +6 -6
  95. package/dist/{chunk-5ACAVJUI.js → chunk-Q2PU57HC.js} +2 -2
  96. package/dist/{chunk-E6YA6UAP.js → chunk-Q7HZX3IF.js} +2 -2
  97. package/dist/{chunk-4ZPE6SKS.js → chunk-QIBVIOXO.js} +3 -3
  98. package/dist/{chunk-WLLUM35R.js → chunk-QIZPZMUI.js} +2 -2
  99. package/dist/{chunk-P6ASQOZR.js → chunk-REDOOY2Q.js} +3 -3
  100. package/dist/chunk-REDOOY2Q.js.map +1 -0
  101. package/dist/{chunk-LKFKXS5K.js → chunk-RMF67KCG.js} +2 -2
  102. package/dist/{chunk-YCSM3GZU.js → chunk-RMS3NEA3.js} +2 -2
  103. package/dist/{chunk-4FPEWQKF.js → chunk-RRNRNANG.js} +27 -17
  104. package/dist/chunk-RRNRNANG.js.map +1 -0
  105. package/dist/chunk-RTBJ5IOO.js +87 -0
  106. package/dist/chunk-RTBJ5IOO.js.map +1 -0
  107. package/dist/chunk-RXLYKVTF.js +17 -0
  108. package/dist/chunk-RXLYKVTF.js.map +1 -0
  109. package/dist/{chunk-OPXR4PB2.js → chunk-SFAWCTEM.js} +2 -2
  110. package/dist/{chunk-3QARDAYW.js → chunk-SKGMN35F.js} +2 -2
  111. package/dist/{chunk-W5LHQXZU.js → chunk-SL3JAAKN.js} +2 -2
  112. package/dist/chunk-SMH6SRX7.js +87 -0
  113. package/dist/chunk-SMH6SRX7.js.map +1 -0
  114. package/dist/{chunk-JJZIIJSA.js → chunk-SPXXX5E4.js} +12 -82
  115. package/dist/chunk-SPXXX5E4.js.map +1 -0
  116. package/dist/{chunk-UALOYGCP.js → chunk-SPYWXKJN.js} +3 -3
  117. package/dist/{chunk-QU3YUP2X.js → chunk-SZJ3DLZA.js} +2 -2
  118. package/dist/chunk-TFMM5DBB.js +20 -0
  119. package/dist/chunk-TFMM5DBB.js.map +1 -0
  120. package/dist/{chunk-225O5CXQ.js → chunk-TFR7DSOV.js} +2 -2
  121. package/dist/{chunk-X67FCULK.js → chunk-TRGTKX5E.js} +3 -3
  122. package/dist/{chunk-JVLSU7S2.js → chunk-TUFM4UZP.js} +2 -2
  123. package/dist/{chunk-VVAVTSTR.js → chunk-U4FOQDY4.js} +5 -172
  124. package/dist/chunk-U4FOQDY4.js.map +1 -0
  125. package/dist/{chunk-HTGRQZFB.js → chunk-UGTBXF5U.js} +3 -3
  126. package/dist/{chunk-THNJ3IKU.js → chunk-ULUMAZ5S.js} +2 -2
  127. package/dist/{chunk-XDVVBETV.js → chunk-UXVWEX5L.js} +2 -2
  128. package/dist/{chunk-FKFIEEY6.js → chunk-UXWB3FPF.js} +10 -10
  129. package/dist/{chunk-NO272T7Q.js → chunk-V4PXLYWM.js} +2 -31
  130. package/dist/chunk-V4PXLYWM.js.map +1 -0
  131. package/dist/{chunk-CBRS2NEK.js → chunk-VTFVLCUH.js} +2 -2
  132. package/dist/{chunk-TOV6VMHF.js → chunk-VXANTWBJ.js} +3 -3
  133. package/dist/{chunk-VSLUSXVK.js → chunk-VXGSWL6L.js} +6 -6
  134. package/dist/{chunk-KHKKD62N.js → chunk-VYYM3MEN.js} +2 -16
  135. package/dist/chunk-VYYM3MEN.js.map +1 -0
  136. package/dist/{chunk-HQINBNHM.js → chunk-WEQEYLCS.js} +7 -7
  137. package/dist/{chunk-U6GCYG2T.js → chunk-X2DLENDQ.js} +3 -3
  138. package/dist/{chunk-XVU7J43V.js → chunk-XLMEZIAJ.js} +2 -2
  139. package/dist/{chunk-ILSR22WM.js → chunk-XTXOCYOJ.js} +5 -5
  140. package/dist/{chunk-KDJGJR7F.js → chunk-YSRUYAVU.js} +2 -2
  141. package/dist/{chunk-NLKLXXTO.js → chunk-YYP7WSEB.js} +2 -2
  142. package/dist/{chunk-4G25SDQL.js → chunk-ZN4FD4PE.js} +4 -4
  143. package/dist/{chunk-XSN63FUS.js → chunk-ZORTV6NH.js} +2 -2
  144. package/dist/{chunk-S3I7VKID.js → chunk-ZVO4QVPD.js} +5 -5
  145. package/dist/classified/index.js +5 -6
  146. package/dist/{classified-marker-KL4YXUXD.js → classified-marker-LI2SF2E4.js} +3 -5
  147. package/dist/{classified-marker-KL4YXUXD.js.map → classified-marker-LI2SF2E4.js.map} +1 -1
  148. package/dist/collection-facade-4GRREZ6C.js +45 -0
  149. package/dist/computed-VPOKQK4N.js +10 -0
  150. package/dist/consent/index.js +9 -10
  151. package/dist/consent/index.js.map +1 -1
  152. package/dist/cover/index.js +9 -10
  153. package/dist/crdt/index.js +0 -1
  154. package/dist/crdt/index.js.map +1 -1
  155. package/dist/custody/index.js +12 -13
  156. package/dist/{dead-filter-ZGRFZKYE.js → dead-filter-TSWZQRR5.js} +2 -3
  157. package/dist/{dead-filter-ZGRFZKYE.js.map → dead-filter-TSWZQRR5.js.map} +1 -1
  158. package/dist/debug/index.js +1 -2
  159. package/dist/debug/index.js.map +1 -1
  160. package/dist/{delegation-2DO3VI5E.js → delegation-OVIFFPG4.js} +11 -12
  161. package/dist/{delegation-2DO3VI5E.js.map → delegation-OVIFFPG4.js.map} +1 -1
  162. package/dist/derivations/index.js +30 -16
  163. package/dist/derive-6O5SWQKN.js +21 -0
  164. package/dist/directory/index.js +10 -11
  165. package/dist/dispatch-S73TK3IY.js +302 -0
  166. package/dist/dispatch-S73TK3IY.js.map +1 -0
  167. package/dist/{dispatch-M62IAL2S.js → dispatch-WC6X2M6C.js} +5 -7
  168. package/dist/{dispatch-M62IAL2S.js.map → dispatch-WC6X2M6C.js.map} +1 -1
  169. package/dist/{enclave-4P4KH5ZW.js → enclave-KJOTOH7X.js} +9 -10
  170. package/dist/executor-5NIMLSKZ.js +8 -0
  171. package/dist/executor-AQVXV5GZ.js +8 -0
  172. package/dist/executor-PUAO6AKJ.js +29 -0
  173. package/dist/export-accessible-72EQNBMR.js +22 -0
  174. package/dist/extract-partition-PUYNU3UF.js +37 -0
  175. package/dist/{fanout-sidecar-BRQHWTZQ.js → fanout-sidecar-WUFXNYP4.js} +9 -10
  176. package/dist/{fanout-sidecar-BRQHWTZQ.js.map → fanout-sidecar-WUFXNYP4.js.map} +1 -1
  177. package/dist/{fence-watcher-ZVSMLKQD.js → fence-watcher-U2PW6JU5.js} +1 -3
  178. package/dist/{fence-watcher-ZVSMLKQD.js.map → fence-watcher-U2PW6JU5.js.map} +1 -1
  179. package/dist/find-2ABFCZX4.js +10 -0
  180. package/dist/forget/index.js +9 -10
  181. package/dist/forget/index.js.map +1 -1
  182. package/dist/guards/index.js +4 -5
  183. package/dist/history/index.js +13 -14
  184. package/dist/history/index.js.map +1 -1
  185. package/dist/i18n/index.js +14 -15
  186. package/dist/i18n/index.js.map +1 -1
  187. package/dist/index.d.ts +20 -4
  188. package/dist/index.js +122 -115
  189. package/dist/index.js.map +1 -1
  190. package/dist/indexing/index.js +2 -3
  191. package/dist/indexing/index.js.map +1 -1
  192. package/dist/introspection/index.js +13 -13
  193. package/dist/issue-SIDORTSZ.js +18 -0
  194. package/dist/{json-schema-I22JCYCG.js → json-schema-V3M5MUCM.js} +1 -3
  195. package/dist/{json-schema-I22JCYCG.js.map → json-schema-V3M5MUCM.js.map} +1 -1
  196. package/dist/kernel/collection-config.d.ts +34 -0
  197. package/dist/kernel/collection.d.ts +11 -6
  198. package/dist/kernel/errors.d.ts +45 -0
  199. package/dist/kernel/match-pairs.d.ts +30 -0
  200. package/dist/kernel/types.d.ts +66 -0
  201. package/dist/lazy/index.js +3 -3
  202. package/dist/{ledger-4X5ZH43X.js → ledger-F33ZVMTK.js} +11 -12
  203. package/dist/liberate-LCDPNAG2.js +24 -0
  204. package/dist/link-set-FKNWAYKS.js +30 -0
  205. package/dist/{managed-secret-CXALLEUB.js → managed-secret-PQYKSR6T.js} +10 -11
  206. package/dist/materialized-views/index.js +21 -21
  207. package/dist/{migrate-cek-LBRKYUZZ.js → migrate-cek-5ENH64AA.js} +2 -3
  208. package/dist/{migrate-cek-LBRKYUZZ.js.map → migrate-cek-5ENH64AA.js.map} +1 -1
  209. package/dist/money/index.js +4 -5
  210. package/dist/noydb-DUXZPKSN.js +90 -0
  211. package/dist/overlay-views/index.js +4 -5
  212. package/dist/periods/index.js +12 -13
  213. package/dist/pod/index.js +64 -60
  214. package/dist/{pod-handle-DHEYBTJ2.js → pod-handle-Q736KYON.js} +10 -11
  215. package/dist/{pod-handle-DHEYBTJ2.js.map → pod-handle-Q736KYON.js.map} +1 -1
  216. package/dist/policy/index.js +10 -11
  217. package/dist/port/to/index.d.ts +40 -0
  218. package/dist/portability/index.js +8 -9
  219. package/dist/portability/index.js.map +1 -1
  220. package/dist/{post-register-4DXRYGTU.js → post-register-LNE2FE2A.js} +6 -7
  221. package/dist/{post-register-4DXRYGTU.js.map → post-register-LNE2FE2A.js.map} +1 -1
  222. package/dist/{purge-scope-FGNNLWHD.js → purge-scope-4HEFPDOW.js} +1 -3
  223. package/dist/{purge-scope-FGNNLWHD.js.map → purge-scope-4HEFPDOW.js.map} +1 -1
  224. package/dist/query/index.js +3 -4
  225. package/dist/{read-only-facade-CHCKSEPD.js → read-only-facade-BIGO37U3.js} +1 -2
  226. package/dist/reduce/index.js +4 -5
  227. package/dist/reduce/index.js.map +1 -1
  228. package/dist/register-I2DZXGAR.js +31 -0
  229. package/dist/registry-23WF3TGH.js +8 -0
  230. package/dist/registry-4AYVUNXK.js +8 -0
  231. package/dist/registry-VSSQPIGF.js +18 -0
  232. package/dist/registry-YLEWMGAC.js +32 -0
  233. package/dist/request-withdrawal-KFQHEZ25.js +30 -0
  234. package/dist/{reveal-X2QMWOVX.js → reveal-67RDQRIN.js} +6 -7
  235. package/dist/{reveal-X2QMWOVX.js.map → reveal-67RDQRIN.js.map} +1 -1
  236. package/dist/revoke-DQDZAZZM.js +23 -0
  237. package/dist/satellites/index.js +1 -2
  238. package/dist/schema-update/index.js +2 -3
  239. package/dist/sealed-record/index.js +12 -13
  240. package/dist/sealed-record/index.js.map +1 -1
  241. package/dist/search/index.js +4 -5
  242. package/dist/{seed-IX5NFSH5.js → seed-G42JYN56.js} +12 -13
  243. package/dist/{seed-IX5NFSH5.js.map → seed-G42JYN56.js.map} +1 -1
  244. package/dist/sequence/index.js +9 -10
  245. package/dist/session/index.js +9 -10
  246. package/dist/session/index.js.map +1 -1
  247. package/dist/shadow/index.js +2 -3
  248. package/dist/shadow/index.js.map +1 -1
  249. package/dist/share-link/index.js +0 -1
  250. package/dist/share-link/index.js.map +1 -1
  251. package/dist/signer-WAMDZHEN.js +24 -0
  252. package/dist/snapshots/index.js +10 -11
  253. package/dist/snapshots/index.js.map +1 -1
  254. package/dist/{stale-5I36LPVK.js → stale-DDL7WQEZ.js} +10 -11
  255. package/dist/storage-FLR73HHF.js +22 -0
  256. package/dist/store/index.js +0 -1
  257. package/dist/{store-coordination-provider-OLPNRMFO.js → store-coordination-provider-MEQ2MJQG.js} +10 -11
  258. package/dist/{store-coordination-provider-OLPNRMFO.js.map → store-coordination-provider-MEQ2MJQG.js.map} +1 -1
  259. package/dist/sync/index.js +10 -11
  260. package/dist/sync/index.js.map +1 -1
  261. package/dist/team/index.js +15 -16
  262. package/dist/tiers/index.js +11 -12
  263. package/dist/to/index.js +2 -3
  264. package/dist/to/index.js.map +1 -1
  265. package/dist/transactions/index.js +3 -4
  266. package/dist/transactions/index.js.map +1 -1
  267. package/dist/{ulid-VQW6ERQN.js → ulid-4MKXG325.js} +1 -2
  268. package/dist/util/index.js +1 -2
  269. package/dist/util/index.js.map +1 -1
  270. package/dist/{vault-diff-FE5J35NJ.js → vault-diff-C6WUJFNP.js} +1 -2
  271. package/dist/vault-head/index.js +8 -9
  272. package/dist/vault-head/index.js.map +1 -1
  273. package/dist/{verify-WYOFLSNA.js → verify-KOV2G5D6.js} +5 -6
  274. package/dist/{verify-WYOFLSNA.js.map → verify-KOV2G5D6.js.map} +1 -1
  275. package/dist/walk-3UQBRMDV.js +21 -0
  276. package/dist/with-formula/derivations/dispatch.d.ts +16 -1
  277. package/dist/with-formula/derivations/registry.d.ts +20 -0
  278. package/dist/with-formula/derivations/trigger-match.d.ts +104 -0
  279. package/dist/with-formula/derivations/types.d.ts +61 -0
  280. package/dist/with-party/team/roster-epoch.d.ts +71 -0
  281. package/dist/with-party/team/roster-tag.d.ts +1 -1
  282. package/dist/with-shape/introspection/behaviors.d.ts +7 -0
  283. package/dist/with-shape/introspection/describe.d.ts +10 -1
  284. package/dist/with-shape/introspection/field-meta.d.ts +86 -0
  285. package/dist/withdraw-accessible-EL5GXZBS.js +27 -0
  286. package/package.json +8 -3
  287. package/dist/api-OAZLPNVV.js +0 -20
  288. package/dist/chunk-4FPEWQKF.js.map +0 -1
  289. package/dist/chunk-5263OEM3.js +0 -344
  290. package/dist/chunk-5263OEM3.js.map +0 -1
  291. package/dist/chunk-GU3LQYW2.js.map +0 -1
  292. package/dist/chunk-JBIV4FLR.js.map +0 -1
  293. package/dist/chunk-JJZIIJSA.js.map +0 -1
  294. package/dist/chunk-KHKKD62N.js.map +0 -1
  295. package/dist/chunk-NO272T7Q.js.map +0 -1
  296. package/dist/chunk-OMHHGOG4.js.map +0 -1
  297. package/dist/chunk-P6ASQOZR.js.map +0 -1
  298. package/dist/chunk-PRHCMEUK.js.map +0 -1
  299. package/dist/chunk-PZ5AY32C.js +0 -10
  300. package/dist/chunk-RDHUZ674.js.map +0 -1
  301. package/dist/chunk-VAG47QHV.js +0 -81
  302. package/dist/chunk-VAG47QHV.js.map +0 -1
  303. package/dist/chunk-VVAVTSTR.js.map +0 -1
  304. package/dist/chunk-YPSOHDNC.js.map +0 -1
  305. package/dist/chunk-ZTYG36DH.js.map +0 -1
  306. package/dist/collection-facade-6IY2LW6W.js +0 -45
  307. package/dist/computed-ASBNTLOK.js +0 -11
  308. package/dist/derive-TCTS7ULE.js +0 -22
  309. package/dist/dispatch-FNCCONFK.js +0 -194
  310. package/dist/dispatch-FNCCONFK.js.map +0 -1
  311. package/dist/executor-AFHQYRAU.js +0 -9
  312. package/dist/executor-CDIMJVE2.js +0 -29
  313. package/dist/executor-YYDW6XQI.js +0 -9
  314. package/dist/export-accessible-WADNWX35.js +0 -23
  315. package/dist/extract-partition-SHQYQSWE.js +0 -38
  316. package/dist/find-SZBL2HPB.js +0 -11
  317. package/dist/issue-2DGG7NKE.js +0 -19
  318. package/dist/liberate-7NEPRE52.js +0 -25
  319. package/dist/link-set-WHTYVTOV.js +0 -31
  320. package/dist/noydb-BQ3ZTN2Z.js +0 -86
  321. package/dist/register-GLCOH73C.js +0 -32
  322. package/dist/registry-GWGHZWGP.js +0 -19
  323. package/dist/registry-IWFMXCHX.js +0 -9
  324. package/dist/registry-Q3FG3OAX.js +0 -9
  325. package/dist/registry-T346IZCF.js +0 -18
  326. package/dist/request-withdrawal-2RERJECX.js +0 -31
  327. package/dist/revoke-4NRSCPNW.js +0 -24
  328. package/dist/signer-HJHTGX7X.js +0 -25
  329. package/dist/storage-ZYYAB3J3.js +0 -23
  330. package/dist/walk-LTV7LOCN.js +0 -21
  331. package/dist/withdraw-accessible-V4XCPH7U.js +0 -28
  332. package/dist/withdraw-accessible-V4XCPH7U.js.map +0 -1
  333. package/dist/zod-HAJM7LMS.js +0 -14763
  334. package/dist/zod-HAJM7LMS.js.map +0 -1
  335. /package/dist/{api-OAZLPNVV.js.map → api-TXFOVOXX.js.map} +0 -0
  336. /package/dist/{chunk-X6TBQKHW.js.map → chunk-2577DKXB.js.map} +0 -0
  337. /package/dist/{chunk-L3FHEWA3.js.map → chunk-2N4GY74U.js.map} +0 -0
  338. /package/dist/{chunk-626TSARM.js.map → chunk-2Y4IMKA6.js.map} +0 -0
  339. /package/dist/{chunk-7CWII4BL.js.map → chunk-3RCJJBNR.js.map} +0 -0
  340. /package/dist/{chunk-M7UC2QPT.js.map → chunk-453F654R.js.map} +0 -0
  341. /package/dist/{chunk-2QNKXGUS.js.map → chunk-4GVM6QZA.js.map} +0 -0
  342. /package/dist/{chunk-AB5P32RE.js.map → chunk-4OZNXTO4.js.map} +0 -0
  343. /package/dist/{chunk-L3HDEHGM.js.map → chunk-5VCRVKOZ.js.map} +0 -0
  344. /package/dist/{chunk-6AQIFBSP.js.map → chunk-5WDXHNSW.js.map} +0 -0
  345. /package/dist/{chunk-BOFRKAUS.js.map → chunk-6GMZ7HEE.js.map} +0 -0
  346. /package/dist/{chunk-XBFEKTIY.js.map → chunk-6I2RQCET.js.map} +0 -0
  347. /package/dist/{chunk-UCUALOSM.js.map → chunk-6YXCPL4T.js.map} +0 -0
  348. /package/dist/{chunk-BYBB4ABD.js.map → chunk-77K4PG6P.js.map} +0 -0
  349. /package/dist/{chunk-S2VG3ABP.js.map → chunk-7MG2LHO5.js.map} +0 -0
  350. /package/dist/{chunk-EO2KGKEJ.js.map → chunk-7V4TP3AF.js.map} +0 -0
  351. /package/dist/{chunk-LFDMKZIP.js.map → chunk-ANATMFIO.js.map} +0 -0
  352. /package/dist/{chunk-T3PHCEN4.js.map → chunk-ANSIZYEG.js.map} +0 -0
  353. /package/dist/{chunk-ZKRRBRSZ.js.map → chunk-AO42KJO6.js.map} +0 -0
  354. /package/dist/{chunk-VFIWDPXZ.js.map → chunk-BLN54W3L.js.map} +0 -0
  355. /package/dist/{chunk-ZQ2UUHSL.js.map → chunk-BM5TWITZ.js.map} +0 -0
  356. /package/dist/{chunk-WLFABTZ6.js.map → chunk-BOET4NA4.js.map} +0 -0
  357. /package/dist/{chunk-FOG7YEJP.js.map → chunk-BOWNCWZT.js.map} +0 -0
  358. /package/dist/{chunk-7XODKGTW.js.map → chunk-BSFNRLK2.js.map} +0 -0
  359. /package/dist/{chunk-J4MN6XIU.js.map → chunk-BZ3534YM.js.map} +0 -0
  360. /package/dist/{chunk-IF56DYJK.js.map → chunk-CPWQB3N5.js.map} +0 -0
  361. /package/dist/{chunk-SHILAQH5.js.map → chunk-DGOZ4UZD.js.map} +0 -0
  362. /package/dist/{chunk-BWWUXE3L.js.map → chunk-ELNXJMGB.js.map} +0 -0
  363. /package/dist/{chunk-44C2URL7.js.map → chunk-EQEYOJBM.js.map} +0 -0
  364. /package/dist/{chunk-Y3XWRDAM.js.map → chunk-EYBQEIUY.js.map} +0 -0
  365. /package/dist/{chunk-Z7ZXZL6Y.js.map → chunk-FAHMLERK.js.map} +0 -0
  366. /package/dist/{chunk-EXDIHWFO.js.map → chunk-FMZY5Q6L.js.map} +0 -0
  367. /package/dist/{chunk-H6WXKZL7.js.map → chunk-FXBIP2WD.js.map} +0 -0
  368. /package/dist/{chunk-672U6STZ.js.map → chunk-GPEQUXHL.js.map} +0 -0
  369. /package/dist/{chunk-Z2PWOSCJ.js.map → chunk-GY4WYNNG.js.map} +0 -0
  370. /package/dist/{chunk-4A4TYISP.js.map → chunk-JBDFMYKQ.js.map} +0 -0
  371. /package/dist/{chunk-POS53FG6.js.map → chunk-JMGDHKQF.js.map} +0 -0
  372. /package/dist/{chunk-Q7GEDVHC.js.map → chunk-K6LHRFBL.js.map} +0 -0
  373. /package/dist/{chunk-4JDIRUTT.js.map → chunk-K7NTTA6P.js.map} +0 -0
  374. /package/dist/{chunk-26W5VETY.js.map → chunk-KG7TZKZG.js.map} +0 -0
  375. /package/dist/{chunk-RJ7RIIX6.js.map → chunk-KJIMGIWO.js.map} +0 -0
  376. /package/dist/{chunk-F7ZFRPGQ.js.map → chunk-KTFRCC5C.js.map} +0 -0
  377. /package/dist/{chunk-HSGEIMJS.js.map → chunk-KUJDV5QH.js.map} +0 -0
  378. /package/dist/{chunk-UPJMBMCR.js.map → chunk-L742JPKZ.js.map} +0 -0
  379. /package/dist/{chunk-4TZUFNXL.js.map → chunk-L7CIOOBW.js.map} +0 -0
  380. /package/dist/{chunk-7LYUJNU3.js.map → chunk-LWBCUYZW.js.map} +0 -0
  381. /package/dist/{chunk-JHLJQUXU.js.map → chunk-MUM7IANK.js.map} +0 -0
  382. /package/dist/{chunk-2GXEQUEX.js.map → chunk-MVMXZYXT.js.map} +0 -0
  383. /package/dist/{chunk-XLPXGN66.js.map → chunk-NA2NIJZI.js.map} +0 -0
  384. /package/dist/{chunk-S6YB5ZRP.js.map → chunk-NKHRDYOR.js.map} +0 -0
  385. /package/dist/{chunk-XJ3FEKEY.js.map → chunk-NQKIUNW5.js.map} +0 -0
  386. /package/dist/{chunk-6NRVFD55.js.map → chunk-PT43Y56J.js.map} +0 -0
  387. /package/dist/{chunk-5ACAVJUI.js.map → chunk-Q2PU57HC.js.map} +0 -0
  388. /package/dist/{chunk-E6YA6UAP.js.map → chunk-Q7HZX3IF.js.map} +0 -0
  389. /package/dist/{chunk-4ZPE6SKS.js.map → chunk-QIBVIOXO.js.map} +0 -0
  390. /package/dist/{chunk-WLLUM35R.js.map → chunk-QIZPZMUI.js.map} +0 -0
  391. /package/dist/{chunk-LKFKXS5K.js.map → chunk-RMF67KCG.js.map} +0 -0
  392. /package/dist/{chunk-YCSM3GZU.js.map → chunk-RMS3NEA3.js.map} +0 -0
  393. /package/dist/{chunk-OPXR4PB2.js.map → chunk-SFAWCTEM.js.map} +0 -0
  394. /package/dist/{chunk-3QARDAYW.js.map → chunk-SKGMN35F.js.map} +0 -0
  395. /package/dist/{chunk-W5LHQXZU.js.map → chunk-SL3JAAKN.js.map} +0 -0
  396. /package/dist/{chunk-UALOYGCP.js.map → chunk-SPYWXKJN.js.map} +0 -0
  397. /package/dist/{chunk-QU3YUP2X.js.map → chunk-SZJ3DLZA.js.map} +0 -0
  398. /package/dist/{chunk-225O5CXQ.js.map → chunk-TFR7DSOV.js.map} +0 -0
  399. /package/dist/{chunk-X67FCULK.js.map → chunk-TRGTKX5E.js.map} +0 -0
  400. /package/dist/{chunk-JVLSU7S2.js.map → chunk-TUFM4UZP.js.map} +0 -0
  401. /package/dist/{chunk-HTGRQZFB.js.map → chunk-UGTBXF5U.js.map} +0 -0
  402. /package/dist/{chunk-THNJ3IKU.js.map → chunk-ULUMAZ5S.js.map} +0 -0
  403. /package/dist/{chunk-XDVVBETV.js.map → chunk-UXVWEX5L.js.map} +0 -0
  404. /package/dist/{chunk-FKFIEEY6.js.map → chunk-UXWB3FPF.js.map} +0 -0
  405. /package/dist/{chunk-CBRS2NEK.js.map → chunk-VTFVLCUH.js.map} +0 -0
  406. /package/dist/{chunk-TOV6VMHF.js.map → chunk-VXANTWBJ.js.map} +0 -0
  407. /package/dist/{chunk-VSLUSXVK.js.map → chunk-VXGSWL6L.js.map} +0 -0
  408. /package/dist/{chunk-HQINBNHM.js.map → chunk-WEQEYLCS.js.map} +0 -0
  409. /package/dist/{chunk-U6GCYG2T.js.map → chunk-X2DLENDQ.js.map} +0 -0
  410. /package/dist/{chunk-XVU7J43V.js.map → chunk-XLMEZIAJ.js.map} +0 -0
  411. /package/dist/{chunk-ILSR22WM.js.map → chunk-XTXOCYOJ.js.map} +0 -0
  412. /package/dist/{chunk-KDJGJR7F.js.map → chunk-YSRUYAVU.js.map} +0 -0
  413. /package/dist/{chunk-NLKLXXTO.js.map → chunk-YYP7WSEB.js.map} +0 -0
  414. /package/dist/{chunk-4G25SDQL.js.map → chunk-ZN4FD4PE.js.map} +0 -0
  415. /package/dist/{chunk-XSN63FUS.js.map → chunk-ZORTV6NH.js.map} +0 -0
  416. /package/dist/{chunk-S3I7VKID.js.map → chunk-ZVO4QVPD.js.map} +0 -0
  417. /package/dist/{chunk-PZ5AY32C.js.map → collection-facade-4GRREZ6C.js.map} +0 -0
  418. /package/dist/{collection-facade-6IY2LW6W.js.map → computed-VPOKQK4N.js.map} +0 -0
  419. /package/dist/{computed-ASBNTLOK.js.map → derive-6O5SWQKN.js.map} +0 -0
  420. /package/dist/{derive-TCTS7ULE.js.map → enclave-KJOTOH7X.js.map} +0 -0
  421. /package/dist/{enclave-4P4KH5ZW.js.map → executor-5NIMLSKZ.js.map} +0 -0
  422. /package/dist/{executor-AFHQYRAU.js.map → executor-AQVXV5GZ.js.map} +0 -0
  423. /package/dist/{executor-CDIMJVE2.js.map → executor-PUAO6AKJ.js.map} +0 -0
  424. /package/dist/{executor-YYDW6XQI.js.map → export-accessible-72EQNBMR.js.map} +0 -0
  425. /package/dist/{export-accessible-WADNWX35.js.map → extract-partition-PUYNU3UF.js.map} +0 -0
  426. /package/dist/{extract-partition-SHQYQSWE.js.map → find-2ABFCZX4.js.map} +0 -0
  427. /package/dist/{find-SZBL2HPB.js.map → issue-SIDORTSZ.js.map} +0 -0
  428. /package/dist/{issue-2DGG7NKE.js.map → ledger-F33ZVMTK.js.map} +0 -0
  429. /package/dist/{ledger-4X5ZH43X.js.map → liberate-LCDPNAG2.js.map} +0 -0
  430. /package/dist/{liberate-7NEPRE52.js.map → link-set-FKNWAYKS.js.map} +0 -0
  431. /package/dist/{link-set-WHTYVTOV.js.map → managed-secret-PQYKSR6T.js.map} +0 -0
  432. /package/dist/{managed-secret-CXALLEUB.js.map → noydb-DUXZPKSN.js.map} +0 -0
  433. /package/dist/{noydb-BQ3ZTN2Z.js.map → read-only-facade-BIGO37U3.js.map} +0 -0
  434. /package/dist/{read-only-facade-CHCKSEPD.js.map → register-I2DZXGAR.js.map} +0 -0
  435. /package/dist/{register-GLCOH73C.js.map → registry-23WF3TGH.js.map} +0 -0
  436. /package/dist/{registry-GWGHZWGP.js.map → registry-4AYVUNXK.js.map} +0 -0
  437. /package/dist/{registry-IWFMXCHX.js.map → registry-VSSQPIGF.js.map} +0 -0
  438. /package/dist/{registry-Q3FG3OAX.js.map → registry-YLEWMGAC.js.map} +0 -0
  439. /package/dist/{registry-T346IZCF.js.map → request-withdrawal-KFQHEZ25.js.map} +0 -0
  440. /package/dist/{request-withdrawal-2RERJECX.js.map → revoke-DQDZAZZM.js.map} +0 -0
  441. /package/dist/{revoke-4NRSCPNW.js.map → signer-WAMDZHEN.js.map} +0 -0
  442. /package/dist/{signer-HJHTGX7X.js.map → stale-DDL7WQEZ.js.map} +0 -0
  443. /package/dist/{stale-5I36LPVK.js.map → storage-FLR73HHF.js.map} +0 -0
  444. /package/dist/{storage-ZYYAB3J3.js.map → ulid-4MKXG325.js.map} +0 -0
  445. /package/dist/{ulid-VQW6ERQN.js.map → vault-diff-C6WUJFNP.js.map} +0 -0
  446. /package/dist/{vault-diff-FE5J35NJ.js.map → walk-3UQBRMDV.js.map} +0 -0
  447. /package/dist/{walk-LTV7LOCN.js.map → withdraw-accessible-EL5GXZBS.js.map} +0 -0
@@ -0,0 +1,1652 @@
1
+ import {
2
+ VectorSet
3
+ } from "./chunk-RTBJ5IOO.js";
4
+ import {
5
+ guardClassifiedCompat,
6
+ resolveClassifiedFields
7
+ } from "./chunk-5VCRVKOZ.js";
8
+ import {
9
+ jsonSchemaToFields
10
+ } from "./chunk-VYYM3MEN.js";
11
+ import {
12
+ derivePersistedSchema,
13
+ isZod4Schema
14
+ } from "./chunk-REDOOY2Q.js";
15
+ import {
16
+ loadPersistedSchema
17
+ } from "./chunk-2Y4IMKA6.js";
18
+ import {
19
+ buildPresentForJoin,
20
+ isLookupDescriptor
21
+ } from "./chunk-U4FOQDY4.js";
22
+ import {
23
+ Lru
24
+ } from "./chunk-V4PXLYWM.js";
25
+ import {
26
+ isDictKeyDescriptor,
27
+ isI18nTextDescriptor,
28
+ isStaticDictDescriptor
29
+ } from "./chunk-TRGTKX5E.js";
30
+ import {
31
+ viaBinder
32
+ } from "./chunk-UXVWEX5L.js";
33
+ import {
34
+ ClassifiedConfigError,
35
+ DerivationCycleError,
36
+ FieldNotQueryableError,
37
+ MaterializedViewCycleError,
38
+ UnsupportedTierCompositionError,
39
+ ValidationError
40
+ } from "./chunk-7O3Y4PPD.js";
41
+
42
+ // src/with-shape/introspection/field-meta.ts
43
+ var FieldMetaUnknownFieldError = class extends Error {
44
+ constructor(collection, key) {
45
+ super(`fieldMeta for collection "${collection}" references unknown field "${key}". Declare it in the schema/config or remove the fieldMeta entry.`);
46
+ this.collection = collection;
47
+ this.key = key;
48
+ this.name = "FieldMetaUnknownFieldError";
49
+ }
50
+ collection;
51
+ key;
52
+ };
53
+ function validateFieldMetaKeys(collection, fieldMeta, knownFields) {
54
+ for (const key of Object.keys(fieldMeta)) {
55
+ if (!knownFields.has(key)) throw new FieldMetaUnknownFieldError(collection, key);
56
+ }
57
+ }
58
+ function humanizeFieldKey(key) {
59
+ return key.replace(/[_-]+/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").trim().split(/\s+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
60
+ }
61
+ function resolveFieldMeta(key, inputs) {
62
+ const { channel, zodMeta, inferred } = inputs;
63
+ const pick = (k) => channel?.[k] ?? zodMeta?.[k] ?? inferred?.[k];
64
+ const description = pick("description");
65
+ const semanticType = pick("semanticType");
66
+ const unit = pick("unit");
67
+ const sensitivity = pick("sensitivity");
68
+ const aggregate = pick("aggregate");
69
+ const aliases = pick("aliases");
70
+ const displayFor = pick("displayFor");
71
+ const widget = pick("widget");
72
+ const group = pick("group");
73
+ const order = pick("order");
74
+ return {
75
+ label: pick("label") ?? humanizeFieldKey(key),
76
+ ...description !== void 0 ? { description } : {},
77
+ ...semanticType !== void 0 ? { semanticType } : {},
78
+ ...unit !== void 0 ? { unit } : {},
79
+ ...sensitivity !== void 0 ? { sensitivity } : {},
80
+ ...aggregate !== void 0 ? { aggregate } : {},
81
+ ...aliases !== void 0 ? { aliases } : {},
82
+ ...displayFor !== void 0 ? { displayFor } : {},
83
+ ...widget !== void 0 ? { widget } : {},
84
+ ...group !== void 0 ? { group } : {},
85
+ ...order !== void 0 ? { order } : {}
86
+ };
87
+ }
88
+ function schemaFieldKeys(schema) {
89
+ let s = schema;
90
+ for (let depth = 0; depth < 10; depth++) {
91
+ if (s === null || typeof s !== "object") return void 0;
92
+ const shape = s.shape;
93
+ if (shape !== null && typeof shape === "object") {
94
+ const keys = Object.keys(shape);
95
+ return keys.length > 0 ? keys : void 0;
96
+ }
97
+ const def = s._def;
98
+ const effect = def?.effect?.type;
99
+ if (def?.schema !== void 0 && (effect === "refinement" || effect === "preprocess")) {
100
+ s = def.schema;
101
+ continue;
102
+ }
103
+ if (def?.out !== void 0) {
104
+ s = def.out;
105
+ continue;
106
+ }
107
+ return void 0;
108
+ }
109
+ return void 0;
110
+ }
111
+ function validateFieldMetaAtRegistration(input) {
112
+ if (input.fieldMeta === void 0) return;
113
+ const validatorKeys = schemaFieldKeys(input.schema);
114
+ if (validatorKeys === void 0) return;
115
+ validateFieldMetaKeys(
116
+ input.collection,
117
+ input.fieldMeta,
118
+ /* @__PURE__ */ new Set([...validatorKeys, ...input.configKeys])
119
+ );
120
+ }
121
+
122
+ // src/with-shape/introspection/describe.ts
123
+ var ZOD_META_KEYS = /* @__PURE__ */ new Set([
124
+ "label",
125
+ "description",
126
+ "unit",
127
+ "semanticType",
128
+ "sensitivity",
129
+ "aggregate",
130
+ "aliases",
131
+ "displayFor",
132
+ "group",
133
+ "order"
134
+ ]);
135
+ async function deriveZodFields(schema) {
136
+ const envelope = await derivePersistedSchema(schema);
137
+ if (!envelope.jsonSchema) return {};
138
+ const isZod4 = isZod4Schema(schema);
139
+ const jsonSchema = envelope.jsonSchema;
140
+ const fieldDescriptors = jsonSchemaToFields(jsonSchema, "live-validator");
141
+ const propertiesRaw = jsonSchema["properties"];
142
+ const result = {};
143
+ for (const [key, descriptor] of Object.entries(fieldDescriptors)) {
144
+ let meta;
145
+ if (isZod4 && propertiesRaw) {
146
+ const prop = propertiesRaw[key];
147
+ if (prop) {
148
+ const extracted = {};
149
+ let hasAny = false;
150
+ for (const mk of ZOD_META_KEYS) {
151
+ if (mk in prop) {
152
+ extracted[mk] = prop[mk];
153
+ hasAny = true;
154
+ }
155
+ }
156
+ if (hasAny) meta = extracted;
157
+ }
158
+ }
159
+ result[key] = {
160
+ type: descriptor.type,
161
+ optional: descriptor.optional === true,
162
+ ...descriptor.constraints !== void 0 ? { constraints: descriptor.constraints } : {},
163
+ ...meta !== void 0 ? { meta } : {}
164
+ };
165
+ }
166
+ return result;
167
+ }
168
+ async function resolveDescribeFieldIds(store, vaultName, collectionName, getDEK) {
169
+ let dek;
170
+ try {
171
+ dek = await getDEK(collectionName);
172
+ } catch {
173
+ return {};
174
+ }
175
+ const persisted = await loadPersistedSchema(store, vaultName, collectionName, dek);
176
+ return persisted?.fieldIds !== void 0 ? { fieldIds: persisted.fieldIds } : {};
177
+ }
178
+ function deriveWidget(opts) {
179
+ if (opts.resolvedWidget !== void 0) return opts.resolvedWidget;
180
+ switch (opts.semanticType) {
181
+ case "date":
182
+ case "datetime":
183
+ return "date";
184
+ case "currency":
185
+ return "money";
186
+ case "entity":
187
+ return "ref-select";
188
+ case "url":
189
+ return "url";
190
+ case "email":
191
+ return "email";
192
+ case "percent":
193
+ return "number";
194
+ }
195
+ if (opts.dict !== void 0 || opts.lookup !== void 0) return "select";
196
+ if (opts.blob !== void 0) return "file";
197
+ if (opts.type === "boolean") return "checkbox";
198
+ if (opts.type === "number") return "number";
199
+ return "text";
200
+ }
201
+ function buildDescription(input) {
202
+ const { collection, fieldMeta, moneyFields, dictKeyFields, lookupFields, computed, refs, zodFields, schema, dictLabels, meta, i18nFields, classified, taint, fieldIds } = input;
203
+ const lookupFragments = input.viaFragments?.["lookup"]?.lookupFields;
204
+ const blobFragments = input.viaFragments?.["blob"]?.blobFields;
205
+ const validatorKeys = zodFields !== void 0 && Object.keys(zodFields).length > 0 ? Object.keys(zodFields) : schemaFieldKeys(schema);
206
+ const canEnumerateFields = validatorKeys !== void 0;
207
+ if (canEnumerateFields && fieldMeta !== void 0) {
208
+ const knownFields = /* @__PURE__ */ new Set([
209
+ ...Object.keys(moneyFields ?? {}),
210
+ ...Object.keys(dictKeyFields ?? {}),
211
+ ...Object.keys(refs),
212
+ ...Object.keys(computed ?? {}),
213
+ ...validatorKeys ?? [],
214
+ ...Object.keys(i18nFields ?? {}),
215
+ ...Object.keys(lookupFields ?? {}),
216
+ ...Object.keys(blobFragments ?? {}),
217
+ ...Object.keys(classified ?? {})
218
+ ]);
219
+ validateFieldMetaKeys(collection, fieldMeta, knownFields);
220
+ }
221
+ const allKeys = /* @__PURE__ */ new Set([
222
+ ...Object.keys(moneyFields ?? {}),
223
+ ...Object.keys(dictKeyFields ?? {}),
224
+ ...Object.keys(lookupFields ?? {}),
225
+ ...Object.keys(refs),
226
+ ...Object.keys(computed ?? {}),
227
+ ...Object.keys(fieldMeta ?? {}),
228
+ ...Object.keys(zodFields ?? {}),
229
+ ...Object.keys(i18nFields ?? {}),
230
+ ...Object.keys(classified ?? {}),
231
+ ...Object.keys(blobFragments ?? {})
232
+ ]);
233
+ const fields = [];
234
+ for (const key of [...allKeys].sort()) {
235
+ const zod = zodFields?.[key];
236
+ const money = moneyFields?.[key];
237
+ const dict = dictKeyFields?.[key];
238
+ const lookupDesc = lookupFields?.[key];
239
+ const refDesc = refs[key];
240
+ const isComputed = computed !== void 0 && key in computed;
241
+ const i18nDesc = i18nFields?.[key];
242
+ const cls = classified?.[key];
243
+ const blobFragmentEntry = blobFragments?.[key];
244
+ const taintPosture = taint?.postures.get(key);
245
+ let type = zod?.type ?? "unknown";
246
+ const inferred = {};
247
+ let moneyBlock;
248
+ let dictBlock;
249
+ let refBlock;
250
+ let lookupBlock;
251
+ let blobBlock;
252
+ if (money) {
253
+ type = "number";
254
+ inferred.semanticType = "currency";
255
+ inferred.aggregate = "sum";
256
+ const currency = money.soleCurrency();
257
+ const scale = currency !== void 0 ? money.scaleFor(currency) : void 0;
258
+ moneyBlock = {
259
+ mode: money.mode,
260
+ ...currency !== void 0 ? { currency } : {},
261
+ ...scale !== void 0 ? { scale } : {},
262
+ ...money.rounding !== void 0 ? { rounding: money.rounding } : {}
263
+ };
264
+ } else if (refDesc) {
265
+ type = refDesc.isArray ? "array" : "string";
266
+ inferred.semanticType = "entity";
267
+ refBlock = {
268
+ target: refDesc.target,
269
+ mode: refDesc.mode,
270
+ ...refDesc.isArray ? { isArray: true } : {}
271
+ };
272
+ } else if (dict) {
273
+ type = "enum";
274
+ if (isStaticDictDescriptor(dict)) {
275
+ const displayLocale = dict.displayLocale;
276
+ const values = dict.keys.map((k) => {
277
+ const localeMap = dict.table[k];
278
+ const label = displayLocale !== void 0 ? localeMap?.[displayLocale] ?? void 0 : void 0;
279
+ return label !== void 0 ? { value: k, label } : { value: k };
280
+ });
281
+ dictBlock = { name: dict.name, static: true, values };
282
+ } else {
283
+ const labelMap = dictLabels?.[dict.name];
284
+ const labelMapHasEntries = labelMap !== void 0 && Object.keys(labelMap).length > 0;
285
+ if (labelMapHasEntries) {
286
+ const values = Object.entries(labelMap).map(([value, label]) => ({ value, label }));
287
+ dictBlock = { name: dict.name, static: false, values };
288
+ } else if (dict.keys !== void 0) {
289
+ const values = dict.keys.map((k) => {
290
+ const label = dict.labels?.[k];
291
+ return label !== void 0 ? { value: k, label } : { value: k };
292
+ });
293
+ dictBlock = { name: dict.name, static: false, values };
294
+ } else {
295
+ dictBlock = { name: dict.name, static: false };
296
+ }
297
+ }
298
+ } else if (lookupDesc) {
299
+ type = "enum";
300
+ const lookupLabelMap = dictLabels?.[lookupDesc.dimension];
301
+ const lookupLabelMapHasEntries = lookupLabelMap !== void 0 && Object.keys(lookupLabelMap).length > 0;
302
+ if (lookupDesc.table !== void 0) {
303
+ const displayLocale = lookupDesc.displayLocale;
304
+ const table = lookupDesc.table;
305
+ const values = (lookupDesc.keys ?? Object.keys(table)).map((k) => {
306
+ const localeMap = table[k];
307
+ const label = displayLocale !== void 0 ? localeMap?.[displayLocale] ?? void 0 : void 0;
308
+ return label !== void 0 ? { value: k, label } : { value: k };
309
+ });
310
+ dictBlock = { name: lookupDesc.dimension, static: true, values };
311
+ } else if (lookupLabelMapHasEntries) {
312
+ const values = Object.entries(lookupLabelMap).map(([value, label]) => ({ value, label }));
313
+ dictBlock = { name: lookupDesc.dimension, static: false, values };
314
+ } else if (lookupDesc.keys !== void 0) {
315
+ const values = lookupDesc.keys.map((k) => {
316
+ const label = lookupDesc.labels?.[k];
317
+ return label !== void 0 ? { value: k, label } : { value: k };
318
+ });
319
+ dictBlock = { name: lookupDesc.dimension, static: false, values };
320
+ } else {
321
+ dictBlock = { name: lookupDesc.dimension, static: false };
322
+ }
323
+ } else if (i18nDesc) {
324
+ type = "string";
325
+ } else if (isComputed) {
326
+ } else if (blobFragmentEntry !== void 0) {
327
+ type = "blob";
328
+ blobBlock = { ...blobFragmentEntry, queryable: "none" };
329
+ }
330
+ const lookupFragmentEntry = lookupFragments?.[key];
331
+ if (lookupFragmentEntry !== void 0) {
332
+ lookupBlock = {
333
+ ...lookupFragmentEntry.dimension !== void 0 ? { dimension: lookupFragmentEntry.dimension } : {},
334
+ backing: lookupFragmentEntry.backing,
335
+ vocabulary: lookupFragmentEntry.vocabulary,
336
+ key: lookupFragmentEntry.key,
337
+ onDelete: lookupFragmentEntry.onDelete,
338
+ ...lookupFragmentEntry.altKeys !== void 0 ? { altKeys: lookupFragmentEntry.altKeys } : {},
339
+ ...lookupFragmentEntry.present !== void 0 ? { present: lookupFragmentEntry.present } : {},
340
+ ...lookupFragmentEntry.sortBy !== void 0 ? { sortBy: lookupFragmentEntry.sortBy } : {},
341
+ ...lookupFragmentEntry.keys !== void 0 ? { keys: lookupFragmentEntry.keys } : {}
342
+ };
343
+ }
344
+ if (cls !== void 0) inferred.sensitivity = cls.sensitivity;
345
+ const channelEntry = fieldMeta?.[key];
346
+ const zodMeta = zod?.meta;
347
+ const resolved = resolveFieldMeta(key, {
348
+ ...channelEntry !== void 0 ? { channel: channelEntry } : {},
349
+ ...zodMeta !== void 0 ? { zodMeta } : {},
350
+ inferred
351
+ });
352
+ let i18nBlock;
353
+ if (i18nDesc !== void 0) {
354
+ const locales = i18nDesc.options.languages;
355
+ const densify = i18nDesc.options.densifyOnWrite;
356
+ i18nBlock = {
357
+ ...locales !== void 0 ? { locales } : {},
358
+ ...densify !== void 0 ? { densify } : {}
359
+ };
360
+ }
361
+ const widget = deriveWidget({
362
+ type,
363
+ ...resolved.semanticType !== void 0 ? { semanticType: resolved.semanticType } : {},
364
+ ...dictBlock !== void 0 ? { dict: dictBlock } : {},
365
+ ...lookupBlock !== void 0 ? { lookup: lookupBlock } : {},
366
+ ...blobBlock !== void 0 ? { blob: blobBlock } : {},
367
+ ...resolved.widget !== void 0 ? { resolvedWidget: resolved.widget } : {}
368
+ });
369
+ const editable = !isComputed && key !== "id" && blobBlock === void 0;
370
+ const field = {
371
+ key,
372
+ ...fieldIds?.[key] !== void 0 ? { id: fieldIds[key] } : {},
373
+ type,
374
+ optional: zod?.optional ?? false,
375
+ ...zod?.constraints !== void 0 ? { constraints: zod.constraints } : {},
376
+ label: resolved.label,
377
+ ...resolved.description !== void 0 ? { description: resolved.description } : {},
378
+ ...resolved.group !== void 0 ? { group: resolved.group } : {},
379
+ ...resolved.order !== void 0 ? { order: resolved.order } : {},
380
+ ...resolved.semanticType !== void 0 ? { semanticType: resolved.semanticType } : {},
381
+ ...resolved.unit !== void 0 ? { unit: resolved.unit } : {},
382
+ ...resolved.sensitivity !== void 0 ? { sensitivity: resolved.sensitivity } : {},
383
+ ...resolved.aggregate !== void 0 ? { aggregate: resolved.aggregate } : {},
384
+ ...resolved.aliases !== void 0 ? { aliases: resolved.aliases } : {},
385
+ ...resolved.displayFor !== void 0 ? { displayFor: resolved.displayFor } : {},
386
+ ...refBlock !== void 0 ? { ref: refBlock } : {},
387
+ ...moneyBlock !== void 0 ? { money: moneyBlock } : {},
388
+ ...dictBlock !== void 0 ? { dict: dictBlock } : {},
389
+ ...lookupBlock !== void 0 ? { lookup: lookupBlock } : {},
390
+ ...blobBlock !== void 0 ? { blob: blobBlock } : {},
391
+ ...isComputed ? { computed: true } : {},
392
+ ...i18nBlock !== void 0 ? { i18n: i18nBlock } : {},
393
+ widget,
394
+ editable,
395
+ ...cls !== void 0 ? {
396
+ classified: {
397
+ preset: cls.preset,
398
+ storage: cls.storage,
399
+ list: cls.list.kind === "omit" ? "omit" : cls.list.kind === "mask" ? { mask: cls.list.pattern } : { rider: cls.list.rider },
400
+ ...cls.equatable === true ? { equatable: true } : {}
401
+ }
402
+ } : {},
403
+ ...taintPosture !== void 0 ? { taint: { posture: taintPosture, forcedBy: taint?.provenance?.get(key) ?? [] } } : {}
404
+ };
405
+ fields.push(field);
406
+ }
407
+ const collectionMeta = {
408
+ ...meta,
409
+ label: meta?.label ?? humanizeFieldKey(collection)
410
+ };
411
+ return {
412
+ collection,
413
+ fields,
414
+ meta: collectionMeta
415
+ };
416
+ }
417
+
418
+ // src/kernel/via/compose.ts
419
+ function via(...descriptors) {
420
+ if (descriptors.length === 0) {
421
+ throw new ValidationError("via(): at least one descriptor is required, e.g. via(money({ currency: 'EUR' }))");
422
+ }
423
+ return { _noydbVia: true, descriptors };
424
+ }
425
+ function isViaFieldSpec(x) {
426
+ return typeof x === "object" && x !== null && x._noydbVia === true;
427
+ }
428
+ function mergeViaFields(sources) {
429
+ for (const field of Object.keys(sources.dictKeyFields ?? {})) {
430
+ if (sources.lookupFields && field in sources.lookupFields) {
431
+ throw new ValidationError(
432
+ `mergeViaFields(): field "${field}" is declared in both \`dictKeyFields\` and \`lookupFields\` \u2014 declare it in one place only.`
433
+ );
434
+ }
435
+ }
436
+ if (!sources.viaFields || Object.keys(sources.viaFields).length === 0) {
437
+ return {
438
+ moneyFields: sources.moneyFields,
439
+ i18nFields: sources.i18nFields,
440
+ dictKeyFields: sources.dictKeyFields,
441
+ computedFields: void 0,
442
+ lookupFields: sources.lookupFields
443
+ };
444
+ }
445
+ const sugarFieldNames = /* @__PURE__ */ new Set([
446
+ ...Object.keys(sources.moneyFields ?? {}),
447
+ ...Object.keys(sources.i18nFields ?? {}),
448
+ ...Object.keys(sources.dictKeyFields ?? {}),
449
+ ...Object.keys(sources.lookupFields ?? {})
450
+ ]);
451
+ const viaMoney = {};
452
+ const viaI18nText = {};
453
+ const viaDictKey = {};
454
+ const viaComputed = {};
455
+ const viaLookup = {};
456
+ for (const [field, spec] of Object.entries(sources.viaFields)) {
457
+ if (sugarFieldNames.has(field)) {
458
+ throw new ValidationError(
459
+ `via(): field "${field}" is declared via both a sugar key and \`viaFields\` \u2014 declare it in one place only.`
460
+ );
461
+ }
462
+ for (const descriptor of spec.descriptors) {
463
+ if (descriptor._viaBrand === "money") {
464
+ viaMoney[field] = descriptor;
465
+ } else if (descriptor._viaBrand === "i18n") {
466
+ if (isI18nTextDescriptor(descriptor)) viaI18nText[field] = descriptor;
467
+ else if (isDictKeyDescriptor(descriptor) || isStaticDictDescriptor(descriptor)) viaDictKey[field] = descriptor;
468
+ } else if (descriptor._viaBrand === "computed") {
469
+ viaComputed[field] = descriptor;
470
+ } else if (descriptor._viaBrand === "lookup" && isLookupDescriptor(descriptor)) {
471
+ viaLookup[field] = descriptor;
472
+ } else {
473
+ throw new ValidationError(`via(): field "${field}" has a descriptor with unrecognized _viaBrand "${descriptor._viaBrand}" \u2014 via() only supports money/i18n/computed/lookup descriptors today.`);
474
+ }
475
+ }
476
+ }
477
+ return {
478
+ moneyFields: Object.keys(viaMoney).length > 0 ? { ...sources.moneyFields ?? {}, ...viaMoney } : sources.moneyFields,
479
+ i18nFields: Object.keys(viaI18nText).length > 0 ? { ...sources.i18nFields ?? {}, ...viaI18nText } : sources.i18nFields,
480
+ dictKeyFields: Object.keys(viaDictKey).length > 0 ? { ...sources.dictKeyFields ?? {}, ...viaDictKey } : sources.dictKeyFields,
481
+ computedFields: Object.keys(viaComputed).length > 0 ? viaComputed : void 0,
482
+ lookupFields: Object.keys(viaLookup).length > 0 ? { ...sources.lookupFields ?? {}, ...viaLookup } : sources.lookupFields
483
+ };
484
+ }
485
+ var VIA_FIELD_MAP_FAMILY = {
486
+ moneyFields: "money",
487
+ i18nFields: "i18n",
488
+ dictKeyFields: "i18n",
489
+ lookupFields: "lookup",
490
+ classifiedFields: "classified",
491
+ blobFields: "blob",
492
+ computed: "computed"
493
+ };
494
+ function guardCrossBindingFieldCollisions(fieldMaps, callerPrefix = "compileVias()") {
495
+ const claimantsByField = /* @__PURE__ */ new Map();
496
+ for (const [sourceKey, map] of Object.entries(fieldMaps)) {
497
+ for (const field of Object.keys(map ?? {})) {
498
+ const claimants = claimantsByField.get(field) ?? /* @__PURE__ */ new Set();
499
+ claimants.add(sourceKey);
500
+ claimantsByField.set(field, claimants);
501
+ }
502
+ }
503
+ for (const [field, sourceKeys] of claimantsByField) {
504
+ const families = new Set([...sourceKeys].map((key) => VIA_FIELD_MAP_FAMILY[key]));
505
+ if (families.size < 2) continue;
506
+ if (sourceKeys.size === 2 && families.has("computed")) {
507
+ const other = [...families].find((f) => f !== "computed");
508
+ if (other === "money" || other === "i18n" || other === "lookup") continue;
509
+ }
510
+ const keys = [...sourceKeys].sort().map((k) => `\`${k}\``);
511
+ const joined = keys.length === 2 ? keys.join(" and ") : `${keys.slice(0, -1).join(", ")}, and ${keys[keys.length - 1]}`;
512
+ throw new ValidationError(
513
+ `${callerPrefix}: field "${field}" is declared in both ${joined} \u2014 a field cannot be claimed by two different via-binding families. Declare it in one place only.`
514
+ );
515
+ }
516
+ }
517
+ function guardReconcileCollisions(existingVia, incomingFieldMaps) {
518
+ guardCrossBindingFieldCollisions(incomingFieldMaps, "guardReconcileCollisions()");
519
+ if (!existingVia) return;
520
+ const existingBindings = existingVia.bindings.filter((b) => b.brand !== "taint");
521
+ for (const [sourceKey, map] of Object.entries(incomingFieldMaps)) {
522
+ const incomingFamily = VIA_FIELD_MAP_FAMILY[sourceKey];
523
+ if (incomingFamily === void 0) continue;
524
+ for (const field of Object.keys(map ?? {})) {
525
+ const existingFamilies = new Set(
526
+ existingBindings.filter((b) => b.covers?.(field)).map((b) => b.brand)
527
+ );
528
+ for (const existingFamily of existingFamilies) {
529
+ if (existingFamily === incomingFamily) continue;
530
+ const isExempt = existingFamily === "computed" && (incomingFamily === "money" || incomingFamily === "i18n" || incomingFamily === "lookup") || incomingFamily === "computed" && (existingFamily === "money" || existingFamily === "i18n" || existingFamily === "lookup");
531
+ if (isExempt) continue;
532
+ throw new ValidationError(
533
+ `vault.collection(): field "${field}" is already bound by the "${existingFamily}" via family on this collection \u2014 an incoming \`${sourceKey}\` declaration cannot claim it for a different family ("${incomingFamily}"). Declare it in one place only.`
534
+ );
535
+ }
536
+ }
537
+ }
538
+ }
539
+
540
+ // src/kernel/via/pipeline.ts
541
+ var ViaPipeline = class _ViaPipeline {
542
+ constructor(bindings, taint) {
543
+ this.bindings = bindings;
544
+ this.taint = taint;
545
+ const moneyVias = bindings.filter((b) => b.brand === "money");
546
+ const computedVias = bindings.filter((b) => b.brand === "computed");
547
+ const restBindings = bindings.filter((b) => b.brand !== "money" && b.brand !== "computed");
548
+ this._presentOrder = [...moneyVias, ...computedVias, ...restBindings];
549
+ this._presentLateBoundary = moneyVias.length + computedVias.length;
550
+ }
551
+ bindings;
552
+ taint;
553
+ /**
554
+ * Present-phase-ONLY order (#665, corrected under #665 review) — a stable
555
+ * THREE-WAY partition of `bindings` computed once here at construction:
556
+ * every `'money'`-brand binding first (existing relative order), then
557
+ * every `'computed'`-brand binding (existing relative order), then
558
+ * everything else (existing relative order). `present()` folds over this
559
+ * instead of `bindings` so a `mode: 'virtual'` computed field's value
560
+ * exists before i18n/lookup's dressing `present()` hooks run on it
561
+ * (today's `compileVias` order is money→i18n→lookup→classified→
562
+ * blob→computed, `collection-config.ts:554`, so dressing unconditionally
563
+ * ran BEFORE the value it dresses existed). This reorder is binding-level,
564
+ * not conditioned on any particular field composition — it applies to
565
+ * EVERY collection that compiles a `'computed'` binding at all, not only
566
+ * ones stacking a dresser on the SAME field as a computed one. EVERY other
567
+ * phase (`ingest`/`encodeWrite`/`encodeAtRest`/`enforceWrite`/etc.) keeps
568
+ * folding over `bindings` unchanged — those write/query phases need
569
+ * money-first (`_applyMoneyFields` PREPENDS money, `_applyClassifiedFields`
570
+ * APPENDS classified to preserve it, `kernel/collection.ts:1275-1284,1364-
571
+ * 1368`).
572
+ *
573
+ * Money is deliberately carved OUT of the generic "everything else" slice
574
+ * and kept FIRST — the original two-way `[computed..., rest...]` partition
575
+ * regressed money's composed-field behavior from a benign missing-dressing
576
+ * gap into VALUE CORRUPTION: money's `present()` DECODES its input as a
577
+ * STORED SCALED-INT (and derives `<field>Formatted` from it) — it is not a
578
+ * pure dressing CONSUMER like i18n/lookup, which only ADD a `<field>Label`
579
+ * key and never rewrite the field's own value. Running money AFTER
580
+ * computed on a field composing `computed(virtual)` + `money(...)` on
581
+ * ITSELF means money's decode sees the virtual field's raw MAJOR-unit
582
+ * output (e.g. `21`) and misreads it as a scaled-int, producing a
583
+ * corrupted value (`'0.21'`) instead of the pre-#665 result (the raw `21`
584
+ * surviving untouched, with no `Formatted` key added — a benign
585
+ * missing-dressing gap, not a wrong value). Money-first restores money's
586
+ * exact pre-#665 present position — byte-identical money behavior; the
587
+ * materialized composition pins from the #631 work and the money suites
588
+ * all ran under money-first. i18n/lookup are genuine dressing consumers
589
+ * (they only ADD, never rewrite), so they stay after computed, which is
590
+ * the fix #665 intended. A `'taint'` binding (appended LAST by
591
+ * `via/graph-wiring.ts#applyTaintOverlay`) stays last here too (it's
592
+ * neither money nor computed, so it lands at the tail of the "everything
593
+ * else" slice), preserving its "runs after computed, redacts tainted
594
+ * virtual output" contract (`via/taint-binding.ts`'s `taintBinding` doc
595
+ * comment).
596
+ *
597
+ * Money-dressing a virtual computed field's OWN output (the composed
598
+ * `computed(virtual) + money` case) is NOT resolved by this partition
599
+ * alone — #669 resolves it with a separate mid-fold hook instead:
600
+ * `NoydbVia.presentLate` runs after every binding's `present()` in this
601
+ * money+computed segment, before the "everything else" segment below, so
602
+ * money can quantize/reinterpret a virtual field's fresh MAJOR-UNITS
603
+ * output as if it were a stored value, without perturbing this ordering
604
+ * or the #665 invariant above it (`_presentLateBoundary` below marks
605
+ * exactly where that mid-fold point sits within `_presentOrder`).
606
+ */
607
+ _presentOrder;
608
+ /** #669 — index into `_presentOrder` where the money+computed segment ends and the
609
+ * "everything else" segment begins (`moneyVias.length + computedVias.length`);
610
+ * `present()` runs every binding's `presentLate` at exactly this boundary. */
611
+ _presentLateBoundary;
612
+ /** undefined when there is nothing to enforce — the zero-via fast path is
613
+ * `this.via === undefined` (#553: keeps an all-plain collection sync). A
614
+ * `'*'`-defaulted output collection (#642) counts as "something to enforce"
615
+ * even with zero field-specific postures and zero bindings. */
616
+ static build(bindings, taint) {
617
+ if (bindings.length === 0 && (!taint || taint.postures.size === 0 && taint.defaultPosture === void 0)) return void 0;
618
+ return new _ViaPipeline(bindings, taint);
619
+ }
620
+ /** Refuse a write before crypto runs: awaits each binding's `enforceWrite` in order — first throw wins. */
621
+ async enforceWrite(record, ctx) {
622
+ for (const b of this.bindings) if (b.enforceWrite) await b.enforceWrite(record, ctx);
623
+ }
624
+ ingest(record) {
625
+ let r = record;
626
+ for (const b of this.bindings) if (b.ingest) r = b.ingest(r);
627
+ return r;
628
+ }
629
+ canonicalizeStored(record) {
630
+ let r = record;
631
+ for (const b of this.bindings) if (b.canonicalizeStored) r = b.canonicalizeStored(r);
632
+ return r;
633
+ }
634
+ async encodeWrite(record, ctx) {
635
+ let r = record;
636
+ for (const b of this.bindings) if (b.encodeWrite) r = await b.encodeWrite(r, ctx);
637
+ return r;
638
+ }
639
+ /**
640
+ * Final write-pipeline stage: folds each binding's `encodeAtRest` in
641
+ * order, threading the record and accumulating the sealed-slot map. A
642
+ * field belongs to exactly one via feature — two bindings sealing the
643
+ * same field is a brand-keyed collision and throws.
644
+ */
645
+ async encodeAtRest(record, crypto) {
646
+ let r = record;
647
+ let sealed;
648
+ const sealedBy = /* @__PURE__ */ new Map();
649
+ for (const b of this.bindings) {
650
+ if (!b.encodeAtRest) continue;
651
+ const result = await b.encodeAtRest(r, crypto);
652
+ r = result.record;
653
+ if (!result.sealed) continue;
654
+ for (const [field, ref] of Object.entries(result.sealed)) {
655
+ const priorBrand = sealedBy.get(field);
656
+ if (priorBrand !== void 0) {
657
+ throw new ValidationError(
658
+ `via encodeAtRest: field "${field}" sealed by binding "${priorBrand}" is also sealed by binding "${b.brand}"`
659
+ );
660
+ }
661
+ sealedBy.set(field, b.brand);
662
+ sealed ??= {};
663
+ sealed[field] = ref;
664
+ }
665
+ }
666
+ return sealed ? { record: r, sealed } : { record: r };
667
+ }
668
+ /** First read-pipeline stage: folds each binding's `decodeAtRest` in order. */
669
+ async decodeAtRest(record, sealed, crypto, opts) {
670
+ let r = record;
671
+ for (const b of this.bindings) if (b.decodeAtRest) r = await b.decodeAtRest(r, sealed, crypto, opts);
672
+ return r;
673
+ }
674
+ async present(record, ctx) {
675
+ let r = record;
676
+ for (let i = 0; i < this._presentLateBoundary; i++) {
677
+ const b = this._presentOrder[i];
678
+ if (b.present) r = await b.present(r, ctx);
679
+ }
680
+ for (const b of this.bindings) if (b.presentLate) r = await b.presentLate(r, ctx);
681
+ for (let i = this._presentLateBoundary; i < this._presentOrder.length; i++) {
682
+ const b = this._presentOrder[i];
683
+ if (b.present) r = await b.present(r, ctx);
684
+ }
685
+ return r;
686
+ }
687
+ buildClause(field, op, value) {
688
+ for (const b of this.bindings) {
689
+ const payload = b.buildClause?.(field, op, value);
690
+ if (payload !== void 0) return { brand: b.brand, payload };
691
+ }
692
+ return void 0;
693
+ }
694
+ evaluateClause(clause, actual, op) {
695
+ const b = this.bindings.find((x) => x.brand === clause.brand);
696
+ return b?.evaluateClause ? b.evaluateClause(actual, op, clause.payload) : false;
697
+ }
698
+ /**
699
+ * Resolve a `buildClause` payload to an index-probe operand (#625) —
700
+ * mirrors `evaluateClause`'s brand dispatch. `undefined` (a binding
701
+ * with no `indexProbe`, or one that declines to probe this op/payload)
702
+ * means the caller (`candidateRecords()`) must fall back to a scan.
703
+ */
704
+ // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
705
+ indexProbe(clause, op) {
706
+ const b = this.bindings.find((x) => x.brand === clause.brand);
707
+ return b?.indexProbe ? b.indexProbe(op, clause.payload) : void 0;
708
+ }
709
+ /**
710
+ * Resolve a raw STORED field value to its canonical eager-index bucket
711
+ * key (#672) — folds every binding's `canonicalizeIndexKey`, first
712
+ * non-undefined wins (same fold discipline as `buildClause`). `undefined`
713
+ * means no binding claims `field` (or the value can't be canonicalized)
714
+ * — the caller buckets the raw stringified value, unchanged from before
715
+ * this hook existed.
716
+ */
717
+ canonicalizeIndexKey(field, rawValue) {
718
+ for (const b of this.bindings) {
719
+ const key = b.canonicalizeIndexKey?.(field, rawValue);
720
+ if (key !== void 0) return key;
721
+ }
722
+ return void 0;
723
+ }
724
+ decodeResults(record) {
725
+ let r = record;
726
+ for (const b of this.bindings) if (b.decodeResults) r = b.decodeResults(r);
727
+ return r;
728
+ }
729
+ /** undefined = no binding covers the field → caller falls back to generic compare. */
730
+ compareForOrder(field, a, b) {
731
+ for (const bind of this.bindings) {
732
+ const c = bind.compareForOrder?.(field, a, b);
733
+ if (c !== void 0) return c;
734
+ }
735
+ return void 0;
736
+ }
737
+ /** undefined = no binding resolves an order-sort label for `key` at `field`/`locale` (#650 Task 7 —
738
+ * the `orderBy(..., {by:'label'})` per-call-locale channel `compareForOrder` above can't serve). */
739
+ resolveOrderLabel(field, key, locale) {
740
+ for (const bind of this.bindings) {
741
+ const label = bind.resolveOrderLabel?.(field, key, locale);
742
+ if (label !== void 0) return label;
743
+ }
744
+ return void 0;
745
+ }
746
+ /**
747
+ * Which posture governs `field`, if any binding covers it — `undefined`
748
+ * means no binding declares `field` (the generic, non-via query path
749
+ * applies). #629 Task 8's posture consumer: `.where()`/`.orderBy()`
750
+ * consult this before building/evaluating a clause, refusing fields whose
751
+ * posture is `queryable: 'none'` (e.g. blob); every other posture
752
+ * ('det-exact'/'ordered'/'full') is left to the existing per-binding
753
+ * buildClause/evaluateClause/compareForOrder machinery, unchanged.
754
+ *
755
+ * #638 Task 3: the graph-computed taint overlay is consulted FIRST — a
756
+ * derived field's assigned (most-restrictive-of-sources) posture wins over
757
+ * whatever a binding would otherwise report for that field name (no
758
+ * binding covers a computed/derived field today, so this never actually
759
+ * shadows one — see `via/taint-binding.ts`'s `taintBinding.covers`, which
760
+ * only claims the sealed subset for `encodeAtRest`/`decodeAtRest`, not for
761
+ * this lookup).
762
+ */
763
+ postureFor(field) {
764
+ const t = this.taint?.postures.get(field);
765
+ if (t) return t;
766
+ for (const b of this.bindings) {
767
+ if (b.covers?.(field)) return b.posture;
768
+ }
769
+ return this.taint?.defaultPosture;
770
+ }
771
+ /**
772
+ * Refuse any field-based reducer over a `queryable: 'none'` field (blob) —
773
+ * metadata-only: walks each reducer's `.field` and checks posture, no
774
+ * rewriting. Reducers with no `.field` (e.g. `count()`) are skipped.
775
+ *
776
+ * Shared by `wrapReducers` below (which ALSO applies each binding's
777
+ * rewrite, e.g. money's exact-BigInt reducer swap) and by
778
+ * `ScanBuilder.aggregate()` (#629 Task 8 review fix wave 1), which must
779
+ * call THIS, not `wrapReducers` — wiring full `wrapReducers` into
780
+ * `ScanBuilder.aggregate()` would newly activate money/i18n reducer
781
+ * wrapping on a path that has never run it, a parity-breaking behavior
782
+ * change for existing brands.
783
+ */
784
+ refuseUnqueryableReducers(spec) {
785
+ for (const reducer of Object.values(spec)) {
786
+ const field = reducer?.field;
787
+ if (field !== void 0 && this.postureFor(field)?.queryable === "none") {
788
+ throw new FieldNotQueryableError(field);
789
+ }
790
+ }
791
+ }
792
+ /**
793
+ * Rewrite an aggregate spec (money exact reducers), then refuse any
794
+ * field-based reducer over a `queryable: 'none'` field (blob) — the same
795
+ * posture gate `.where()`/`.orderBy()` apply, extended to `.aggregate()`
796
+ * (both the bare-spec and builder forms funnel through here).
797
+ */
798
+ wrapReducers(spec) {
799
+ this.refuseUnqueryableReducers(spec);
800
+ let s = spec;
801
+ for (const b of this.bindings) if (b.wrapReducers) s = b.wrapReducers(s);
802
+ return s;
803
+ }
804
+ /**
805
+ * Deliberate export-layer redaction (#629 Task 9's posture consumer):
806
+ * for every OWN field the decoded record carries, if the covering
807
+ * binding's posture declares `exportable: false` (classified today;
808
+ * money/i18n/blob are all `true`), replace the value with
809
+ * {@link EXPORT_REDACTION_MARKER} — the same `'[sealed]'` string
810
+ * `SealedHandle.toJSON()` (`kernel/types.ts`) already emits, so this is
811
+ * byte-parity with today's accidental redaction, now independent of the
812
+ * field's runtime shape. `SealedHandle.toJSON()` stays untouched as
813
+ * defense-in-depth: a record read via `collection.get()` and
814
+ * JSON.stringify'd outside `exportStream()` still gets the accident's
815
+ * redaction on its own. Never mutates the input; returns a new object
816
+ * only when a field was actually redacted.
817
+ */
818
+ redactForExport(record) {
819
+ let out;
820
+ for (const field of Object.keys(record)) {
821
+ if (this.postureFor(field)?.exportable === false) {
822
+ out ??= { ...record };
823
+ out[field] = EXPORT_REDACTION_MARKER;
824
+ }
825
+ }
826
+ return out ?? record;
827
+ }
828
+ /**
829
+ * Shared fold over a subset of `this.bindings`: runs each binding's
830
+ * `erase`, concatenating shredded/retainedShared counts and residue.
831
+ * Consults `posture.forgettable` (#629 Task 10) — a binding declaring
832
+ * `forgettable: false` is skipped even if it defines `erase` (none does
833
+ * today; a future non-forgettable binding is supported without a brand check).
834
+ */
835
+ async foldErase(ctx, bindings) {
836
+ let shredded = 0;
837
+ let retainedShared = 0;
838
+ const residue = [];
839
+ for (const b of bindings) {
840
+ if (!b.erase || b.posture.forgettable === false) continue;
841
+ const report = await b.erase(ctx);
842
+ shredded += report.shredded;
843
+ retainedShared += report.retainedShared ?? 0;
844
+ residue.push(...report.residue);
845
+ }
846
+ return retainedShared > 0 ? { shredded, residue, retainedShared } : { shredded, residue };
847
+ }
848
+ /** `forget()`'s per-ref erasure door: folds every binding's `erase`. */
849
+ async erase(ctx) {
850
+ return this.foldErase(ctx, this.bindings);
851
+ }
852
+ /**
853
+ * `forget()`'s SEALED-posture-only erase fold (#629 Task 10, `Collection._onViaErase`'s
854
+ * one caller) — classified today; metadata-filtered on
855
+ * `posture.encryptedAtRest`, not brand-checked. `undefined` when no
856
+ * sealed-posture binding is compiled in — `vault.ts` then falls back to
857
+ * its own bare-`sensitive` classification, which no via binding covers.
858
+ */
859
+ async eraseSealed(ctx) {
860
+ const sealed = this.bindings.filter((b) => b.posture.encryptedAtRest === "sealed");
861
+ return sealed.length === 0 ? void 0 : this.foldErase(ctx, sealed);
862
+ }
863
+ /** True iff any binding implements decodeResults (query fast-path gating). */
864
+ get hasResultDecode() {
865
+ return this.bindings.some((b) => b.decodeResults !== void 0);
866
+ }
867
+ /**
868
+ * True iff any binding declares an at-rest hook (`encodeAtRest`/
869
+ * `decodeAtRest`) — the codec boundary's async-stack gate (#629 Task 3
870
+ * consults this to choose between the hook path and today's inline
871
+ * sealed-slot path; a stack with only sync hooks, e.g. money-only, stays
872
+ * `false`).
873
+ */
874
+ get hasAtRestHooks() {
875
+ return this.bindings.some((b) => b.encodeAtRest !== void 0 || b.decodeAtRest !== void 0);
876
+ }
877
+ /**
878
+ * Fold every binding's `describeFragment()` into one `brand -> fragment`
879
+ * map (#650 Task 7 — the first-ever consumer; `describeFragment` was
880
+ * declared at `via/index.ts:136` since #623 with zero callers until this task).
881
+ * `undefined` when no compiled binding implements it. Consumed by
882
+ * `Collection.describe()`/`describeAsync()`, threaded to `buildDescription`
883
+ * as `BuildDescriptionInput.viaFragments`.
884
+ */
885
+ describeFragments() {
886
+ let out;
887
+ for (const b of this.bindings) {
888
+ const f = b.describeFragment?.();
889
+ if (f !== void 0) {
890
+ out ??= {};
891
+ out[b.brand] = f;
892
+ }
893
+ }
894
+ return out;
895
+ }
896
+ };
897
+ var EXPORT_REDACTION_MARKER = "[sealed]";
898
+ function exportRedact(coll, record) {
899
+ if (record === null || typeof record !== "object") return record;
900
+ const via2 = coll._via;
901
+ return via2 ? via2.redactForExport(record) : record;
902
+ }
903
+
904
+ // src/kernel/collection-config.ts
905
+ function computedEntryParts(entry) {
906
+ if (typeof entry === "function") return { fn: entry, mode: "materialized" };
907
+ return { fn: entry.fn, ...entry.deps !== void 0 ? { deps: entry.deps } : {}, mode: entry.mode ?? "materialized" };
908
+ }
909
+ function matchTargetFieldNames(opts) {
910
+ const declared = [];
911
+ const virtual = [];
912
+ for (const [field, entry] of Object.entries(opts.computed ?? {})) {
913
+ declared.push(field);
914
+ const parts = computedEntryParts(entry);
915
+ if (parts.mode === "virtual") virtual.push(field);
916
+ }
917
+ for (const [field, spec] of Object.entries(opts.viaFields ?? {})) {
918
+ declared.push(field);
919
+ const descriptors = spec.descriptors ?? [];
920
+ for (const d of descriptors) {
921
+ if (d._viaBrand === "computed" && d.mode === "virtual") virtual.push(field);
922
+ }
923
+ }
924
+ return { declared, virtual };
925
+ }
926
+ function unifyComputedFields(opts, viaComputedFields) {
927
+ return { ...opts.computed ?? {}, ...viaComputedFields ?? {} };
928
+ }
929
+ function compileVias(opts, classifiedGuardCtx, eraseCfgOut) {
930
+ const { moneyFields, i18nFields, dictKeyFields, computedFields, lookupFields } = mergeViaFields(opts);
931
+ const allComputedFields = unifyComputedFields(opts, computedFields);
932
+ guardCrossBindingFieldCollisions({
933
+ moneyFields,
934
+ i18nFields,
935
+ dictKeyFields,
936
+ lookupFields,
937
+ classifiedFields: opts.classifiedFields !== void 0 ? resolveClassifiedFields(opts.name, opts.classifiedFields).byField : void 0,
938
+ blobFields: opts.blobFields,
939
+ computed: allComputedFields
940
+ });
941
+ const bindings = [];
942
+ const virtualFields = /* @__PURE__ */ new Map();
943
+ for (const [field, entry] of Object.entries(allComputedFields)) {
944
+ const parts = computedEntryParts(entry);
945
+ if (parts.mode === "virtual") {
946
+ virtualFields.set(field, { _viaBrand: "computed", fn: parts.fn, mode: "virtual", ...parts.deps !== void 0 ? { deps: parts.deps } : {} });
947
+ }
948
+ }
949
+ if (moneyFields) {
950
+ const virtualMoney = resolveVirtualMoneyFields(Object.keys(moneyFields), (f) => virtualFields.has(f));
951
+ bindings.push(viaBinder("money")({ moneyFields, ...virtualMoney.size > 0 ? { virtualMoneyFields: virtualMoney } : {} }));
952
+ }
953
+ if (i18nFields || dictKeyFields) {
954
+ const densify = i18nFields ? Object.fromEntries(
955
+ Object.entries(i18nFields).filter(([, d]) => d.options.densifyOnWrite === true)
956
+ ) : {};
957
+ const i18nDensifyFields = Object.keys(densify).length > 0 ? densify : void 0;
958
+ bindings.push(viaBinder("i18n")({
959
+ ...i18nFields !== void 0 ? { i18nFields } : {},
960
+ ...dictKeyFields !== void 0 ? { dictKeyFields } : {},
961
+ ...i18nDensifyFields !== void 0 ? { i18nDensifyFields } : {},
962
+ strategy: opts.strategies.i18n,
963
+ ...opts.defaultLocale !== void 0 ? { defaultLocale: opts.defaultLocale } : {},
964
+ ...opts.autoTranslateHook !== void 0 ? { autoTranslateHook: opts.autoTranslateHook } : {},
965
+ ...opts.dictLabelResolver !== void 0 ? { dictLabelResolver: opts.dictLabelResolver } : {},
966
+ ...opts.i18nPutValidator !== void 0 ? { i18nPutValidator: opts.i18nPutValidator } : {},
967
+ collectionName: opts.name
968
+ }));
969
+ }
970
+ if (lookupFields !== void 0) {
971
+ bindings.push(viaBinder("lookup")({
972
+ lookupFields,
973
+ ...opts.lookupLabelResolver !== void 0 ? { lookupLabelResolver: opts.lookupLabelResolver } : {},
974
+ ...opts.getLookupBacking !== void 0 ? { getLookupBacking: opts.getLookupBacking } : {},
975
+ ...opts.membership !== void 0 ? { membership: opts.membership } : {},
976
+ ...opts.getAltIndex !== void 0 ? { getAltIndex: opts.getAltIndex } : {},
977
+ ...opts.snapshotFor !== void 0 ? { snapshotFor: opts.snapshotFor } : {},
978
+ collectionName: opts.name
979
+ }));
980
+ }
981
+ if (opts.classifiedFields !== void 0) {
982
+ const classifiedCfg = {
983
+ entries: opts.classifiedFields,
984
+ collectionName: opts.name,
985
+ guardCtx: classifiedGuardCtx
986
+ };
987
+ if (eraseCfgOut) eraseCfgOut.classified = classifiedCfg;
988
+ bindings.push(viaBinder("classified")(classifiedCfg));
989
+ }
990
+ if (opts.blobFields !== void 0) {
991
+ bindings.push(viaBinder("blob")({
992
+ fields: opts.blobFields,
993
+ collectionName: opts.name
994
+ }));
995
+ }
996
+ if (virtualFields.size > 0) {
997
+ bindings.push(viaBinder("computed")({ virtualFields }));
998
+ }
999
+ return bindings;
1000
+ }
1001
+ function resolveVirtualMoneyFields(moneyFieldNames, isVirtual) {
1002
+ const out = /* @__PURE__ */ new Set();
1003
+ for (const field of moneyFieldNames) if (isVirtual(field)) out.add(field);
1004
+ return out;
1005
+ }
1006
+ function collectKnownFieldNames(parts) {
1007
+ return /* @__PURE__ */ new Set([
1008
+ ...Object.keys(parts.moneyFields ?? {}),
1009
+ ...Object.keys(parts.i18nFields ?? {}),
1010
+ ...Object.keys(parts.dictKeyFields ?? {}),
1011
+ ...Object.keys(parts.classifiedFields ?? {}),
1012
+ ...Object.keys(parts.computed ?? {}),
1013
+ ...Object.keys(parts.lookupFields ?? {})
1014
+ ]);
1015
+ }
1016
+ var EMPTY_KNOWN_FIELDS = /* @__PURE__ */ new Set();
1017
+ function resolveComputedEdges(collectionName, computed, hasClassifiedFields, knownFields = EMPTY_KNOWN_FIELDS) {
1018
+ if (!computed) return [];
1019
+ const edges = [];
1020
+ for (const [field, entry] of Object.entries(computed)) {
1021
+ const parts = computedEntryParts(entry);
1022
+ const deps = parts.deps;
1023
+ if (deps === void 0) {
1024
+ if (hasClassifiedFields) {
1025
+ throw new ValidationError(
1026
+ `Collection "${collectionName}": computed field "${field}" has no declared \`deps\` and the collection declares classified fields \u2014 an opaque computed function could silently copy a classified field's plaintext into an ordinary, unredacted field. Declare \`deps\` naming the source fields it reads, e.g. computed: { ${field}: { fn, deps: [...] } } or via(computed(fn, { deps: [...] })).`
1027
+ );
1028
+ }
1029
+ continue;
1030
+ }
1031
+ if (deps.length === 0) {
1032
+ throw new ValidationError(`Collection "${collectionName}": computed field "${field}"'s \`deps\` must be non-empty.`);
1033
+ }
1034
+ for (const dep of deps) {
1035
+ if (typeof dep !== "string" || dep.length === 0) {
1036
+ throw new ValidationError(`Collection "${collectionName}": computed field "${field}"'s \`deps\` entries must be non-empty strings.`);
1037
+ }
1038
+ if (hasClassifiedFields && !knownFields.has(dep)) {
1039
+ throw new ValidationError(
1040
+ `Collection "${collectionName}": computed field "${field}"'s \`deps\` entry "${dep}" does not name a declared field, and the collection declares classified fields \u2014 an opaque computed function could silently copy a classified field's plaintext into an ordinary, unredacted field via a mistyped/unknown dep name. Declare \`deps\` naming only known fields (money/i18n/dictKey/classified/computed) \u2014 check "${dep}" for a typo.`
1041
+ );
1042
+ }
1043
+ }
1044
+ edges.push({
1045
+ target: { collection: collectionName, field },
1046
+ sources: deps.map((d) => ({ collection: collectionName, field: d })),
1047
+ grain: parts.mode === "virtual" ? "virtual" : "record"
1048
+ });
1049
+ }
1050
+ return edges;
1051
+ }
1052
+ function resolveViaDepsEdges(collectionName, bindings, knownFields) {
1053
+ const edges = [];
1054
+ for (const binding of bindings) {
1055
+ if (!binding.deps || binding.deps.length === 0) continue;
1056
+ for (const dep of binding.deps) {
1057
+ if (!knownFields.has(dep)) {
1058
+ throw new ValidationError(
1059
+ `Collection "${collectionName}": via binding "${binding.brand}" deps references undeclared field "${dep}".`
1060
+ );
1061
+ }
1062
+ }
1063
+ const sources = binding.deps.map((d) => ({ collection: collectionName, field: d }));
1064
+ for (const field of knownFields) {
1065
+ if (binding.covers?.(field)) edges.push({ target: { collection: collectionName, field }, sources });
1066
+ }
1067
+ }
1068
+ return edges;
1069
+ }
1070
+ function resolveCollectionConfig(opts) {
1071
+ if (opts.embeddings && opts.crdt) {
1072
+ throw new Error(
1073
+ `Collection "${opts.name}": embeddings are not supported on CRDT collections (L2). Use a non-CRDT collection for semantic search.`
1074
+ );
1075
+ }
1076
+ {
1077
+ const virtualFieldNames = matchTargetFieldNames({
1078
+ computed: opts.computed,
1079
+ viaFields: opts.viaFields
1080
+ }).virtual;
1081
+ if (virtualFieldNames.length > 0) {
1082
+ const virtualSet = new Set(virtualFieldNames);
1083
+ for (const reg of opts.materializedViewSource?.registry().mvsForSource(opts.name) ?? []) {
1084
+ const spec = reg.spec;
1085
+ const fields = spec.groupBy === void 0 ? [] : typeof spec.groupBy === "string" ? [spec.groupBy] : spec.groupBy;
1086
+ for (const f of fields) {
1087
+ if (!virtualSet.has(f)) continue;
1088
+ throw new ValidationError(
1089
+ `materialized view "${spec.name ?? reg.outputCollection}": groupBy names "${f}", which "${opts.name}" declares as a VIRTUAL computed field. Virtual fields are evaluated on read and never stored, so every row would bucket under an undefined key and the aggregate would be silently WRONG rather than an error. Declare it as \`mode: 'materialized'\` (stored) or group on a stored field.`
1090
+ );
1091
+ }
1092
+ }
1093
+ }
1094
+ }
1095
+ validateFieldMetaAtRegistration({
1096
+ collection: opts.name,
1097
+ schema: opts.schema,
1098
+ fieldMeta: opts.fieldMeta,
1099
+ configKeys: Object.keys({
1100
+ ...opts.moneyFields,
1101
+ ...opts.dictKeyFields,
1102
+ ...opts.declaredRefs,
1103
+ ...opts.computed,
1104
+ ...opts.i18nFields,
1105
+ ...opts.lookupFields,
1106
+ ...opts.blobFields,
1107
+ ...opts.classifiedFields,
1108
+ ...opts.viaFields
1109
+ })
1110
+ });
1111
+ if (opts.sensitive && opts.sensitive.length > 0 && opts.crdt) {
1112
+ throw new Error(
1113
+ `Collection "${opts.name}": sensitive (structural group-encryption) is not supported on CRDT collections \u2014 the CRDT write path bypasses per-field sealing, so the fields would be stored in the ordinary encrypted body with no \`_sealed\` slot and no per-field key. Use a non-CRDT collection for sealed fields.`
1114
+ );
1115
+ }
1116
+ if (opts.tiers && opts.tiers.length > 0 && opts.blobFields !== void 0 && Object.keys(opts.blobFields).length > 0 && opts.perRecordKeys !== true) {
1117
+ throw new UnsupportedTierCompositionError(
1118
+ "blobs",
1119
+ `Collection "${opts.name}": tiered collections that declare blobFields require \`perRecordKeys: true\` \u2014 legacy (non-perRecordKeys) blobs have no per-blob content CEK and cannot be tier-isolated on elevate/demote.`
1120
+ );
1121
+ }
1122
+ if (opts.tiers && opts.tiers.length > 0 && opts.blobFields !== void 0) {
1123
+ for (const [field, policy] of Object.entries(opts.blobFields)) {
1124
+ if (policy?.external && policy.public === true) {
1125
+ throw new UnsupportedTierCompositionError(
1126
+ "blobs",
1127
+ `Collection "${opts.name}": blob field "${field}" cannot be both \`external: true, public: true\` and declared on a tiered collection \u2014 the object key is deterministic and its bytes are world-readable by design, so tier-invisibility can never be enforced for it once elevated. Use a private/presigned external field (\`public\` omitted or \`false\`) or move this field to a non-tiered collection.`
1128
+ );
1129
+ }
1130
+ }
1131
+ }
1132
+ if (opts.tiers && opts.tiers.length > 0 && opts.encrypted === false) {
1133
+ throw new UnsupportedTierCompositionError(
1134
+ "plaintext",
1135
+ `Collection "${opts.name}": tiers are per-tier ENCRYPTION keys \u2014 a plaintext collection (\`encrypted: false\`) has nothing to re-key, so \`putAtTier\`/\`elevate\` would encrypt/decrypt incoherently. Use an encrypted collection.`
1136
+ );
1137
+ }
1138
+ if (opts.tiers && opts.tiers.length > 0 && opts.crdt !== void 0 && ((opts.derivationSource?.registry().strategiesForSource(opts.name).length ?? 0) > 0 || (opts.materializedViewSource?.registry().mvsForSource(opts.name).length ?? 0) > 0)) {
1139
+ throw new UnsupportedTierCompositionError(
1140
+ "crdt-derivation",
1141
+ `Collection "${opts.name}": tiers + crdt cannot be combined with this collection acting as a derivation/rollup source (#739) \u2014 the tier-aware pre-move decode \`syncDerived\` uses on elevate()/demote() does not resolve CRDT state, so a registered derivation/rollup reads raw CrdtState instead of the record and silently no-ops. Use a non-CRDT collection for a tiered derivation/rollup source, or move the derivation off this collection.`
1142
+ );
1143
+ }
1144
+ const effectiveViaFields = mergeViaFields(opts);
1145
+ const resolvedClassified = opts.classifiedFields !== void 0 ? resolveClassifiedFields(opts.name, opts.classifiedFields) : void 0;
1146
+ const allComputed = unifyComputedFields(opts, effectiveViaFields.computedFields);
1147
+ const materializedComputed = {};
1148
+ for (const [field, entry] of Object.entries(allComputed)) {
1149
+ if (computedEntryParts(entry).mode !== "virtual") materializedComputed[field] = entry;
1150
+ }
1151
+ let mergedComputed = Object.keys(materializedComputed).length > 0 ? materializedComputed : void 0;
1152
+ if (resolvedClassified !== void 0) {
1153
+ for (const key of Object.keys(allComputed)) {
1154
+ if (resolvedClassified.riderComputed[key] !== void 0) {
1155
+ throw new ClassifiedConfigError(opts.name, `computed field "${key}" collides with a rider companion`);
1156
+ }
1157
+ }
1158
+ mergedComputed = { ...resolvedClassified.riderComputed, ...materializedComputed };
1159
+ }
1160
+ let deterministicFields;
1161
+ if (opts.deterministicFields && opts.deterministicFields.length > 0) {
1162
+ if (opts.acknowledgeDeterministicRisk !== true) {
1163
+ throw new Error(
1164
+ `Collection "${opts.name}": deterministicFields requires \`acknowledgeDeterministicRisk: true\`. Deterministic encryption leaks equality between records \u2014 two records with the same field value produce identical ciphertexts visible to anyone with store access. If that trade-off is acceptable for your threat model, set \`acknowledgeDeterministicRisk: true\` to enable.`
1165
+ );
1166
+ }
1167
+ deterministicFields = Object.freeze(new Set(opts.deterministicFields));
1168
+ } else {
1169
+ deterministicFields = null;
1170
+ }
1171
+ const guardIndexedFields = /* @__PURE__ */ new Set();
1172
+ for (const ix of opts.indexes ?? []) {
1173
+ if (typeof ix === "string") guardIndexedFields.add(ix);
1174
+ else if (Array.isArray(ix)) for (const f of ix) guardIndexedFields.add(f);
1175
+ else for (const f of ix.fields) guardIndexedFields.add(f);
1176
+ }
1177
+ const embeddingSources = opts.embeddings === void 0 ? [] : typeof opts.embeddings.source === "string" ? [opts.embeddings.source] : [...opts.embeddings.source];
1178
+ const classifiedGuardCtx = {
1179
+ perRecordKeys: opts.perRecordKeys === true,
1180
+ crdt: opts.crdt !== void 0,
1181
+ hasConflictPolicy: opts.conflictPolicy !== void 0,
1182
+ storeCiphertext: opts.encrypted,
1183
+ deterministicFields,
1184
+ indexedFields: guardIndexedFields,
1185
+ textIndexFields: new Set(opts.textIndexes ?? []),
1186
+ vectorSourceFields: new Set(embeddingSources),
1187
+ subjectKeyField: opts.subjectKeyField,
1188
+ bareSensitiveFields: new Set(opts.sensitive ?? []),
1189
+ acknowledgeEquatableRisk: opts.acknowledgeEquatableRisk === true
1190
+ };
1191
+ if (resolvedClassified !== void 0) {
1192
+ guardClassifiedCompat(opts.name, resolvedClassified.byField, classifiedGuardCtx);
1193
+ }
1194
+ const classifiedSensitive = resolvedClassified === void 0 ? [] : Object.entries(resolvedClassified.byField).filter(([, s]) => s.storage === "recoverable").map(([f]) => f);
1195
+ const sensitiveList = [...opts.sensitive ?? [], ...classifiedSensitive];
1196
+ const sensitiveFields = sensitiveList.length > 0 ? Object.freeze(new Set(sensitiveList)) : Object.freeze(/* @__PURE__ */ new Set());
1197
+ const vdigEntries = resolvedClassified === void 0 ? [] : Object.entries(resolvedClassified.byField).filter(([, s]) => s.storage === "digest-only").map(([f, s]) => [f, {
1198
+ normalize: s.verifyNormalize ?? "password",
1199
+ notLastN: s.notLastN ?? 0,
1200
+ equatable: s.equatable === true,
1201
+ ...s.rotateDays !== void 0 ? { rotateDays: s.rotateDays } : {}
1202
+ }]);
1203
+ const vdigFields = vdigEntries.length > 0 ? new Map(vdigEntries) : null;
1204
+ const perRecordCek = opts.perRecordKeys === true;
1205
+ const cekCache = perRecordCek ? new Lru({ maxRecords: 4096 }) : null;
1206
+ const viaEraseCfgOut = {};
1207
+ const via2 = ViaPipeline.build(compileVias(opts, classifiedGuardCtx, viaEraseCfgOut));
1208
+ const knownFields = collectKnownFieldNames({
1209
+ moneyFields: effectiveViaFields.moneyFields,
1210
+ i18nFields: effectiveViaFields.i18nFields,
1211
+ dictKeyFields: effectiveViaFields.dictKeyFields,
1212
+ classifiedFields: resolvedClassified?.byField,
1213
+ computed: allComputed,
1214
+ lookupFields: effectiveViaFields.lookupFields
1215
+ });
1216
+ const computedEdges = resolveComputedEdges(opts.name, allComputed, resolvedClassified !== void 0, knownFields);
1217
+ const viaDepsEdges = resolveViaDepsEdges(opts.name, via2?.bindings ?? [], knownFields);
1218
+ return {
1219
+ adapter: opts.adapter,
1220
+ vault: opts.vault,
1221
+ name: opts.name,
1222
+ keyring: opts.keyring,
1223
+ storeCiphertext: opts.encrypted,
1224
+ ramCiphertext: opts.ramCiphertext ?? false,
1225
+ emitter: opts.emitter,
1226
+ writeQueue: opts.writeQueue,
1227
+ schemaUpdateGate: opts.schemaUpdateGate,
1228
+ schemaFence: opts.schemaFence,
1229
+ writeHooks: opts.writeHooks,
1230
+ subsystemBus: opts.subsystemBus,
1231
+ activeTxId: opts.activeTxId,
1232
+ strategies: opts.strategies,
1233
+ objectStore: opts.objectStore,
1234
+ blobFields: opts.blobFields,
1235
+ reconcileOnOpen: opts.reconcileOnOpen ?? "off",
1236
+ getDEK: opts.getDEK,
1237
+ onDirty: opts.onDirty,
1238
+ tabCoordinated: opts.tabCoordinated,
1239
+ historyConfig: opts.historyConfig ?? { enabled: true },
1240
+ historyConfigExplicit: opts.historyConfigExplicit ?? false,
1241
+ schema: opts.schema,
1242
+ ledger: opts.ledger,
1243
+ refEnforcer: opts.refEnforcer,
1244
+ joinResolver: opts.joinResolver,
1245
+ i18nFields: effectiveViaFields.i18nFields,
1246
+ textIndexes: opts.textIndexes,
1247
+ embeddings: opts.embeddings,
1248
+ vectorSet: opts.embeddings ? new VectorSet() : void 0,
1249
+ dictKeyFields: effectiveViaFields.dictKeyFields,
1250
+ lookupFields: effectiveViaFields.lookupFields,
1251
+ // #650 Task 6 — the sync join-dressing hook (#626 retirement, spec §5);
1252
+ // `undefined` when this collection declares neither i18nText nor lookup
1253
+ // fields, matching today's `i18nFields`-absent JoinableSource shape.
1254
+ presentForJoin: buildPresentForJoin(effectiveViaFields.i18nFields, effectiveViaFields.lookupFields, opts.snapshotFor),
1255
+ fieldMeta: opts.fieldMeta,
1256
+ meta: opts.meta,
1257
+ _refs: opts.declaredRefs ?? {},
1258
+ via: via2,
1259
+ classifiedEraseCfg: viaEraseCfgOut.classified,
1260
+ moneyFields: effectiveViaFields.moneyFields,
1261
+ classified: resolvedClassified,
1262
+ classifiedGuardCtx,
1263
+ computed: mergedComputed,
1264
+ computedEdges,
1265
+ viaDepsEdges,
1266
+ // #638 Task 7 — every declared computed field name (both modes, both surfaces); the
1267
+ // reconcile path's cross-call depsless-computed leak-guard memory
1268
+ // (`via/graph-wiring.ts#registerCollectionGraphSources`) reads this instead of
1269
+ // `Object.keys(opts.computed ?? {})` alone, so a via(computed(...))-declared field
1270
+ // participates in that guard identically to a sugar-declared one.
1271
+ computedFieldNames: Object.keys(allComputed),
1272
+ dictLabelResolver: opts.dictLabelResolver,
1273
+ getDictionary: opts.getDictionary,
1274
+ i18nPutValidator: opts.i18nPutValidator,
1275
+ autoTranslateHook: opts.autoTranslateHook,
1276
+ defaultLocale: opts.defaultLocale,
1277
+ crdtMode: opts.crdt,
1278
+ syncAdapter: opts.syncAdapter,
1279
+ onAccess: opts.onAccess,
1280
+ derivationSource: opts.derivationSource,
1281
+ materializedViewSource: opts.materializedViewSource,
1282
+ graphDispatch: opts.graphDispatch,
1283
+ tiers: opts.tiers && opts.tiers.length > 0 ? new Set(opts.tiers) : null,
1284
+ tierMode: opts.tierMode ?? "invisibility",
1285
+ blobTierPolicy: opts.blobTierPolicy ?? "isolate",
1286
+ onCrossTierAccess: opts.onCrossTierAccess,
1287
+ addSubjectRef: opts.addSubjectRef,
1288
+ deterministicFields,
1289
+ sensitiveFields,
1290
+ vdigFields,
1291
+ perRecordCek,
1292
+ cekCache,
1293
+ provenance: opts.provenance === true
1294
+ };
1295
+ }
1296
+
1297
+ // src/kernel/via/graph.ts
1298
+ var DEFAULT_POSTURE = { encryptedAtRest: "envelope", queryable: "full", exportable: true, forgettable: false };
1299
+ var QUERYABLE_RANK = {
1300
+ none: 0,
1301
+ "det-exact": 1,
1302
+ ordered: 2,
1303
+ full: 3
1304
+ };
1305
+ function foldPosture(a, b) {
1306
+ return {
1307
+ encryptedAtRest: a.encryptedAtRest === "sealed" || b.encryptedAtRest === "sealed" ? "sealed" : "envelope",
1308
+ queryable: QUERYABLE_RANK[a.queryable] <= QUERYABLE_RANK[b.queryable] ? a.queryable : b.queryable,
1309
+ exportable: a.exportable && b.exportable,
1310
+ forgettable: a.forgettable || b.forgettable
1311
+ };
1312
+ }
1313
+ function foldWildcardSecurity(base, contributor) {
1314
+ return {
1315
+ encryptedAtRest: base.encryptedAtRest === "sealed" || contributor.encryptedAtRest === "sealed" ? "sealed" : "envelope",
1316
+ queryable: base.queryable,
1317
+ exportable: base.exportable && contributor.exportable,
1318
+ forgettable: base.forgettable || contributor.forgettable
1319
+ };
1320
+ }
1321
+ var FOLDED_KINDS = /* @__PURE__ */ new Set(["derivation", "rollup", "mv", "overlay"]);
1322
+ function isDefaultPosture(p) {
1323
+ return p.encryptedAtRest === DEFAULT_POSTURE.encryptedAtRest && p.queryable === DEFAULT_POSTURE.queryable && p.exportable === DEFAULT_POSTURE.exportable && p.forgettable === DEFAULT_POSTURE.forgettable;
1324
+ }
1325
+ var SEP = "\0";
1326
+ var EMPTY_SET = /* @__PURE__ */ new Set();
1327
+ function nodeId(ref) {
1328
+ return `${ref.collection}${SEP}${ref.field}`;
1329
+ }
1330
+ function displayNodeId(id) {
1331
+ const sep = id.indexOf(SEP);
1332
+ return `${id.slice(0, sep)}.${id.slice(sep + 1)}`;
1333
+ }
1334
+ var ViaGraph = class {
1335
+ /** Declared source-field postures (registerField), keyed by node id. */
1336
+ _posture = /* @__PURE__ */ new Map();
1337
+ /** Every derived target's registration, keyed by the target's node id. */
1338
+ _in = /* @__PURE__ */ new Map();
1339
+ /** source node id -> derived edges that depend on it (dispatch/erasure), each carrying
1340
+ * its own registration's `kind` (#678 — see {@link OutEdge}). */
1341
+ _out = /* @__PURE__ */ new Map();
1342
+ /** Memoized effective posture per derived target node id. */
1343
+ _effectiveCache = /* @__PURE__ */ new Map();
1344
+ /** Memoized whole-collection security-axes fold for `'*'` wildcard LEAF nodes (#642),
1345
+ * keyed by collection name — see {@link _wildcardContribution}. Cleared alongside
1346
+ * `_effectiveCache` on every `registerField`/`registerDerived` (a later-registered
1347
+ * field must re-fold on the next read — registration ordering is free). */
1348
+ _wildcardCache = /* @__PURE__ */ new Map();
1349
+ /** Collections with at least one classified field (#638 Task 2 fix wave 2,
1350
+ * Finding I1 — the reconcile path's combined-state leak guard memory). */
1351
+ _classifiedCollections = /* @__PURE__ */ new Set();
1352
+ /** Computed field names declared with no `deps` entry, per collection
1353
+ * (Finding I1 — such a field registers no edge when no classified field is
1354
+ * present yet, so a LATER, separate reconcile call attaching classifiedFields
1355
+ * still needs to see it regardless of declaration order). */
1356
+ _depslessComputed = /* @__PURE__ */ new Map();
1357
+ /** Declare a source field's posture (money/i18n/classified/plain). Plain fields
1358
+ * default to `DEFAULT_POSTURE`; a later declaration for the same node wins-first (idempotent). */
1359
+ registerField(collection, field, posture) {
1360
+ const id = nodeId({ collection, field });
1361
+ if (this._posture.has(id)) return;
1362
+ this._posture.set(id, posture);
1363
+ this._effectiveCache.clear();
1364
+ this._wildcardCache.clear();
1365
+ }
1366
+ /** A derived target depends on `sources` (may be cross-collection). `kind`/`grain`
1367
+ * drive dispatch + erasure semantics; sources drive taint. Re-registering the same
1368
+ * target replaces `_in` but does not prune stale `_out` edges — callers must
1369
+ * register each target at most once per graph lifetime. `onDelete`/`keyField` (#650 Task 5)
1370
+ * are meaningful only for `kind === 'ref'` edges — {@link referencingEdgesOf} reads them back. */
1371
+ registerDerived(target, sources, kind, grain, onDelete, keyField) {
1372
+ const id = nodeId(target);
1373
+ this._in.set(id, {
1374
+ target,
1375
+ sources,
1376
+ kind,
1377
+ grain,
1378
+ ...onDelete !== void 0 ? { onDelete } : {},
1379
+ ...keyField !== void 0 ? { keyField } : {}
1380
+ });
1381
+ for (const source of sources) {
1382
+ const sourceId = nodeId(source);
1383
+ const outEdge = { target, kind };
1384
+ const dependents = this._out.get(sourceId);
1385
+ if (dependents) dependents.push(outEdge);
1386
+ else this._out.set(sourceId, [outEdge]);
1387
+ }
1388
+ this._effectiveCache.clear();
1389
+ this._wildcardCache.clear();
1390
+ }
1391
+ /** Whether `target` already has a registered in-edge — lets a caller skip
1392
+ * re-registering the same target (#638 Task 2 fix wave 2, Finding I2i:
1393
+ * `registerDerived`'s at-most-once contract must hold across repeated
1394
+ * identical `vault.collection()` calls, not just within a single one). */
1395
+ hasDerived(target) {
1396
+ return this._in.has(nodeId(target));
1397
+ }
1398
+ /** Mark/query a collection as having declared at least one classified field. */
1399
+ markClassified(collection) {
1400
+ this._classifiedCollections.add(collection);
1401
+ }
1402
+ isClassified(collection) {
1403
+ return this._classifiedCollections.has(collection);
1404
+ }
1405
+ /** Mark/query a collection's depsless (no declared `deps`) computed
1406
+ * field names — see `_depslessComputed`'s doc comment above. */
1407
+ markDepslessComputed(collection, field) {
1408
+ let set = this._depslessComputed.get(collection);
1409
+ if (!set) {
1410
+ set = /* @__PURE__ */ new Set();
1411
+ this._depslessComputed.set(collection, set);
1412
+ }
1413
+ set.add(field);
1414
+ }
1415
+ depslessComputedFields(collection) {
1416
+ return this._depslessComputed.get(collection) ?? EMPTY_SET;
1417
+ }
1418
+ /** Every field name the graph already has memory of for `collection` — from an
1419
+ * EARLIER, separate `vault.collection()` call (registered postures, derived
1420
+ * targets, depsless-computed names) — regardless of which via feature declared
1421
+ * it. #645 — `via/graph-wiring.ts`'s reconcile-path `knownFields` universe
1422
+ * (`collectKnownFieldNames`) is scoped to THIS call's own options only, so a
1423
+ * computed field attached in a LATER call whose `deps` correctly names a field
1424
+ * declared in an EARLIER call was spuriously refused as "unknown"; this method
1425
+ * lets that call site union in the graph's cross-call memory. Excludes the `'*'`
1426
+ * wildcard target (an overlay/derivation whole-record fold node, never a real
1427
+ * record field — see {@link registerDerived}'s doc comment). */
1428
+ knownFieldNames(collection) {
1429
+ const out = /* @__PURE__ */ new Set();
1430
+ const prefix = `${collection}${SEP}`;
1431
+ for (const id of this._posture.keys()) {
1432
+ if (id.startsWith(prefix)) out.add(id.slice(prefix.length));
1433
+ }
1434
+ for (const edge of this._in.values()) {
1435
+ if (edge.target.collection === collection && edge.target.field !== "*") out.add(edge.target.field);
1436
+ }
1437
+ const depsless = this._depslessComputed.get(collection);
1438
+ if (depsless) for (const field of depsless) out.add(field);
1439
+ return out;
1440
+ }
1441
+ /** Reject cycles at declare time (vault open). Throws `DerivationCycleError` for a
1442
+ * derivation/rollup/computed cycle, `MaterializedViewCycleError` for an MV cycle —
1443
+ * same classes + message shape the registries throw today (behavior lock). */
1444
+ assertAcyclic() {
1445
+ const visited = /* @__PURE__ */ new Set();
1446
+ const stack = [];
1447
+ const notRefEdge = (entry) => entry.kind !== "ref";
1448
+ const neighboursOf = (id) => {
1449
+ const own = (this._out.get(id) ?? []).filter(notRefEdge).map((entry) => entry.target);
1450
+ const sep = id.indexOf(SEP);
1451
+ if (id.slice(sep + 1) === "*") return own;
1452
+ const wildcard = (this._out.get(`${id.slice(0, sep)}${SEP}*`) ?? []).filter(notRefEdge).map((entry) => entry.target);
1453
+ if (wildcard.length === 0) return own;
1454
+ return [...own, ...wildcard];
1455
+ };
1456
+ const visit = (id) => {
1457
+ const idx = stack.indexOf(id);
1458
+ if (idx !== -1) {
1459
+ const cycle = stack.slice(idx).concat(id);
1460
+ const isMv = cycle.some((cycleId) => this._in.get(cycleId)?.kind === "mv");
1461
+ const path = cycle.map(displayNodeId);
1462
+ if (isMv) throw new MaterializedViewCycleError(path);
1463
+ throw new DerivationCycleError(path);
1464
+ }
1465
+ if (visited.has(id)) return;
1466
+ stack.push(id);
1467
+ for (const dependent of neighboursOf(id)) visit(nodeId(dependent));
1468
+ stack.pop();
1469
+ visited.add(id);
1470
+ };
1471
+ for (const id of this._out.keys()) visit(id);
1472
+ }
1473
+ /** A leaf (non-derived) node's own posture contribution: its declared posture,
1474
+ * or `DEFAULT_POSTURE` if never declared via `registerField`. */
1475
+ _declaredPosture(id) {
1476
+ return this._posture.get(id) ?? DEFAULT_POSTURE;
1477
+ }
1478
+ /** A node's posture contribution when folded into a dependent: recurse if it is itself
1479
+ * derived; else its declared/default posture — UNLESS it is a `'*'` LEAF node consumed
1480
+ * by a folded formula kind (#642, `derivation|rollup|mv|overlay`), in which case it
1481
+ * contributes its collection's whole-record security fold ({@link _wildcardContribution}).
1482
+ * `kind` is the CONSUMING edge's kind, threaded from {@link _computeEffective}. `'ref'`
1483
+ * edges (and the provenance-only untyped call, `kind` left `undefined`) keep `'*'` =
1484
+ * identity — the phase-D lookup reliance (`via/lookup/registry.ts:392-397`) that a
1485
+ * referencing field must not seal just because its dimension collection has a classified
1486
+ * column. */
1487
+ _contribution(id, kind) {
1488
+ const edge = this._in.get(id);
1489
+ if (edge) return this._computeEffective(id, edge);
1490
+ if (kind !== void 0 && FOLDED_KINDS.has(kind) && id.endsWith(`${SEP}*`)) {
1491
+ return this._wildcardContribution(id.slice(0, -2));
1492
+ }
1493
+ return this._declaredPosture(id);
1494
+ }
1495
+ /** Lazy fold (#642) of a collection's REGISTERED field postures on the security axes only
1496
+ * ({@link foldWildcardSecurity} — sealed-wins encryptedAtRest, AND exportable, OR
1497
+ * forgettable; queryable stays at DEFAULT_POSTURE's 'full', never folded), seeded at
1498
+ * DEFAULT_POSTURE. This is the collection-level posture a `'*'` LEAF node contributes to a
1499
+ * folded-kind formula edge (derivation/rollup/mv/overlay) — see {@link _contribution}. A
1500
+ * plain (unregistered) field contributes nothing (the identity), so the fold is strictly
1501
+ * more conservative than deps-based taint and never hits the KNOWN-LIMIT wall (it names no
1502
+ * fields — seam map §1d). Memoized per collection in `_wildcardCache`. */
1503
+ _wildcardContribution(collection) {
1504
+ const cached = this._wildcardCache.get(collection);
1505
+ if (cached) return cached;
1506
+ let result = DEFAULT_POSTURE;
1507
+ const prefix = `${collection}${SEP}`;
1508
+ for (const [id, posture] of this._posture) {
1509
+ if (!id.startsWith(prefix) || id === `${prefix}*`) continue;
1510
+ result = foldWildcardSecurity(result, posture);
1511
+ }
1512
+ this._wildcardCache.set(collection, result);
1513
+ return result;
1514
+ }
1515
+ _computeEffective(id, edge) {
1516
+ const cached = this._effectiveCache.get(id);
1517
+ if (cached) return cached;
1518
+ let result = DEFAULT_POSTURE;
1519
+ for (const source of edge.sources) {
1520
+ result = foldPosture(result, this._contribution(nodeId(source), edge.kind));
1521
+ }
1522
+ if (edge.grain === "virtual" && result.queryable !== "none") {
1523
+ result = { ...result, queryable: "none" };
1524
+ }
1525
+ this._effectiveCache.set(id, result);
1526
+ return result;
1527
+ }
1528
+ /** Strictest source posture on every axis, per §2. `undefined` when `target` has no
1529
+ * in-edges (not a derived field). Transitive: folds through chained derivations. */
1530
+ effectivePosture(target) {
1531
+ const id = nodeId(target);
1532
+ const edge = this._in.get(id);
1533
+ if (!edge) return void 0;
1534
+ return this._computeEffective(id, edge);
1535
+ }
1536
+ /** Per-collection { field → effectivePosture } overlay the pipeline consumes (Task 3). */
1537
+ taintedPostures(collection) {
1538
+ const out = /* @__PURE__ */ new Map();
1539
+ for (const edge of this._in.values()) {
1540
+ if (edge.target.collection !== collection) continue;
1541
+ out.set(edge.target.field, this._computeEffective(nodeId(edge.target), edge));
1542
+ }
1543
+ return out;
1544
+ }
1545
+ /** Materialized (`grain !== 'virtual'`) derived fields on `collection` whose effective
1546
+ * encryptedAtRest resolves to 'sealed' — the taint-seal set (Task 3). #638 Task 7
1547
+ * makes the `grain !== 'virtual'` filter meaningful: a `computed(fn, { mode: 'virtual' })`
1548
+ * field is never stored (rides the `present` phase, seam map Part 4's money-Formatted/
1549
+ * i18n-Label precedent), so it is EXCLUDED here even when its effective `encryptedAtRest`
1550
+ * folds to `'sealed'` — there is no envelope slot to seal. It still surfaces in
1551
+ * {@link taintedPostures} (query refusal via `postureFor`'s `queryable` clamp above, and
1552
+ * export refusal via `exportable`) — only the AT-REST SEALING ACTION is skipped. */
1553
+ taintSealedFields(collection) {
1554
+ const out = /* @__PURE__ */ new Set();
1555
+ for (const edge of this._in.values()) {
1556
+ if (edge.target.collection !== collection || edge.grain === "virtual") continue;
1557
+ const posture = this._computeEffective(nodeId(edge.target), edge);
1558
+ if (posture.encryptedAtRest === "sealed") out.add(edge.target.field);
1559
+ }
1560
+ return out;
1561
+ }
1562
+ /** Fields on `collection` whose registered edge is `grain === 'virtual'` (#638 Task 7) —
1563
+ * `via/graph-wiring.ts#applyTaintOverlay` intersects this with `exportable === false`
1564
+ * postures to know which virtual fields need PRESENT-TIME (not just export-time)
1565
+ * redaction, since a virtual field's value is only ever materialized inside `present()`. */
1566
+ virtualFields(collection) {
1567
+ const out = /* @__PURE__ */ new Set();
1568
+ for (const edge of this._in.values()) {
1569
+ if (edge.target.collection === collection && edge.grain === "virtual") out.add(edge.target.field);
1570
+ }
1571
+ return out;
1572
+ }
1573
+ /** Per-collection { field → immediate source field names that forced its
1574
+ * effective posture away from `DEFAULT_POSTURE` } — `describe()`'s
1575
+ * provenance (Task 3). Only the DIRECT declared sources are named (not the
1576
+ * ultimate origin several hops up a transitive chain); a source absent
1577
+ * from the result contributed nothing restrictive. */
1578
+ taintProvenance(collection) {
1579
+ const out = /* @__PURE__ */ new Map();
1580
+ for (const edge of this._in.values()) {
1581
+ if (edge.target.collection !== collection) continue;
1582
+ const forcedBy = edge.sources.filter((source) => !isDefaultPosture(this._contribution(nodeId(source)))).map((source) => source.field);
1583
+ if (forcedBy.length > 0) out.set(edge.target.field, forcedBy);
1584
+ }
1585
+ return out;
1586
+ }
1587
+ _targetsDependingOn(collection) {
1588
+ const out = [];
1589
+ for (const edge of this._in.values()) {
1590
+ if (edge.sources.some((source) => source.collection === collection)) {
1591
+ out.push({ target: edge.target, kind: edge.kind, grain: edge.grain });
1592
+ }
1593
+ }
1594
+ return out;
1595
+ }
1596
+ /** Dispatch (Task 4): every derived target triggered by a write to `collection`. Excludes
1597
+ * `'ref'` edges (#650 Task 5 review, folded Minor) — a `'ref'` edge is consulted only by the
1598
+ * delete/forget-time restrict/cascade/nullify path ({@link referencingEdgesOf}), never by the
1599
+ * sync/cutover/restore dispatch wave (`runGraphDispatchWave`); counting it here defeated that
1600
+ * wave's zero-cost early-continue, costing every write to a referenced backing collection an
1601
+ * unconditional decrypt + two no-op dispatch passes. {@link derivedArtifactsOf} (erasure
1602
+ * fanout) still includes `'ref'` edges — the forget path genuinely needs them. */
1603
+ dependentsOf(collection) {
1604
+ return this._targetsDependingOn(collection).filter((edge) => edge.kind !== "ref");
1605
+ }
1606
+ /** Erasure (Task 6): derived artifacts of a forgotten record whose source is `collection`. */
1607
+ derivedArtifactsOf(collection) {
1608
+ return this._targetsDependingOn(collection);
1609
+ }
1610
+ /** Referencing edges pointing AT a backing dimension (delete/forget-time restrict/cascade/
1611
+ * nullify, #650 Task 5) — an O(1) reverse lookup via the existing `_out` map (keyed at the
1612
+ * dimension's wildcard `field:'*'` node, the same convention every whole-collection source
1613
+ * already uses), NEVER a scan across collections or records. `backing` is the collection name
1614
+ * a lookup field's edge was registered against (a reserved dimension's `_dict_<name>`/
1615
+ * `_lookup_<name>` collection name, or a matrix dimension's own collection name). */
1616
+ referencingEdgesOf(backing) {
1617
+ const targets = this._out.get(nodeId({ collection: backing, field: "*" }));
1618
+ if (!targets) return [];
1619
+ const out = [];
1620
+ for (const entry of targets) {
1621
+ if (entry.kind !== "ref") continue;
1622
+ const edge = this._in.get(nodeId(entry.target));
1623
+ if (edge?.onDelete !== void 0) {
1624
+ out.push({ referencing: entry.target, onDelete: edge.onDelete, keyField: edge.keyField ?? "id" });
1625
+ }
1626
+ }
1627
+ return out;
1628
+ }
1629
+ };
1630
+
1631
+ export {
1632
+ ViaPipeline,
1633
+ EXPORT_REDACTION_MARKER,
1634
+ exportRedact,
1635
+ schemaFieldKeys,
1636
+ deriveZodFields,
1637
+ resolveDescribeFieldIds,
1638
+ buildDescription,
1639
+ via,
1640
+ isViaFieldSpec,
1641
+ mergeViaFields,
1642
+ guardReconcileCollisions,
1643
+ computedEntryParts,
1644
+ matchTargetFieldNames,
1645
+ resolveVirtualMoneyFields,
1646
+ collectKnownFieldNames,
1647
+ resolveComputedEdges,
1648
+ resolveCollectionConfig,
1649
+ DEFAULT_POSTURE,
1650
+ ViaGraph
1651
+ };
1652
+ //# sourceMappingURL=chunk-2C3AQB46.js.map