@noy-db/hub 0.2.0-pre.8 → 0.3.0-pre.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (541) hide show
  1. package/README.md +129 -3
  2. package/dist/adapter/index.d.ts +5 -0
  3. package/dist/adapter/index.js +15 -0
  4. package/dist/aggregate/index.d.ts +6 -2
  5. package/dist/aggregate/index.js +24 -16
  6. package/dist/aggregate/index.js.map +1 -1
  7. package/dist/api-RW3KP7WU.js +14 -0
  8. package/dist/as/index.d.ts +7 -0
  9. package/dist/as/index.js +24 -0
  10. package/dist/at/index.d.ts +5 -0
  11. package/dist/at/index.js +1 -0
  12. package/dist/attestation/index.d.ts +15 -47
  13. package/dist/attestation/index.js +54 -10
  14. package/dist/attestation/index.js.map +1 -1
  15. package/dist/backup-XV3IOEGB.js +217 -0
  16. package/dist/backup-XV3IOEGB.js.map +1 -0
  17. package/dist/blobs/index.d.ts +6 -8
  18. package/dist/blobs/index.js +19 -12
  19. package/dist/blobs/index.js.map +1 -1
  20. package/dist/bundle/index.d.ts +16 -70
  21. package/dist/bundle/index.js +39 -476
  22. package/dist/bundle/index.js.map +1 -1
  23. package/dist/{ulid-BFJkYRRW.d.ts → bundle-CH-H06dp.d.ts} +31 -86
  24. package/dist/by/index.d.ts +1 -0
  25. package/dist/by/index.js +11 -0
  26. package/dist/cargo/index.d.ts +9 -0
  27. package/dist/cargo/index.js +89 -0
  28. package/dist/chunk-26LGBE4T.js +42 -0
  29. package/dist/chunk-26LGBE4T.js.map +1 -0
  30. package/dist/chunk-2P2HZEXU.js +233 -0
  31. package/dist/chunk-2P2HZEXU.js.map +1 -0
  32. package/dist/{chunk-K3DK3NU5.js → chunk-3YFXJ3ZP.js} +20 -5
  33. package/dist/chunk-3YFXJ3ZP.js.map +1 -0
  34. package/dist/chunk-4Q6HSHHL.js +90 -0
  35. package/dist/chunk-4Q6HSHHL.js.map +1 -0
  36. package/dist/chunk-5LUY7UTV.js +380 -0
  37. package/dist/chunk-5LUY7UTV.js.map +1 -0
  38. package/dist/chunk-5N6CZTCY.js +367 -0
  39. package/dist/chunk-5N6CZTCY.js.map +1 -0
  40. package/dist/chunk-5O3AOPDT.js +992 -0
  41. package/dist/chunk-5O3AOPDT.js.map +1 -0
  42. package/dist/chunk-5R3ERCDH.js +239 -0
  43. package/dist/chunk-5R3ERCDH.js.map +1 -0
  44. package/dist/{chunk-6774ZOQ7.js → chunk-5R5JW2JT.js} +7095 -4769
  45. package/dist/chunk-5R5JW2JT.js.map +1 -0
  46. package/dist/chunk-5TDJ56JE.js +32 -0
  47. package/dist/chunk-5TDJ56JE.js.map +1 -0
  48. package/dist/{chunk-T7JEBOGN.js → chunk-62QYRORB.js} +18 -11
  49. package/dist/chunk-62QYRORB.js.map +1 -0
  50. package/dist/{chunk-J66GRPNH.js → chunk-6S7T6WC4.js} +2 -2
  51. package/dist/chunk-6S7T6WC4.js.map +1 -0
  52. package/dist/chunk-76722EBH.js +451 -0
  53. package/dist/chunk-76722EBH.js.map +1 -0
  54. package/dist/{chunk-Z6FNBOTC.js → chunk-AIWULCUO.js} +13 -17
  55. package/dist/chunk-AIWULCUO.js.map +1 -0
  56. package/dist/{chunk-O3VZPBZG.js → chunk-AQTBSL7R.js} +47 -11
  57. package/dist/chunk-AQTBSL7R.js.map +1 -0
  58. package/dist/chunk-AURFOK3D.js +35 -0
  59. package/dist/chunk-AURFOK3D.js.map +1 -0
  60. package/dist/{chunk-53XBRIRT.js → chunk-AXRXJTE2.js} +9 -9
  61. package/dist/chunk-AXRXJTE2.js.map +1 -0
  62. package/dist/chunk-AZAOEIKW.js +155 -0
  63. package/dist/chunk-AZAOEIKW.js.map +1 -0
  64. package/dist/{chunk-HNRHLRDC.js → chunk-BG3SPSR4.js} +3 -3
  65. package/dist/chunk-BG3SPSR4.js.map +1 -0
  66. package/dist/chunk-BGIZAFY7.js +1 -0
  67. package/dist/chunk-CHFZDSE4.js +1 -0
  68. package/dist/{chunk-DJHHA6XH.js → chunk-CMGR4ZEW.js} +50 -20
  69. package/dist/chunk-CMGR4ZEW.js.map +1 -0
  70. package/dist/chunk-CWPPNPOH.js +23 -0
  71. package/dist/chunk-CWPPNPOH.js.map +1 -0
  72. package/dist/{chunk-QODLLGQ7.js → chunk-DFEMTNPJ.js} +371 -38
  73. package/dist/chunk-DFEMTNPJ.js.map +1 -0
  74. package/dist/{chunk-ZYWZWG6G.js → chunk-DGDI2D4M.js} +10 -10
  75. package/dist/chunk-DGDI2D4M.js.map +1 -0
  76. package/dist/{chunk-SYMWGEET.js → chunk-EIZUR2XW.js} +3 -3
  77. package/dist/chunk-EIZUR2XW.js.map +1 -0
  78. package/dist/{chunk-BVRYKATC.js → chunk-FISN7WE4.js} +36 -33
  79. package/dist/chunk-FISN7WE4.js.map +1 -0
  80. package/dist/chunk-GHVIKOHT.js +1 -0
  81. package/dist/chunk-GYGWYIOZ.js +200 -0
  82. package/dist/chunk-GYGWYIOZ.js.map +1 -0
  83. package/dist/chunk-HCIPRAGS.js +45 -0
  84. package/dist/chunk-HCIPRAGS.js.map +1 -0
  85. package/dist/{chunk-PX35GA7L.js → chunk-I2NOIW44.js} +10 -10
  86. package/dist/chunk-I2NOIW44.js.map +1 -0
  87. package/dist/{chunk-OIF6LZUR.js → chunk-I3TIKTJO.js} +3 -3
  88. package/dist/chunk-I3TIKTJO.js.map +1 -0
  89. package/dist/chunk-I7FD46FF.js +9 -0
  90. package/dist/chunk-I7FD46FF.js.map +1 -0
  91. package/dist/chunk-IAGBDSCS.js +40 -0
  92. package/dist/chunk-IAGBDSCS.js.map +1 -0
  93. package/dist/{chunk-JWRVQKRZ.js → chunk-IELYAOGG.js} +6 -18
  94. package/dist/chunk-IELYAOGG.js.map +1 -0
  95. package/dist/chunk-IGUYVGGI.js +205 -0
  96. package/dist/chunk-IGUYVGGI.js.map +1 -0
  97. package/dist/{chunk-U26HQ6KJ.js → chunk-IO6GRPT6.js} +4 -4
  98. package/dist/chunk-IO6GRPT6.js.map +1 -0
  99. package/dist/chunk-IPB7FTQX.js +273 -0
  100. package/dist/chunk-IPB7FTQX.js.map +1 -0
  101. package/dist/chunk-ITNUCOXM.js +148 -0
  102. package/dist/chunk-ITNUCOXM.js.map +1 -0
  103. package/dist/{chunk-WPLVTJ5D.js → chunk-IUEN57TV.js} +10 -10
  104. package/dist/chunk-IUEN57TV.js.map +1 -0
  105. package/dist/{chunk-DL3HWOQ5.js → chunk-JNUWZ6D3.js} +9 -9
  106. package/dist/chunk-JNUWZ6D3.js.map +1 -0
  107. package/dist/chunk-K2WCO3NX.js +1 -0
  108. package/dist/chunk-KVOXU4T5.js +30 -0
  109. package/dist/chunk-KVOXU4T5.js.map +1 -0
  110. package/dist/chunk-KXGNJJXB.js +135 -0
  111. package/dist/chunk-KXGNJJXB.js.map +1 -0
  112. package/dist/chunk-LB7FD65R.js +163 -0
  113. package/dist/chunk-LB7FD65R.js.map +1 -0
  114. package/dist/{chunk-22DWZL57.js → chunk-LFLXAY2W.js} +43 -218
  115. package/dist/chunk-LFLXAY2W.js.map +1 -0
  116. package/dist/chunk-LMTH2RM6.js +129 -0
  117. package/dist/chunk-LMTH2RM6.js.map +1 -0
  118. package/dist/{aggregate/index.cjs → chunk-LV7M27WM.js} +390 -219
  119. package/dist/chunk-LV7M27WM.js.map +1 -0
  120. package/dist/{chunk-PE2FR4J3.js → chunk-LXQT4WMP.js} +16 -18
  121. package/dist/chunk-LXQT4WMP.js.map +1 -0
  122. package/dist/chunk-M2YKN37S.js +524 -0
  123. package/dist/chunk-M2YKN37S.js.map +1 -0
  124. package/dist/chunk-M6OST55S.js +14 -0
  125. package/dist/chunk-M6OST55S.js.map +1 -0
  126. package/dist/{chunk-F3GDRNUT.js → chunk-MD3Y6J3L.js} +35 -69
  127. package/dist/chunk-MD3Y6J3L.js.map +1 -0
  128. package/dist/{chunk-XJFLDA7A.js → chunk-MTMJVJ5W.js} +8 -7
  129. package/dist/chunk-MTMJVJ5W.js.map +1 -0
  130. package/dist/{chunk-DFMLEQZB.js → chunk-NF5JWERG.js} +5 -10
  131. package/dist/chunk-NF5JWERG.js.map +1 -0
  132. package/dist/{chunk-DO7C2TOG.js → chunk-PKHL44ER.js} +3 -3
  133. package/dist/{chunk-DO7C2TOG.js.map → chunk-PKHL44ER.js.map} +1 -1
  134. package/dist/chunk-PSMV73A5.js +117 -0
  135. package/dist/chunk-PSMV73A5.js.map +1 -0
  136. package/dist/chunk-PY4KJPYU.js +9 -0
  137. package/dist/chunk-PY4KJPYU.js.map +1 -0
  138. package/dist/chunk-PZ5AY32C.js +10 -0
  139. package/dist/{chunk-DE6GKS6G.js → chunk-Q7SS3IME.js} +50 -9
  140. package/dist/chunk-Q7SS3IME.js.map +1 -0
  141. package/dist/chunk-QHJW5EXU.js +54 -0
  142. package/dist/chunk-QHJW5EXU.js.map +1 -0
  143. package/dist/{chunk-NONAAENK.js → chunk-RUEKROOS.js} +11 -4
  144. package/dist/chunk-RUEKROOS.js.map +1 -0
  145. package/dist/chunk-RUIMKQTA.js +23 -0
  146. package/dist/chunk-RUIMKQTA.js.map +1 -0
  147. package/dist/{chunk-TFBP23BX.js → chunk-SKF73JOP.js} +66 -7
  148. package/dist/chunk-SKF73JOP.js.map +1 -0
  149. package/dist/chunk-SM3AVUHC.js +42 -0
  150. package/dist/chunk-SM3AVUHC.js.map +1 -0
  151. package/dist/{chunk-ML236QKC.js → chunk-SMXWYP24.js} +5 -5
  152. package/dist/chunk-SMXWYP24.js.map +1 -0
  153. package/dist/chunk-SRB2XEWB.js +148 -0
  154. package/dist/chunk-SRB2XEWB.js.map +1 -0
  155. package/dist/chunk-SVLR4POP.js +64 -0
  156. package/dist/chunk-SVLR4POP.js.map +1 -0
  157. package/dist/chunk-TA66UMI4.js +123 -0
  158. package/dist/chunk-TA66UMI4.js.map +1 -0
  159. package/dist/chunk-TEILUWOI.js +664 -0
  160. package/dist/chunk-TEILUWOI.js.map +1 -0
  161. package/dist/chunk-TJYQIGAP.js +82 -0
  162. package/dist/chunk-TJYQIGAP.js.map +1 -0
  163. package/dist/{chunk-H2X3ISXG.js → chunk-UAG5KWVA.js} +7 -7
  164. package/dist/chunk-UAG5KWVA.js.map +1 -0
  165. package/dist/chunk-UDRIWL7A.js +382 -0
  166. package/dist/chunk-UDRIWL7A.js.map +1 -0
  167. package/dist/{chunk-2GLDA55J.js → chunk-UIU2THRG.js} +498 -133
  168. package/dist/chunk-UIU2THRG.js.map +1 -0
  169. package/dist/{chunk-3YPCK6JX.js → chunk-UPJNJGGA.js} +165 -423
  170. package/dist/chunk-UPJNJGGA.js.map +1 -0
  171. package/dist/chunk-UV5MFVO3.js +21 -0
  172. package/dist/chunk-UV5MFVO3.js.map +1 -0
  173. package/dist/{chunk-2WUSG3IT.js → chunk-V7RWQRG7.js} +5 -5
  174. package/dist/chunk-V7RWQRG7.js.map +1 -0
  175. package/dist/{chunk-VTKGMEPP.js → chunk-VCTFO5CO.js} +13 -3
  176. package/dist/chunk-VCTFO5CO.js.map +1 -0
  177. package/dist/{chunk-5T22KDPN.js → chunk-VFQGRQIH.js} +8 -8
  178. package/dist/chunk-VFQGRQIH.js.map +1 -0
  179. package/dist/{chunk-2QR2PQTT.js → chunk-VQNJ7UZL.js} +5 -3
  180. package/dist/chunk-VQNJ7UZL.js.map +1 -0
  181. package/dist/{chunk-DONMZAD2.js → chunk-WWGT2MDV.js} +43 -165
  182. package/dist/chunk-WWGT2MDV.js.map +1 -0
  183. package/dist/{chunk-EMIGCR7X.js → chunk-WXSYDNBT.js} +2 -2
  184. package/dist/chunk-WXSYDNBT.js.map +1 -0
  185. package/dist/chunk-WYSO2NIH.js +30 -0
  186. package/dist/chunk-WYSO2NIH.js.map +1 -0
  187. package/dist/chunk-XXYIOFUB.js +164 -0
  188. package/dist/chunk-XXYIOFUB.js.map +1 -0
  189. package/dist/{chunk-3BFJOWSU.js → chunk-Y22T3KQE.js} +35 -7
  190. package/dist/chunk-Y22T3KQE.js.map +1 -0
  191. package/dist/{chunk-A3JMGXPG.js → chunk-YMUGBZN2.js} +2 -2
  192. package/dist/chunk-YMUGBZN2.js.map +1 -0
  193. package/dist/{chunk-I5FOWO4J.js → chunk-ZCGAHGUS.js} +52 -73
  194. package/dist/chunk-ZCGAHGUS.js.map +1 -0
  195. package/dist/{chunk-FZU343FL.js → chunk-ZJADGNYF.js} +2 -2
  196. package/dist/chunk-ZJADGNYF.js.map +1 -0
  197. package/dist/{chunk-B6PB7JLN.js → chunk-ZYUC53LT.js} +427 -6
  198. package/dist/chunk-ZYUC53LT.js.map +1 -0
  199. package/dist/collection-facade-GQAOGJP2.js +33 -0
  200. package/dist/consent/index.d.ts +5 -7
  201. package/dist/consent/index.js +7 -5
  202. package/dist/consent/index.js.map +1 -1
  203. package/dist/crdt/index.d.ts +6 -2
  204. package/dist/crdt/index.js +3 -2
  205. package/dist/crdt/index.js.map +1 -1
  206. package/dist/decrypt-partition-IHtxEnTi.d.ts +21 -0
  207. package/dist/delegation-UL5HKLER.js +19 -0
  208. package/dist/derivations/index.d.ts +7 -9
  209. package/dist/derivations/index.js +11 -6
  210. package/dist/describe/index.d.ts +1 -0
  211. package/dist/describe/index.js +1 -0
  212. package/dist/describe-aBkJR2sd.d.ts +131 -0
  213. package/dist/{dev-unlock-p3ysikWP.d.ts → dev-unlock-C9Ro3v_O.d.ts} +1 -1
  214. package/dist/discriminant-BN9REW3o.d.ts +60 -0
  215. package/dist/enclave-UL5LW66V.js +88 -0
  216. package/dist/executor-2FWQRLMG.js +15 -0
  217. package/dist/executor-QZ7BXICW.js +9 -0
  218. package/dist/executor-Z5ZLJVTV.js +9 -0
  219. package/dist/export-accessible-KRV5W4GH.js +17 -0
  220. package/dist/extract-partition-GLKBOXFQ.js +30 -0
  221. package/dist/{fanout-sidecar-OKPMMPLG.js → fanout-sidecar-GF3DJ6KR.js} +34 -14
  222. package/dist/fanout-sidecar-GF3DJ6KR.js.map +1 -0
  223. package/dist/forget/index.d.ts +36 -0
  224. package/dist/forget/index.js +19 -0
  225. package/dist/forget/index.js.map +1 -0
  226. package/dist/guards/index.d.ts +13 -9
  227. package/dist/guards/index.js +12 -5
  228. package/dist/{hash-BPsYPcv_.d.cts → hash-Cp5uwiox.d.ts} +5 -1
  229. package/dist/history/index.d.ts +6 -8
  230. package/dist/history/index.js +19 -12
  231. package/dist/history/index.js.map +1 -1
  232. package/dist/i18n/index.d.ts +5 -7
  233. package/dist/i18n/index.js +104 -15
  234. package/dist/i18n/index.js.map +1 -1
  235. package/dist/in/index.d.ts +5 -0
  236. package/dist/in/index.js +1 -0
  237. package/dist/in/index.js.map +1 -0
  238. package/dist/index-B9QdHytu.d.ts +123 -0
  239. package/dist/index-BF9_96A5.d.ts +123 -0
  240. package/dist/{types-DGU60JDt.d.ts → index-BzUo1B6n.d.ts} +16306 -8352
  241. package/dist/index.d.ts +1088 -450
  242. package/dist/index.js +1165 -293
  243. package/dist/index.js.map +1 -1
  244. package/dist/indexing/index.d.ts +6 -3
  245. package/dist/indexing/index.js +6 -5
  246. package/dist/indexing/index.js.map +1 -1
  247. package/dist/issue-Y6UVIR43.js +13 -0
  248. package/dist/issue-Y6UVIR43.js.map +1 -0
  249. package/dist/kernel/index.d.ts +32 -0
  250. package/dist/kernel/index.js +53 -0
  251. package/dist/kernel/index.js.map +1 -0
  252. package/dist/{ledger-TMRZYNVJ.js → ledger-RYI35CDS.js} +12 -9
  253. package/dist/ledger-RYI35CDS.js.map +1 -0
  254. package/dist/liberate-CRPZEV7O.js +18 -0
  255. package/dist/liberate-CRPZEV7O.js.map +1 -0
  256. package/dist/materialized-views/index.d.ts +6 -19
  257. package/dist/materialized-views/index.js +16 -12
  258. package/dist/mime-magic-CGhw37_E.d.ts +103 -0
  259. package/dist/noydb-367AM4HT.js +50 -0
  260. package/dist/noydb-367AM4HT.js.map +1 -0
  261. package/dist/on/index.d.ts +5 -0
  262. package/dist/on/index.js +11 -0
  263. package/dist/on/index.js.map +1 -0
  264. package/dist/overlay-views/index.d.ts +27 -11
  265. package/dist/overlay-views/index.js +7 -6
  266. package/dist/periods/index.d.ts +5 -7
  267. package/dist/periods/index.js +13 -9
  268. package/dist/pod/index.d.ts +63 -0
  269. package/dist/pod/index.js +61 -0
  270. package/dist/pod/index.js.map +1 -0
  271. package/dist/policy-IXK4FVXP.js +41 -0
  272. package/dist/policy-IXK4FVXP.js.map +1 -0
  273. package/dist/portability/index.d.ts +20 -0
  274. package/dist/portability/index.js +43 -0
  275. package/dist/portability/index.js.map +1 -0
  276. package/dist/{public-envelope-BW6OXORV.js → public-envelope-JHDQCPSX.js} +6 -5
  277. package/dist/public-envelope-JHDQCPSX.js.map +1 -0
  278. package/dist/query/index.d.ts +5 -3
  279. package/dist/query/index.js +21 -13
  280. package/dist/read-only-facade-5ADRJVTM.js +8 -0
  281. package/dist/read-only-facade-5ADRJVTM.js.map +1 -0
  282. package/dist/registry-45RJNWGU.js +9 -0
  283. package/dist/registry-45RJNWGU.js.map +1 -0
  284. package/dist/registry-5GRV5VXI.js +13 -0
  285. package/dist/registry-5GRV5VXI.js.map +1 -0
  286. package/dist/registry-VW6P6A3J.js +8 -0
  287. package/dist/registry-VW6P6A3J.js.map +1 -0
  288. package/dist/registry-WEUCHBO4.js +11 -0
  289. package/dist/registry-WEUCHBO4.js.map +1 -0
  290. package/dist/request-withdrawal-GBPH2FDY.js +25 -0
  291. package/dist/request-withdrawal-GBPH2FDY.js.map +1 -0
  292. package/dist/revoke-TUFRGI6S.js +18 -0
  293. package/dist/revoke-TUFRGI6S.js.map +1 -0
  294. package/dist/sealed-record/index.d.ts +69 -0
  295. package/dist/sealed-record/index.js +65 -0
  296. package/dist/sealed-record/index.js.map +1 -0
  297. package/dist/session/index.d.ts +6 -8
  298. package/dist/session/index.js +7 -5
  299. package/dist/session/index.js.map +1 -1
  300. package/dist/shadow/index.d.ts +5 -7
  301. package/dist/shadow/index.js +4 -3
  302. package/dist/shadow/index.js.map +1 -1
  303. package/dist/{signer-72QAUSVW.js → signer-PNKTBVF7.js} +6 -5
  304. package/dist/signer-PNKTBVF7.js.map +1 -0
  305. package/dist/snapshots/index.d.ts +16 -11
  306. package/dist/snapshots/index.js +49 -13
  307. package/dist/snapshots/index.js.map +1 -1
  308. package/dist/{stale-6ZDBTQT7.js → stale-3JWHNDIY.js} +3 -2
  309. package/dist/stale-3JWHNDIY.js.map +1 -0
  310. package/dist/store-coordination-provider-3I7XWZZK.js +142 -0
  311. package/dist/store-coordination-provider-3I7XWZZK.js.map +1 -0
  312. package/dist/subject-index-O75wKshW.d.ts +362 -0
  313. package/dist/sync/index.d.ts +4 -6
  314. package/dist/sync/index.js +7 -6
  315. package/dist/sync/index.js.map +1 -1
  316. package/dist/team/index.d.ts +5 -7
  317. package/dist/team/index.js +20 -16
  318. package/dist/tiers/index.d.ts +5 -0
  319. package/dist/tiers/index.js +33 -0
  320. package/dist/tiers/index.js.map +1 -0
  321. package/dist/to/index.d.ts +5 -0
  322. package/dist/to/index.js +17 -0
  323. package/dist/to/index.js.map +1 -0
  324. package/dist/transition-guard-C7ol6oPw.d.ts +165 -0
  325. package/dist/tx/index.d.ts +23 -9
  326. package/dist/tx/index.js +13 -8
  327. package/dist/tx/index.js.map +1 -1
  328. package/dist/ui/index.d.ts +1 -0
  329. package/dist/ui/index.js +1 -0
  330. package/dist/ui/index.js.map +1 -0
  331. package/dist/ulid-DRH25k3y.d.ts +66 -0
  332. package/dist/ulid-PTAIMDG4.js +10 -0
  333. package/dist/ulid-PTAIMDG4.js.map +1 -0
  334. package/dist/util/index.d.ts +2 -0
  335. package/dist/util/index.js +7 -2
  336. package/dist/util/index.js.map +1 -1
  337. package/dist/vault-diff-B5fYNBL7.d.ts +147 -0
  338. package/dist/with/index.d.ts +38 -0
  339. package/dist/with/index.js +25 -0
  340. package/dist/with/index.js.map +1 -0
  341. package/dist/{with-materialized-view-BiasFcYx.d.ts → with-materialized-view-6p0Fk8bL.d.ts} +1 -1
  342. package/dist/{with-overlayed-view-CQViuko_.d.ts → with-overlayed-view-BJ6mXGMd.d.ts} +2 -3
  343. package/dist/with-rollup-BvQo3ROo.d.ts +47 -0
  344. package/dist/withdraw-accessible-FFS46EOD.js +22 -0
  345. package/dist/withdraw-accessible-FFS46EOD.js.map +1 -0
  346. package/dist/zod-HAJM7LMS.js +14763 -0
  347. package/dist/zod-HAJM7LMS.js.map +1 -0
  348. package/package.json +121 -201
  349. package/dist/aggregate/index.cjs.map +0 -1
  350. package/dist/aggregate/index.d.cts +0 -38
  351. package/dist/attestation/index.cjs +0 -305
  352. package/dist/attestation/index.cjs.map +0 -1
  353. package/dist/attestation/index.d.cts +0 -52
  354. package/dist/blobs/index.cjs +0 -1480
  355. package/dist/blobs/index.cjs.map +0 -1
  356. package/dist/blobs/index.d.cts +0 -46
  357. package/dist/bundle/index.cjs +0 -19104
  358. package/dist/bundle/index.cjs.map +0 -1
  359. package/dist/bundle/index.d.cts +0 -176
  360. package/dist/chunk-22DWZL57.js.map +0 -1
  361. package/dist/chunk-2GLDA55J.js.map +0 -1
  362. package/dist/chunk-2QR2PQTT.js.map +0 -1
  363. package/dist/chunk-2WUSG3IT.js.map +0 -1
  364. package/dist/chunk-3BFJOWSU.js.map +0 -1
  365. package/dist/chunk-3YPCK6JX.js.map +0 -1
  366. package/dist/chunk-53XBRIRT.js.map +0 -1
  367. package/dist/chunk-5T22KDPN.js.map +0 -1
  368. package/dist/chunk-5XHKQ56N.js +0 -340
  369. package/dist/chunk-5XHKQ56N.js.map +0 -1
  370. package/dist/chunk-6774ZOQ7.js.map +0 -1
  371. package/dist/chunk-6STK5TQP.js +0 -139
  372. package/dist/chunk-6STK5TQP.js.map +0 -1
  373. package/dist/chunk-A3JMGXPG.js.map +0 -1
  374. package/dist/chunk-B6PB7JLN.js.map +0 -1
  375. package/dist/chunk-BVRYKATC.js.map +0 -1
  376. package/dist/chunk-DE6GKS6G.js.map +0 -1
  377. package/dist/chunk-DFMLEQZB.js.map +0 -1
  378. package/dist/chunk-DJHHA6XH.js.map +0 -1
  379. package/dist/chunk-DL3HWOQ5.js.map +0 -1
  380. package/dist/chunk-DONMZAD2.js.map +0 -1
  381. package/dist/chunk-EMIGCR7X.js.map +0 -1
  382. package/dist/chunk-F3GDRNUT.js.map +0 -1
  383. package/dist/chunk-FZU343FL.js.map +0 -1
  384. package/dist/chunk-H2X3ISXG.js.map +0 -1
  385. package/dist/chunk-HNRHLRDC.js.map +0 -1
  386. package/dist/chunk-I5FOWO4J.js.map +0 -1
  387. package/dist/chunk-J66GRPNH.js.map +0 -1
  388. package/dist/chunk-JWRVQKRZ.js.map +0 -1
  389. package/dist/chunk-K3DK3NU5.js.map +0 -1
  390. package/dist/chunk-ML236QKC.js.map +0 -1
  391. package/dist/chunk-NONAAENK.js.map +0 -1
  392. package/dist/chunk-O3VZPBZG.js.map +0 -1
  393. package/dist/chunk-OIF6LZUR.js.map +0 -1
  394. package/dist/chunk-OQ6PIGHA.js +0 -19
  395. package/dist/chunk-OQ6PIGHA.js.map +0 -1
  396. package/dist/chunk-PE2FR4J3.js.map +0 -1
  397. package/dist/chunk-PP6W64Y3.js +0 -275
  398. package/dist/chunk-PP6W64Y3.js.map +0 -1
  399. package/dist/chunk-PX35GA7L.js.map +0 -1
  400. package/dist/chunk-QEILDE6R.js +0 -793
  401. package/dist/chunk-QEILDE6R.js.map +0 -1
  402. package/dist/chunk-QODLLGQ7.js.map +0 -1
  403. package/dist/chunk-RAZ4OVLL.js +0 -51
  404. package/dist/chunk-RAZ4OVLL.js.map +0 -1
  405. package/dist/chunk-SYMWGEET.js.map +0 -1
  406. package/dist/chunk-T7JEBOGN.js.map +0 -1
  407. package/dist/chunk-TFBP23BX.js.map +0 -1
  408. package/dist/chunk-TV3YZ35S.js +0 -90
  409. package/dist/chunk-TV3YZ35S.js.map +0 -1
  410. package/dist/chunk-U26HQ6KJ.js.map +0 -1
  411. package/dist/chunk-UF3BUNQZ.js +0 -1
  412. package/dist/chunk-UMLVJTYV.js +0 -20
  413. package/dist/chunk-UMLVJTYV.js.map +0 -1
  414. package/dist/chunk-VTKGMEPP.js.map +0 -1
  415. package/dist/chunk-W6EQLGMB.js +0 -100
  416. package/dist/chunk-W6EQLGMB.js.map +0 -1
  417. package/dist/chunk-WIRRPTFH.js +0 -17
  418. package/dist/chunk-WIRRPTFH.js.map +0 -1
  419. package/dist/chunk-WPLVTJ5D.js.map +0 -1
  420. package/dist/chunk-XJFLDA7A.js.map +0 -1
  421. package/dist/chunk-Z6FNBOTC.js.map +0 -1
  422. package/dist/chunk-ZYWZWG6G.js.map +0 -1
  423. package/dist/consent/index.cjs +0 -204
  424. package/dist/consent/index.cjs.map +0 -1
  425. package/dist/consent/index.d.cts +0 -25
  426. package/dist/crdt/index.cjs +0 -152
  427. package/dist/crdt/index.cjs.map +0 -1
  428. package/dist/crdt/index.d.cts +0 -30
  429. package/dist/crypto-HTZ4FJOP.js +0 -44
  430. package/dist/delegation-RI54P6I5.js +0 -17
  431. package/dist/derivations/index.cjs +0 -351
  432. package/dist/derivations/index.cjs.map +0 -1
  433. package/dist/derivations/index.d.cts +0 -72
  434. package/dist/dev-unlock-M4VAWNq_.d.cts +0 -263
  435. package/dist/executor-5PNY7LGW.js +0 -8
  436. package/dist/executor-B4QIYGZX.js +0 -8
  437. package/dist/executor-BWXXDQ7K.js +0 -11
  438. package/dist/fanout-sidecar-OKPMMPLG.js.map +0 -1
  439. package/dist/guards/index.cjs +0 -322
  440. package/dist/guards/index.cjs.map +0 -1
  441. package/dist/guards/index.d.cts +0 -31
  442. package/dist/hash-C1GtiOhR.d.ts +0 -63
  443. package/dist/history/index.cjs +0 -1222
  444. package/dist/history/index.cjs.map +0 -1
  445. package/dist/history/index.d.cts +0 -63
  446. package/dist/i18n/index.cjs +0 -1100
  447. package/dist/i18n/index.cjs.map +0 -1
  448. package/dist/i18n/index.d.cts +0 -39
  449. package/dist/index-4fBVt8j9.d.cts +0 -2387
  450. package/dist/index-D8I_pyJD.d.ts +0 -2387
  451. package/dist/index.cjs +0 -24334
  452. package/dist/index.cjs.map +0 -1
  453. package/dist/index.d.cts +0 -776
  454. package/dist/indexing/index.cjs +0 -742
  455. package/dist/indexing/index.cjs.map +0 -1
  456. package/dist/indexing/index.d.cts +0 -36
  457. package/dist/issue-VGDPP4B5.js +0 -12
  458. package/dist/lazy-builder-7tIpFyWN.d.ts +0 -304
  459. package/dist/lazy-builder-wY4pMCEe.d.cts +0 -304
  460. package/dist/materialized-views/index.cjs +0 -854
  461. package/dist/materialized-views/index.cjs.map +0 -1
  462. package/dist/materialized-views/index.d.cts +0 -186
  463. package/dist/mime-magic-CBBSOkjm.d.cts +0 -50
  464. package/dist/mime-magic-CBBSOkjm.d.ts +0 -50
  465. package/dist/noydb-LZBH3XDK.js +0 -34
  466. package/dist/overlay-views/index.cjs +0 -359
  467. package/dist/overlay-views/index.cjs.map +0 -1
  468. package/dist/overlay-views/index.d.cts +0 -82
  469. package/dist/periods/index.cjs +0 -1041
  470. package/dist/periods/index.cjs.map +0 -1
  471. package/dist/periods/index.d.cts +0 -22
  472. package/dist/predicate-BSAGEyu5.d.cts +0 -209
  473. package/dist/predicate-BSAGEyu5.d.ts +0 -209
  474. package/dist/query/index.cjs +0 -2375
  475. package/dist/query/index.cjs.map +0 -1
  476. package/dist/query/index.d.cts +0 -3
  477. package/dist/read-only-facade-ITU6L7BL.js +0 -7
  478. package/dist/registry-3QP3YKQS.js +0 -8
  479. package/dist/registry-DKEXOJVO.js +0 -7
  480. package/dist/registry-OJIOSBV6.js +0 -10
  481. package/dist/registry-USRVT6YF.js +0 -8
  482. package/dist/revoke-JCC7N56X.js +0 -17
  483. package/dist/session/index.cjs +0 -495
  484. package/dist/session/index.cjs.map +0 -1
  485. package/dist/session/index.d.cts +0 -46
  486. package/dist/shadow/index.cjs +0 -133
  487. package/dist/shadow/index.cjs.map +0 -1
  488. package/dist/shadow/index.d.cts +0 -17
  489. package/dist/snapshots/index.cjs +0 -903
  490. package/dist/snapshots/index.cjs.map +0 -1
  491. package/dist/snapshots/index.d.cts +0 -21
  492. package/dist/store/index.cjs +0 -1083
  493. package/dist/store/index.cjs.map +0 -1
  494. package/dist/store/index.d.cts +0 -492
  495. package/dist/store/index.d.ts +0 -492
  496. package/dist/store/index.js +0 -37
  497. package/dist/strategy-BSxFXGzb.d.cts +0 -110
  498. package/dist/strategy-BSxFXGzb.d.ts +0 -110
  499. package/dist/strategy-DSTrsZ8t.d.cts +0 -601
  500. package/dist/strategy-DSTrsZ8t.d.ts +0 -601
  501. package/dist/sync/index.cjs +0 -1062
  502. package/dist/sync/index.cjs.map +0 -1
  503. package/dist/sync/index.d.cts +0 -43
  504. package/dist/team/index.cjs +0 -2798
  505. package/dist/team/index.cjs.map +0 -1
  506. package/dist/team/index.d.cts +0 -118
  507. package/dist/tx/index.cjs +0 -544
  508. package/dist/tx/index.cjs.map +0 -1
  509. package/dist/tx/index.d.cts +0 -21
  510. package/dist/types-DjunxzJa.d.cts +0 -12776
  511. package/dist/ulid-COREQ2RQ.js +0 -9
  512. package/dist/ulid-DPeuPgi3.d.cts +0 -603
  513. package/dist/util/index.cjs +0 -230
  514. package/dist/util/index.cjs.map +0 -1
  515. package/dist/util/index.d.cts +0 -77
  516. package/dist/with-derivation-Df0kMlED.d.cts +0 -13
  517. package/dist/with-derivation-DfOpKjFw.d.ts +0 -13
  518. package/dist/with-guard-0KksDtSR.d.ts +0 -18
  519. package/dist/with-guard-C6W5RVrH.d.cts +0 -18
  520. package/dist/with-materialized-view-BmDKyHrm.d.cts +0 -27
  521. package/dist/with-overlayed-view-CA66vhHz.d.cts +0 -13
  522. /package/dist/{store → adapter}/index.js.map +0 -0
  523. /package/dist/{chunk-UF3BUNQZ.js.map → api-RW3KP7WU.js.map} +0 -0
  524. /package/dist/{crypto-HTZ4FJOP.js.map → as/index.js.map} +0 -0
  525. /package/dist/{delegation-RI54P6I5.js.map → at/index.js.map} +0 -0
  526. /package/dist/{executor-5PNY7LGW.js.map → by/index.js.map} +0 -0
  527. /package/dist/{executor-B4QIYGZX.js.map → cargo/index.js.map} +0 -0
  528. /package/dist/{executor-BWXXDQ7K.js.map → chunk-BGIZAFY7.js.map} +0 -0
  529. /package/dist/{issue-VGDPP4B5.js.map → chunk-CHFZDSE4.js.map} +0 -0
  530. /package/dist/{ledger-TMRZYNVJ.js.map → chunk-GHVIKOHT.js.map} +0 -0
  531. /package/dist/{noydb-LZBH3XDK.js.map → chunk-K2WCO3NX.js.map} +0 -0
  532. /package/dist/{public-envelope-BW6OXORV.js.map → chunk-PZ5AY32C.js.map} +0 -0
  533. /package/dist/{read-only-facade-ITU6L7BL.js.map → collection-facade-GQAOGJP2.js.map} +0 -0
  534. /package/dist/{registry-3QP3YKQS.js.map → delegation-UL5HKLER.js.map} +0 -0
  535. /package/dist/{registry-DKEXOJVO.js.map → describe/index.js.map} +0 -0
  536. /package/dist/{registry-OJIOSBV6.js.map → enclave-UL5LW66V.js.map} +0 -0
  537. /package/dist/{registry-USRVT6YF.js.map → executor-2FWQRLMG.js.map} +0 -0
  538. /package/dist/{revoke-JCC7N56X.js.map → executor-QZ7BXICW.js.map} +0 -0
  539. /package/dist/{signer-72QAUSVW.js.map → executor-Z5ZLJVTV.js.map} +0 -0
  540. /package/dist/{stale-6ZDBTQT7.js.map → export-accessible-KRV5W4GH.js.map} +0 -0
  541. /package/dist/{ulid-COREQ2RQ.js.map → extract-partition-GLKBOXFQ.js.map} +0 -0
@@ -1,31 +1,52 @@
1
+ import {
2
+ sha256Hex
3
+ } from "./chunk-5O3AOPDT.js";
1
4
  import {
2
5
  DerivationCycleError
3
- } from "./chunk-B6PB7JLN.js";
6
+ } from "./chunk-ZYUC53LT.js";
4
7
 
5
- // src/derivations/strategy-hash.ts
6
- async function computeStrategyHash(source, outputKeys, derive) {
8
+ // src/with-formula/derivations/strategy-hash.ts
9
+ async function computeStrategyHash(source, outputKeys, derive, sources) {
7
10
  const canonical = JSON.stringify({
8
11
  source,
9
12
  outputs: [...outputKeys].sort(),
10
- derive: derive.toString()
13
+ derive: derive.toString(),
14
+ // Declared sibling sources — adding/removing a trigger
15
+ // collection invalidates cached derived records. Omitted when empty
16
+ // so strategies without siblings keep their existing hash.
17
+ ...sources?.length ? { sources: [...sources].sort() } : {}
11
18
  });
12
19
  const bytes = new TextEncoder().encode(canonical);
13
- const digest = await crypto.subtle.digest("SHA-256", bytes);
14
- return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
20
+ return sha256Hex(bytes);
15
21
  }
16
22
 
17
- // src/derivations/registry.ts
23
+ // src/with-formula/derivations/registry.ts
18
24
  var DerivationRegistry = class {
19
25
  _bySource = /* @__PURE__ */ new Map();
20
26
  _byOutput = /* @__PURE__ */ new Map();
21
27
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
28
  async register(spec) {
23
29
  const outputKeys = Object.keys(spec.outputs);
24
- const strategyHash = await computeStrategyHash(spec.source, outputKeys, spec.derive);
30
+ const strategyHash = await computeStrategyHash(spec.source, outputKeys, spec.derive, spec.sources);
25
31
  const reg = { spec, strategyHash };
26
32
  const fromSource = this._bySource.get(spec.source);
27
33
  if (fromSource) fromSource.push(reg);
28
34
  else this._bySource.set(spec.source, [reg]);
35
+ for (const extra of spec.sources ?? []) {
36
+ const fromExtra = this._bySource.get(extra);
37
+ if (fromExtra) fromExtra.push(reg);
38
+ else this._bySource.set(extra, [reg]);
39
+ }
40
+ for (const t of spec.triggerBy ?? []) {
41
+ const fromTrigger = this._bySource.get(t.collection);
42
+ if (fromTrigger) fromTrigger.push(reg);
43
+ else this._bySource.set(t.collection, [reg]);
44
+ }
45
+ if (spec.rollup) {
46
+ const fromRollup = this._bySource.get(spec.rollup.from);
47
+ if (fromRollup) fromRollup.push(reg);
48
+ else this._bySource.set(spec.rollup.from, [reg]);
49
+ }
29
50
  for (const key of outputKeys) {
30
51
  const output = spec.outputs[key];
31
52
  if (!output) continue;
@@ -41,6 +62,23 @@ var DerivationRegistry = class {
41
62
  strategiesProducingOutput(collection) {
42
63
  return this._byOutput.get(collection) ?? [];
43
64
  }
65
+ /**
66
+ * All registered strategies as a flat, deduplicated array.
67
+ * Each strategy is indexed once per source (not once per output key),
68
+ * so iterating `_bySource.values()` naturally yields each strategy
69
+ * exactly once per source — deduplication is handled by flattening
70
+ * the per-source arrays and collecting into a Set by identity.
71
+ *
72
+ * Used by `dumpSchema()` / `describeDerivations()` in the introspection
73
+ * walker to populate the derivations map.
74
+ */
75
+ all() {
76
+ const seen = /* @__PURE__ */ new Set();
77
+ for (const strategies of this._bySource.values()) {
78
+ for (const s of strategies) seen.add(s);
79
+ }
80
+ return [...seen];
81
+ }
44
82
  /**
45
83
  * Cycle detection over the source → output → … graph. Call after all
46
84
  * `register()` calls complete (i.e. at vault open). Throws
@@ -62,6 +100,9 @@ var DerivationRegistry = class {
62
100
  for (const key of Object.keys(s.spec.outputs)) {
63
101
  const output = s.spec.outputs[key];
64
102
  if (!output) continue;
103
+ if (output.shape === "record" && output.collection === s.spec.source && output.denorm !== void 0) {
104
+ continue;
105
+ }
65
106
  visit(output.collection);
66
107
  }
67
108
  }
@@ -76,4 +117,4 @@ var DerivationRegistry = class {
76
117
  export {
77
118
  DerivationRegistry
78
119
  };
79
- //# sourceMappingURL=chunk-DE6GKS6G.js.map
120
+ //# sourceMappingURL=chunk-Q7SS3IME.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-formula/derivations/strategy-hash.ts","../src/with-formula/derivations/registry.ts"],"sourcesContent":["/**\n * Deterministic hash of a derivation strategy's \"shape\": source\n * collection, declared sibling sources, output keys, derive function\n * source. Used to detect\n * strategy drift: a record whose `_derivedFrom.strategyHash` doesn't\n * match the current strategy is considered stale.\n *\n * Web Crypto SHA-256 — no extra deps.\n */\nimport { sha256Hex } from '../../kernel/enclave/index.js'\n\nexport async function computeStrategyHash(\n source: string,\n outputKeys: readonly string[],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n derive: (...args: any[]) => any,\n sources?: ReadonlyArray<string>,\n): Promise<string> {\n const canonical = JSON.stringify({\n source,\n outputs: [...outputKeys].sort(),\n derive: derive.toString(),\n // Declared sibling sources — adding/removing a trigger\n // collection invalidates cached derived records. Omitted when empty\n // so strategies without siblings keep their existing hash.\n ...(sources?.length ? { sources: [...sources].sort() } : {}),\n })\n const bytes = new TextEncoder().encode(canonical)\n return sha256Hex(bytes)\n}\n","import { DerivationCycleError } from '../../kernel/errors.js'\nimport { computeStrategyHash } from './strategy-hash.js'\nimport type { DerivationStrategy } from './types.js'\n\ninterface RegisteredStrategy {\n // Type-erased to allow the registry to hold heterogeneous strategies.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n spec: DerivationStrategy<any, any>\n strategyHash: string\n}\n\n/**\n * Vault-internal registry of derivation strategies. Owned by `Vault`;\n * not exported.\n *\n * @internal\n */\nexport class DerivationRegistry {\n private readonly _bySource = new Map<string, RegisteredStrategy[]>()\n private readonly _byOutput = new Map<string, RegisteredStrategy[]>()\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async register(spec: DerivationStrategy<any, any>): Promise<void> {\n const outputKeys = Object.keys(spec.outputs)\n const strategyHash = await computeStrategyHash(spec.source, outputKeys, spec.derive, spec.sources)\n const reg: RegisteredStrategy = { spec, strategyHash }\n\n const fromSource = this._bySource.get(spec.source)\n if (fromSource) fromSource.push(reg)\n else this._bySource.set(spec.source, [reg])\n\n // Declared sibling sources index the SAME `reg` under each\n // extra collection so `strategiesForSource(extra)` returns it and a\n // sibling write re-fires the derivation. Sibling keys also enter\n // `_bySource`, so `validate()`'s cycle DFS walks them automatically.\n for (const extra of spec.sources ?? []) {\n const fromExtra = this._bySource.get(extra)\n if (fromExtra) fromExtra.push(reg)\n else this._bySource.set(extra, [reg])\n }\n\n // FK triggers index the SAME `reg` under each parent collection so\n // a parent write re-fires the derivation (fanned out to matching source\n // records in `dispatchDerivations`). Like sources[], these keys enter\n // `_bySource` so the cycle DFS walks the trigger→output edge.\n for (const t of spec.triggerBy ?? []) {\n const fromTrigger = this._bySource.get(t.collection)\n if (fromTrigger) fromTrigger.push(reg)\n else this._bySource.set(t.collection, [reg])\n }\n\n // Rollup: a write to the child `from` collection recomputes\n // the parent (= spec.source = into) at id child[key]. Index under `from`\n // so a child write fires it; spec.source (into) is already indexed above,\n // so a parent write also recomputes its own aggregate (covers the\n // parent-created-after-children case). The from→into edge enters the cycle\n // DFS automatically.\n if (spec.rollup) {\n const fromRollup = this._bySource.get(spec.rollup.from)\n if (fromRollup) fromRollup.push(reg)\n else this._bySource.set(spec.rollup.from, [reg])\n }\n\n for (const key of outputKeys) {\n const output = spec.outputs[key]\n if (!output) continue\n const outputCollection = output.collection\n const arr = this._byOutput.get(outputCollection)\n if (arr) arr.push(reg)\n else this._byOutput.set(outputCollection, [reg])\n }\n }\n\n strategiesForSource(source: string): ReadonlyArray<RegisteredStrategy> {\n return this._bySource.get(source) ?? []\n }\n\n strategiesProducingOutput(collection: string): ReadonlyArray<RegisteredStrategy> {\n return this._byOutput.get(collection) ?? []\n }\n\n /**\n * All registered strategies as a flat, deduplicated array.\n * Each strategy is indexed once per source (not once per output key),\n * so iterating `_bySource.values()` naturally yields each strategy\n * exactly once per source — deduplication is handled by flattening\n * the per-source arrays and collecting into a Set by identity.\n *\n * Used by `dumpSchema()` / `describeDerivations()` in the introspection\n * walker to populate the derivations map.\n */\n all(): ReadonlyArray<RegisteredStrategy> {\n const seen = new Set<RegisteredStrategy>()\n for (const strategies of this._bySource.values()) {\n for (const s of strategies) seen.add(s)\n }\n return [...seen]\n }\n\n /**\n * Cycle detection over the source → output → … graph. Call after all\n * `register()` calls complete (i.e. at vault open). Throws\n * `DerivationCycleError` on the first cycle found.\n */\n validate(): void {\n const visited = new Set<string>()\n const stack: string[] = []\n\n const visit = (node: string): void => {\n if (stack.includes(node)) {\n const cycle = stack.slice(stack.indexOf(node)).concat(node)\n throw new DerivationCycleError(cycle)\n }\n if (visited.has(node)) return\n stack.push(node)\n const strategies = this._bySource.get(node)\n if (strategies) {\n for (const s of strategies) {\n for (const key of Object.keys(s.spec.outputs)) {\n const output = s.spec.outputs[key]\n if (!output) continue\n // Self-write reverse-denorm: an output back to its own\n // source is intentional, not an infinite cycle — the value-equality\n // guard in dispatch terminates it. Skip this edge so it isn't\n // flagged. (Self-write outputs are required to declare `denorm`.)\n if (\n output.shape === 'record' &&\n output.collection === s.spec.source &&\n output.denorm !== undefined\n ) {\n continue\n }\n visit(output.collection)\n }\n }\n }\n stack.pop()\n visited.add(node)\n }\n\n for (const src of this._bySource.keys()) visit(src)\n }\n}\n"],"mappings":";;;;;;;;AAWA,eAAsB,oBACpB,QACA,YAEA,QACA,SACiB;AACjB,QAAM,YAAY,KAAK,UAAU;AAAA,IAC/B;AAAA,IACA,SAAS,CAAC,GAAG,UAAU,EAAE,KAAK;AAAA,IAC9B,QAAQ,OAAO,SAAS;AAAA;AAAA;AAAA;AAAA,IAIxB,GAAI,SAAS,SAAS,EAAE,SAAS,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC;AAAA,EAC5D,CAAC;AACD,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,SAAS;AAChD,SAAO,UAAU,KAAK;AACxB;;;ACZO,IAAM,qBAAN,MAAyB;AAAA,EACb,YAAY,oBAAI,IAAkC;AAAA,EAClD,YAAY,oBAAI,IAAkC;AAAA;AAAA,EAGnE,MAAM,SAAS,MAAmD;AAChE,UAAM,aAAa,OAAO,KAAK,KAAK,OAAO;AAC3C,UAAM,eAAe,MAAM,oBAAoB,KAAK,QAAQ,YAAY,KAAK,QAAQ,KAAK,OAAO;AACjG,UAAM,MAA0B,EAAE,MAAM,aAAa;AAErD,UAAM,aAAa,KAAK,UAAU,IAAI,KAAK,MAAM;AACjD,QAAI,WAAY,YAAW,KAAK,GAAG;AAAA,QAC9B,MAAK,UAAU,IAAI,KAAK,QAAQ,CAAC,GAAG,CAAC;AAM1C,eAAW,SAAS,KAAK,WAAW,CAAC,GAAG;AACtC,YAAM,YAAY,KAAK,UAAU,IAAI,KAAK;AAC1C,UAAI,UAAW,WAAU,KAAK,GAAG;AAAA,UAC5B,MAAK,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC;AAAA,IACtC;AAMA,eAAW,KAAK,KAAK,aAAa,CAAC,GAAG;AACpC,YAAM,cAAc,KAAK,UAAU,IAAI,EAAE,UAAU;AACnD,UAAI,YAAa,aAAY,KAAK,GAAG;AAAA,UAChC,MAAK,UAAU,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC;AAAA,IAC7C;AAQA,QAAI,KAAK,QAAQ;AACf,YAAM,aAAa,KAAK,UAAU,IAAI,KAAK,OAAO,IAAI;AACtD,UAAI,WAAY,YAAW,KAAK,GAAG;AAAA,UAC9B,MAAK,UAAU,IAAI,KAAK,OAAO,MAAM,CAAC,GAAG,CAAC;AAAA,IACjD;AAEA,eAAW,OAAO,YAAY;AAC5B,YAAM,SAAS,KAAK,QAAQ,GAAG;AAC/B,UAAI,CAAC,OAAQ;AACb,YAAM,mBAAmB,OAAO;AAChC,YAAM,MAAM,KAAK,UAAU,IAAI,gBAAgB;AAC/C,UAAI,IAAK,KAAI,KAAK,GAAG;AAAA,UAChB,MAAK,UAAU,IAAI,kBAAkB,CAAC,GAAG,CAAC;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,oBAAoB,QAAmD;AACrE,WAAO,KAAK,UAAU,IAAI,MAAM,KAAK,CAAC;AAAA,EACxC;AAAA,EAEA,0BAA0B,YAAuD;AAC/E,WAAO,KAAK,UAAU,IAAI,UAAU,KAAK,CAAC;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAyC;AACvC,UAAM,OAAO,oBAAI,IAAwB;AACzC,eAAW,cAAc,KAAK,UAAU,OAAO,GAAG;AAChD,iBAAW,KAAK,WAAY,MAAK,IAAI,CAAC;AAAA,IACxC;AACA,WAAO,CAAC,GAAG,IAAI;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAiB;AACf,UAAM,UAAU,oBAAI,IAAY;AAChC,UAAM,QAAkB,CAAC;AAEzB,UAAM,QAAQ,CAAC,SAAuB;AACpC,UAAI,MAAM,SAAS,IAAI,GAAG;AACxB,cAAM,QAAQ,MAAM,MAAM,MAAM,QAAQ,IAAI,CAAC,EAAE,OAAO,IAAI;AAC1D,cAAM,IAAI,qBAAqB,KAAK;AAAA,MACtC;AACA,UAAI,QAAQ,IAAI,IAAI,EAAG;AACvB,YAAM,KAAK,IAAI;AACf,YAAM,aAAa,KAAK,UAAU,IAAI,IAAI;AAC1C,UAAI,YAAY;AACd,mBAAW,KAAK,YAAY;AAC1B,qBAAW,OAAO,OAAO,KAAK,EAAE,KAAK,OAAO,GAAG;AAC7C,kBAAM,SAAS,EAAE,KAAK,QAAQ,GAAG;AACjC,gBAAI,CAAC,OAAQ;AAKb,gBACE,OAAO,UAAU,YACjB,OAAO,eAAe,EAAE,KAAK,UAC7B,OAAO,WAAW,QAClB;AACA;AAAA,YACF;AACA,kBAAM,OAAO,UAAU;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AACA,YAAM,IAAI;AACV,cAAQ,IAAI,IAAI;AAAA,IAClB;AAEA,eAAW,OAAO,KAAK,UAAU,KAAK,EAAG,OAAM,GAAG;AAAA,EACpD;AACF;","names":[]}
@@ -0,0 +1,54 @@
1
+ import {
2
+ QuiesceTimeoutError
3
+ } from "./chunk-ZYUC53LT.js";
4
+
5
+ // src/port/by/types.ts
6
+ function isQuorum(writers, generation, excludeWriterId) {
7
+ return writers.filter((w) => w.writerId !== excludeWriterId).every((w) => w.quiescedAtVersion === generation);
8
+ }
9
+ async function runDrainBarrier(provider, o, run) {
10
+ await provider.setFence(o.vault, { currentSchemaVersion: o.generation, fenceState: "draining" });
11
+ await o.onFlush();
12
+ const deadline = o.now() + o.quiesceTimeoutMs;
13
+ const seeded = await provider.reachableWriters(o.vault, { staleMs: o.staleMs, now: o.now() });
14
+ if (!isQuorum(seeded, o.generation, o.writerId)) {
15
+ await new Promise((resolve, reject) => {
16
+ let settled = false;
17
+ const finish = (fn) => {
18
+ if (!settled) {
19
+ settled = true;
20
+ unsub();
21
+ fn();
22
+ }
23
+ };
24
+ const unsub = provider.observePresence(o.vault, (writers) => {
25
+ if (isQuorum(writers, o.generation, o.writerId)) finish(resolve);
26
+ });
27
+ const tick = async () => {
28
+ if (settled) return;
29
+ if (o.now() >= deadline) {
30
+ finish(
31
+ () => reject(
32
+ new QuiesceTimeoutError(
33
+ `Cutover of vault "${o.vault}" to generation ${o.generation} timed out after ${o.quiesceTimeoutMs}ms waiting for active writers to quiesce.`
34
+ )
35
+ )
36
+ );
37
+ return;
38
+ }
39
+ if (o.onPoll) await o.onPoll();
40
+ const w = await provider.reachableWriters(o.vault, { staleMs: o.staleMs, now: o.now() });
41
+ if (isQuorum(w, o.generation, o.writerId)) finish(resolve);
42
+ else setTimeout(() => void tick(), 25);
43
+ };
44
+ void tick();
45
+ });
46
+ }
47
+ await run();
48
+ }
49
+
50
+ export {
51
+ isQuorum,
52
+ runDrainBarrier
53
+ };
54
+ //# sourceMappingURL=chunk-QHJW5EXU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/port/by/types.ts"],"sourcesContent":["/**\n * Kernel coordination port — the injected `CoordinationProvider` seam for the\n * schema-fence drain-barrier.\n *\n * The kernel defines this port; `@noy-db/by-tabs` / `@noy-db/by-peer` implement\n * it for real-time quorum, and an external orchestrator (`@klum-db/lobby`)\n * drives it through the `Noydb` handle without ever naming a `by-*` package.\n * The dependency arrow is `by-* → kernel ← klum`, the app at the apex.\n *\n * This module carries only the port TYPES plus two pure-ish helpers:\n * {@link isQuorum} (a pure quorum predicate extracted from the legacy\n * `activeQuiesced`) and {@link runDrainBarrier} (the reusable barrier protocol\n * the migration cutover and klum both call).\n *\n * @module\n */\n\nimport { QuiesceTimeoutError } from '../../kernel/errors.js'\nimport type { Unsubscribe } from '../with/write-hooks.js'\n\n/** Vault fence state (the existing FenceDoc shape). */\nexport interface FenceState {\n readonly currentSchemaVersion: number\n readonly fenceState: 'normal' | 'draining' | 'migrating' | 'complete'\n}\n\n/** A writer's presence + ack, tagged with the session that owns it. */\nexport interface WriterPresence {\n /** = today's clientId (one per tab/peer). */\n readonly writerId: string\n /** Groups one user's writers across vaults (consolidation is klum's job). */\n readonly sessionId: string\n readonly lastSeen: number\n readonly quiescedAtVersion: number | null\n}\n\n/** Session-addressable drain-barrier coordination transport. Per-vault ops. */\nexport interface CoordinationProvider {\n /** orchestrator → all writers */\n setFence(vault: string, fence: FenceState): Promise<void>\n /**\n * Fresh one-shot fence read for the write-path gate (`assertWritable`).\n * A direct read (not a cached `observeFence` snapshot) avoids a staleness\n * window and keeps the timing-sensitive cutover gate exact. The store\n * default reads `_meta/schema-fence`; `by-*` return their last-pushed fence.\n */\n readFence(vault: string): Promise<FenceState>\n /** writer observes fence changes (default: poll-emit; by-*: push) */\n observeFence(vault: string, onChange: (f: FenceState) => void): Unsubscribe\n /** writer → orchestrator: presence + ack (heartbeat + quiescedAtVersion) */\n reportPresence(vault: string, p: WriterPresence): Promise<void>\n /** orchestrator observes presence changes (default: poll-emit; by-*: push) */\n observePresence(vault: string, onChange: (writers: readonly WriterPresence[]) => void): Unsubscribe\n /** orchestrator one-shot snapshot of reachable writers (quorum input) */\n reachableWriters(vault: string, o: { staleMs: number; now: number }): Promise<readonly WriterPresence[]>\n}\n\n/**\n * Pure quorum predicate: true when every writer (other than `excludeWriterId`)\n * has acked at exactly `generation`. An empty set is trivially a quorum.\n *\n * Extracted from the legacy `activeQuiesced` store-polling check so the\n * migration cutover, the store default provider, and `by-*` real-time\n * providers all share one definition of \"everyone has drained\".\n */\nexport function isQuorum(\n writers: readonly WriterPresence[],\n generation: number,\n excludeWriterId?: string,\n): boolean {\n return writers.filter((w) => w.writerId !== excludeWriterId).every((w) => w.quiescedAtVersion === generation)\n}\n\n/** Inputs for {@link runDrainBarrier}. */\nexport interface DrainBarrierOptions {\n readonly vault: string\n readonly generation: number\n readonly writerId: string\n readonly onFlush: () => Promise<void>\n readonly staleMs: number\n readonly quiesceTimeoutMs: number\n readonly now: () => number\n /** Optional seam (mainly for deterministic tests) run before each poll tick. */\n readonly onPoll?: () => Promise<void>\n}\n\n/**\n * The reusable drain-barrier protocol shared by the migration cutover and klum:\n *\n * drain self → setFence(draining) → await quorum (presence push + isQuorum,\n * polling as a fallback, or timeout) → run() → release-by-caller.\n *\n * Resolves once every reachable writer (excluding `writerId`) has quiesced at\n * `generation`, at which point `run` is invoked exactly once. Rejects with\n * {@link QuiesceTimeoutError} if `quiesceTimeoutMs` elapses first.\n */\nexport async function runDrainBarrier(\n provider: CoordinationProvider,\n o: DrainBarrierOptions,\n run: () => Promise<void>,\n): Promise<void> {\n await provider.setFence(o.vault, { currentSchemaVersion: o.generation, fenceState: 'draining' })\n await o.onFlush()\n\n const deadline = o.now() + o.quiesceTimeoutMs\n const seeded = await provider.reachableWriters(o.vault, { staleMs: o.staleMs, now: o.now() })\n if (!isQuorum(seeded, o.generation, o.writerId)) {\n await new Promise<void>((resolve, reject) => {\n let settled = false\n const finish = (fn: () => void) => {\n if (!settled) {\n settled = true\n unsub()\n fn()\n }\n }\n const unsub = provider.observePresence(o.vault, (writers) => {\n if (isQuorum(writers, o.generation, o.writerId)) finish(resolve)\n })\n const tick = async () => {\n if (settled) return\n if (o.now() >= deadline) {\n finish(() =>\n reject(\n new QuiesceTimeoutError(\n `Cutover of vault \"${o.vault}\" to generation ${o.generation} timed out ` +\n `after ${o.quiesceTimeoutMs}ms waiting for active writers to quiesce.`,\n ),\n ),\n )\n return\n }\n if (o.onPoll) await o.onPoll()\n const w = await provider.reachableWriters(o.vault, { staleMs: o.staleMs, now: o.now() })\n if (isQuorum(w, o.generation, o.writerId)) finish(resolve)\n else setTimeout(() => void tick(), 25)\n }\n void tick()\n })\n }\n await run()\n}\n"],"mappings":";;;;;AAiEO,SAAS,SACd,SACA,YACA,iBACS;AACT,SAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,aAAa,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,UAAU;AAC9G;AAyBA,eAAsB,gBACpB,UACA,GACA,KACe;AACf,QAAM,SAAS,SAAS,EAAE,OAAO,EAAE,sBAAsB,EAAE,YAAY,YAAY,WAAW,CAAC;AAC/F,QAAM,EAAE,QAAQ;AAEhB,QAAM,WAAW,EAAE,IAAI,IAAI,EAAE;AAC7B,QAAM,SAAS,MAAM,SAAS,iBAAiB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,KAAK,EAAE,IAAI,EAAE,CAAC;AAC5F,MAAI,CAAC,SAAS,QAAQ,EAAE,YAAY,EAAE,QAAQ,GAAG;AAC/C,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,UAAI,UAAU;AACd,YAAM,SAAS,CAAC,OAAmB;AACjC,YAAI,CAAC,SAAS;AACZ,oBAAU;AACV,gBAAM;AACN,aAAG;AAAA,QACL;AAAA,MACF;AACA,YAAM,QAAQ,SAAS,gBAAgB,EAAE,OAAO,CAAC,YAAY;AAC3D,YAAI,SAAS,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAG,QAAO,OAAO;AAAA,MACjE,CAAC;AACD,YAAM,OAAO,YAAY;AACvB,YAAI,QAAS;AACb,YAAI,EAAE,IAAI,KAAK,UAAU;AACvB;AAAA,YAAO,MACL;AAAA,cACE,IAAI;AAAA,gBACF,qBAAqB,EAAE,KAAK,mBAAmB,EAAE,UAAU,oBAChD,EAAE,gBAAgB;AAAA,cAC/B;AAAA,YACF;AAAA,UACF;AACA;AAAA,QACF;AACA,YAAI,EAAE,OAAQ,OAAM,EAAE,OAAO;AAC7B,cAAM,IAAI,MAAM,SAAS,iBAAiB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,KAAK,EAAE,IAAI,EAAE,CAAC;AACvF,YAAI,SAAS,GAAG,EAAE,YAAY,EAAE,QAAQ,EAAG,QAAO,OAAO;AAAA,YACpD,YAAW,MAAM,KAAK,KAAK,GAAG,EAAE;AAAA,MACvC;AACA,WAAK,KAAK;AAAA,IACZ,CAAC;AAAA,EACH;AACA,QAAM,IAAI;AACZ;","names":[]}
@@ -1,22 +1,29 @@
1
1
  import {
2
2
  FieldFrozenError,
3
3
  InvariantError
4
- } from "./chunk-B6PB7JLN.js";
4
+ } from "./chunk-ZYUC53LT.js";
5
5
 
6
- // src/guards/executor.ts
6
+ // src/with-audit/guards/executor.ts
7
7
  var GuardExecutor = {
8
8
  /**
9
9
  * Compare existing vs incoming for each `frozenFields.fields` entry
10
10
  * when `frozenFields.when(existing)` is true. Throws
11
11
  * `FieldFrozenError` listing every changed frozen field.
12
+ *
13
+ * @param skipFields — field names that are schema-owned computed fields.
14
+ * These are excluded from the comparison because `incoming` carries the
15
+ * raw user input (computed fields not yet evaluated), so comparing
16
+ * `existing[field]` vs `incoming[field]` would always look like a
17
+ * change even when the computed result is unchanged.
12
18
  */
13
- async checkFrozenFields(guard, id, existing, incoming) {
19
+ async checkFrozenFields(guard, id, existing, incoming, skipFields) {
14
20
  const ff = guard.frozenFields;
15
21
  if (!ff) return;
16
22
  if (existing === null) return;
17
23
  if (!ff.when(existing)) return;
18
24
  const changed = [];
19
25
  for (const f of ff.fields) {
26
+ if (skipFields?.has(String(f))) continue;
20
27
  if (existing[f] !== incoming[f]) {
21
28
  if (!deepEqual(existing[f], incoming[f])) changed.push(String(f));
22
29
  }
@@ -70,4 +77,4 @@ function deepEqual(a, b) {
70
77
  export {
71
78
  GuardExecutor
72
79
  };
73
- //# sourceMappingURL=chunk-NONAAENK.js.map
80
+ //# sourceMappingURL=chunk-RUEKROOS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-audit/guards/executor.ts"],"sourcesContent":["import { FieldFrozenError, InvariantError } from '../../kernel/errors.js'\nimport type { GuardStrategy, GuardContext, GuardChange } from './types.js'\n\n/**\n * Pure functions that execute the work declared by a `GuardStrategy`.\n * Stateless — `GuardRegistry` decides when to call these.\n *\n * @internal\n */\nexport const GuardExecutor = {\n /**\n * Compare existing vs incoming for each `frozenFields.fields` entry\n * when `frozenFields.when(existing)` is true. Throws\n * `FieldFrozenError` listing every changed frozen field.\n *\n * @param skipFields — field names that are schema-owned computed fields.\n * These are excluded from the comparison because `incoming` carries the\n * raw user input (computed fields not yet evaluated), so comparing\n * `existing[field]` vs `incoming[field]` would always look like a\n * change even when the computed result is unchanged.\n */\n async checkFrozenFields<T extends Record<string, unknown>>(\n guard: GuardStrategy<T>,\n id: string,\n existing: T | null,\n incoming: T,\n skipFields?: ReadonlySet<string>,\n ): Promise<void> {\n const ff = guard.frozenFields\n if (!ff) return\n if (existing === null) return // insert — nothing to freeze\n if (!ff.when(existing)) return\n\n const changed: string[] = []\n for (const f of ff.fields) {\n // Skip computed fields — they are re-evaluated after this gate and\n // their raw-input value is not comparable to the prior computed value.\n if (skipFields?.has(String(f))) continue\n // Strict equality first, then deep-equality fallback for objects.\n if (existing[f] !== incoming[f]) {\n if (!deepEqual(existing[f], incoming[f])) changed.push(String(f))\n }\n }\n if (changed.length > 0) {\n throw new FieldFrozenError(guard.collection, id, changed)\n }\n },\n\n /**\n * Run a single guard's invariant over its slice of the change-set.\n * Any throw is converted to `InvariantError` unless it already is one.\n */\n async runInvariant<T extends Record<string, unknown>>(\n guard: GuardStrategy<T>,\n changes: ReadonlyArray<GuardChange<T>>,\n ctx: GuardContext<T>,\n ): Promise<void> {\n const amendment = guard.amendment\n if (!amendment) return\n try {\n await amendment.invariant(changes, ctx)\n } catch (err) {\n if (err instanceof InvariantError) throw err\n throw new InvariantError(\n err instanceof Error ? err.message : `invariant violated: ${String(err)}`,\n )\n }\n },\n}\n\n/**\n * Minimal deep-equality for guarded field diff. Handles arrays, plain\n * objects, primitives. Not for cyclic structures.\n *\n * @internal\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (a === null || b === null) return a === b\n if (typeof a !== typeof b) return false\n if (typeof a !== 'object') return a === b\n if (Array.isArray(a) !== Array.isArray(b)) return false\n if (Array.isArray(a)) {\n const aa = a as unknown[]\n const bb = b as unknown[]\n if (aa.length !== bb.length) return false\n for (let i = 0; i < aa.length; i++) if (!deepEqual(aa[i], bb[i])) return false\n return true\n }\n const ao = a as Record<string, unknown>\n const bo = b as Record<string, unknown>\n const ak = Object.keys(ao)\n const bk = Object.keys(bo)\n if (ak.length !== bk.length) return false\n for (const k of ak) {\n if (!Object.prototype.hasOwnProperty.call(bo, k)) return false\n if (!deepEqual(ao[k], bo[k])) return false\n }\n return true\n}\n"],"mappings":";;;;;;AASO,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAY3B,MAAM,kBACJ,OACA,IACA,UACA,UACA,YACe;AACf,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,GAAI;AACT,QAAI,aAAa,KAAM;AACvB,QAAI,CAAC,GAAG,KAAK,QAAQ,EAAG;AAExB,UAAM,UAAoB,CAAC;AAC3B,eAAW,KAAK,GAAG,QAAQ;AAGzB,UAAI,YAAY,IAAI,OAAO,CAAC,CAAC,EAAG;AAEhC,UAAI,SAAS,CAAC,MAAM,SAAS,CAAC,GAAG;AAC/B,YAAI,CAAC,UAAU,SAAS,CAAC,GAAG,SAAS,CAAC,CAAC,EAAG,SAAQ,KAAK,OAAO,CAAC,CAAC;AAAA,MAClE;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,IAAI,iBAAiB,MAAM,YAAY,IAAI,OAAO;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aACJ,OACA,SACA,KACe;AACf,UAAM,YAAY,MAAM;AACxB,QAAI,CAAC,UAAW;AAChB,QAAI;AACF,YAAM,UAAU,UAAU,SAAS,GAAG;AAAA,IACxC,SAAS,KAAK;AACZ,UAAI,eAAe,eAAgB,OAAM;AACzC,YAAM,IAAI;AAAA,QACR,eAAe,QAAQ,IAAI,UAAU,uBAAuB,OAAO,GAAG,CAAC;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AACF;AAQA,SAAS,UAAU,GAAY,GAAqB;AAClD,MAAI,MAAM,EAAG,QAAO;AACpB,MAAI,MAAM,QAAQ,MAAM,KAAM,QAAO,MAAM;AAC3C,MAAI,OAAO,MAAM,OAAO,EAAG,QAAO;AAClC,MAAI,OAAO,MAAM,SAAU,QAAO,MAAM;AACxC,MAAI,MAAM,QAAQ,CAAC,MAAM,MAAM,QAAQ,CAAC,EAAG,QAAO;AAClD,MAAI,MAAM,QAAQ,CAAC,GAAG;AACpB,UAAM,KAAK;AACX,UAAM,KAAK;AACX,QAAI,GAAG,WAAW,GAAG,OAAQ,QAAO;AACpC,aAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,IAAK,KAAI,CAAC,UAAU,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,EAAG,QAAO;AACzE,WAAO;AAAA,EACT;AACA,QAAM,KAAK;AACX,QAAM,KAAK;AACX,QAAM,KAAK,OAAO,KAAK,EAAE;AACzB,QAAM,KAAK,OAAO,KAAK,EAAE;AACzB,MAAI,GAAG,WAAW,GAAG,OAAQ,QAAO;AACpC,aAAW,KAAK,IAAI;AAClB,QAAI,CAAC,OAAO,UAAU,eAAe,KAAK,IAAI,CAAC,EAAG,QAAO;AACzD,QAAI,CAAC,UAAU,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,EAAG,QAAO;AAAA,EACvC;AACA,SAAO;AACT;","names":[]}
@@ -0,0 +1,23 @@
1
+ // src/with-audit/guards/read-only-facade.ts
2
+ var ReadOnlyVaultFacade = class {
3
+ _vault;
4
+ _layer;
5
+ constructor(vault, layer = "read") {
6
+ this._vault = vault;
7
+ this._layer = layer;
8
+ }
9
+ collection(name) {
10
+ const c = this._vault.collection(name);
11
+ const layer = this._layer;
12
+ return {
13
+ get: (id) => c.get(id, { _layer: layer }),
14
+ list: () => c.list({ _layer: layer }),
15
+ query: () => c.query()
16
+ };
17
+ }
18
+ };
19
+
20
+ export {
21
+ ReadOnlyVaultFacade
22
+ };
23
+ //# sourceMappingURL=chunk-RUIMKQTA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-audit/guards/read-only-facade.ts"],"sourcesContent":["import type { Vault } from '../../kernel/vault.js'\nimport type { Query } from '../../kernel/query/builder.js'\nimport type { Layer } from '../../with-shape/i18n/policy.js'\nimport type { ReadOnlyVaultFacade as ReadOnlyVaultFacadeContract } from './types.js'\n\n/**\n * Minimal read-only wrapper over a `Vault`. Used as `ctx.vault` inside\n * guard / derivation callbacks so they can fetch related records without\n * acquiring any write capability.\n *\n * The `layer` tags every `get`/`list` read with the resolution layer it\n * belongs to. A guard-seeded facade reads at `'guard'`, a\n * derivation-seeded one at `'derivation'`, so i18nText / dictKey fields\n * resolve under that layer's `onMissing` policy instead of the `'read'`\n * policy — e.g. a guard read can `substitute` a missing locale (lenient\n * default) while the same field `throw`s on an ordinary app read.\n *\n * `query()` is left untagged: the query/aggregate pipeline reads raw\n * `{locale}` maps (no resolution call site), so a layer tag there would be\n * inert. Routing `mv`/`join` resolution through the pipeline is tracked\n * separately.\n */\nexport class ReadOnlyVaultFacade implements ReadOnlyVaultFacadeContract {\n private readonly _vault: Vault\n private readonly _layer: Layer\n\n constructor(vault: Vault, layer: Layer = 'read') {\n this._vault = vault\n this._layer = layer\n }\n\n collection<T = unknown>(name: string): {\n get(id: string): Promise<T | null>\n list(): Promise<T[]>\n query(): Query<T>\n } {\n const c = this._vault.collection<T>(name)\n const layer = this._layer\n return {\n get: (id: string) => c.get(id, { _layer: layer }),\n list: () => c.list({ _layer: layer }),\n query: () => c.query(),\n }\n }\n}\n"],"mappings":";AAsBO,IAAM,sBAAN,MAAiE;AAAA,EACrD;AAAA,EACA;AAAA,EAEjB,YAAY,OAAc,QAAe,QAAQ;AAC/C,SAAK,SAAS;AACd,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,WAAwB,MAItB;AACA,UAAM,IAAI,KAAK,OAAO,WAAc,IAAI;AACxC,UAAM,QAAQ,KAAK;AACnB,WAAO;AAAA,MACL,KAAK,CAAC,OAAe,EAAE,IAAI,IAAI,EAAE,QAAQ,MAAM,CAAC;AAAA,MAChD,MAAM,MAAM,EAAE,KAAK,EAAE,QAAQ,MAAM,CAAC;AAAA,MACpC,OAAO,MAAM,EAAE,MAAM;AAAA,IACvB;AAAA,EACF;AACF;","names":[]}
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  generateULID
3
- } from "./chunk-FZU343FL.js";
3
+ } from "./chunk-ZJADGNYF.js";
4
4
  import {
5
5
  AmendmentForbiddenError,
6
6
  ConflictError,
7
7
  InvariantError,
8
8
  ValidationError
9
- } from "./chunk-B6PB7JLN.js";
9
+ } from "./chunk-ZYUC53LT.js";
10
10
 
11
- // src/tx/transaction.ts
11
+ // src/with-commit/tx/transaction.ts
12
12
  var TxContext = class {
13
13
  /** Stable id for this transaction; shared by all writes it performs. */
14
14
  txId = generateULID();
@@ -43,7 +43,7 @@ var TxContext = class {
43
43
  const v = this._db.vault(name);
44
44
  if (this._amendment && !this._amendmentVaults.has(name)) {
45
45
  const role = v.role;
46
- if (role !== "admin" && role !== "owner") {
46
+ if (role !== "admin" && role !== "owner" && role !== "custodian") {
47
47
  throw new AmendmentForbiddenError(v.userId, role);
48
48
  }
49
49
  const reg = v._getGuardRegistry();
@@ -137,7 +137,7 @@ var TxCollection = class {
137
137
  this._ctx._ops.push(op);
138
138
  }
139
139
  };
140
- async function runTransaction(db, fn, options) {
140
+ async function runTransaction(db, fn, options, txInvariants) {
141
141
  if (options?.amendment) {
142
142
  if (typeof options.reason !== "string" || options.reason.trim().length === 0) {
143
143
  throw new ValidationError(
@@ -161,12 +161,19 @@ async function runTransaction(db, fn, options) {
161
161
  }
162
162
  const priorEnvelopes = /* @__PURE__ */ new Map();
163
163
  const store = db._store;
164
+ const invariants = txInvariants ?? [];
165
+ const watchedScopes = new Set(invariants.map((i) => i.scope));
166
+ const plainBefore = /* @__PURE__ */ new Map();
164
167
  for (const op of ctx._ops) {
165
168
  const key = keyOf(op);
166
169
  if (!priorEnvelopes.has(key)) {
167
170
  const env = await store.get(op.vaultName, op.collectionName, op.id);
168
171
  priorEnvelopes.set(key, env);
169
172
  }
173
+ if (watchedScopes.has(op.collectionName) && !plainBefore.has(key)) {
174
+ const prior = await db.vault(op.vaultName).collection(op.collectionName).get(op.id);
175
+ plainBefore.set(key, prior ?? null);
176
+ }
170
177
  if (op.expectedVersion !== void 0) {
171
178
  const env = priorEnvelopes.get(key) ?? null;
172
179
  const actual = env?._v ?? 0;
@@ -209,7 +216,7 @@ async function runTransaction(db, fn, options) {
209
216
  db._clearActiveTxContext(ctx);
210
217
  }
211
218
  if (ctx._amendment) {
212
- const { GuardExecutor } = await import("./executor-5PNY7LGW.js");
219
+ const { GuardExecutor } = await import("./executor-QZ7BXICW.js");
213
220
  try {
214
221
  for (const [vaultName, v] of ctx._amendmentVaults) {
215
222
  const registry = v._getGuardRegistry();
@@ -264,6 +271,58 @@ async function runTransaction(db, fn, options) {
264
271
  );
265
272
  }
266
273
  }
274
+ if (invariants.length > 0) {
275
+ const lastOp = /* @__PURE__ */ new Map();
276
+ const order = [];
277
+ for (const op of ctx._ops) {
278
+ const key = keyOf(op);
279
+ if (!lastOp.has(key)) order.push(key);
280
+ lastOp.set(key, op);
281
+ }
282
+ const changesByScope = /* @__PURE__ */ new Map();
283
+ const scopeVault = /* @__PURE__ */ new Map();
284
+ for (const key of order) {
285
+ const op = lastOp.get(key);
286
+ if (!watchedScopes.has(op.collectionName)) continue;
287
+ const before = plainBefore.get(key) ?? null;
288
+ const after = op.type === "delete" ? null : op.record ?? null;
289
+ const change = { before, after };
290
+ const arr = changesByScope.get(op.collectionName);
291
+ if (arr) arr.push(change);
292
+ else changesByScope.set(op.collectionName, [change]);
293
+ scopeVault.set(op.collectionName, op.vaultName);
294
+ }
295
+ try {
296
+ for (const inv of invariants) {
297
+ const changes = changesByScope.get(inv.scope);
298
+ if (changes === void 0 || changes.length === 0) continue;
299
+ const vaultName = scopeVault.get(inv.scope);
300
+ const v = db.vault(vaultName);
301
+ const facade = v._getReadOnlyFacade() ?? {
302
+ collection(name) {
303
+ const c = v.collection(name);
304
+ return {
305
+ get: (id) => c.get(id),
306
+ list: () => c.list(),
307
+ query: () => c.query()
308
+ };
309
+ }
310
+ };
311
+ const ctxForInv = {
312
+ existing: null,
313
+ vault: facade,
314
+ userId: v.userId,
315
+ role: v.role
316
+ };
317
+ await inv.check(changes, ctxForInv);
318
+ }
319
+ } catch (err) {
320
+ await revertExecuted(ctx._executed, store, db);
321
+ throw err instanceof InvariantError ? err : new InvariantError(
322
+ err instanceof Error ? err.message : `invariant violated: ${String(err)}`
323
+ );
324
+ }
325
+ }
267
326
  return bodyResult;
268
327
  }
269
328
  async function revertExecuted(executed, store, db) {
@@ -293,4 +352,4 @@ export {
293
352
  runTransaction,
294
353
  revertExecuted
295
354
  };
296
- //# sourceMappingURL=chunk-TFBP23BX.js.map
355
+ //# sourceMappingURL=chunk-SKF73JOP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-commit/tx/transaction.ts"],"sourcesContent":["/**\n * Multi-record atomic transactions.\n *\n * Lets an application stage writes across two or more collections (or\n * vaults) and commit them all-or-nothing.\n *\n * ```ts\n * await db.transaction(async (tx) => {\n * const inv = tx.vault('acme').collection<Invoice>('invoices')\n * const pay = tx.vault('acme').collection<Payment>('payments')\n * await inv.put(invoiceId, { ...invoice, status: 'paid' })\n * await pay.put(paymentId, { invoiceId, amount, paidAt })\n * })\n * // If the body throws before returning: nothing persisted.\n * // If the body returns: all puts committed; any CAS mismatch rolls\n * // the batch back and surfaces as ConflictError.\n * ```\n *\n * ## Atomicity semantics\n *\n * Ops are buffered during the body. On body-return the hub:\n *\n * 1. **Pre-flight** — re-reads every touched envelope and enforces\n * any caller-supplied `expectedVersion`. A mismatch throws\n * `ConflictError` with *no* writes performed.\n * 2. **Execute** — calls `Collection.put()` / `.delete()` for each\n * staged op in declaration order. History snapshots, ledger\n * appends, and change events fire as normal per op.\n * 3. **Unwind on failure** — if step 2 throws mid-batch, each\n * already-committed op is reverted via the raw store (restoring\n * the captured prior envelope, or deleting if none existed). The\n * ledger is NOT rewritten — audit history preserves the partial\n * commit and the revert.\n *\n * **Crash window.** Steps 2–3 are not a storage-layer transaction —\n * if the process dies between two executed ops, the on-disk state is\n * partial. True all-or-nothing atomicity requires a store that\n * implements `NoydbStore.tx()` (DynamoDB `TransactWriteItems`,\n * IndexedDB `readwrite` transaction, …). This executor declares\n * that future integration point via the `tx?()` method + the\n * `StoreCapabilities.txAtomic` bit, but does not yet delegate\n * to it — the cascade into `Fork · Stores` tracks the per-adapter\n * wire-up.\n *\n * ## Not covered\n *\n * - Cross-sync-peer atomicity. Transactions commit against the\n * primary store only; the sync engine pushes on its normal\n * schedule. For cross-peer two-phase commit use `SyncTransaction`\n * via `db.transaction(vaultName)`.\n * - Read-your-writes within the body. `tx.collection().get(id)`\n * returns the most-recently-staged value for that id when one\n * exists; if no staged op has touched the id, it reads the current\n * committed state. Version numbers returned by `get` reflect the\n * pre-transaction state (staged puts have no version yet).\n *\n * @module\n */\n\nimport type { Noydb } from '../../kernel/noydb.js'\nimport type { Vault } from '../../kernel/vault.js'\nimport type { Collection } from '../../kernel/collection.js'\nimport type { EncryptedEnvelope } from '../../kernel/types.js'\nimport {\n AmendmentForbiddenError,\n ConflictError,\n InvariantError,\n ValidationError,\n} from '../../kernel/errors.js'\nimport { generateULID } from '../../with-pod/ulid.js'\nimport type { GuardExecutor as GuardExecutorModule } from '../../with-audit/guards/executor.js'\nimport type { LedgerEntry } from '../history/ledger/entry.js'\nimport type { TransactionInvariant } from './invariants.js'\nimport type { GuardChange, GuardContext, ReadOnlyVaultFacade } from '../../with-audit/guards/types.js'\n\n/** One op buffered inside a running `TxContext`. @internal */\nexport interface StagedOp {\n type: 'put' | 'delete'\n vaultName: string\n collectionName: string\n id: string\n record?: unknown\n expectedVersion?: number\n /**\n * Optional human-readable tag forwarded to the resulting ledger\n * entry's `reason` field. Set by callers via\n * `tx.vault(v).collection(c).put(id, record, { reason })`.\n */\n reason?: string\n}\n\n/**\n * One executed op (main staged op or recursive side-effect like a\n * derivation output) paired with the envelope captured before the write.\n * `revertExecuted` walks this array in reverse on rollback.\n * @internal\n */\nexport interface ExecutedOp {\n op: StagedOp\n priorEnvelope: EncryptedEnvelope | null\n}\n\n/**\n * Options accepted by `db.transaction({ amendment, reason }, fn)`.\n * Only the amendment variant uses these — a plain `db.transaction(fn)`\n * never sees this shape.\n */\nexport interface AmendmentTxOptions {\n /** Opt into amendment mode. Required to be `true`. */\n readonly amendment: true\n /** Human-readable rationale recorded in the ledger entry. Required. */\n readonly reason: string\n}\n\n/**\n * Transaction handle passed to the user's body. Use\n * `tx.vault(name).collection<T>(name)` to get a per-collection\n * facade; its `put`/`delete`/`get` calls stage ops against the tx.\n */\nexport class TxContext {\n /** Stable id for this transaction; shared by all writes it performs. */\n readonly txId: string = generateULID()\n /** @internal */\n readonly _ops: StagedOp[] = []\n /**\n * @internal — write log built up in Phase 2. Each entry records the\n * envelope captured BEFORE the write so a mid-batch failure can\n * restore prior state via `revertExecuted`. Side-effect writes (e.g.\n * recursive derivation outputs fired inside `Collection.put`) are\n * appended here in execution order so they roll back alongside the\n * main staged ops.\n */\n readonly _executed: ExecutedOp[] = []\n /** @internal */\n readonly _db: Noydb\n /**\n * @internal — true when this TxContext was opened in amendment\n * mode. Toggles the lazy-`beginAmendment` + role-check path on first\n * `tx.vault(name)` and unlocks the post-Phase-2 invariant + audit run.\n */\n readonly _amendment: boolean\n /** @internal — vaults that have already had `beginAmendment` called. */\n readonly _amendmentVaults = new Map<string, Vault>()\n\n /** @internal */\n constructor(db: Noydb, amendment = false) {\n this._db = db\n this._amendment = amendment\n }\n\n /** Scope subsequent `collection()` calls to the named vault. */\n vault(name: string): TxVault {\n const v = this._db.vault(name)\n if (this._amendment && !this._amendmentVaults.has(name)) {\n // Role check is per-vault. The task spec (\"only admin or owner\n // can open an amendment\") is implemented lazy-on-first-touch\n // because the role lives on the vault's keyring, and `tx.vault()`\n // is the first place we know which vault we're addressing. The\n // observable effect is identical to an eager check in the single-\n // vault case the tests exercise; multi-vault amendments check\n // each touched vault as they first appear.\n const role = v.role\n // FR-6: custodian is admin-rank for operational mutations, and an\n // amendment is an operational (data-correcting) act — not an ownership\n // meta-capability — so custodian is allowed alongside owner/admin.\n if (role !== 'admin' && role !== 'owner' && role !== 'custodian') {\n throw new AmendmentForbiddenError(v.userId, role)\n }\n // Amendments require an initialised guard registry — they\n // produce a structured invariant + change-set audit. A vault\n // opened without `guardStrategies` (or via the sync fallback\n // path) has a null registry and cannot run an amendment.\n const reg = v._getGuardRegistry()\n if (reg === null) {\n throw new ValidationError(\n `Vault \"${name}\": amendment mode requires at least one ` +\n `guardStrategy registered via createNoydb({ guardStrategies }). ` +\n `Open the vault with guardStrategies before calling ` +\n `db.transaction({ amendment: true }).`,\n )\n }\n reg.beginAmendment()\n this._amendmentVaults.set(name, v)\n }\n return new TxVault(this, v)\n }\n}\n\n/** Per-vault facade inside a running transaction. */\nexport class TxVault {\n /** @internal */\n readonly _ctx: TxContext\n /** @internal */\n readonly _vault: Vault\n\n /** @internal */\n constructor(ctx: TxContext, vault: Vault) {\n this._ctx = ctx\n this._vault = vault\n }\n\n /** Scope subsequent op calls to the named collection. */\n collection<T>(name: string): TxCollection<T> {\n const c = this._vault.collection<T>(name)\n return new TxCollection<T>(this._ctx, this._vault, c, name)\n }\n}\n\n/** Per-collection facade inside a running transaction. */\nexport class TxCollection<T> {\n /** @internal */\n readonly _ctx: TxContext\n /** @internal */\n readonly _vault: Vault\n /** @internal */\n readonly _coll: Collection<T>\n /** @internal */\n readonly _name: string\n\n /** @internal */\n constructor(ctx: TxContext, vault: Vault, coll: Collection<T>, name: string) {\n this._ctx = ctx\n this._vault = vault\n this._coll = coll\n this._name = name\n }\n\n /**\n * Read the current committed value, or the most-recently-staged\n * value from the same transaction if one exists.\n */\n async get(id: string): Promise<T | null> {\n for (let i = this._ctx._ops.length - 1; i >= 0; i--) {\n const op = this._ctx._ops[i]!\n if (\n op.vaultName === this._vault.name &&\n op.collectionName === this._name &&\n op.id === id\n ) {\n if (op.type === 'delete') return null\n return op.record as T\n }\n }\n return this._coll.get(id)\n }\n\n /**\n * Stage a put. Does not write until the transaction body returns.\n * Supply `{ expectedVersion }` to enforce optimistic concurrency\n * during the commit pre-flight.\n */\n put(id: string, record: T, options?: { expectedVersion?: number; reason?: string }): void {\n const op: StagedOp = {\n type: 'put',\n vaultName: this._vault.name,\n collectionName: this._name,\n id,\n record,\n }\n if (options?.expectedVersion !== undefined) op.expectedVersion = options.expectedVersion\n if (options?.reason !== undefined) op.reason = options.reason\n this._ctx._ops.push(op)\n }\n\n /**\n * Stage a delete. Does not write until the transaction body returns.\n * Supply `{ expectedVersion }` to enforce optimistic concurrency\n * during the commit pre-flight.\n */\n delete(id: string, options?: { expectedVersion?: number }): void {\n const op: StagedOp = {\n type: 'delete',\n vaultName: this._vault.name,\n collectionName: this._name,\n id,\n }\n if (options?.expectedVersion !== undefined) op.expectedVersion = options.expectedVersion\n this._ctx._ops.push(op)\n }\n}\n\n/**\n * Commit plan: pre-flight check + execution + revert plan.\n *\n * @internal — driven by `withTransactions()` (via `tx/active.ts`) for\n * user-facing `db.transaction(...)` calls and by the `amendment` path\n * in `noydb.ts`. `Collection.putManyAtomic` runs its own Phase 2 loop\n * but shares the `_activeTxContext` mechanism (and the `revertExecuted`\n * helper) so nested side-effect derivation writes get registered for\n * revert alongside the bulk-put source ops.\n */\nexport async function runTransaction<T>(\n db: Noydb,\n fn: (tx: TxContext) => Promise<T> | T,\n options?: AmendmentTxOptions,\n txInvariants?: ReadonlyArray<TransactionInvariant>,\n): Promise<T> {\n // ─── Amendment-mode pre-flight ───────────────────────────────\n // `reason` is the only thing we can validate before the body runs;\n // the per-vault role check happens lazily on first `tx.vault(name)`\n // because we don't know which vaults the body will touch ahead of\n // time. Throwing here keeps the failure mode close to the call site\n // so the developer doesn't have to walk an async stack to find the\n // missing-reason mistake.\n if (options?.amendment) {\n if (typeof options.reason !== 'string' || options.reason.trim().length === 0) {\n throw new ValidationError(\n 'db.transaction({ amendment: true }) requires a non-empty `reason` string.',\n )\n }\n }\n\n const ctx = new TxContext(db, options?.amendment === true)\n const bodyResult = await fn(ctx)\n\n if (ctx._ops.length === 0) {\n // Body produced no ops. If amendment mode was active we still\n // need to close any opened windows so a subsequent (unrelated)\n // write doesn't surprise-collect into a stale change-set. Each\n // `beginAmendment` is matched by exactly one `consumeChanges`.\n if (ctx._amendment) {\n for (const v of ctx._amendmentVaults.values()) {\n // Registry is guaranteed non-null here — `tx.vault(name)`\n // threw above if it was null before adding to\n // `_amendmentVaults`.\n const reg = v._getGuardRegistry()\n if (reg !== null) {\n reg.consumeChanges()\n reg.consumeMeta()\n }\n }\n }\n return bodyResult\n }\n\n // Phase 1 — pre-flight: snapshot every touched envelope and enforce\n // any caller-supplied expectedVersion. Same (vault, coll, id) touched\n // more than once in one tx snapshots only the *initial* committed\n // state; the in-order replay in Phase 2 takes care of successor ops.\n const priorEnvelopes = new Map<string, EncryptedEnvelope | null>()\n const store = db._store\n\n // Commit-time changeset invariants need PLAINTEXT prior records\n // for `before`, but `priorEnvelopes` holds ENCRYPTED envelopes. So for\n // ops in a watched scope we additionally decrypt the prior record here,\n // in Phase 1, BEFORE Phase 2 overwrites it. Snapshots only the initial\n // committed state per (vault, coll, id), matching the envelope snapshot.\n const invariants = txInvariants ?? []\n const watchedScopes = new Set(invariants.map(i => i.scope))\n const plainBefore = new Map<string, unknown>()\n\n for (const op of ctx._ops) {\n const key = keyOf(op)\n if (!priorEnvelopes.has(key)) {\n const env = await store.get(op.vaultName, op.collectionName, op.id)\n priorEnvelopes.set(key, env)\n }\n if (watchedScopes.has(op.collectionName) && !plainBefore.has(key)) {\n const prior = await db\n .vault(op.vaultName)\n .collection(op.collectionName)\n .get(op.id)\n plainBefore.set(key, prior ?? null)\n }\n if (op.expectedVersion !== undefined) {\n const env = priorEnvelopes.get(key) ?? null\n const actual = env?._v ?? 0\n if (actual !== op.expectedVersion) {\n throw new ConflictError(\n actual,\n `Transaction pre-flight: ${op.vaultName}/${op.collectionName}/${op.id} ` +\n `expected v${op.expectedVersion}, found v${actual}`,\n )\n }\n }\n }\n\n // Phase 2 — execute via the Collection layer so history snapshots,\n // ledger entries, and change events fire normally. We capture each\n // successful op so a mid-batch throw can revert in Phase 3.\n //\n // `_activeTxContext` is published on the Noydb instance for the\n // duration of Phase 2 so recursive writes triggered inside\n // `Collection.put` (today: eager derivation outputs) can register\n // their own envelopes onto `ctx._executed` and roll back alongside\n // the main staged ops. The `finally` clears it before the\n // amendment commit phase runs.\n db._setActiveTxContext(ctx)\n try {\n try {\n for (const op of ctx._ops) {\n const coll = db.vault(op.vaultName).collection(op.collectionName)\n const key = keyOf(op)\n const prior = priorEnvelopes.get(key) ?? null\n // Record the revert plan BEFORE the call so a mid-`coll.put` throw\n // (e.g. strict-mode derivation failure firing after `store.put`\n // has already committed the envelope) still has its source write\n // reverted. `revertExecuted` is best-effort: putting prior back is\n // idempotent when the failing op never actually wrote, and\n // `_invalidateCacheEntry` is a no-op when the collection isn't\n // hydrated.\n ctx._executed.push({ op, priorEnvelope: prior })\n if (op.type === 'put') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await coll.put(op.id, op.record as any, op.reason !== undefined ? { reason: op.reason } : undefined)\n } else {\n await coll.delete(op.id)\n }\n }\n } catch (err) {\n // Phase 3 — best-effort revert. See helper docstring.\n await revertExecuted(ctx._executed, store, db)\n // Drain amendment windows so the next transaction starts clean.\n if (ctx._amendment) {\n for (const v of ctx._amendmentVaults.values()) {\n const reg = v._getGuardRegistry()\n if (reg !== null) {\n reg.consumeChanges()\n reg.consumeMeta()\n }\n }\n }\n throw err\n }\n } finally {\n db._clearActiveTxContext(ctx)\n }\n\n // ─── Amendment commit phase (only if amendment === true) ────\n // Body succeeded — now run each touched vault's invariants over the\n // collected change-set, then append a structured ledger entry. If\n // any invariant throws, treat it exactly like a mid-Phase-2 failure:\n // revert every executed op and re-throw the InvariantError.\n if (ctx._amendment) {\n // Lazy-load GuardExecutor at the dispatch site — keeps the floor\n // bundle free of the guards service when amendments aren't used.\n // Mirrors the deferred-load pattern from elsewhere in this module.\n const { GuardExecutor } = (await import('../../with-audit/guards/executor.js')) as {\n GuardExecutor: typeof GuardExecutorModule\n }\n try {\n for (const [vaultName, v] of ctx._amendmentVaults) {\n const registry = v._getGuardRegistry()\n // Registry is guaranteed non-null at this point — the\n // `tx.vault(name)` path that populates `_amendmentVaults`\n // throws if the registry is null. The defensive check here\n // is for TypeScript's narrowing.\n if (registry === null) continue\n const changesByCollection = registry.consumeChanges()\n const meta = registry.consumeMeta()\n if (changesByCollection.size === 0) continue\n\n const readOnlyVault = v._getReadOnlyFacade()\n if (readOnlyVault === null) continue\n\n // Build the invariant ctx once per vault — it's the same shape\n // every guard sees on the normal `check` path, just with a\n // synthetic `existing: null` (invariants get the full change\n // set in their first parameter; `existing` is a per-record\n // concept that doesn't apply here).\n const invariantsPassed: string[] = []\n for (const [collection, changes] of changesByCollection) {\n const guards = registry.guardsFor(collection).filter(g => g.amendment !== undefined)\n for (const guard of guards) {\n await GuardExecutor.runInvariant(guard, changes, {\n existing: null,\n vault: readOnlyVault,\n userId: v.userId,\n role: v.role,\n })\n }\n if (guards.length > 0) invariantsPassed.push(collection)\n }\n\n // Append the audit ledger entry. Silent no-op when the\n // history strategy isn't configured — the records still\n // committed, only the multi-record summary is unavailable.\n const ledger = v._getLedgerOrNull()\n if (ledger) {\n const role = v.role as 'admin' | 'owner'\n const amendment: NonNullable<LedgerEntry['amendment']> = {\n reason: options!.reason,\n role,\n changes: meta,\n invariantsPassed,\n }\n await ledger.append({\n op: 'amendment',\n collection: '',\n id: '',\n version: 0,\n actor: v.userId,\n // No payload to hash — the per-record entries already\n // captured `payloadHash` at their own append time. We use\n // a sha256 of the canonical reason string so the field is\n // populated with something deterministic and non-empty.\n payloadHash: '',\n amendment,\n })\n }\n void vaultName\n }\n } catch (err) {\n await revertExecuted(ctx._executed, store, db)\n throw err instanceof InvariantError ? err : new InvariantError(\n err instanceof Error ? err.message : `invariant violated: ${String(err)}`,\n )\n }\n }\n\n // ─── Commit-time changeset invariant phase ───────────\n // Runs for BOTH ordinary and amendment transactions (placed after the\n // amendment phase so an amendment commit is still subject to these\n // set-level constraints). Assemble the changeset from the executed\n // staged ops, deduped to the LAST write per (vault, coll, id) while\n // preserving write order, then group `GuardChange` by collection\n // (scope) and run each matching invariant. A throw mirrors the\n // amendment-phase failure mode exactly: revert every executed op and\n // re-throw as `InvariantError`.\n if (invariants.length > 0) {\n // Dedup ctx._ops to the last write per key, preserving first-seen\n // (write) order so the changeset is stable and order-meaningful.\n const lastOp = new Map<string, StagedOp>()\n const order: string[] = []\n for (const op of ctx._ops) {\n const key = keyOf(op)\n if (!lastOp.has(key)) order.push(key)\n lastOp.set(key, op)\n }\n\n // Group {before, after} pairs by collection name (the invariant\n // scope). `before` is the plaintext prior captured in Phase 1 (null\n // for inserts / unwatched — only watched scopes were captured, and\n // every grouped key belongs to a watched scope). `after` is the\n // written record, null for a delete.\n const changesByScope = new Map<string, GuardChange<unknown>[]>()\n // Parallel map: scope → the vault name of its (last-seen) op, used to\n // build the per-invariant read-only ctx (facade + userId + role).\n const scopeVault = new Map<string, string>()\n for (const key of order) {\n const op = lastOp.get(key)!\n if (!watchedScopes.has(op.collectionName)) continue\n const before = plainBefore.get(key) ?? null\n const after = op.type === 'delete' ? null : (op.record ?? null)\n const change = { before, after } as GuardChange<unknown>\n const arr = changesByScope.get(op.collectionName)\n if (arr) arr.push(change)\n else changesByScope.set(op.collectionName, [change])\n\n // Stash the vault name alongside so we can build a per-vault ctx.\n // (All ops in a scope group could span vaults; we resolve the\n // vault per change below via a parallel map keyed the same way.)\n scopeVault.set(op.collectionName, op.vaultName)\n }\n\n try {\n for (const inv of invariants) {\n const changes = changesByScope.get(inv.scope)\n if (changes === undefined || changes.length === 0) continue\n const vaultName = scopeVault.get(inv.scope)!\n const v = db.vault(vaultName)\n // Prefer the real read-only facade so the invariant can read\n // sibling collections; fall back to a minimal read-only stub.\n const facade: ReadOnlyVaultFacade =\n v._getReadOnlyFacade() ?? {\n collection<R = unknown>(name: string) {\n const c = v.collection<R>(name)\n return {\n get: (id: string) => c.get(id),\n list: () => c.list(),\n query: () => c.query(),\n }\n },\n }\n const ctxForInv: GuardContext<unknown> = {\n existing: null,\n vault: facade,\n userId: v.userId,\n role: v.role,\n }\n await inv.check(changes, ctxForInv)\n }\n } catch (err) {\n await revertExecuted(ctx._executed, store, db)\n throw err instanceof InvariantError ? err : new InvariantError(\n err instanceof Error ? err.message : `invariant violated: ${String(err)}`,\n )\n }\n }\n\n return bodyResult\n}\n\n/**\n * Phase 3 helper — restore captured prior envelopes via the raw store\n * to avoid re-firing Collection-level side effects (we don't want a\n * cascade of change events undoing themselves). The ledger is left\n * as-is: each committed op appended an entry; the revert is\n * deliberately NOT recorded as a compensating entry because the\n * caller-facing contract is \"atomic or not at all,\" not \"every write\n * visible in the audit trail.\" Auditors who need the intermediate\n * state can still reconstruct it by walking the ledger through the\n * failed-tx timestamp.\n *\n * @internal — shared between `runTransaction` and\n * `Collection.putManyAtomic`. Both register source ops + nested\n * derivation side-effect ops onto `_executed`; this helper unwinds the\n * combined list in reverse on rollback.\n */\nexport async function revertExecuted(\n executed: ReadonlyArray<ExecutedOp>,\n store: Noydb['_store'],\n db?: Noydb,\n): Promise<void> {\n for (const { op, priorEnvelope } of executed.slice().reverse()) {\n try {\n if (priorEnvelope) {\n await store.put(op.vaultName, op.collectionName, op.id, priorEnvelope)\n } else {\n await store.delete(op.vaultName, op.collectionName, op.id)\n }\n // Sync the Collection-layer cache with what we just wrote at\n // the raw store. Without this, eager-mode `get` would still\n // return the rolled-back record from its in-memory map. The\n // Collection's `_invalidateCacheEntry` is a no-op when the\n // collection hasn't yet been hydrated.\n if (db) {\n const coll = db.vault(op.vaultName).collection(op.collectionName)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await (coll as any)._invalidateCacheEntry(op.id)\n }\n } catch {\n // swallow — best-effort. Surfacing the revert error would mask\n // the original one that triggered the rollback.\n }\n }\n}\n\nfunction keyOf(op: StagedOp): string {\n return `${op.vaultName}\\x00${op.collectionName}\\x00${op.id}`\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,42 @@
1
+ import {
2
+ NOYDB_FORMAT_VERSION
3
+ } from "./chunk-5TDJ56JE.js";
4
+
5
+ // src/with-party/policy/storage.ts
6
+ var META_COLLECTION = "_meta";
7
+ var POLICY_RECORD_ID = "policy";
8
+ async function loadVaultPolicy(store, vault) {
9
+ const envelope = await store.get(vault, META_COLLECTION, POLICY_RECORD_ID);
10
+ if (!envelope) return void 0;
11
+ try {
12
+ const parsed = JSON.parse(envelope._data);
13
+ if (!isVaultPolicy(parsed)) return void 0;
14
+ return parsed;
15
+ } catch {
16
+ return void 0;
17
+ }
18
+ }
19
+ async function saveVaultPolicy(store, vault, policy) {
20
+ const envelope = {
21
+ _noydb: NOYDB_FORMAT_VERSION,
22
+ _v: 1,
23
+ _ts: (/* @__PURE__ */ new Date()).toISOString(),
24
+ _iv: "",
25
+ _data: JSON.stringify(policy)
26
+ };
27
+ await store.put(vault, META_COLLECTION, POLICY_RECORD_ID, envelope);
28
+ }
29
+ function isVaultPolicy(x) {
30
+ if (x === null || typeof x !== "object") return false;
31
+ if (!("gates" in x)) return false;
32
+ const gates = x.gates;
33
+ return gates !== null && typeof gates === "object";
34
+ }
35
+
36
+ export {
37
+ META_COLLECTION,
38
+ POLICY_RECORD_ID,
39
+ loadVaultPolicy,
40
+ saveVaultPolicy
41
+ };
42
+ //# sourceMappingURL=chunk-SM3AVUHC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-party/policy/storage.ts"],"sourcesContent":["/**\n * Persistence helpers for the vault-level policy document\n * (`_meta/policy`). Mirrors the bypass-AES pattern used by\n * `_meta/handle` — the policy document is plain JSON, the envelope's\n * `_iv` field is left empty.\n *\n * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/session-tiers.md → Storage location\n *\n * @module\n */\nimport type { NoydbStore, EncryptedEnvelope, VaultPolicy } from '../../kernel/types.js'\nimport { NOYDB_FORMAT_VERSION } from '../../kernel/types.js'\n\n/** Reserved collection name for vault-level metadata documents. */\nexport const META_COLLECTION = '_meta'\n/** Reserved id for the vault-level policy document. */\nexport const POLICY_RECORD_ID = 'policy'\n\n/**\n * Read the vault-level policy from `_meta/policy`. Returns `undefined`\n * when no policy has been persisted (fresh vault, or a vault written\n * before the policy module landed). The caller falls back to the\n * default preset.\n *\n * Tolerates corrupted documents the same way `_meta/handle` does: a\n * JSON parse failure surfaces as `undefined`, not a thrown error, so\n * a bad write never permanently locks a vault.\n */\nexport async function loadVaultPolicy(\n store: NoydbStore,\n vault: string,\n): Promise<VaultPolicy | undefined> {\n const envelope = await store.get(vault, META_COLLECTION, POLICY_RECORD_ID)\n if (!envelope) return undefined\n try {\n const parsed = JSON.parse(envelope._data) as unknown\n if (!isVaultPolicy(parsed)) return undefined\n return parsed\n } catch {\n return undefined\n }\n}\n\n/**\n * Persist the vault-level policy at `_meta/policy`. Idempotent — call\n * once at vault creation and again on `db.updatePolicy()` invocations.\n */\nexport async function saveVaultPolicy(\n store: NoydbStore,\n vault: string,\n policy: VaultPolicy,\n): Promise<void> {\n const envelope: EncryptedEnvelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: 1,\n _ts: new Date().toISOString(),\n _iv: '',\n _data: JSON.stringify(policy),\n }\n await store.put(vault, META_COLLECTION, POLICY_RECORD_ID, envelope)\n}\n\nfunction isVaultPolicy(x: unknown): x is VaultPolicy {\n if (x === null || typeof x !== 'object') return false\n if (!('gates' in x)) return false\n const gates = (x as { gates: unknown }).gates\n return gates !== null && typeof gates === 'object'\n}\n"],"mappings":";;;;;AAcO,IAAM,kBAAkB;AAExB,IAAM,mBAAmB;AAYhC,eAAsB,gBACpB,OACA,OACkC;AAClC,QAAM,WAAW,MAAM,MAAM,IAAI,OAAO,iBAAiB,gBAAgB;AACzE,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,SAAS,KAAK;AACxC,QAAI,CAAC,cAAc,MAAM,EAAG,QAAO;AACnC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,gBACpB,OACA,OACA,QACe;AACf,QAAM,WAA8B;AAAA,IAClC,QAAQ;AAAA,IACR,IAAI;AAAA,IACJ,MAAK,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC5B,KAAK;AAAA,IACL,OAAO,KAAK,UAAU,MAAM;AAAA,EAC9B;AACA,QAAM,MAAM,IAAI,OAAO,iBAAiB,kBAAkB,QAAQ;AACpE;AAEA,SAAS,cAAc,GAA8B;AACnD,MAAI,MAAM,QAAQ,OAAO,MAAM,SAAU,QAAO;AAChD,MAAI,EAAE,WAAW,GAAI,QAAO;AAC5B,QAAM,QAAS,EAAyB;AACxC,SAAO,UAAU,QAAQ,OAAO,UAAU;AAC5C;","names":[]}
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  NOYDB_FORMAT_VERSION
3
- } from "./chunk-WIRRPTFH.js";
3
+ } from "./chunk-5TDJ56JE.js";
4
4
  import {
5
5
  ValidationError
6
- } from "./chunk-B6PB7JLN.js";
6
+ } from "./chunk-ZYUC53LT.js";
7
7
 
8
- // src/meta/public-envelope/schema.ts
8
+ // src/with-party/directory/public-envelope/schema.ts
9
9
  var DATA_URL_PREFIX = /^data:([a-zA-Z0-9.+-]+\/[a-zA-Z0-9.+-]+);base64,/;
10
10
  function validatePublicEnvelopeInput(input, schema) {
11
11
  const allowed = new Set(schema.fields);
@@ -94,7 +94,7 @@ function isPublicEnvelope(x) {
94
94
  return obj["_noydb_public"] === 1 && typeof obj["version"] === "number";
95
95
  }
96
96
 
97
- // src/meta/public-envelope/storage.ts
97
+ // src/with-party/directory/public-envelope/storage.ts
98
98
  var PUBLIC_ENVELOPE_RECORD_ID = "public-envelope";
99
99
  async function loadPublicEnvelope(store, vault) {
100
100
  const envelope = await store.get(vault, "_meta", PUBLIC_ENVELOPE_RECORD_ID);
@@ -152,4 +152,4 @@ export {
152
152
  resolveLocale,
153
153
  pickLocale
154
154
  };
155
- //# sourceMappingURL=chunk-ML236QKC.js.map
155
+ //# sourceMappingURL=chunk-SMXWYP24.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/with-party/directory/public-envelope/schema.ts","../src/with-party/directory/public-envelope/storage.ts"],"sourcesContent":["/**\n * Validate-on-write for the public envelope. Runs at every\n * `setPublicEnvelope` call; the developer's schema decides which\n * fields are allowed and the size caps that apply.\n *\n * @module\n */\nimport { ValidationError } from '../../../kernel/errors.js'\nimport type {\n PublicEnvelope,\n PublicEnvelopeText,\n ResolvedPublicEnvelopeSchema,\n PublicEnvelopeField,\n} from './types.js'\n\n/** Owner-supplied input — the subset of {@link PublicEnvelope} the owner can set. */\nexport interface SetPublicEnvelopeInput {\n readonly name?: PublicEnvelopeText\n readonly description?: PublicEnvelopeText\n readonly icon?: string\n readonly defaultLocale?: string\n}\n\nconst DATA_URL_PREFIX = /^data:([a-zA-Z0-9.+-]+\\/[a-zA-Z0-9.+-]+);base64,/\n\n/**\n * Validate an owner-supplied envelope input against the developer's\n * resolved schema. Throws `ValidationError` on the first violation;\n * returns void on success.\n *\n * The validator is deliberately strict: every fail mode is a hard\n * error rather than a silent drop, so the owner finds out immediately\n * which field they oversized rather than discovering a truncated\n * label months later.\n */\nexport function validatePublicEnvelopeInput(\n input: SetPublicEnvelopeInput,\n schema: ResolvedPublicEnvelopeSchema,\n): void {\n const allowed = new Set<PublicEnvelopeField>(schema.fields)\n\n // Reject any key not in the schema's allowed-field list.\n for (const key of Object.keys(input)) {\n const known: PublicEnvelopeField | undefined =\n key === 'name' || key === 'description' || key === 'icon' || key === 'defaultLocale'\n ? key\n : undefined\n if (!known) {\n throw new ValidationError(\n `setPublicEnvelope: unknown field \"${key}\". ` +\n `Allowed fields: ${[...allowed].join(', ')}.`,\n )\n }\n if (!allowed.has(known)) {\n throw new ValidationError(\n `setPublicEnvelope: field \"${known}\" is not enabled in this vault's schema. ` +\n `Allowed fields: ${[...allowed].join(', ')}.`,\n )\n }\n }\n\n if (input.name !== undefined) {\n validateText(input.name, 'name', schema.maxStringChars)\n }\n if (input.description !== undefined) {\n validateText(input.description, 'description', schema.maxStringChars)\n }\n if (input.icon !== undefined) {\n validateIcon(input.icon, schema)\n }\n if (input.defaultLocale !== undefined && typeof input.defaultLocale !== 'string') {\n throw new ValidationError(\n `setPublicEnvelope: defaultLocale must be a string (BCP-47), got ${typeof input.defaultLocale}.`,\n )\n }\n}\n\nfunction validateText(\n value: PublicEnvelopeText,\n field: string,\n maxChars: number,\n): void {\n if (typeof value === 'string') {\n if (value.length > maxChars) {\n throw new ValidationError(\n `setPublicEnvelope: ${field} exceeds the ${maxChars}-character cap (got ${value.length}).`,\n )\n }\n return\n }\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new ValidationError(\n `setPublicEnvelope: ${field} must be a string or { [locale]: string } map, got ${typeof value}.`,\n )\n }\n // Locale map. Each value must be a non-empty string within the cap.\n for (const [locale, str] of Object.entries(value)) {\n if (typeof str !== 'string') {\n throw new ValidationError(\n `setPublicEnvelope: ${field}[${locale}] must be a string, got ${typeof str}.`,\n )\n }\n if (str.length > maxChars) {\n throw new ValidationError(\n `setPublicEnvelope: ${field}[${locale}] exceeds the ${maxChars}-character cap (got ${str.length}).`,\n )\n }\n }\n}\n\nfunction validateIcon(icon: string, schema: ResolvedPublicEnvelopeSchema): void {\n if (typeof icon !== 'string') {\n throw new ValidationError(\n `setPublicEnvelope: icon must be a data: URL string, got ${typeof icon}.`,\n )\n }\n if (icon.length > schema.maxIconBytes) {\n throw new ValidationError(\n `setPublicEnvelope: icon exceeds the ${schema.maxIconBytes}-byte cap (got ${icon.length}).`,\n )\n }\n const m = DATA_URL_PREFIX.exec(icon)\n if (!m) {\n throw new ValidationError(\n 'setPublicEnvelope: icon must be a base64 data URL ' +\n '(`data:image/png;base64,…` or `data:image/svg+xml;base64,…`). ' +\n 'External URLs are not supported in v1.',\n )\n }\n const mime = m[1]!\n if (!schema.iconMimeTypes.includes(mime)) {\n throw new ValidationError(\n `setPublicEnvelope: icon MIME type \"${mime}\" is not allowed. ` +\n `Permitted types: ${schema.iconMimeTypes.join(', ')}.`,\n )\n }\n}\n\n/**\n * Lightweight runtime predicate — used by the bundle header\n * validator to recognise a public envelope without requiring it.\n */\nexport function isPublicEnvelope(x: unknown): x is PublicEnvelope {\n if (x === null || typeof x !== 'object' || Array.isArray(x)) return false\n const obj = x as Record<string, unknown>\n return obj['_noydb_public'] === 1 && typeof obj['version'] === 'number'\n}\n","/**\n * Persistence helpers for `_meta/public-envelope`. Mirrors the\n * bypass-AES pattern used by `_meta/handle` and `_meta/policy` —\n * the document is plaintext JSON, the envelope's `_iv` field is\n * left empty.\n *\n * @module\n */\nimport type { NoydbStore, EncryptedEnvelope } from '../../../kernel/types.js'\nimport { NOYDB_FORMAT_VERSION } from '../../../kernel/types.js'\nimport type { PublicEnvelope } from './types.js'\nimport { isPublicEnvelope } from './schema.js'\n\n/** Reserved id for the vault-level public envelope record. */\nexport const PUBLIC_ENVELOPE_RECORD_ID = 'public-envelope'\n\n/**\n * Read the public envelope from `_meta/public-envelope`. Returns\n * `undefined` when no envelope has been persisted (fresh vault, or\n * a vault written before the feature was enabled). Tolerates\n * corrupted documents — a JSON parse failure surfaces as `undefined`,\n * not a thrown error, mirroring `_meta/handle`'s contract.\n */\nexport async function loadPublicEnvelope(\n store: NoydbStore,\n vault: string,\n): Promise<PublicEnvelope | undefined> {\n const envelope = await store.get(vault, '_meta', PUBLIC_ENVELOPE_RECORD_ID)\n if (!envelope) return undefined\n try {\n const parsed = JSON.parse(envelope._data) as unknown\n if (!isPublicEnvelope(parsed)) return undefined\n return parsed\n } catch {\n return undefined\n }\n}\n\n/** Persist the public envelope. Idempotent — overwrites any prior write. */\nexport async function savePublicEnvelope(\n store: NoydbStore,\n vault: string,\n envelope: PublicEnvelope,\n): Promise<void> {\n const wireEnvelope: EncryptedEnvelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: 1,\n _ts: new Date().toISOString(),\n _iv: '',\n _data: JSON.stringify(envelope),\n }\n await store.put(vault, '_meta', PUBLIC_ENVELOPE_RECORD_ID, wireEnvelope)\n}\n\n/**\n * Public, no-key reader. Plain function, not a method on `Noydb` —\n * the whole point is it works without an authenticated session, so\n * a UI can show \"Acme 2026 Tax Records\" before unlocking.\n *\n * Resolves any `name` / `description` locale map through the supplied\n * `locale` (when provided). Omitting `locale` returns the raw\n * envelope, which a multilingual picker can render as it pleases.\n */\nexport async function readPublicEnvelope(\n store: NoydbStore,\n vault: string,\n opts: { readonly locale?: string } = {},\n): Promise<PublicEnvelope | undefined> {\n const raw = await loadPublicEnvelope(store, vault)\n if (!raw) return undefined\n if (opts.locale === undefined) return raw\n return resolveLocale(raw, opts.locale)\n}\n\n/**\n * Resolve the locale-map fields (`name`, `description`) of a public\n * envelope to plain strings for the requested locale, falling back\n * through `defaultLocale` and then any available translation.\n *\n * @internal\n */\nexport function resolveLocale(\n envelope: PublicEnvelope,\n locale: string,\n): PublicEnvelope {\n return {\n ...envelope,\n ...(envelope.name !== undefined ? { name: pickLocale(envelope.name, locale, envelope.defaultLocale) } : {}),\n ...(envelope.description !== undefined ? { description: pickLocale(envelope.description, locale, envelope.defaultLocale) } : {}),\n }\n}\n\n/**\n * Resolve a `string | { [locale]: string }` value to a string for a\n * given locale. Exported so the bundle reader can reuse it without\n * duplicating the fallback chain.\n *\n * **Looser than `resolveI18nText`** — the hub's record-field resolver\n * throws `LocaleNotSpecifiedError` when no translation matches, but\n * label semantics deliberately prefer \"show *something*\" over\n * throwing. The fallback chain is:\n * 1. Exact `locale` match.\n * 2. `defaultLocale` (when supplied on the envelope).\n * 3. First non-empty value in the map.\n * 4. Empty string (only if every translation is empty — pathological).\n *\n * This deviation is documented in `https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md`.\n */\nexport function pickLocale(\n value: string | Record<string, string>,\n locale: string,\n defaultLocale: string | undefined,\n): string {\n if (typeof value === 'string') return value\n if (value[locale] !== undefined && value[locale] !== '') return value[locale]\n if (defaultLocale && value[defaultLocale] !== undefined && value[defaultLocale] !== '') {\n return value[defaultLocale]\n }\n for (const v of Object.values(value)) {\n if (v !== '') return v\n }\n return ''\n}\n"],"mappings":"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","names":[]}