@noy-db/hub 0.2.0-pre.12 → 0.2.0-pre.14

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 (249) hide show
  1. package/dist/aggregate/index.cjs.map +1 -1
  2. package/dist/aggregate/index.d.cts +2 -2
  3. package/dist/aggregate/index.d.ts +2 -2
  4. package/dist/aggregate/index.js +2 -2
  5. package/dist/attestation/index.cjs.map +1 -1
  6. package/dist/attestation/index.d.cts +3 -3
  7. package/dist/attestation/index.d.ts +3 -3
  8. package/dist/attestation/index.js +6 -6
  9. package/dist/blobs/index.cjs.map +1 -1
  10. package/dist/blobs/index.d.cts +4 -4
  11. package/dist/blobs/index.d.ts +4 -4
  12. package/dist/blobs/index.js +5 -5
  13. package/dist/bundle/index.cjs +683 -39
  14. package/dist/bundle/index.cjs.map +1 -1
  15. package/dist/bundle/index.d.cts +5 -5
  16. package/dist/bundle/index.d.ts +5 -5
  17. package/dist/bundle/index.js +9 -9
  18. package/dist/{chunk-OPDTLHFA.js → chunk-3EWA37FV.js} +2 -2
  19. package/dist/{chunk-ZCFS7U4J.js → chunk-4PEFEETV.js} +2 -2
  20. package/dist/{chunk-ZC7MNVYN.js → chunk-4TBBMHVC.js} +2 -2
  21. package/dist/{chunk-AGRC7NQQ.js → chunk-535SSHBS.js} +33 -1
  22. package/dist/chunk-535SSHBS.js.map +1 -0
  23. package/dist/{chunk-SJJQKNMP.js → chunk-56DJ7JVK.js} +4 -4
  24. package/dist/{chunk-C2CIIQRG.js → chunk-5LQG6ZO2.js} +2 -2
  25. package/dist/{chunk-6AD5TBF2.js → chunk-6AJBSQU4.js} +3 -3
  26. package/dist/{chunk-LWSD4QPT.js → chunk-6RR3MNMG.js} +3 -3
  27. package/dist/{chunk-O53RIZCC.js → chunk-7HT2MEZ5.js} +5 -5
  28. package/dist/{chunk-7LVRIW4G.js → chunk-7PS7EOCF.js} +4 -4
  29. package/dist/{chunk-GFPR7VJS.js → chunk-A5ZOOZFB.js} +4 -4
  30. package/dist/{chunk-B7GGYNKQ.js → chunk-AAVWKNZW.js} +2 -2
  31. package/dist/{chunk-TMHJEYW7.js → chunk-ACKFRSAH.js} +302 -137
  32. package/dist/chunk-ACKFRSAH.js.map +1 -0
  33. package/dist/{chunk-SZ4N3IL5.js → chunk-BIYRQQV6.js} +5 -5
  34. package/dist/{chunk-CILT6V3V.js → chunk-BQ65SS5A.js} +2 -2
  35. package/dist/{chunk-DLTU4M2I.js → chunk-COFPAMX6.js} +6 -6
  36. package/dist/{chunk-UA6G45ME.js → chunk-DKO2QFSA.js} +3 -3
  37. package/dist/{chunk-L6BYRCYB.js → chunk-DQU36Q7I.js} +2 -2
  38. package/dist/{chunk-VOXMU6LB.js → chunk-EGD5DXFT.js} +2 -2
  39. package/dist/{chunk-BXOUVUES.js → chunk-F4OJZIWQ.js} +4 -4
  40. package/dist/{chunk-P3Z5Y2TS.js → chunk-FWPKCXTN.js} +2 -2
  41. package/dist/{chunk-LYNNZEQD.js → chunk-GC4V7RU7.js} +1 -1
  42. package/dist/chunk-GC4V7RU7.js.map +1 -0
  43. package/dist/{chunk-6BYBVRZU.js → chunk-HOR4R722.js} +3 -3
  44. package/dist/{chunk-XSIFXX54.js → chunk-JD3OZAI4.js} +2 -2
  45. package/dist/{chunk-UOC7JMZO.js → chunk-KGCORI4L.js} +135 -10
  46. package/dist/chunk-KGCORI4L.js.map +1 -0
  47. package/dist/{chunk-RRDWXNBQ.js → chunk-KI6HAJWL.js} +3 -3
  48. package/dist/{chunk-LSEW3ZZ2.js → chunk-L2FE64BU.js} +3 -3
  49. package/dist/{chunk-HBAJDI2N.js → chunk-LX3CB26H.js} +5 -5
  50. package/dist/{chunk-LOA2VCMS.js → chunk-NSCVNK5K.js} +5 -5
  51. package/dist/{chunk-4BHFNKTP.js → chunk-OHVFWCJP.js} +2 -2
  52. package/dist/{chunk-7JJE3OMJ.js → chunk-PE4AQGFH.js} +5 -5
  53. package/dist/{chunk-RHQYVHFH.js → chunk-TS26M2SB.js} +2 -2
  54. package/dist/{chunk-EKNUBIIQ.js → chunk-UWNYBOOO.js} +4 -4
  55. package/dist/{chunk-WNRGOVLG.js → chunk-VU7SWWT5.js} +2 -2
  56. package/dist/{chunk-WUG3E423.js → chunk-WBAYSNUQ.js} +4 -4
  57. package/dist/{chunk-XHM2SARW.js → chunk-WGHU7BLI.js} +3 -3
  58. package/dist/{chunk-5ARRXIVR.js → chunk-X73VS74Y.js} +2 -2
  59. package/dist/{chunk-M45IRXDM.js → chunk-YHPM5D7Y.js} +3 -3
  60. package/dist/{chunk-P4EDT5ZP.js → chunk-YNTBADIY.js} +2 -2
  61. package/dist/{chunk-IUBHXEPJ.js → chunk-YULZKK4F.js} +2 -2
  62. package/dist/{chunk-IEPT7HVP.js → chunk-Z4DO7YSI.js} +2 -2
  63. package/dist/chunk-ZC7J6ZYV.js +7 -0
  64. package/dist/chunk-ZC7J6ZYV.js.map +1 -0
  65. package/dist/{chunk-HLGDYFWR.js → chunk-ZNQYHJXX.js} +2 -2
  66. package/dist/{chunk-CHBXWJZQ.js → chunk-ZWTNWAO4.js} +2 -2
  67. package/dist/consent/index.cjs.map +1 -1
  68. package/dist/consent/index.d.cts +4 -4
  69. package/dist/consent/index.d.ts +4 -4
  70. package/dist/consent/index.js +3 -3
  71. package/dist/{crypto-AJB72OKN.js → crypto-QXQOHMHF.js} +3 -3
  72. package/dist/{delegation-6FCWDRUS.js → delegation-NIQ43IPU.js} +5 -5
  73. package/dist/derivations/index.cjs.map +1 -1
  74. package/dist/derivations/index.d.cts +5 -5
  75. package/dist/derivations/index.d.ts +5 -5
  76. package/dist/derivations/index.js +4 -4
  77. package/dist/{dev-unlock-ckqa_Nso.d.cts → dev-unlock-BF4OSxRv.d.cts} +1 -1
  78. package/dist/{dev-unlock-D3mpVFRc.d.ts → dev-unlock-DV7ujTCI.d.ts} +1 -1
  79. package/dist/executor-6ZDSDZ6V.js +8 -0
  80. package/dist/executor-723ZP6TH.js +11 -0
  81. package/dist/executor-IDZDAFNH.js +8 -0
  82. package/dist/{fanout-sidecar-ZSKEQ6NI.js → fanout-sidecar-N6OJX6QR.js} +2 -2
  83. package/dist/guards/index.cjs.map +1 -1
  84. package/dist/guards/index.d.cts +5 -5
  85. package/dist/guards/index.d.ts +5 -5
  86. package/dist/guards/index.js +3 -3
  87. package/dist/{hash-rDSSd_oW.d.cts → hash-BcF5WQXl.d.cts} +1 -1
  88. package/dist/{hash-CTZVkXLx.d.ts → hash-DswxkLtW.d.ts} +1 -1
  89. package/dist/history/index.cjs.map +1 -1
  90. package/dist/history/index.d.cts +5 -5
  91. package/dist/history/index.d.ts +5 -5
  92. package/dist/history/index.js +5 -5
  93. package/dist/i18n/index.cjs.map +1 -1
  94. package/dist/i18n/index.d.cts +4 -4
  95. package/dist/i18n/index.d.ts +4 -4
  96. package/dist/i18n/index.js +6 -6
  97. package/dist/{immutable-guard-C51vAHuh.d.cts → immutable-guard-7KqslW2K.d.cts} +1 -1
  98. package/dist/{immutable-guard-DyD0qg2k.d.ts → immutable-guard-C8IYdzfu.d.ts} +1 -1
  99. package/dist/{index-Cmop06zJ.d.cts → index-CUVOMtgg.d.cts} +28 -2
  100. package/dist/{index-CkFHr4OP.d.ts → index-Cqzp4tt9.d.ts} +28 -2
  101. package/dist/index.cjs +699 -42
  102. package/dist/index.cjs.map +1 -1
  103. package/dist/index.d.cts +22 -13
  104. package/dist/index.d.ts +22 -13
  105. package/dist/index.js +59 -40
  106. package/dist/index.js.map +1 -1
  107. package/dist/indexing/index.cjs.map +1 -1
  108. package/dist/indexing/index.js +2 -2
  109. package/dist/issue-ADVS4OVP.js +12 -0
  110. package/dist/{ledger-5JMVF7PY.js → ledger-CWSE3BLF.js} +5 -5
  111. package/dist/materialized-views/index.cjs.map +1 -1
  112. package/dist/materialized-views/index.d.cts +5 -5
  113. package/dist/materialized-views/index.d.ts +5 -5
  114. package/dist/materialized-views/index.js +6 -6
  115. package/dist/noydb-VZ4JVW55.js +35 -0
  116. package/dist/overlay-views/index.cjs.map +1 -1
  117. package/dist/overlay-views/index.d.cts +5 -5
  118. package/dist/overlay-views/index.d.ts +5 -5
  119. package/dist/overlay-views/index.js +4 -4
  120. package/dist/periods/index.cjs.map +1 -1
  121. package/dist/periods/index.d.cts +4 -4
  122. package/dist/periods/index.d.ts +4 -4
  123. package/dist/periods/index.js +5 -5
  124. package/dist/{public-envelope-PFLZI5MO.js → public-envelope-SYHEYQ3X.js} +4 -4
  125. package/dist/query/index.cjs +89 -7
  126. package/dist/query/index.cjs.map +1 -1
  127. package/dist/query/index.d.cts +2 -2
  128. package/dist/query/index.d.ts +2 -2
  129. package/dist/query/index.js +3 -3
  130. package/dist/{registry-NCY445U5.js → registry-DK5YWAAA.js} +3 -3
  131. package/dist/registry-IUZQVVBB.js +8 -0
  132. package/dist/registry-XGLNADIE.js +8 -0
  133. package/dist/{revoke-7RLGQWZ7.js → revoke-ZDFKMR5E.js} +6 -6
  134. package/dist/session/index.cjs.map +1 -1
  135. package/dist/session/index.d.cts +5 -5
  136. package/dist/session/index.d.ts +5 -5
  137. package/dist/session/index.js +3 -3
  138. package/dist/shadow/index.cjs.map +1 -1
  139. package/dist/shadow/index.d.cts +4 -4
  140. package/dist/shadow/index.d.ts +4 -4
  141. package/dist/shadow/index.js +2 -2
  142. package/dist/{signer-6JF44I4A.js → signer-P5D7Y72U.js} +5 -5
  143. package/dist/snapshots/index.cjs.map +1 -1
  144. package/dist/snapshots/index.d.cts +4 -4
  145. package/dist/snapshots/index.d.ts +4 -4
  146. package/dist/snapshots/index.js +4 -4
  147. package/dist/{stale-UBLP3RJ3.js → stale-7FRJVHN6.js} +2 -2
  148. package/dist/state-vault-TMXZRTY5.js +147 -0
  149. package/dist/state-vault-TMXZRTY5.js.map +1 -0
  150. package/dist/store/index.cjs.map +1 -1
  151. package/dist/store/index.d.cts +4 -4
  152. package/dist/store/index.d.ts +4 -4
  153. package/dist/store/index.js +2 -2
  154. package/dist/{strategy-rtpKDfTC.d.ts → strategy-CrS7PnbE.d.cts} +20 -1
  155. package/dist/{strategy-rtpKDfTC.d.cts → strategy-CrS7PnbE.d.ts} +20 -1
  156. package/dist/sync/index.cjs.map +1 -1
  157. package/dist/sync/index.d.cts +3 -3
  158. package/dist/sync/index.d.ts +3 -3
  159. package/dist/sync/index.js +4 -4
  160. package/dist/team/index.cjs.map +1 -1
  161. package/dist/team/index.d.cts +4 -4
  162. package/dist/team/index.d.ts +4 -4
  163. package/dist/team/index.js +8 -8
  164. package/dist/tx/index.cjs.map +1 -1
  165. package/dist/tx/index.d.cts +4 -4
  166. package/dist/tx/index.d.ts +4 -4
  167. package/dist/tx/index.js +3 -3
  168. package/dist/{types-DRdfwgTG.d.ts → types-BFHQUjdy.d.ts} +341 -90
  169. package/dist/{types-BGwjsDef.d.cts → types-V5R2-pd4.d.cts} +341 -90
  170. package/dist/{ulid-D4d0Xto3.d.cts → ulid-CwNf9e6-.d.cts} +1 -1
  171. package/dist/{ulid-DOTPZ5_h.d.ts → ulid-p2nKiiKg.d.ts} +1 -1
  172. package/dist/util/index.cjs.map +1 -1
  173. package/dist/util/index.js +1 -1
  174. package/dist/{vault-group-Z4KB75ZH.js → vault-group-W7QC4UYW.js} +175 -18
  175. package/dist/vault-group-W7QC4UYW.js.map +1 -0
  176. package/dist/{with-derivation-CB1EdcFF.d.cts → with-derivation-C9K43BOB.d.cts} +1 -1
  177. package/dist/{with-derivation-B082Y_WQ.d.ts → with-derivation-Ds9yZgCj.d.ts} +1 -1
  178. package/dist/{with-materialized-view-CzRg1Dpr.d.cts → with-materialized-view-DgQcAjYv.d.cts} +1 -1
  179. package/dist/{with-materialized-view-Dw4SwjKl.d.ts → with-materialized-view-DwR4jkV5.d.ts} +1 -1
  180. package/dist/{with-overlayed-view-C9YFKXzn.d.cts → with-overlayed-view-7-rUB3vD.d.cts} +1 -1
  181. package/dist/{with-overlayed-view-CaCXeW26.d.ts → with-overlayed-view-ByyhHdVr.d.ts} +1 -1
  182. package/package.json +3 -3
  183. package/dist/chunk-AGRC7NQQ.js.map +0 -1
  184. package/dist/chunk-LYNNZEQD.js.map +0 -1
  185. package/dist/chunk-TMHJEYW7.js.map +0 -1
  186. package/dist/chunk-UOC7JMZO.js.map +0 -1
  187. package/dist/executor-7KSCEIFA.js +0 -8
  188. package/dist/executor-D2QMNGRJ.js +0 -8
  189. package/dist/executor-O5AZK7UW.js +0 -11
  190. package/dist/issue-YIYG4OW5.js +0 -12
  191. package/dist/noydb-D5SLAJ6V.js +0 -34
  192. package/dist/registry-BVQ5ITMF.js +0 -8
  193. package/dist/registry-JLP3QOLD.js +0 -8
  194. package/dist/vault-group-Z4KB75ZH.js.map +0 -1
  195. /package/dist/{chunk-OPDTLHFA.js.map → chunk-3EWA37FV.js.map} +0 -0
  196. /package/dist/{chunk-ZCFS7U4J.js.map → chunk-4PEFEETV.js.map} +0 -0
  197. /package/dist/{chunk-ZC7MNVYN.js.map → chunk-4TBBMHVC.js.map} +0 -0
  198. /package/dist/{chunk-SJJQKNMP.js.map → chunk-56DJ7JVK.js.map} +0 -0
  199. /package/dist/{chunk-C2CIIQRG.js.map → chunk-5LQG6ZO2.js.map} +0 -0
  200. /package/dist/{chunk-6AD5TBF2.js.map → chunk-6AJBSQU4.js.map} +0 -0
  201. /package/dist/{chunk-LWSD4QPT.js.map → chunk-6RR3MNMG.js.map} +0 -0
  202. /package/dist/{chunk-O53RIZCC.js.map → chunk-7HT2MEZ5.js.map} +0 -0
  203. /package/dist/{chunk-7LVRIW4G.js.map → chunk-7PS7EOCF.js.map} +0 -0
  204. /package/dist/{chunk-GFPR7VJS.js.map → chunk-A5ZOOZFB.js.map} +0 -0
  205. /package/dist/{chunk-B7GGYNKQ.js.map → chunk-AAVWKNZW.js.map} +0 -0
  206. /package/dist/{chunk-SZ4N3IL5.js.map → chunk-BIYRQQV6.js.map} +0 -0
  207. /package/dist/{chunk-CILT6V3V.js.map → chunk-BQ65SS5A.js.map} +0 -0
  208. /package/dist/{chunk-DLTU4M2I.js.map → chunk-COFPAMX6.js.map} +0 -0
  209. /package/dist/{chunk-UA6G45ME.js.map → chunk-DKO2QFSA.js.map} +0 -0
  210. /package/dist/{chunk-L6BYRCYB.js.map → chunk-DQU36Q7I.js.map} +0 -0
  211. /package/dist/{chunk-VOXMU6LB.js.map → chunk-EGD5DXFT.js.map} +0 -0
  212. /package/dist/{chunk-BXOUVUES.js.map → chunk-F4OJZIWQ.js.map} +0 -0
  213. /package/dist/{chunk-P3Z5Y2TS.js.map → chunk-FWPKCXTN.js.map} +0 -0
  214. /package/dist/{chunk-6BYBVRZU.js.map → chunk-HOR4R722.js.map} +0 -0
  215. /package/dist/{chunk-XSIFXX54.js.map → chunk-JD3OZAI4.js.map} +0 -0
  216. /package/dist/{chunk-RRDWXNBQ.js.map → chunk-KI6HAJWL.js.map} +0 -0
  217. /package/dist/{chunk-LSEW3ZZ2.js.map → chunk-L2FE64BU.js.map} +0 -0
  218. /package/dist/{chunk-HBAJDI2N.js.map → chunk-LX3CB26H.js.map} +0 -0
  219. /package/dist/{chunk-LOA2VCMS.js.map → chunk-NSCVNK5K.js.map} +0 -0
  220. /package/dist/{chunk-4BHFNKTP.js.map → chunk-OHVFWCJP.js.map} +0 -0
  221. /package/dist/{chunk-7JJE3OMJ.js.map → chunk-PE4AQGFH.js.map} +0 -0
  222. /package/dist/{chunk-RHQYVHFH.js.map → chunk-TS26M2SB.js.map} +0 -0
  223. /package/dist/{chunk-EKNUBIIQ.js.map → chunk-UWNYBOOO.js.map} +0 -0
  224. /package/dist/{chunk-WNRGOVLG.js.map → chunk-VU7SWWT5.js.map} +0 -0
  225. /package/dist/{chunk-WUG3E423.js.map → chunk-WBAYSNUQ.js.map} +0 -0
  226. /package/dist/{chunk-XHM2SARW.js.map → chunk-WGHU7BLI.js.map} +0 -0
  227. /package/dist/{chunk-5ARRXIVR.js.map → chunk-X73VS74Y.js.map} +0 -0
  228. /package/dist/{chunk-M45IRXDM.js.map → chunk-YHPM5D7Y.js.map} +0 -0
  229. /package/dist/{chunk-P4EDT5ZP.js.map → chunk-YNTBADIY.js.map} +0 -0
  230. /package/dist/{chunk-IUBHXEPJ.js.map → chunk-YULZKK4F.js.map} +0 -0
  231. /package/dist/{chunk-IEPT7HVP.js.map → chunk-Z4DO7YSI.js.map} +0 -0
  232. /package/dist/{chunk-HLGDYFWR.js.map → chunk-ZNQYHJXX.js.map} +0 -0
  233. /package/dist/{chunk-CHBXWJZQ.js.map → chunk-ZWTNWAO4.js.map} +0 -0
  234. /package/dist/{crypto-AJB72OKN.js.map → crypto-QXQOHMHF.js.map} +0 -0
  235. /package/dist/{delegation-6FCWDRUS.js.map → delegation-NIQ43IPU.js.map} +0 -0
  236. /package/dist/{executor-7KSCEIFA.js.map → executor-6ZDSDZ6V.js.map} +0 -0
  237. /package/dist/{executor-D2QMNGRJ.js.map → executor-723ZP6TH.js.map} +0 -0
  238. /package/dist/{executor-O5AZK7UW.js.map → executor-IDZDAFNH.js.map} +0 -0
  239. /package/dist/{fanout-sidecar-ZSKEQ6NI.js.map → fanout-sidecar-N6OJX6QR.js.map} +0 -0
  240. /package/dist/{issue-YIYG4OW5.js.map → issue-ADVS4OVP.js.map} +0 -0
  241. /package/dist/{ledger-5JMVF7PY.js.map → ledger-CWSE3BLF.js.map} +0 -0
  242. /package/dist/{noydb-D5SLAJ6V.js.map → noydb-VZ4JVW55.js.map} +0 -0
  243. /package/dist/{public-envelope-PFLZI5MO.js.map → public-envelope-SYHEYQ3X.js.map} +0 -0
  244. /package/dist/{registry-BVQ5ITMF.js.map → registry-DK5YWAAA.js.map} +0 -0
  245. /package/dist/{registry-JLP3QOLD.js.map → registry-IUZQVVBB.js.map} +0 -0
  246. /package/dist/{registry-NCY445U5.js.map → registry-XGLNADIE.js.map} +0 -0
  247. /package/dist/{revoke-7RLGQWZ7.js.map → revoke-ZDFKMR5E.js.map} +0 -0
  248. /package/dist/{signer-6JF44I4A.js.map → signer-P5D7Y72U.js.map} +0 -0
  249. /package/dist/{stale-UBLP3RJ3.js.map → stale-7FRJVHN6.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -46,7 +46,7 @@ var init_types = __esm({
46
46
  });
47
47
 
48
48
  // src/errors.ts
49
- var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, ReadOnlyAtInstantError, ReadOnlyFrameError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, PeriodClosedError, RecordLockedError, FieldFrozenError, InvariantError, AmendmentForbiddenError, DirectoryDisabledError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, SequenceContentionError, SequenceOfflineError, BundleVersionConflictError, NetworkError, NotFoundError, ValidationError, SchemaValidationError, SchemaUpdateError, NonAdditiveSchemaChangeError, SchemaLockedError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, DictKeyMissingError, DictKeyInUseError, MissingTranslationError, LocaleNotSpecifiedError, ScriptViolationError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, AttestationError, SessionExpiredError, SessionNotFoundError, SessionPolicyError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, FilenameSanitizationError, PathEscapeError, DerivationCycleError, DerivationDepthError, DerivationOutputUnknownError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, MaterializedViewConfigError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, SnapshotNotFoundError, UnknownShardError, ShardProvisioningError, VaultTemplateNotFoundError;
49
+ var NoydbError, DecryptionError, TamperedError, InvalidKeyError, KeyringCorruptError, NoAccessError, ReadOnlyError, ReadOnlyAtInstantError, ReadOnlyFrameError, PermissionDeniedError, ExportCapabilityError, KeyringExpiredError, ImportCapabilityError, StoreCapabilityError, PrivilegeEscalationError, ReservedVaultNameError, PeriodClosedError, RecordLockedError, FieldFrozenError, InvariantError, AmendmentForbiddenError, DirectoryDisabledError, TierNotGrantedError, ElevationExpiredError, AlreadyElevatedError, TierDemoteDeniedError, DelegationTargetMissingError, ConflictError, LedgerContentionError, SequenceContentionError, SequenceOfflineError, NumberingUncertaintyError, BundleVersionConflictError, NetworkError, NotFoundError, ValidationError, SchemaValidationError, SchemaUpdateError, NonAdditiveSchemaChangeError, SchemaLockedError, SchemaFenceError, MigrationRequiredError, QuiesceTimeoutError, GroupCardinalityError, IndexRequiredError, UniqueConstraintError, UnsupportedIndexOptionError, IndexWriteFailureError, BundleIntegrityError, BundleSealMismatchError, ReservedCollectionNameError, DictKeyMissingError, DictKeyInUseError, MissingTranslationError, LocaleNotSpecifiedError, ScriptViolationError, TranslatorNotConfiguredError, BackupLedgerError, BackupCorruptedError, AttestationError, SessionExpiredError, SessionNotFoundError, SessionPolicyError, JoinTooLargeError, CrossJoinTooLargeError, CrossJoinSourceUnknownError, DanglingReferenceError, FilenameSanitizationError, PathEscapeError, DerivationCycleError, DerivationDepthError, DerivationOutputUnknownError, DerivationOutputShapeError, DerivationCapExceededError, MaterializedViewCycleError, MaterializedViewSourceUnknownError, MaterializedViewTooLargeError, MaterializedViewConfigError, OverlayBaseIsVirtualError, OverlayCollectionUnavailableError, OverlayNameCollisionError, OverlayIdMismatchError, SnapshotNotFoundError, UnknownShardError, ShardProvisioningError, CrossShardJoinError, VaultTemplateNotFoundError;
50
50
  var init_errors = __esm({
51
51
  "src/errors.ts"() {
52
52
  "use strict";
@@ -188,6 +188,18 @@ var init_errors = __esm({
188
188
  this.offendingCollection = offendingCollection;
189
189
  }
190
190
  };
191
+ ReservedVaultNameError = class extends NoydbError {
192
+ /** The rejected vault name. */
193
+ vaultName;
194
+ constructor(vaultName) {
195
+ super(
196
+ "RESERVED_VAULT_NAME",
197
+ `"${vaultName}" is a reserved internal vault name and cannot be used as a group name or partition key`
198
+ );
199
+ this.name = "ReservedVaultNameError";
200
+ this.vaultName = vaultName;
201
+ }
202
+ };
191
203
  PeriodClosedError = class extends NoydbError {
192
204
  periodName;
193
205
  endDate;
@@ -362,6 +374,17 @@ var init_errors = __esm({
362
374
  this.name = "SequenceOfflineError";
363
375
  }
364
376
  };
377
+ NumberingUncertaintyError = class extends NoydbError {
378
+ series;
379
+ constructor(series) {
380
+ super(
381
+ "NUMBERING_UNCERTAINTY",
382
+ `Deferred numbering for series "${series}" cannot run: the store does not expose getStoreTime() (capabilities.serverWriteTime). Use a CAS sequence or a store with serverWriteTime.`
383
+ );
384
+ this.name = "NumberingUncertaintyError";
385
+ this.series = series;
386
+ }
387
+ };
365
388
  BundleVersionConflictError = class extends NoydbError {
366
389
  /** The bundle handle of the newer remote version that rejected the push. */
367
390
  remoteVersion;
@@ -965,6 +988,12 @@ Resolutions:
965
988
  this.vaultId = vaultId;
966
989
  }
967
990
  };
991
+ CrossShardJoinError = class extends NoydbError {
992
+ constructor(message) {
993
+ super("CROSS_SHARD_JOIN", message);
994
+ this.name = "CrossShardJoinError";
995
+ }
996
+ };
968
997
  VaultTemplateNotFoundError = class extends NoydbError {
969
998
  templateName;
970
999
  constructor(templateName) {
@@ -1255,6 +1284,15 @@ var init_crypto = __esm({
1255
1284
  }
1256
1285
  });
1257
1286
 
1287
+ // src/federation/constants.ts
1288
+ var STATE_VAULT_NAME;
1289
+ var init_constants = __esm({
1290
+ "src/federation/constants.ts"() {
1291
+ "use strict";
1292
+ STATE_VAULT_NAME = "__noydb_state__";
1293
+ }
1294
+ });
1295
+
1258
1296
  // src/meta/public-envelope/schema.ts
1259
1297
  function validatePublicEnvelopeInput(input, schema) {
1260
1298
  const allowed = new Set(schema.fields);
@@ -1719,7 +1757,7 @@ var init_patch = __esm({
1719
1757
 
1720
1758
  // src/history/ledger/constants.ts
1721
1759
  var LEDGER_COLLECTION, LEDGER_DELTAS_COLLECTION;
1722
- var init_constants = __esm({
1760
+ var init_constants2 = __esm({
1723
1761
  "src/history/ledger/constants.ts"() {
1724
1762
  "use strict";
1725
1763
  LEDGER_COLLECTION = "_ledger";
@@ -1754,7 +1792,7 @@ var init_store = __esm({
1754
1792
  init_errors();
1755
1793
  init_entry();
1756
1794
  init_patch();
1757
- init_constants();
1795
+ init_constants2();
1758
1796
  init_hash();
1759
1797
  MAX_APPEND_ATTEMPTS = 8;
1760
1798
  LedgerStore = class {
@@ -2330,10 +2368,10 @@ function shouldRoundUp(negative, lastKeptDigit, firstDiscarded, hasMoreNonZeroAf
2330
2368
  }
2331
2369
  }
2332
2370
  function parseToScaledInt(input, scale, rounding) {
2333
- const canonical = toCanonicalDecimalString(input);
2334
- if (canonical === null) return { ok: false, reason: "nonfinite" };
2335
- const negative = canonical.startsWith("-");
2336
- const unsigned = negative ? canonical.slice(1) : canonical;
2371
+ const canonical2 = toCanonicalDecimalString(input);
2372
+ if (canonical2 === null) return { ok: false, reason: "nonfinite" };
2373
+ const negative = canonical2.startsWith("-");
2374
+ const unsigned = negative ? canonical2.slice(1) : canonical2;
2337
2375
  const dot = unsigned.indexOf(".");
2338
2376
  const intPart = dot === -1 ? unsigned : unsigned.slice(0, dot);
2339
2377
  const fracPart = dot === -1 ? "" : unsigned.slice(dot + 1);
@@ -3466,12 +3504,12 @@ var init_dependency_analyzer = __esm({
3466
3504
 
3467
3505
  // src/materialized-views/query-hash.ts
3468
3506
  async function computeQueryHash(mvName, dependencies, queryPlanSummary) {
3469
- const canonical = JSON.stringify({
3507
+ const canonical2 = JSON.stringify({
3470
3508
  mvName,
3471
3509
  dependencies: [...dependencies].sort(),
3472
3510
  queryPlanSummary
3473
3511
  });
3474
- const bytes = new TextEncoder().encode(canonical);
3512
+ const bytes = new TextEncoder().encode(canonical2);
3475
3513
  const digest = await crypto.subtle.digest("SHA-256", bytes);
3476
3514
  return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
3477
3515
  }
@@ -4310,12 +4348,12 @@ var init_read_only_facade = __esm({
4310
4348
 
4311
4349
  // src/derivations/strategy-hash.ts
4312
4350
  async function computeStrategyHash(source, outputKeys, derive) {
4313
- const canonical = JSON.stringify({
4351
+ const canonical2 = JSON.stringify({
4314
4352
  source,
4315
4353
  outputs: [...outputKeys].sort(),
4316
4354
  derive: derive.toString()
4317
4355
  });
4318
- const bytes = new TextEncoder().encode(canonical);
4356
+ const bytes = new TextEncoder().encode(canonical2);
4319
4357
  const digest = await crypto.subtle.digest("SHA-256", bytes);
4320
4358
  return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
4321
4359
  }
@@ -4587,6 +4625,54 @@ var init_classify_skip = __esm({
4587
4625
  }
4588
4626
  });
4589
4627
 
4628
+ // src/federation/cross-shard-join.ts
4629
+ function coerceKey(value) {
4630
+ if (value === null || value === void 0) return null;
4631
+ if (typeof value === "string") return value;
4632
+ if (typeof value === "number" || typeof value === "bigint") return String(value);
4633
+ return null;
4634
+ }
4635
+ function warnOnceBroadcastMiss(field, as, key) {
4636
+ const dedup = `${field}\u2192${as}:${key}`;
4637
+ if (warnedBroadcastKeys.has(dedup)) return;
4638
+ warnedBroadcastKeys.add(dedup);
4639
+ console.warn(
4640
+ `[noy-db] broadcastJoin: no "${as}" dimension row for ${field}="${key}". Attaching null. Use mode: 'cascade' to silence.`
4641
+ );
4642
+ }
4643
+ async function applyBroadcastLegs(rows, legs) {
4644
+ if (legs.length === 0) return [...rows];
4645
+ const indexes = [];
4646
+ for (const leg of legs) {
4647
+ const map = /* @__PURE__ */ new Map();
4648
+ for (const rec of await leg.from.list()) {
4649
+ const k = coerceKey(readPath(rec, leg.on));
4650
+ if (k !== null && !map.has(k)) map.set(k, rec);
4651
+ }
4652
+ indexes.push({ leg, map });
4653
+ }
4654
+ return rows.map((row) => {
4655
+ const out = { ...row };
4656
+ for (const { leg, map } of indexes) {
4657
+ const key = coerceKey(readPath(row, leg.field));
4658
+ const match = key === null ? null : map.get(key) ?? null;
4659
+ if (match === null && leg.mode === "warn") {
4660
+ warnOnceBroadcastMiss(leg.field, leg.as, key ?? "<null>");
4661
+ }
4662
+ out[leg.as] = match;
4663
+ }
4664
+ return out;
4665
+ });
4666
+ }
4667
+ var warnedBroadcastKeys;
4668
+ var init_cross_shard_join = __esm({
4669
+ "src/federation/cross-shard-join.ts"() {
4670
+ "use strict";
4671
+ init_predicate();
4672
+ warnedBroadcastKeys = /* @__PURE__ */ new Set();
4673
+ }
4674
+ });
4675
+
4590
4676
  // src/federation/cross-vault-live.ts
4591
4677
  var CrossVaultLive;
4592
4678
  var init_cross_vault_live = __esm({
@@ -4794,6 +4880,9 @@ function assertSafePartitionKey(partitionKey) {
4794
4880
  if (partitionKey.length === 0) {
4795
4881
  throw new ValidationError("partitionKey must be a non-empty string");
4796
4882
  }
4883
+ if (partitionKey === STATE_VAULT_NAME) {
4884
+ throw new ReservedVaultNameError(partitionKey);
4885
+ }
4797
4886
  if (!SAFE_PARTITION_KEY.test(partitionKey)) {
4798
4887
  throw new ValidationError(
4799
4888
  `partitionKey "${partitionKey}" contains characters outside [A-Za-z0-9._-]. Map your records to a store-safe key in sharding.keyOf.`
@@ -4810,7 +4899,9 @@ var init_vault_group = __esm({
4810
4899
  "src/federation/vault-group.ts"() {
4811
4900
  "use strict";
4812
4901
  init_errors();
4902
+ init_constants();
4813
4903
  init_classify_skip();
4904
+ init_cross_shard_join();
4814
4905
  init_cross_vault_live();
4815
4906
  init_aggregate_across();
4816
4907
  SHARD_SEPARATOR = "--";
@@ -4833,15 +4924,38 @@ var init_vault_group = __esm({
4833
4924
  registry;
4834
4925
  sharding;
4835
4926
  template;
4927
+ /** @internal — set when the group is managed (no explicit registry). */
4928
+ stateVault;
4929
+ /** @internal */
4930
+ _attachStateVault(sv) {
4931
+ this.stateVault = sv;
4932
+ }
4836
4933
  /** Deterministic vault name for a partition key, namespaced by the group. */
4837
4934
  shardVaultId(partitionKey) {
4838
4935
  assertSafePartitionKey(partitionKey);
4839
4936
  return `${this.name}${SHARD_SEPARATOR}${partitionKey}`;
4840
4937
  }
4841
- /** All registry rows (hydrates the registry collection first). */
4938
+ /**
4939
+ * @internal — group-qualified registry record key (avoids cross-group key
4940
+ * collisions). Identical to the shard vault id by design — the registry row
4941
+ * for a shard is keyed by that shard's vault id — so it delegates to
4942
+ * `shardVaultId`, reusing its partition-key validation.
4943
+ */
4944
+ registryId(partitionKey) {
4945
+ return this.shardVaultId(partitionKey);
4946
+ }
4947
+ /**
4948
+ * Registry rows for THIS group (hydrates the registry collection first).
4949
+ * The registry may be shared across groups (the auto-wired StateManagement
4950
+ * vault holds one `vaultRegistry` for the whole instance), so rows are
4951
+ * filtered by `group` — without this, a group's fan-out reads would leak
4952
+ * across into other groups' shards. Mirrors the `${group}--` scoping that
4953
+ * `liveBinding().isRelevant` already applies to the reactive path.
4954
+ */
4842
4955
  async allRows() {
4843
4956
  await this.registry.list();
4844
- return this.registry.query().toArray();
4957
+ const rows = this.registry.query().toArray();
4958
+ return rows.filter((r) => r.group === this.name);
4845
4959
  }
4846
4960
  /** Open an existing shard and apply the template. */
4847
4961
  async openShard(partitionKey) {
@@ -4859,19 +4973,32 @@ var init_vault_group = __esm({
4859
4973
  */
4860
4974
  async createShard(partitionKey) {
4861
4975
  const vaultId = this.shardVaultId(partitionKey);
4862
- const row = await this.registry.get(partitionKey);
4976
+ const row = await this.registry.get(this.registryId(partitionKey));
4863
4977
  const provisioned = await this.db._shardVaultProvisioned(vaultId);
4864
4978
  if (row && !provisioned) throw new ShardProvisioningError(vaultId, partitionKey);
4865
4979
  if (row && provisioned) return this.openShard(partitionKey);
4866
4980
  const vault = await this.db.openVault(vaultId);
4867
4981
  this.template.configure(vault);
4868
- await this.registry.put(partitionKey, {
4982
+ await this.registry.put(this.registryId(partitionKey), {
4869
4983
  vaultId,
4870
4984
  partitionKey,
4871
4985
  templateName: this.sharding.vaultTemplate,
4872
4986
  schemaVersion: this.template.version,
4873
- createdAt: Date.now()
4987
+ createdAt: Date.now(),
4988
+ group: this.name
4874
4989
  });
4990
+ if (this.stateVault) {
4991
+ try {
4992
+ await this.stateVault.appendEvent({
4993
+ type: "shard-created",
4994
+ group: this.name,
4995
+ vaultId,
4996
+ templateName: this.sharding.vaultTemplate,
4997
+ version: this.template.version
4998
+ });
4999
+ } catch {
5000
+ }
5001
+ }
4875
5002
  return vault;
4876
5003
  }
4877
5004
  /**
@@ -4881,7 +5008,7 @@ var init_vault_group = __esm({
4881
5008
  */
4882
5009
  async shard(partitionKey) {
4883
5010
  const vaultId = this.shardVaultId(partitionKey);
4884
- const row = await this.registry.get(partitionKey);
5011
+ const row = await this.registry.get(this.registryId(partitionKey));
4885
5012
  if (!row) throw new UnknownShardError(partitionKey, this.name);
4886
5013
  const provisioned = await this.db._shardVaultProvisioned(vaultId);
4887
5014
  if (!provisioned) throw new ShardProvisioningError(vaultId, partitionKey);
@@ -4920,7 +5047,7 @@ var init_vault_group = __esm({
4920
5047
  /** Route a write to the shard owning `keyOf(record)`. */
4921
5048
  async put(id, record) {
4922
5049
  const key = this.group.sharding.keyOf(record);
4923
- const row = await this.group.registry.get(key);
5050
+ const row = await this.group.registry.get(this.group.registryId(key));
4924
5051
  let vault;
4925
5052
  if (!row) {
4926
5053
  if (this.group.sharding.autoCreate === false) {
@@ -4938,31 +5065,89 @@ var init_vault_group = __esm({
4938
5065
  }
4939
5066
  };
4940
5067
  ShardedQuery = class _ShardedQuery {
4941
- constructor(group, collectionName, clauses) {
5068
+ constructor(group, collectionName, clauses, coPartitionedLegs = [], broadcastLegs = []) {
4942
5069
  this.group = group;
4943
5070
  this.collectionName = collectionName;
4944
5071
  this.clauses = clauses;
5072
+ this.coPartitionedLegs = coPartitionedLegs;
5073
+ this.broadcastLegs = broadcastLegs;
4945
5074
  }
4946
5075
  group;
4947
5076
  collectionName;
4948
5077
  clauses;
5078
+ coPartitionedLegs;
5079
+ broadcastLegs;
4949
5080
  where(field, op, value) {
4950
- return new _ShardedQuery(this.group, this.collectionName, [
4951
- ...this.clauses,
4952
- { field, op, value }
4953
- ]);
5081
+ return new _ShardedQuery(
5082
+ this.group,
5083
+ this.collectionName,
5084
+ [...this.clauses, { field, op, value }],
5085
+ this.coPartitionedLegs,
5086
+ this.broadcastLegs
5087
+ );
5088
+ }
5089
+ /** Co-partitioned join: each shard joins its own same-vault right collection (resolved via ref()), then union. */
5090
+ crossShardJoin(field, opts) {
5091
+ const leg = { field, as: opts.as, maxRows: opts.maxRows, strategy: opts.strategy };
5092
+ return new _ShardedQuery(
5093
+ this.group,
5094
+ this.collectionName,
5095
+ this.clauses,
5096
+ [...this.coPartitionedLegs, leg],
5097
+ this.broadcastLegs
5098
+ );
5099
+ }
5100
+ /** Broadcast dimension join: enrich every merged row from a single shared collection. */
5101
+ broadcastJoin(field, opts) {
5102
+ const leg = {
5103
+ field,
5104
+ as: opts.as,
5105
+ from: opts.from,
5106
+ on: opts.on ?? "id",
5107
+ mode: opts.mode ?? "warn"
5108
+ };
5109
+ return new _ShardedQuery(
5110
+ this.group,
5111
+ this.collectionName,
5112
+ this.clauses,
5113
+ this.coPartitionedLegs,
5114
+ [...this.broadcastLegs, leg]
5115
+ );
4954
5116
  }
4955
5117
  /** @internal — fan out the where-filtered records across eligible shards. */
4956
5118
  async fanoutRecords(options = {}) {
4957
5119
  const { eligible, skipped } = await this.group.resolveEligible(options);
5120
+ const probeRow = eligible[0];
5121
+ if (this.coPartitionedLegs.length > 0 && probeRow) {
5122
+ const probe = await this.group.openShard(probeRow.partitionKey);
5123
+ this.group.template.configure(probe);
5124
+ for (const leg of this.coPartitionedLegs) {
5125
+ if (!probe.resolveRef(this.collectionName, leg.field)) {
5126
+ throw new CrossShardJoinError(
5127
+ `crossShardJoin("${leg.field}"): no ref() declared for "${leg.field}" on collection "${this.collectionName}" in template "${this.group.sharding.vaultTemplate}". Add refs: { ${leg.field}: ref('<target>') } to the template's collection options.`
5128
+ );
5129
+ }
5130
+ }
5131
+ }
4958
5132
  const across = await this.group.db.queryAcross(
4959
5133
  eligible.map((r) => r.vaultId),
4960
5134
  async (vault) => {
4961
5135
  this.group.template.configure(vault);
4962
5136
  const coll = vault.collection(this.collectionName);
4963
5137
  await coll.list();
5138
+ for (const leg of this.coPartitionedLegs) {
5139
+ const desc = vault.resolveRef(this.collectionName, leg.field);
5140
+ if (desc) await vault.collection(desc.target).list();
5141
+ }
4964
5142
  let q = coll.query();
4965
5143
  for (const c of this.clauses) q = q.where(c.field, c.op, c.value);
5144
+ for (const leg of this.coPartitionedLegs) {
5145
+ q = q.join(leg.field, {
5146
+ as: leg.as,
5147
+ ...leg.maxRows !== void 0 ? { maxRows: leg.maxRows } : {},
5148
+ ...leg.strategy ? { strategy: leg.strategy } : {}
5149
+ });
5150
+ }
4966
5151
  return q.toArray();
4967
5152
  },
4968
5153
  { concurrency: options.concurrency ?? 1, create: false }
@@ -4974,10 +5159,11 @@ var init_vault_group = __esm({
4974
5159
  }
4975
5160
  return { records: results, skippedVaults: skipped };
4976
5161
  }
4977
- /** Fan out across eligible shards and merge results. */
5162
+ /** Fan out across eligible shards, merge, then apply any broadcast dimension legs. */
4978
5163
  async toArray(options = {}) {
4979
5164
  const { records, skippedVaults } = await this.fanoutRecords(options);
4980
- return { results: records, skippedVaults };
5165
+ const results = await applyBroadcastLegs(records, this.broadcastLegs);
5166
+ return { results, skippedVaults };
4981
5167
  }
4982
5168
  /** @internal — build the change-subscription + relevance binding for this query's group+collection. */
4983
5169
  liveBinding() {
@@ -4991,8 +5177,17 @@ var init_vault_group = __esm({
4991
5177
  isRelevant: (e) => e.collection === collectionName && e.vault.startsWith(`${group.name}--`)
4992
5178
  };
4993
5179
  }
5180
+ /** @internal — joined queries don't support reactive/aggregate surfaces in v1. */
5181
+ assertNoJoinLegs(surface) {
5182
+ if (this.coPartitionedLegs.length || this.broadcastLegs.length) {
5183
+ throw new CrossShardJoinError(
5184
+ `${surface}() is not supported on a ShardedQuery with crossShardJoin/broadcastJoin legs in v1. Use toArray() for joined cross-shard queries.`
5185
+ );
5186
+ }
5187
+ }
4994
5188
  /** Returns a reactive cross-shard live query — a facade over CrossVaultLive. */
4995
5189
  live(options = {}) {
5190
+ this.assertNoJoinLegs("live");
4996
5191
  const bind = this.liveBinding();
4997
5192
  const core = new CrossVaultLive({
4998
5193
  ...bind,
@@ -5020,10 +5215,12 @@ var init_vault_group = __esm({
5020
5215
  }
5021
5216
  /** One-shot distributed aggregate — central reduce over all shard records. */
5022
5217
  aggregate(spec) {
5218
+ this.assertNoJoinLegs("aggregate");
5023
5219
  return new CrossVaultAggregation(this, spec, this.liveBinding());
5024
5220
  }
5025
5221
  /** Begin a grouped cross-shard aggregate. */
5026
5222
  groupBy(field) {
5223
+ this.assertNoJoinLegs("groupBy");
5027
5224
  return new ShardedGroupedQuery(this, field);
5028
5225
  }
5029
5226
  };
@@ -5046,6 +5243,159 @@ var init_vault_group = __esm({
5046
5243
  }
5047
5244
  });
5048
5245
 
5246
+ // src/federation/schema-manifest.ts
5247
+ function captureBlueprint(configure) {
5248
+ const recorded = [];
5249
+ const collectionStub = new Proxy(
5250
+ {},
5251
+ {
5252
+ get: () => () => collectionStub
5253
+ }
5254
+ );
5255
+ const proxy = new Proxy(
5256
+ {},
5257
+ {
5258
+ get: (_t, prop) => {
5259
+ if (prop === "collection") {
5260
+ return (name, opts) => {
5261
+ recorded.push({
5262
+ name,
5263
+ indexes: opts?.indexes ?? [],
5264
+ persistJsonSchema: !!opts?.persistJsonSchema
5265
+ });
5266
+ return collectionStub;
5267
+ };
5268
+ }
5269
+ return () => proxy;
5270
+ }
5271
+ }
5272
+ );
5273
+ configure(proxy);
5274
+ const sorted = [...recorded].sort((a, b) => a.name.localeCompare(b.name));
5275
+ const indexes = {};
5276
+ const persistJsonSchema = [];
5277
+ for (const c of sorted) {
5278
+ indexes[c.name] = c.indexes;
5279
+ if (c.persistJsonSchema) persistJsonSchema.push(c.name);
5280
+ }
5281
+ return {
5282
+ // `persistJsonSchema` is already name-sorted: it is populated while
5283
+ // iterating `sorted` (collections in name order).
5284
+ collections: sorted.map((c) => c.name),
5285
+ indexes,
5286
+ persistJsonSchema
5287
+ };
5288
+ }
5289
+ function canonical(value) {
5290
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
5291
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
5292
+ const obj = value;
5293
+ const keys = Object.keys(obj).sort();
5294
+ return `{${keys.map((k) => `${JSON.stringify(k)}:${canonical(obj[k])}`).join(",")}}`;
5295
+ }
5296
+ async function fingerprintBlueprint(bp) {
5297
+ return sha256Hex(new TextEncoder().encode(canonical(bp)));
5298
+ }
5299
+ var init_schema_manifest = __esm({
5300
+ "src/federation/schema-manifest.ts"() {
5301
+ "use strict";
5302
+ init_crypto();
5303
+ }
5304
+ });
5305
+
5306
+ // src/federation/state-vault.ts
5307
+ var state_vault_exports = {};
5308
+ __export(state_vault_exports, {
5309
+ STATE_VAULT_NAME: () => STATE_VAULT_NAME,
5310
+ StateManagementVault: () => StateManagementVault
5311
+ });
5312
+ var REGISTRY, MANIFEST, EVENTS, StateManagementVault;
5313
+ var init_state_vault = __esm({
5314
+ "src/federation/state-vault.ts"() {
5315
+ "use strict";
5316
+ init_schema_manifest();
5317
+ init_constants();
5318
+ init_ulid();
5319
+ init_constants();
5320
+ REGISTRY = "vaultRegistry";
5321
+ MANIFEST = "schemaManifest";
5322
+ EVENTS = "deploymentEvents";
5323
+ StateManagementVault = class _StateManagementVault {
5324
+ constructor(registry, schemaManifest, events) {
5325
+ this.registry = registry;
5326
+ this.schemaManifest = schemaManifest;
5327
+ this.#events = events;
5328
+ }
5329
+ registry;
5330
+ schemaManifest;
5331
+ /**
5332
+ * The append-only deployment-events log is kept truly private so the raw
5333
+ * mutable Collection is never surfaced — events may only be written via
5334
+ * `appendEvent` and read via `queryEvents`. (`registry` and
5335
+ * `schemaManifest` are deliberately public: consumers read and write them.)
5336
+ */
5337
+ #events;
5338
+ /** Idempotently open the reserved state vault and bind the three control-plane collections. */
5339
+ static async open(db) {
5340
+ const vault = await db.openVault(STATE_VAULT_NAME);
5341
+ return new _StateManagementVault(
5342
+ vault.collection(REGISTRY),
5343
+ vault.collection(MANIFEST),
5344
+ vault.collection(EVENTS)
5345
+ );
5346
+ }
5347
+ /** Read-only query over the append-only deployment-events log. */
5348
+ queryEvents() {
5349
+ return this.#events.query();
5350
+ }
5351
+ /**
5352
+ * Append a deployment event with a fresh unique (ULID) id. This is the
5353
+ * only write path to the events log; no update/delete is exposed.
5354
+ * Callers should treat failures as non-fatal — this method does not
5355
+ * swallow errors, so wrap the call site in try/catch where appropriate.
5356
+ */
5357
+ async appendEvent(event) {
5358
+ const ts = event.ts ?? Date.now();
5359
+ const id = generateULID();
5360
+ await this.#events.put(id, { ...event, id, ts });
5361
+ }
5362
+ /**
5363
+ * Ensure a manifest row exists for `(templateName, template.version)`.
5364
+ * Safe to call repeatedly: the `fingerprint` is a deterministic hash of
5365
+ * the template's declared shape (stable across calls), though each call
5366
+ * refreshes `recordedAt`.
5367
+ */
5368
+ async recordManifest(templateName, template) {
5369
+ const bp = captureBlueprint(template.configure);
5370
+ const fingerprint = await fingerprintBlueprint(bp);
5371
+ await this.schemaManifest.put(`${templateName}:${template.version}`, {
5372
+ templateName,
5373
+ version: template.version,
5374
+ collections: bp.collections,
5375
+ indexes: bp.indexes,
5376
+ persistJsonSchema: bp.persistJsonSchema,
5377
+ fingerprint,
5378
+ recordedAt: Date.now()
5379
+ });
5380
+ return fingerprint;
5381
+ }
5382
+ /**
5383
+ * True when `template`'s current declared shape does not match the recorded
5384
+ * manifest for `(templateName, template.version)`. Because shards carry no
5385
+ * schema state independent of their template, this catches "a template's
5386
+ * shape changed without bumping `version`" — not independent per-shard drift.
5387
+ * A missing manifest is treated as drift (nothing to verify against).
5388
+ */
5389
+ async detectDrift(templateName, template) {
5390
+ const row = await this.schemaManifest.get(`${templateName}:${template.version}`);
5391
+ if (!row) return true;
5392
+ const current = await fingerprintBlueprint(captureBlueprint(template.configure));
5393
+ return current !== row.fingerprint;
5394
+ }
5395
+ };
5396
+ }
5397
+ });
5398
+
5049
5399
  // src/index.ts
5050
5400
  var src_exports = {};
5051
5401
  __export(src_exports, {
@@ -5150,6 +5500,7 @@ __export(src_exports, {
5150
5500
  NotFoundError: () => NotFoundError,
5151
5501
  Noydb: () => Noydb,
5152
5502
  NoydbError: () => NoydbError,
5503
+ NumberingUncertaintyError: () => NumberingUncertaintyError,
5153
5504
  OverlayBaseIsVirtualError: () => OverlayBaseIsVirtualError,
5154
5505
  OverlayCollectionUnavailableError: () => OverlayCollectionUnavailableError,
5155
5506
  OverlayIdMismatchError: () => OverlayIdMismatchError,
@@ -5179,8 +5530,10 @@ __export(src_exports, {
5179
5530
  RefRegistry: () => RefRegistry,
5180
5531
  RefScopeError: () => RefScopeError,
5181
5532
  ReservedCollectionNameError: () => ReservedCollectionNameError,
5533
+ ReservedVaultNameError: () => ReservedVaultNameError,
5182
5534
  SCHEMAS_COLLECTION: () => SCHEMAS_COLLECTION,
5183
5535
  SEALED_PASSPHRASE_RECORD_ID: () => SEALED_PASSPHRASE_RECORD_ID,
5536
+ STATE_VAULT_NAME: () => STATE_VAULT_NAME,
5184
5537
  STRICT_POLICY: () => STRICT_POLICY,
5185
5538
  SYNC_CREDENTIALS_COLLECTION: () => SYNC_CREDENTIALS_COLLECTION,
5186
5539
  ScanBuilder: () => ScanBuilder,
@@ -5392,6 +5745,7 @@ __export(src_exports, {
5392
5745
  withArchive: () => withArchive,
5393
5746
  withCache: () => withCache,
5394
5747
  withCircuitBreaker: () => withCircuitBreaker,
5748
+ withDeferredNumbering: () => withDeferredNumbering,
5395
5749
  withDerivation: () => withDerivation,
5396
5750
  withGuard: () => withGuard,
5397
5751
  withHealthCheck: () => withHealthCheck,
@@ -7543,8 +7897,20 @@ var SequenceStore = class {
7543
7897
  }
7544
7898
  };
7545
7899
 
7900
+ // src/numbering/descriptor.ts
7901
+ function withDeferredNumbering(config) {
7902
+ return {
7903
+ series: config.series,
7904
+ collection: config.collection,
7905
+ field: config.field,
7906
+ settleWindowMs: config.settleWindowMs ?? 0
7907
+ };
7908
+ }
7909
+
7546
7910
  // src/index.ts
7547
7911
  init_errors();
7912
+ init_constants();
7913
+ init_errors();
7548
7914
 
7549
7915
  // src/bundle/format.ts
7550
7916
  var NOYDB_BUNDLE_MAGIC = new Uint8Array([78, 68, 66, 49]);
@@ -8351,8 +8717,8 @@ async function derivePersistedSchema(validator) {
8351
8717
  if (kind === "Zod") {
8352
8718
  const convert = await loadZodConverter();
8353
8719
  const jsonSchema = convert(validator);
8354
- const canonical = canonicalize(jsonSchema);
8355
- const hash = await sha256Hex(new TextEncoder().encode(canonical));
8720
+ const canonical2 = canonicalize(jsonSchema);
8721
+ const hash = await sha256Hex(new TextEncoder().encode(canonical2));
8356
8722
  return { _noydb_schema: 1, kind, jsonSchema, hash, derivedAt };
8357
8723
  }
8358
8724
  return {
@@ -10983,6 +11349,7 @@ init_errors();
10983
11349
 
10984
11350
  // src/noydb.ts
10985
11351
  init_errors();
11352
+ init_constants();
10986
11353
  init_ulid();
10987
11354
  init_public_envelope();
10988
11355
 
@@ -12009,7 +12376,7 @@ var Query = class _Query {
12009
12376
  * for the ordering rationale.
12010
12377
  */
12011
12378
  toArray() {
12012
- const base = executePlanWithSource(this.source, this.plan, this.joinContext);
12379
+ const base = this.decodeMoney(executePlanWithSource(this.source, this.plan, this.joinContext));
12013
12380
  if (this.plan.joins.length === 0) return base;
12014
12381
  if (!this.joinContext) {
12015
12382
  throw new Error(
@@ -12018,6 +12385,23 @@ var Query = class _Query {
12018
12385
  }
12019
12386
  return applyJoins(base, this.plan.joins, this.joinContext);
12020
12387
  }
12388
+ /**
12389
+ * Decode this source's money fields on read (stored scaled-int → canonical
12390
+ * decimal), so `query().toArray()` agrees with `get()`/`sum()` on the value.
12391
+ * No-op when the source declares no money fields.
12392
+ *
12393
+ * The query layer carries no locale context, so we decode with `'raw'` —
12394
+ * canonical decimal, WITHOUT fabricating locale-formatted `<field>Formatted`
12395
+ * / `<field>Number` virtuals. Producing a guessed-locale string here would
12396
+ * just reintroduce #322's "two read paths disagree" failure on the virtual
12397
+ * field (e.g. it-IT via `get()` vs en-US here). Consumers who need formatted
12398
+ * money read through `get()`/`list()` with a locale.
12399
+ */
12400
+ decodeMoney(records) {
12401
+ const moneyFields = this.source.moneyFields;
12402
+ if (!moneyFields || Object.keys(moneyFields).length === 0) return records;
12403
+ return records.map((r) => decodeMoneyFields(r, moneyFields, "raw"));
12404
+ }
12021
12405
  /** Return the first matching record, or null. Joins are applied. */
12022
12406
  first() {
12023
12407
  const arr = this.limit(1).toArray();
@@ -12502,7 +12886,7 @@ function serializeClause(clause) {
12502
12886
  }
12503
12887
  function canonicalCtxHash(ctx) {
12504
12888
  if (ctx === void 0) return "";
12505
- const canonical = JSON.stringify(ctx, (_key, value) => {
12889
+ const canonical2 = JSON.stringify(ctx, (_key, value) => {
12506
12890
  if (value && typeof value === "object" && !Array.isArray(value)) {
12507
12891
  const sorted = {};
12508
12892
  for (const k of Object.keys(value).sort()) {
@@ -12513,8 +12897,8 @@ function canonicalCtxHash(ctx) {
12513
12897
  return value;
12514
12898
  });
12515
12899
  let h = 5381;
12516
- for (let i = 0; i < canonical.length; i++) {
12517
- h = (h << 5) + h ^ canonical.charCodeAt(i);
12900
+ for (let i = 0; i < canonical2.length; i++) {
12901
+ h = (h << 5) + h ^ canonical2.charCodeAt(i);
12518
12902
  }
12519
12903
  return (h >>> 0).toString(16).padStart(8, "0");
12520
12904
  }
@@ -12820,12 +13204,29 @@ var ScanBuilder = class _ScanBuilder {
12820
13204
  * context throws with an actionable error.
12821
13205
  */
12822
13206
  joinContext;
12823
- constructor(pageProvider, pageSize = DEFAULT_SCAN_PAGE_SIZE, clauses = [], joins = [], joinContext) {
13207
+ /**
13208
+ * Money field descriptors for the backing collection. When present, yielded
13209
+ * records are decoded (stored scaled-int → canonical decimal) so `scan()`
13210
+ * agrees with `get()`/`list()`/`query().toArray()` — #322. Decoded with
13211
+ * `'raw'` (canonical decimal, no locale-formatted virtuals) since the scan
13212
+ * stream carries no locale context, mirroring `Query.toArray()`.
13213
+ */
13214
+ moneyFields;
13215
+ constructor(pageProvider, pageSize = DEFAULT_SCAN_PAGE_SIZE, clauses = [], joins = [], joinContext, moneyFields) {
12824
13216
  this.pageProvider = pageProvider;
12825
13217
  this.pageSize = pageSize;
12826
13218
  this.clauses = clauses;
12827
13219
  this.joins = joins;
12828
13220
  this.joinContext = joinContext;
13221
+ this.moneyFields = moneyFields;
13222
+ }
13223
+ /**
13224
+ * Decode this scan's money fields on a record (stored scaled-int → canonical
13225
+ * decimal). No-op when no money fields are declared. See {@link moneyFields}.
13226
+ */
13227
+ decodeMoney(record) {
13228
+ if (!this.moneyFields || Object.keys(this.moneyFields).length === 0) return record;
13229
+ return decodeMoneyFields(record, this.moneyFields, "raw");
12829
13230
  }
12830
13231
  /**
12831
13232
  * Add a field comparison. Runs per record as the scan stream
@@ -12847,7 +13248,8 @@ var ScanBuilder = class _ScanBuilder {
12847
13248
  this.pageSize,
12848
13249
  [...this.clauses, clause],
12849
13250
  this.joins,
12850
- this.joinContext
13251
+ this.joinContext,
13252
+ this.moneyFields
12851
13253
  );
12852
13254
  }
12853
13255
  /**
@@ -12866,7 +13268,8 @@ var ScanBuilder = class _ScanBuilder {
12866
13268
  this.pageSize,
12867
13269
  [...this.clauses, clause],
12868
13270
  this.joins,
12869
- this.joinContext
13271
+ this.joinContext,
13272
+ this.moneyFields
12870
13273
  );
12871
13274
  }
12872
13275
  /**
@@ -12977,7 +13380,8 @@ var ScanBuilder = class _ScanBuilder {
12977
13380
  this.pageSize,
12978
13381
  this.clauses,
12979
13382
  [...this.joins, leg],
12980
- this.joinContext
13383
+ this.joinContext,
13384
+ this.moneyFields
12981
13385
  );
12982
13386
  }
12983
13387
  /**
@@ -12994,10 +13398,11 @@ var ScanBuilder = class _ScanBuilder {
12994
13398
  while (true) {
12995
13399
  for (const record of page.items) {
12996
13400
  if (!this.recordMatches(record)) continue;
13401
+ const decoded = this.decodeMoney(record);
12997
13402
  if (joinResolvers === null) {
12998
- yield record;
13403
+ yield decoded;
12999
13404
  } else {
13000
- let attached = record;
13405
+ let attached = decoded;
13001
13406
  for (const resolver of joinResolvers) {
13002
13407
  attached = this.applyOneJoinStreaming(attached, resolver);
13003
13408
  }
@@ -15332,9 +15737,17 @@ var Collection = class {
15332
15737
  }
15333
15738
  await this.ensureHydrated();
15334
15739
  const records = [...this.cache.values()].map((e) => e.record);
15335
- if (!locale) return records;
15740
+ if (!this.hasReadTransforms()) return records;
15336
15741
  return Promise.all(records.map((r) => this.applyLocaleToRecord(r, locale)));
15337
15742
  }
15743
+ /**
15744
+ * @internal — whether any read-side record transform is registered
15745
+ * (money decode, i18nText resolution, dictKey labels). Gates the
15746
+ * no-transform fast path in {@link list}.
15747
+ */
15748
+ hasReadTransforms() {
15749
+ return this.moneyFields !== void 0 && Object.keys(this.moneyFields).length > 0 || this.i18nFields !== void 0 && Object.keys(this.i18nFields).length > 0 || this.dictKeyFields !== void 0 && Object.keys(this.dictKeyFields).length > 0;
15750
+ }
15338
15751
  // ─── Bulk operations ─────────────────────────────────────
15339
15752
  /**
15340
15753
  * Put many records in one call. Each item is processed sequentially
@@ -15840,7 +16253,8 @@ var Collection = class {
15840
16253
  pageSize,
15841
16254
  [],
15842
16255
  [],
15843
- joinContext
16256
+ joinContext,
16257
+ this.moneyFields
15844
16258
  );
15845
16259
  }
15846
16260
  /** Decrypt a page of envelopes returned by `adapter.listPage`. */
@@ -17064,7 +17478,165 @@ var OverlayedCollection = class {
17064
17478
  // src/vault.ts
17065
17479
  init_errors();
17066
17480
  init_errors();
17067
- init_constants();
17481
+
17482
+ // src/numbering/index.ts
17483
+ init_types();
17484
+ init_crypto();
17485
+ init_errors();
17486
+ var NUMBERING_HEAD_COLLECTION = "_numbering_head";
17487
+ var NUMBERING_PENDING_COLLECTION = "_numbering_pending";
17488
+ var DeferredNumberingStore = class {
17489
+ adapter;
17490
+ vault;
17491
+ encrypted;
17492
+ getDEK;
17493
+ actor;
17494
+ configs;
17495
+ /**
17496
+ * Stamp a serial onto a USER record THROUGH the Collection layer (so the
17497
+ * cache, indexes, and MVs stay coherent — the engine must NOT write user
17498
+ * collections at the raw adapter level). Returns false if the record is
17499
+ * gone (the engine then skips it without burning a serial). Provided by the
17500
+ * vault; unit tests pass a Map-backed double.
17501
+ */
17502
+ stamp;
17503
+ /** In-process registry: `${series}::${recordId}` → resolver for the live next() Promise. */
17504
+ waiters = /* @__PURE__ */ new Map();
17505
+ dekCache = /* @__PURE__ */ new Map();
17506
+ constructor(opts) {
17507
+ this.adapter = opts.adapter;
17508
+ this.vault = opts.vault;
17509
+ this.encrypted = opts.encrypted;
17510
+ this.getDEK = opts.getDEK;
17511
+ this.actor = opts.actor;
17512
+ this.configs = opts.configs;
17513
+ this.stamp = opts.stamp;
17514
+ }
17515
+ has(series) {
17516
+ return this.configs.has(series);
17517
+ }
17518
+ dek(collection) {
17519
+ let p = this.dekCache.get(collection);
17520
+ if (!p) {
17521
+ p = this.getDEK(collection);
17522
+ this.dekCache.set(collection, p);
17523
+ }
17524
+ return p;
17525
+ }
17526
+ async readJson(collection, id) {
17527
+ const env = await this.adapter.get(this.vault, collection, id);
17528
+ if (!env) return { env: null, value: null };
17529
+ const json = this.encrypted ? await decrypt(env._iv, env._data, await this.dek(collection)) : env._data;
17530
+ return { env, value: JSON.parse(json) };
17531
+ }
17532
+ async writeJson(collection, id, value, expectedVersion) {
17533
+ const json = JSON.stringify(value);
17534
+ let env;
17535
+ if (!this.encrypted) {
17536
+ env = { _noydb: NOYDB_FORMAT_VERSION, _v: expectedVersion + 1, _ts: (/* @__PURE__ */ new Date()).toISOString(), _iv: "", _data: json, _by: this.actor };
17537
+ } else {
17538
+ const { iv, data } = await encrypt(json, await this.dek(collection));
17539
+ env = { _noydb: NOYDB_FORMAT_VERSION, _v: expectedVersion + 1, _ts: (/* @__PURE__ */ new Date()).toISOString(), _iv: iv, _data: data, _by: this.actor };
17540
+ }
17541
+ await this.adapter.put(this.vault, collection, id, env, expectedVersion);
17542
+ }
17543
+ pendingId(series, recordId3) {
17544
+ return `${series}::${recordId3}`;
17545
+ }
17546
+ /** Current last-assigned serial for a series (0 if none). */
17547
+ async peek(series) {
17548
+ const { value } = await this.readJson(NUMBERING_HEAD_COLLECTION, series);
17549
+ return value?.lastSerial ?? 0;
17550
+ }
17551
+ /**
17552
+ * Enqueue a record for numbering: stamp it with the current store clock and
17553
+ * durably write a pending entry. The returned Promise resolves once the
17554
+ * record is durably enqueued; its `assigned` field resolves with the serial
17555
+ * at the next pass (the record's `field` is the durable source of truth —
17556
+ * `assigned` is an in-process convenience that a crash may drop).
17557
+ */
17558
+ async enqueue(series, recordId3) {
17559
+ const cfg = this.configs.get(series);
17560
+ if (!cfg) throw new NumberingUncertaintyError(series);
17561
+ if (typeof this.adapter.getStoreTime !== "function") throw new NumberingUncertaintyError(series);
17562
+ const st = await this.adapter.getStoreTime();
17563
+ const id = this.pendingId(series, recordId3);
17564
+ const { env } = await this.readJson(NUMBERING_PENDING_COLLECTION, id);
17565
+ const entry = {
17566
+ series,
17567
+ recordId: recordId3,
17568
+ collection: cfg.collection,
17569
+ field: cfg.field,
17570
+ storeEarliest: st.earliest,
17571
+ storeLatest: st.latest,
17572
+ enqueuedAt: Date.now()
17573
+ };
17574
+ await this.writeJson(NUMBERING_PENDING_COLLECTION, id, entry, env?._v ?? 0);
17575
+ const assigned = new Promise((resolve, reject) => {
17576
+ this.waiters.set(id, { resolve, reject });
17577
+ });
17578
+ return { assigned };
17579
+ }
17580
+ async listPending(series) {
17581
+ const ids = await this.adapter.list(this.vault, NUMBERING_PENDING_COLLECTION);
17582
+ const prefix = `${series}::`;
17583
+ const out = [];
17584
+ for (const id of ids) {
17585
+ if (!id.startsWith(prefix)) continue;
17586
+ const { value } = await this.readJson(NUMBERING_PENDING_COLLECTION, id);
17587
+ if (value) out.push({ id, entry: value });
17588
+ }
17589
+ return out;
17590
+ }
17591
+ /**
17592
+ * Run a numbering pass for `series`: select entries provably settled
17593
+ * (`storeLatest ≤ now.earliest` — commit-wait), order by
17594
+ * `(storeEarliest, recordId)`, assign serials after the head, stamp each
17595
+ * record's field, advance the head with one CAS, and consume the entries.
17596
+ * Idempotent/convergent: a losing concurrent pass returns `[]` and the next
17597
+ * pass reconciles. Resolves any in-process enqueue() `assigned` Promises.
17598
+ */
17599
+ async runPass(series) {
17600
+ const cfg = this.configs.get(series);
17601
+ if (!cfg) throw new NumberingUncertaintyError(series);
17602
+ if (typeof this.adapter.getStoreTime !== "function") throw new NumberingUncertaintyError(series);
17603
+ const now = await this.adapter.getStoreTime();
17604
+ const settled = (await this.listPending(series)).filter((p) => p.entry.storeLatest <= now.earliest).sort(
17605
+ (a, b) => a.entry.storeEarliest - b.entry.storeEarliest || (a.entry.recordId < b.entry.recordId ? -1 : a.entry.recordId > b.entry.recordId ? 1 : 0)
17606
+ );
17607
+ if (settled.length === 0) return [];
17608
+ const { env: headEnv, value: head } = await this.readJson(NUMBERING_HEAD_COLLECTION, series);
17609
+ let serial = head?.lastSerial ?? 0;
17610
+ const assignments = [];
17611
+ for (const { entry } of settled) {
17612
+ serial += 1;
17613
+ const ok = await this.stamp(entry.collection, entry.recordId, entry.field, serial);
17614
+ if (!ok) {
17615
+ serial -= 1;
17616
+ continue;
17617
+ }
17618
+ assignments.push({ recordId: entry.recordId, serial });
17619
+ }
17620
+ try {
17621
+ await this.writeJson(NUMBERING_HEAD_COLLECTION, series, { series, lastSerial: serial, watermark: now.earliest }, headEnv?._v ?? 0);
17622
+ } catch (err) {
17623
+ if (err instanceof ConflictError) return [];
17624
+ throw err;
17625
+ }
17626
+ for (const { id, entry } of settled) {
17627
+ await this.adapter.delete(this.vault, NUMBERING_PENDING_COLLECTION, id);
17628
+ const a = assignments.find((x) => x.recordId === entry.recordId);
17629
+ if (a) {
17630
+ this.waiters.get(id)?.resolve(a.serial);
17631
+ this.waiters.delete(id);
17632
+ }
17633
+ }
17634
+ return assignments;
17635
+ }
17636
+ };
17637
+
17638
+ // src/vault.ts
17639
+ init_constants2();
17068
17640
  init_entry();
17069
17641
 
17070
17642
  // src/shadow/strategy.ts
@@ -18495,6 +19067,10 @@ var Vault = class {
18495
19067
  ledgerStore = null;
18496
19068
  /** Lazily-built atomic-sequence store. See {@link sequence}. */
18497
19069
  sequenceStore = null;
19070
+ /** Lazily-built deferred-numbering engine. See {@link runNumberingPass}. */
19071
+ deferredNumbering = null;
19072
+ /** Registered deferred-numbering series, keyed by series name. */
19073
+ numberingConfigs;
18498
19074
  /**
18499
19075
  * Background writes for persisted-schema envelopes (#schema-dump v0
18500
19076
  * slice 1). One promise per `collection({ persistJsonSchema: true })`
@@ -18581,6 +19157,7 @@ var Vault = class {
18581
19157
  constructor(opts) {
18582
19158
  this.adapter = opts.adapter;
18583
19159
  this.name = opts.name;
19160
+ this.numberingConfigs = new Map((opts.numberingConfigs ?? []).map((c) => [c.series, c]));
18584
19161
  this.noydb = opts.noydb;
18585
19162
  this.keyring = opts.keyring;
18586
19163
  this.encrypted = opts.encrypted;
@@ -19255,6 +19832,18 @@ var Vault = class {
19255
19832
  * ```
19256
19833
  */
19257
19834
  sequence(name) {
19835
+ if (this.numberingConfigs.has(name)) {
19836
+ const eng = this.deferred();
19837
+ return {
19838
+ next: async (opts) => {
19839
+ if (!opts?.for) {
19840
+ throw new ValidationError(`sequence("${name}") is a deferred-numbering series; call next({ for: recordId }).`);
19841
+ }
19842
+ return (await eng.enqueue(name, opts.for)).assigned;
19843
+ },
19844
+ peek: () => eng.peek(name)
19845
+ };
19846
+ }
19258
19847
  if (!this.sequenceStore) {
19259
19848
  this.sequenceStore = new SequenceStore({
19260
19849
  adapter: this.adapter,
@@ -19266,6 +19855,38 @@ var Vault = class {
19266
19855
  }
19267
19856
  return this.sequenceStore.handle(name);
19268
19857
  }
19858
+ /** @internal — lazily build the deferred-numbering engine with a cache-coherent stamp. */
19859
+ deferred() {
19860
+ if (!this.deferredNumbering) {
19861
+ this.deferredNumbering = new DeferredNumberingStore({
19862
+ adapter: this.adapter,
19863
+ vault: this.name,
19864
+ encrypted: this.encrypted,
19865
+ getDEK: this.getDEK,
19866
+ actor: this.keyring.userId,
19867
+ configs: this.numberingConfigs,
19868
+ // Stamp THROUGH the Collection layer so cache/indexes/MVs stay coherent —
19869
+ // `this.collection(name)` returns the shared cached instance, so a
19870
+ // subsequent user `collection.get(id)` sees the assigned serial.
19871
+ stamp: async (collection, recordId3, field, serial) => {
19872
+ const coll = this.collection(collection);
19873
+ const rec = await coll.get(recordId3);
19874
+ if (!rec) return false;
19875
+ await coll.put(recordId3, { ...rec, [field]: serial });
19876
+ return true;
19877
+ }
19878
+ });
19879
+ }
19880
+ return this.deferredNumbering;
19881
+ }
19882
+ /**
19883
+ * Run a deferred-numbering pass for `series`: assign gap-free serials to all
19884
+ * records whose store-commit-time interval has settled, in store-time order.
19885
+ * Returns the assignments made. See {@link sequence} / `withDeferredNumbering`.
19886
+ */
19887
+ async runNumberingPass(series) {
19888
+ return this.deferred().runPass(series);
19889
+ }
19269
19890
  async compact(options = {}) {
19270
19891
  return runCompaction({
19271
19892
  adapter: this.adapter,
@@ -22329,6 +22950,7 @@ var Noydb = class {
22329
22950
  ...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
22330
22951
  ...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
22331
22952
  ...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
22953
+ ...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
22332
22954
  locale: opts?.locale,
22333
22955
  // Thread the translator hook so Collection.put() can invoke it
22334
22956
  plaintextTranslator: this.options.plaintextTranslator ? (text, from, to, field, collection) => this.invokeTranslator(text, from, to, field, collection) : void 0,
@@ -22382,7 +23004,8 @@ var Noydb = class {
22382
23004
  ...this.options.historyStrategy !== void 0 ? { historyStrategy: this.options.historyStrategy } : {},
22383
23005
  ...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
22384
23006
  ...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
22385
- ...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {}
23007
+ ...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
23008
+ ...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {}
22386
23009
  });
22387
23010
  this.vaultCache.set(name, comp2);
22388
23011
  return comp2;
@@ -22412,6 +23035,7 @@ var Noydb = class {
22412
23035
  ...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
22413
23036
  ...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
22414
23037
  ...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
23038
+ ...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
22415
23039
  emitter: this.emitter
22416
23040
  });
22417
23041
  this.vaultCache.set(name, comp);
@@ -22730,10 +23354,39 @@ var Noydb = class {
22730
23354
  */
22731
23355
  async openVaultGroup(name, opts) {
22732
23356
  if (this.closed) throw new ValidationError("Instance is closed");
23357
+ if (name === STATE_VAULT_NAME) throw new ReservedVaultNameError(name);
22733
23358
  const template = this.vaultTemplates.get(opts.sharding.vaultTemplate);
22734
23359
  if (!template) throw new VaultTemplateNotFoundError(opts.sharding.vaultTemplate);
22735
23360
  const { VaultGroup: VaultGroup2 } = await Promise.resolve().then(() => (init_vault_group(), vault_group_exports));
22736
- return new VaultGroup2(this, name, opts.registry, opts.sharding, template);
23361
+ const { StateManagementVault: StateManagementVault2 } = await Promise.resolve().then(() => (init_state_vault(), state_vault_exports));
23362
+ const stateVault = opts.registry ? void 0 : await StateManagementVault2.open(this);
23363
+ const registry = opts.registry ?? stateVault.registry;
23364
+ const group = new VaultGroup2(this, name, registry, opts.sharding, template);
23365
+ if (stateVault) {
23366
+ group._attachStateVault(stateVault);
23367
+ await stateVault.recordManifest(opts.sharding.vaultTemplate, template);
23368
+ try {
23369
+ await stateVault.appendEvent({
23370
+ type: "manifest-recorded",
23371
+ group: name,
23372
+ templateName: opts.sharding.vaultTemplate,
23373
+ version: template.version
23374
+ });
23375
+ await stateVault.appendEvent({ type: "group-opened", group: name });
23376
+ } catch {
23377
+ }
23378
+ }
23379
+ return group;
23380
+ }
23381
+ /**
23382
+ * Open the reserved StateManagement control-plane vault (registry +
23383
+ * schema-manifest + deployment-events). Lazy-loaded so the federation
23384
+ * chunk stays out of the core graph until used.
23385
+ */
23386
+ async openStateManagementVault() {
23387
+ if (this.closed) throw new ValidationError("Instance is closed");
23388
+ const { StateManagementVault: StateManagementVault2 } = await Promise.resolve().then(() => (init_state_vault(), state_vault_exports));
23389
+ return StateManagementVault2.open(this);
22737
23390
  }
22738
23391
  /**
22739
23392
  * @internal — true when an encrypted shard vault is provisioned
@@ -26074,6 +26727,7 @@ function shortJSON(value) {
26074
26727
  NotFoundError,
26075
26728
  Noydb,
26076
26729
  NoydbError,
26730
+ NumberingUncertaintyError,
26077
26731
  OverlayBaseIsVirtualError,
26078
26732
  OverlayCollectionUnavailableError,
26079
26733
  OverlayIdMismatchError,
@@ -26103,8 +26757,10 @@ function shortJSON(value) {
26103
26757
  RefRegistry,
26104
26758
  RefScopeError,
26105
26759
  ReservedCollectionNameError,
26760
+ ReservedVaultNameError,
26106
26761
  SCHEMAS_COLLECTION,
26107
26762
  SEALED_PASSPHRASE_RECORD_ID,
26763
+ STATE_VAULT_NAME,
26108
26764
  STRICT_POLICY,
26109
26765
  SYNC_CREDENTIALS_COLLECTION,
26110
26766
  ScanBuilder,
@@ -26316,6 +26972,7 @@ function shortJSON(value) {
26316
26972
  withArchive,
26317
26973
  withCache,
26318
26974
  withCircuitBreaker,
26975
+ withDeferredNumbering,
26319
26976
  withDerivation,
26320
26977
  withGuard,
26321
26978
  withHealthCheck,