@noy-db/hub 0.3.0-pre.1 → 0.3.0-pre.11

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 (938) hide show
  1. package/dist/aggregate/index.js +9 -8
  2. package/dist/aggregate/index.js.map +1 -1
  3. package/dist/api-YGMINAET.js +20 -0
  4. package/dist/as/index.js +12 -6
  5. package/dist/attestation/index.js +19 -13
  6. package/dist/attestation/index.js.map +1 -1
  7. package/dist/backup-XA5STIYQ.js +225 -0
  8. package/dist/backup-XA5STIYQ.js.map +1 -0
  9. package/dist/blobs/index.js +12 -6
  10. package/dist/blobs/index.js.map +1 -1
  11. package/dist/broker/index.js +92 -0
  12. package/dist/broker/index.js.map +1 -0
  13. package/dist/bundle/index.js +21 -15
  14. package/dist/bundle/index.js.map +1 -1
  15. package/dist/by/index.js +2 -2
  16. package/dist/cargo/index.js +32 -26
  17. package/dist/chunk-25NDNMQ7.js +70 -0
  18. package/dist/chunk-25NDNMQ7.js.map +1 -0
  19. package/dist/chunk-2JMMY7HZ.js +188 -0
  20. package/dist/chunk-2JMMY7HZ.js.map +1 -0
  21. package/dist/chunk-3CNQ7FQ3.js +430 -0
  22. package/dist/chunk-3G4KMVUN.js +291 -0
  23. package/dist/chunk-3G4KMVUN.js.map +1 -0
  24. package/dist/chunk-3MSQLQNZ.js +74 -0
  25. package/dist/chunk-45ZZLTFH.js +38 -0
  26. package/dist/chunk-45ZZLTFH.js.map +1 -0
  27. package/dist/chunk-4GPE63GU.js +111 -0
  28. package/dist/chunk-4GPE63GU.js.map +1 -0
  29. package/dist/chunk-4N5QFSNQ.js +150 -0
  30. package/dist/chunk-4N5QFSNQ.js.map +1 -0
  31. package/dist/chunk-4R4Q64W5.js +34 -0
  32. package/dist/chunk-57V5S7PW.js +130 -0
  33. package/dist/chunk-57V5S7PW.js.map +1 -0
  34. package/dist/chunk-5JB73NMC.js +202 -0
  35. package/dist/chunk-5JB73NMC.js.map +1 -0
  36. package/dist/chunk-5XIPOCQC.js +155 -0
  37. package/dist/chunk-5ZOSG3RJ.js +778 -0
  38. package/dist/chunk-5ZOSG3RJ.js.map +1 -0
  39. package/dist/chunk-67TNU77I.js +36 -0
  40. package/dist/chunk-67TNU77I.js.map +1 -0
  41. package/dist/chunk-6QILBDZU.js +205 -0
  42. package/dist/chunk-7E67FJ33.js +155 -0
  43. package/dist/chunk-7ITPJFGC.js +50 -0
  44. package/dist/chunk-7ITPJFGC.js.map +1 -0
  45. package/dist/chunk-7NS43EXZ.js +117 -0
  46. package/dist/chunk-7QIXUSDQ.js +341 -0
  47. package/dist/chunk-7QIXUSDQ.js.map +1 -0
  48. package/dist/chunk-7VSGW5KJ.js +74 -0
  49. package/dist/chunk-7VSGW5KJ.js.map +1 -0
  50. package/dist/chunk-A2QF4JUE.js +14073 -0
  51. package/dist/chunk-A2QF4JUE.js.map +1 -0
  52. package/dist/chunk-A2Y6YFVN.js +209 -0
  53. package/dist/chunk-AOVDSIL3.js +1221 -0
  54. package/dist/chunk-AOVDSIL3.js.map +1 -0
  55. package/dist/chunk-ARSAMO24.js +29 -0
  56. package/dist/chunk-ARSAMO24.js.map +1 -0
  57. package/dist/chunk-AWB5JZW6.js +41 -0
  58. package/dist/chunk-AWB5JZW6.js.map +1 -0
  59. package/dist/chunk-BCYQA5BK.js +45 -0
  60. package/dist/chunk-BE7N3AXA.js +621 -0
  61. package/dist/chunk-BE7N3AXA.js.map +1 -0
  62. package/dist/chunk-BEIRE5K4.js +164 -0
  63. package/dist/chunk-BEIRE5K4.js.map +1 -0
  64. package/dist/chunk-BZO4WCJI.js +86 -0
  65. package/dist/chunk-BZO4WCJI.js.map +1 -0
  66. package/dist/chunk-C3YH34IL.js +75 -0
  67. package/dist/chunk-C3YH34IL.js.map +1 -0
  68. package/dist/chunk-C7NTK5I3.js +49 -0
  69. package/dist/chunk-C7NTK5I3.js.map +1 -0
  70. package/dist/chunk-CB25ONKC.js +129 -0
  71. package/dist/chunk-CIKY6I4W.js +21 -0
  72. package/dist/chunk-CKZW6P5V.js +32 -0
  73. package/dist/chunk-CKZW6P5V.js.map +1 -0
  74. package/dist/chunk-D26JB3LZ.js +54 -0
  75. package/dist/chunk-D3EFFFOL.js +59 -0
  76. package/dist/chunk-D3EFFFOL.js.map +1 -0
  77. package/dist/chunk-DGH65E7Q.js +466 -0
  78. package/dist/chunk-DGH65E7Q.js.map +1 -0
  79. package/dist/chunk-DIRRS7WP.js +42 -0
  80. package/dist/chunk-DJ3VKYFA.js +150 -0
  81. package/dist/chunk-DJ3VKYFA.js.map +1 -0
  82. package/dist/chunk-DMFNPHCX.js +247 -0
  83. package/dist/chunk-DMFNPHCX.js.map +1 -0
  84. package/dist/chunk-ELNBMFOS.js +392 -0
  85. package/dist/chunk-ELNBMFOS.js.map +1 -0
  86. package/dist/chunk-FH542DDY.js +1505 -0
  87. package/dist/chunk-FH542DDY.js.map +1 -0
  88. package/dist/chunk-FQQF23MC.js +45 -0
  89. package/dist/chunk-FQQF23MC.js.map +1 -0
  90. package/dist/chunk-FXK4X4BL.js +91 -0
  91. package/dist/chunk-FXK4X4BL.js.map +1 -0
  92. package/dist/chunk-GA2QHD6P.js +235 -0
  93. package/dist/chunk-GA2QHD6P.js.map +1 -0
  94. package/dist/chunk-GYGLAVCX.js +19 -0
  95. package/dist/chunk-GYGLAVCX.js.map +1 -0
  96. package/dist/chunk-H44ZE4IE.js +355 -0
  97. package/dist/chunk-H6CZSDWK.js +1697 -0
  98. package/dist/chunk-H6CZSDWK.js.map +1 -0
  99. package/dist/chunk-H6HM6CVR.js +279 -0
  100. package/dist/chunk-H6HM6CVR.js.map +1 -0
  101. package/dist/chunk-HFJIGWJC.js +382 -0
  102. package/dist/chunk-HUS3J5WM.js +404 -0
  103. package/dist/chunk-HUS3J5WM.js.map +1 -0
  104. package/dist/chunk-IDIV5NVH.js +99 -0
  105. package/dist/chunk-IDIV5NVH.js.map +1 -0
  106. package/dist/chunk-IGJCYUT5.js +99 -0
  107. package/dist/chunk-IGJCYUT5.js.map +1 -0
  108. package/dist/chunk-IGJHJYM6.js +515 -0
  109. package/dist/chunk-IGJHJYM6.js.map +1 -0
  110. package/dist/chunk-IP2QBAGS.js +589 -0
  111. package/dist/chunk-IP2QBAGS.js.map +1 -0
  112. package/dist/chunk-JK733I5V.js +23 -0
  113. package/dist/chunk-JK733I5V.js.map +1 -0
  114. package/dist/chunk-JOQ53DMI.js +255 -0
  115. package/dist/chunk-JOQ53DMI.js.map +1 -0
  116. package/dist/chunk-K62IUKOD.js +823 -0
  117. package/dist/chunk-K62IUKOD.js.map +1 -0
  118. package/dist/chunk-KPGX66PM.js +230 -0
  119. package/dist/chunk-KPZS5QAQ.js +151 -0
  120. package/dist/chunk-KPZS5QAQ.js.map +1 -0
  121. package/dist/chunk-L2SNBIV7.js +453 -0
  122. package/dist/chunk-L2SNBIV7.js.map +1 -0
  123. package/dist/chunk-LP7BEXCT.js +32 -0
  124. package/dist/chunk-LP7BEXCT.js.map +1 -0
  125. package/dist/chunk-MCEKIAO4.js +367 -0
  126. package/dist/chunk-MELR46EF.js +280 -0
  127. package/dist/chunk-MELR46EF.js.map +1 -0
  128. package/dist/chunk-MSPNM2OM.js +95 -0
  129. package/dist/chunk-MSPNM2OM.js.map +1 -0
  130. package/dist/chunk-NO272T7Q.js +194 -0
  131. package/dist/chunk-NO272T7Q.js.map +1 -0
  132. package/dist/chunk-O2DYPAZY.js +23 -0
  133. package/dist/chunk-ODJWBC5I.js +30 -0
  134. package/dist/chunk-OEAATWH5.js +686 -0
  135. package/dist/chunk-OEAATWH5.js.map +1 -0
  136. package/dist/chunk-OFJ5GPNA.js +71 -0
  137. package/dist/chunk-OOLO4LQG.js +99 -0
  138. package/dist/chunk-OOLO4LQG.js.map +1 -0
  139. package/dist/chunk-P5RY4ZWD.js +662 -0
  140. package/dist/chunk-P5RY4ZWD.js.map +1 -0
  141. package/dist/chunk-PR5LC5YX.js +265 -0
  142. package/dist/chunk-PR5LC5YX.js.map +1 -0
  143. package/dist/chunk-PXWVF7MC.js +135 -0
  144. package/dist/chunk-Q3XSMOZM.js +40 -0
  145. package/dist/chunk-QLLKLFE2.js +94 -0
  146. package/dist/chunk-QLLKLFE2.js.map +1 -0
  147. package/dist/chunk-QQJXBZCO.js +1056 -0
  148. package/dist/chunk-QQJXBZCO.js.map +1 -0
  149. package/dist/chunk-QYPKGVT4.js +261 -0
  150. package/dist/chunk-QYPKGVT4.js.map +1 -0
  151. package/dist/chunk-RKRGDAS7.js +59 -0
  152. package/dist/chunk-SRVQHVNX.js +164 -0
  153. package/dist/chunk-SYMS4546.js +29 -0
  154. package/dist/chunk-SYMS4546.js.map +1 -0
  155. package/dist/chunk-THNJ3IKU.js +17 -0
  156. package/dist/chunk-THNJ3IKU.js.map +1 -0
  157. package/dist/chunk-TPH5EO6L.js +54 -0
  158. package/dist/chunk-TPH5EO6L.js.map +1 -0
  159. package/dist/chunk-UFILRICG.js +14 -0
  160. package/dist/chunk-UTLEAJXC.js +97 -0
  161. package/dist/chunk-VA4ZWLFY.js +123 -0
  162. package/dist/chunk-VR24ILCR.js +367 -0
  163. package/dist/chunk-VYYM3MEN.js +98 -0
  164. package/dist/chunk-VYYM3MEN.js.map +1 -0
  165. package/dist/chunk-W5D62AQD.js +944 -0
  166. package/dist/chunk-W5D62AQD.js.map +1 -0
  167. package/dist/chunk-WGV4CUZT.js +167 -0
  168. package/dist/chunk-WGV4CUZT.js.map +1 -0
  169. package/dist/chunk-WTUNZACT.js +30 -0
  170. package/dist/chunk-WTUNZACT.js.map +1 -0
  171. package/dist/chunk-X6CMGUAG.js +69 -0
  172. package/dist/chunk-X6CMGUAG.js.map +1 -0
  173. package/dist/chunk-XFXUTFWQ.js +85 -0
  174. package/dist/chunk-XFXUTFWQ.js.map +1 -0
  175. package/dist/chunk-XHV25KBM.js +30 -0
  176. package/dist/chunk-YSXEFGND.js +124 -0
  177. package/dist/chunk-YXOUQ2H7.js +36 -0
  178. package/dist/chunk-ZP5PL65C.js +80 -0
  179. package/dist/classified/index.js +40 -0
  180. package/dist/classified-marker-LQWWQNIJ.js +24 -0
  181. package/dist/classified-marker-LQWWQNIJ.js.map +1 -0
  182. package/dist/collection-facade-YE2O4J4O.js +39 -0
  183. package/dist/computed-W6MVAMWZ.js +11 -0
  184. package/dist/consent/index.js +10 -4
  185. package/dist/consent/index.js.map +1 -1
  186. package/dist/crdt/index.js +1 -1
  187. package/dist/dead-filter-4KXZEB3X.js +28 -0
  188. package/dist/dead-filter-4KXZEB3X.js.map +1 -0
  189. package/dist/delegation-OPUU3R2E.js +25 -0
  190. package/dist/derivations/index.js +13 -6
  191. package/dist/derive-BGUHU663.js +21 -0
  192. package/dist/enclave-VXAQD4XJ.js +135 -0
  193. package/dist/executor-GTVSUUBX.js +25 -0
  194. package/dist/executor-GZWMTOXB.js +9 -0
  195. package/dist/executor-XXGS4S3K.js +9 -0
  196. package/dist/export-accessible-BMULIOYB.js +23 -0
  197. package/dist/extract-partition-JUQTWDXR.js +36 -0
  198. package/dist/fanout-sidecar-CKYFH33E.js +74 -0
  199. package/dist/fanout-sidecar-CKYFH33E.js.map +1 -0
  200. package/dist/fence-watcher-DHQ775JB.js +69 -0
  201. package/dist/fence-watcher-DHQ775JB.js.map +1 -0
  202. package/dist/find-XRGCNGNN.js +11 -0
  203. package/dist/forget/index.js +11 -5
  204. package/dist/forget/index.js.map +1 -1
  205. package/dist/guards/index.js +4 -4
  206. package/dist/history/index.js +12 -6
  207. package/dist/history/index.js.map +1 -1
  208. package/dist/i18n/index.js +50 -31
  209. package/dist/i18n/index.js.map +1 -1
  210. package/dist/index.d.ts +303 -1400
  211. package/dist/index.js +1525 -184
  212. package/dist/index.js.map +1 -1
  213. package/dist/indexing/index.js +4 -4
  214. package/dist/issue-UB6AA5M6.js +19 -0
  215. package/dist/json-schema-I22JCYCG.js +44 -0
  216. package/dist/json-schema-I22JCYCG.js.map +1 -0
  217. package/dist/kernel/cache/index.d.ts +10 -0
  218. package/dist/kernel/cache/lru.d.ts +97 -0
  219. package/dist/kernel/cache/policy.d.ts +32 -0
  220. package/dist/kernel/collection-config.d.ts +781 -0
  221. package/dist/kernel/collection.d.ts +1505 -0
  222. package/dist/kernel/constants.d.ts +18 -0
  223. package/dist/kernel/debug.d.ts +25 -0
  224. package/dist/kernel/enclave/broker/proof.d.ts +154 -0
  225. package/dist/kernel/enclave/classify/bidx.d.ts +77 -0
  226. package/dist/kernel/enclave/classify/compare.d.ts +10 -0
  227. package/dist/kernel/enclave/classify/digest.d.ts +8 -0
  228. package/dist/kernel/enclave/classify/find.d.ts +36 -0
  229. package/dist/kernel/enclave/classify/kofn.d.ts +7 -0
  230. package/dist/kernel/enclave/classify/normalize.d.ts +7 -0
  231. package/dist/kernel/enclave/classify/reveal.d.ts +10 -0
  232. package/dist/kernel/enclave/classify/vdig.d.ts +39 -0
  233. package/dist/kernel/enclave/classify/verify.d.ts +33 -0
  234. package/dist/kernel/enclave/classify/write.d.ts +8 -0
  235. package/dist/kernel/enclave/crypto.d.ts +263 -0
  236. package/dist/kernel/enclave/index.d.ts +78 -0
  237. package/dist/kernel/enclave/record-keys/deterministic.d.ts +54 -0
  238. package/dist/kernel/enclave/record-keys/envelope-body.d.ts +79 -0
  239. package/dist/kernel/enclave/record-keys/lifecycle.d.ts +57 -0
  240. package/dist/kernel/enclave/record-keys/record-codec.d.ts +301 -0
  241. package/dist/kernel/enclave/record-keys/sealed-slot.d.ts +14 -0
  242. package/dist/kernel/enclave/record-keys/sealed-slots.d.ts +123 -0
  243. package/dist/kernel/enclave/record-keys/sealing.d.ts +70 -0
  244. package/dist/kernel/enclave/record-keys/tombstone.d.ts +57 -0
  245. package/dist/kernel/env-check.d.ts +1 -0
  246. package/dist/kernel/errors.d.ts +1848 -0
  247. package/dist/kernel/events.d.ts +11 -0
  248. package/dist/kernel/memory-store.d.ts +17 -0
  249. package/dist/kernel/mutation.d.ts +14 -0
  250. package/dist/kernel/noydb.d.ts +818 -0
  251. package/dist/kernel/paths.d.ts +25 -0
  252. package/dist/kernel/query/builder.d.ts +520 -0
  253. package/dist/kernel/query/index.d.ts +31 -0
  254. package/dist/kernel/query/join.d.ts +205 -0
  255. package/dist/kernel/query/live.d.ts +111 -0
  256. package/dist/kernel/query/predicate.d.ts +139 -0
  257. package/dist/kernel/query/scan-builder.d.ts +334 -0
  258. package/dist/kernel/refs.d.ts +205 -0
  259. package/dist/kernel/schema.d.ts +134 -0
  260. package/dist/kernel/sync-policy.d.ts +188 -0
  261. package/dist/kernel/types.d.ts +3147 -0
  262. package/dist/kernel/util/discriminant.d.ts +58 -0
  263. package/dist/kernel/util/index.d.ts +14 -0
  264. package/dist/kernel/util/sanitize-filename.d.ts +75 -0
  265. package/dist/kernel/validation.d.ts +130 -0
  266. package/dist/kernel/vault.d.ts +1723 -0
  267. package/dist/kernel/via/compose.d.ts +144 -0
  268. package/dist/kernel/via/dispatch.d.ts +185 -0
  269. package/dist/kernel/via/graph-wiring.d.ts +145 -0
  270. package/dist/kernel/via/graph.d.ts +165 -0
  271. package/dist/kernel/via/index.d.ts +200 -0
  272. package/dist/kernel/via/pipeline.d.ts +266 -0
  273. package/dist/kernel/via/reconcile.d.ts +153 -0
  274. package/dist/kernel/via/taint-binding.d.ts +66 -0
  275. package/dist/kernel/write-queue.d.ts +46 -0
  276. package/dist/lazy/index.js +12 -0
  277. package/dist/ledger-FU6GH5EH.js +42 -0
  278. package/dist/legacy/bundle.d.ts +30 -0
  279. package/dist/legacy/kernel.d.ts +33 -0
  280. package/dist/liberate-YUN7W5QG.js +24 -0
  281. package/dist/link-set-MNADSH5M.js +31 -0
  282. package/dist/materialized-views/index.js +20 -10
  283. package/dist/noydb-6JLBZU4U.js +67 -0
  284. package/dist/on/index.js +10 -4
  285. package/dist/overlay-views/index.js +4 -4
  286. package/dist/periods/index.js +21 -7
  287. package/dist/pod/index.js +12 -6
  288. package/dist/policy-JTFOPPUU.js +41 -0
  289. package/dist/port/as/index.d.ts +26 -0
  290. package/dist/port/at/index.d.ts +18 -0
  291. package/dist/port/by/default-provider.d.ts +9 -0
  292. package/dist/port/by/index.d.ts +17 -0
  293. package/dist/port/by/types.d.ts +86 -0
  294. package/dist/port/in/index.d.ts +21 -0
  295. package/dist/port/on/index.d.ts +27 -0
  296. package/dist/port/to/index.d.ts +19 -0
  297. package/dist/port/ui/index.d.ts +21 -0
  298. package/dist/port/with/blob-strategy.d.ts +81 -0
  299. package/dist/port/with/broker-strategy.d.ts +84 -0
  300. package/dist/port/with/capabilities.d.ts +31 -0
  301. package/dist/port/with/classified-marker.d.ts +9 -0
  302. package/dist/port/with/classified-strategy.d.ts +62 -0
  303. package/dist/port/with/computed-strategy.d.ts +19 -0
  304. package/dist/port/with/i18n-strategy.d.ts +175 -0
  305. package/dist/port/with/index.d.ts +18 -0
  306. package/dist/port/with/lazy-strategy.d.ts +48 -0
  307. package/dist/port/with/lookup-strategy.d.ts +128 -0
  308. package/dist/port/with/service-bus.d.ts +156 -0
  309. package/dist/port/with/team-strategy.d.ts +36 -0
  310. package/dist/port/with/write-hooks.d.ts +34 -0
  311. package/dist/portability/index.js +8 -8
  312. package/dist/post-register-HAWO3O7O.js +55 -0
  313. package/dist/post-register-HAWO3O7O.js.map +1 -0
  314. package/dist/public-envelope-NJVB7LPA.js +32 -0
  315. package/dist/purge-scope-FGNNLWHD.js +24 -0
  316. package/dist/purge-scope-FGNNLWHD.js.map +1 -0
  317. package/dist/query/index.js +9 -6
  318. package/dist/read-only-facade-CHCKSEPD.js +8 -0
  319. package/dist/register-VCKOBWKT.js +23 -0
  320. package/dist/registry-72UKJ2L4.js +9 -0
  321. package/dist/registry-BZFLJNEH.js +18 -0
  322. package/dist/registry-YJEYSYI5.js +19 -0
  323. package/dist/request-withdrawal-6MJRMFHF.js +31 -0
  324. package/dist/reveal-BOY7XYFH.js +38 -0
  325. package/dist/reveal-BOY7XYFH.js.map +1 -0
  326. package/dist/revoke-4KUNSVJC.js +24 -0
  327. package/dist/satellites/index.js +8 -0
  328. package/dist/sealed-record/index.js +13 -7
  329. package/dist/sealed-record/index.js.map +1 -1
  330. package/dist/seed-4RRXT42N.js +231 -0
  331. package/dist/seed-4RRXT42N.js.map +1 -0
  332. package/dist/session/index.js +10 -4
  333. package/dist/session/index.js.map +1 -1
  334. package/dist/shadow/index.js +2 -2
  335. package/dist/signer-DDDXP5JD.js +25 -0
  336. package/dist/signer-DDDXP5JD.js.map +1 -0
  337. package/dist/snapshots/index.js +11 -5
  338. package/dist/snapshots/index.js.map +1 -1
  339. package/dist/stale-NXPT56JA.js +14 -0
  340. package/dist/stale-NXPT56JA.js.map +1 -0
  341. package/dist/storage-IR6EEAV2.js +23 -0
  342. package/dist/storage-IR6EEAV2.js.map +1 -0
  343. package/dist/store-coordination-provider-HPYVFJCV.js +142 -0
  344. package/dist/sync/index.js +10 -4
  345. package/dist/sync/index.js.map +1 -1
  346. package/dist/team/index.js +25 -12
  347. package/dist/tiers/index.js +11 -5
  348. package/dist/to/index.js +1 -2
  349. package/dist/tx/index.js +3 -3
  350. package/dist/util/index.js +1 -1
  351. package/dist/verify-66RHOW7N.js +139 -0
  352. package/dist/verify-66RHOW7N.js.map +1 -0
  353. package/dist/via/blob/active.d.ts +34 -0
  354. package/dist/via/blob/binding.d.ts +86 -0
  355. package/dist/via/blob/index.d.ts +34 -0
  356. package/dist/via/classified/active.d.ts +3 -0
  357. package/dist/via/classified/binding.d.ts +83 -0
  358. package/dist/via/classified/config-drift.d.ts +34 -0
  359. package/dist/via/classified/descriptor.d.ts +66 -0
  360. package/dist/via/classified/errors.d.ts +19 -0
  361. package/dist/via/classified/guards.d.ts +23 -0
  362. package/dist/via/classified/index.d.ts +11 -0
  363. package/dist/via/classified/presets.d.ts +65 -0
  364. package/dist/via/classified/resolve.d.ts +9 -0
  365. package/dist/via/classified/strategy.d.ts +11 -0
  366. package/dist/via/classified/validators.d.ts +3 -0
  367. package/dist/via/classified/write.d.ts +4 -0
  368. package/dist/via/computed/binding.d.ts +34 -0
  369. package/dist/via/computed/descriptor.d.ts +35 -0
  370. package/dist/via/i18n/active.d.ts +28 -0
  371. package/dist/via/i18n/binding.d.ts +36 -0
  372. package/dist/via/i18n/core.d.ts +267 -0
  373. package/dist/via/i18n/densify.d.ts +24 -0
  374. package/dist/via/i18n/dictionary.d.ts +200 -0
  375. package/dist/via/i18n/index.d.ts +21 -0
  376. package/dist/via/i18n/policy.d.ts +44 -0
  377. package/dist/via/i18n/script.d.ts +26 -0
  378. package/dist/via/i18n/strategy.d.ts +13 -0
  379. package/dist/via/lookup/active.d.ts +19 -0
  380. package/dist/via/lookup/binding.d.ts +99 -0
  381. package/dist/via/lookup/descriptor.d.ts +123 -0
  382. package/dist/via/lookup/handle.d.ts +220 -0
  383. package/dist/via/lookup/index.d.ts +17 -0
  384. package/dist/via/lookup/registry.d.ts +219 -0
  385. package/dist/via/lookup/snapshot.d.ts +67 -0
  386. package/dist/via/money/arith.d.ts +68 -0
  387. package/dist/via/money/binding.d.ts +21 -0
  388. package/dist/via/money/branded.d.ts +61 -0
  389. package/dist/via/money/descriptor.d.ts +73 -0
  390. package/dist/via/money/fixed-point.d.ts +51 -0
  391. package/dist/via/money/index.d.ts +15 -0
  392. package/dist/via/money/iso4217.d.ts +6 -0
  393. package/dist/via/money/money-reducer.d.ts +33 -0
  394. package/dist/via/money/normalize.d.ts +105 -0
  395. package/dist/via/money/paths.d.ts +61 -0
  396. package/dist/via/money/where.d.ts +106 -0
  397. package/dist/walk-2RWEOCAS.js +241 -0
  398. package/dist/walk-2RWEOCAS.js.map +1 -0
  399. package/dist/with/index.js +12 -6
  400. package/dist/with-audit/attestation/active.d.ts +10 -0
  401. package/dist/with-audit/attestation/index.d.ts +16 -0
  402. package/dist/with-audit/attestation/issue.d.ts +29 -0
  403. package/dist/with-audit/attestation/revoke.d.ts +15 -0
  404. package/dist/with-audit/attestation/signer.d.ts +33 -0
  405. package/dist/with-audit/attestation/strategy.d.ts +44 -0
  406. package/dist/with-audit/attestation/vault-facade.d.ts +62 -0
  407. package/dist/with-audit/consent/active.d.ts +14 -0
  408. package/dist/with-audit/consent/consent.d.ts +114 -0
  409. package/dist/with-audit/consent/index.d.ts +14 -0
  410. package/dist/with-audit/consent/strategy.d.ts +36 -0
  411. package/dist/with-audit/forget/active.d.ts +31 -0
  412. package/dist/with-audit/forget/index.d.ts +28 -0
  413. package/dist/with-audit/forget/purge-scope.d.ts +54 -0
  414. package/dist/with-audit/forget/strategy.d.ts +177 -0
  415. package/dist/with-audit/forget/subject-index.d.ts +83 -0
  416. package/dist/with-audit/guards/executor.d.ts +26 -0
  417. package/dist/with-audit/guards/immutable-guard.d.ts +63 -0
  418. package/dist/with-audit/guards/index.d.ts +10 -0
  419. package/dist/with-audit/guards/read-only-facade.d.ts +31 -0
  420. package/dist/with-audit/guards/registry.d.ts +83 -0
  421. package/dist/with-audit/guards/transition-guard.d.ts +82 -0
  422. package/dist/with-audit/guards/types.d.ts +134 -0
  423. package/dist/with-audit/guards/with-guard.d.ts +15 -0
  424. package/dist/with-audit/periods/active.d.ts +11 -0
  425. package/dist/with-audit/periods/index.d.ts +18 -0
  426. package/dist/with-audit/periods/periods.d.ts +417 -0
  427. package/dist/with-audit/periods/strategy.d.ts +32 -0
  428. package/dist/with-audit/periods/vault-facade.d.ts +95 -0
  429. package/dist/with-audit/portability/active.d.ts +11 -0
  430. package/dist/with-audit/portability/export-accessible.d.ts +46 -0
  431. package/dist/with-audit/portability/index.d.ts +18 -0
  432. package/dist/with-audit/portability/request-withdrawal.d.ts +85 -0
  433. package/dist/with-audit/portability/strategy.d.ts +31 -0
  434. package/dist/with-audit/portability/withdraw-accessible.d.ts +82 -0
  435. package/dist/with-audit/sealed-record/active.d.ts +9 -0
  436. package/dist/with-audit/sealed-record/index.d.ts +55 -0
  437. package/dist/with-audit/sealed-record/strategy.d.ts +34 -0
  438. package/dist/with-audit/sealed-record/types.d.ts +27 -0
  439. package/dist/with-audit/tiers/active.d.ts +9 -0
  440. package/dist/with-audit/tiers/index.d.ts +122 -0
  441. package/dist/with-audit/tiers/strategy.d.ts +35 -0
  442. package/dist/with-cargo/active.d.ts +11 -0
  443. package/dist/with-cargo/adopt-partition.d.ts +81 -0
  444. package/dist/with-cargo/decrypt-partition.d.ts +19 -0
  445. package/dist/with-cargo/describe-extraction.d.ts +33 -0
  446. package/dist/with-cargo/extract-partition.d.ts +147 -0
  447. package/dist/with-cargo/index.d.ts +33 -0
  448. package/dist/with-cargo/strategy.d.ts +30 -0
  449. package/dist/with-cargo/vault-diff.d.ts +144 -0
  450. package/dist/with-cargo/walk-closure.d.ts +38 -0
  451. package/dist/with-commit/crdt/active.d.ts +25 -0
  452. package/dist/with-commit/crdt/crdt.d.ts +42 -0
  453. package/dist/with-commit/crdt/index.d.ts +16 -0
  454. package/dist/with-commit/crdt/strategy.d.ts +25 -0
  455. package/dist/with-commit/history/active.d.ts +40 -0
  456. package/dist/with-commit/history/diff.d.ts +23 -0
  457. package/dist/with-commit/history/history.d.ts +27 -0
  458. package/dist/with-commit/history/index.d.ts +30 -0
  459. package/dist/with-commit/history/ledger/constants.d.ts +37 -0
  460. package/dist/with-commit/history/ledger/entry.d.ts +195 -0
  461. package/dist/with-commit/history/ledger/hash.d.ts +30 -0
  462. package/dist/with-commit/history/ledger/index.d.ts +19 -0
  463. package/dist/with-commit/history/ledger/patch.d.ts +99 -0
  464. package/dist/with-commit/history/ledger/store.d.ts +335 -0
  465. package/dist/with-commit/history/strategy.d.ts +126 -0
  466. package/dist/with-commit/history/time-machine.d.ts +179 -0
  467. package/dist/with-commit/numbering/descriptor.d.ts +27 -0
  468. package/dist/with-commit/numbering/index.d.ts +69 -0
  469. package/dist/with-commit/sequence/active.d.ts +10 -0
  470. package/dist/with-commit/sequence/index.d.ts +150 -0
  471. package/dist/with-commit/sequence/strategy.d.ts +26 -0
  472. package/dist/with-commit/tx/active.d.ts +27 -0
  473. package/dist/with-commit/tx/dry-run.d.ts +29 -0
  474. package/dist/with-commit/tx/elevated-handle.d.ts +58 -0
  475. package/dist/with-commit/tx/index.d.ts +13 -0
  476. package/dist/with-commit/tx/invariants.d.ts +68 -0
  477. package/dist/with-commit/tx/strategy.d.ts +23 -0
  478. package/dist/with-commit/tx/transaction.d.ts +207 -0
  479. package/dist/with-fork/archive/engine.d.ts +71 -0
  480. package/dist/with-fork/archive/index.d.ts +23 -0
  481. package/dist/with-fork/shadow/active.d.ts +6 -0
  482. package/dist/with-fork/shadow/index.d.ts +14 -0
  483. package/dist/with-fork/shadow/strategy.d.ts +28 -0
  484. package/dist/with-fork/shadow/vault-frame.d.ts +93 -0
  485. package/dist/with-fork/snapshots/active.d.ts +20 -0
  486. package/dist/with-fork/snapshots/engine.d.ts +36 -0
  487. package/dist/with-fork/snapshots/index.d.ts +5 -0
  488. package/dist/with-fork/snapshots/noydb-facade.d.ts +64 -0
  489. package/dist/with-fork/snapshots/policy.d.ts +23 -0
  490. package/dist/with-fork/snapshots/scheduler.d.ts +34 -0
  491. package/dist/with-fork/snapshots/strategy.d.ts +48 -0
  492. package/dist/with-formula/computed/index.d.ts +48 -0
  493. package/dist/with-formula/computed/lazy.d.ts +13 -0
  494. package/dist/with-formula/derivations/executor.d.ts +61 -0
  495. package/dist/with-formula/derivations/fanout-sidecar.d.ts +75 -0
  496. package/dist/with-formula/derivations/index.d.ts +6 -0
  497. package/dist/with-formula/derivations/registry.d.ts +67 -0
  498. package/dist/with-formula/derivations/stale.d.ts +39 -0
  499. package/dist/with-formula/derivations/strategy-hash.d.ts +1 -0
  500. package/dist/with-formula/derivations/types.d.ts +248 -0
  501. package/dist/with-formula/derivations/with-derivation.d.ts +10 -0
  502. package/dist/with-formula/derivations/with-rollup.d.ts +34 -0
  503. package/dist/with-formula/materialized-views/dependency-analyzer.d.ts +58 -0
  504. package/dist/with-formula/materialized-views/executor.d.ts +71 -0
  505. package/dist/with-formula/materialized-views/index.d.ts +11 -0
  506. package/dist/with-formula/materialized-views/query-hash.d.ts +23 -0
  507. package/dist/with-formula/materialized-views/registry.d.ts +99 -0
  508. package/dist/with-formula/materialized-views/stale.d.ts +62 -0
  509. package/dist/with-formula/materialized-views/types.d.ts +318 -0
  510. package/dist/with-formula/materialized-views/with-materialized-view.d.ts +24 -0
  511. package/dist/with-formula/overlay-views/index.d.ts +5 -0
  512. package/dist/with-formula/overlay-views/registry.d.ts +42 -0
  513. package/dist/with-formula/overlay-views/types.d.ts +97 -0
  514. package/dist/with-formula/overlay-views/virtual-collection.d.ts +90 -0
  515. package/dist/with-formula/overlay-views/with-overlayed-view.d.ts +9 -0
  516. package/dist/with-lookup/aggregate/active.d.ts +33 -0
  517. package/dist/with-lookup/aggregate/aggregation.d.ts +166 -0
  518. package/dist/with-lookup/aggregate/canonical-key.d.ts +16 -0
  519. package/dist/with-lookup/aggregate/groupby.d.ts +280 -0
  520. package/dist/with-lookup/aggregate/index.d.ts +23 -0
  521. package/dist/with-lookup/aggregate/reducers.d.ts +257 -0
  522. package/dist/with-lookup/aggregate/strategy.d.ts +59 -0
  523. package/dist/with-lookup/embeddings/cosine.d.ts +2 -0
  524. package/dist/with-lookup/embeddings/descriptor.d.ts +8 -0
  525. package/dist/with-lookup/embeddings/index.d.ts +3 -0
  526. package/dist/with-lookup/embeddings/vector-set.d.ts +19 -0
  527. package/dist/with-lookup/indexing/active.d.ts +30 -0
  528. package/dist/with-lookup/indexing/collection-facade.d.ts +120 -0
  529. package/dist/with-lookup/indexing/eager-indexes.d.ts +122 -0
  530. package/dist/with-lookup/indexing/index.d.ts +27 -0
  531. package/dist/with-lookup/indexing/lazy-builder.d.ts +69 -0
  532. package/dist/with-lookup/indexing/persisted-indexes.d.ts +186 -0
  533. package/dist/with-lookup/indexing/strategy.d.ts +56 -0
  534. package/dist/with-lookup/indexing/unique-constraints.d.ts +74 -0
  535. package/dist/with-lookup/search/active.d.ts +10 -0
  536. package/dist/with-lookup/search/build-docs.d.ts +15 -0
  537. package/dist/with-lookup/search/collection-facade.d.ts +123 -0
  538. package/dist/with-lookup/search/fuse.d.ts +22 -0
  539. package/dist/with-lookup/search/index-store.d.ts +19 -0
  540. package/dist/with-lookup/search/index.d.ts +19 -0
  541. package/dist/with-lookup/search/inverted-index.d.ts +47 -0
  542. package/dist/with-lookup/search/persisted-index-store.d.ts +41 -0
  543. package/dist/with-lookup/search/retrieve-types.d.ts +29 -0
  544. package/dist/with-lookup/search/scan.d.ts +28 -0
  545. package/dist/with-lookup/search/segment.d.ts +15 -0
  546. package/dist/with-lookup/search/serialize.d.ts +4 -0
  547. package/dist/with-lookup/search/snippet.d.ts +5 -0
  548. package/dist/with-lookup/search/strategy.d.ts +37 -0
  549. package/dist/with-lookup/search/tokenize.d.ts +12 -0
  550. package/dist/with-party/auth-introspection/index.d.ts +44 -0
  551. package/dist/with-party/broker/active.d.ts +23 -0
  552. package/dist/with-party/broker/index.d.ts +28 -0
  553. package/dist/with-party/broker/seed.d.ts +77 -0
  554. package/dist/with-party/custody/active.d.ts +10 -0
  555. package/dist/with-party/custody/index.d.ts +69 -0
  556. package/dist/with-party/custody/liberate.d.ts +64 -0
  557. package/dist/with-party/custody/strategy.d.ts +48 -0
  558. package/dist/with-party/directory/index.d.ts +11 -0
  559. package/dist/with-party/directory/public-envelope/index.d.ts +12 -0
  560. package/dist/with-party/directory/public-envelope/schema.d.ts +24 -0
  561. package/dist/with-party/directory/public-envelope/storage.d.ts +59 -0
  562. package/dist/with-party/directory/public-envelope/types.d.ts +80 -0
  563. package/dist/with-party/directory/storage.d.ts +33 -0
  564. package/dist/with-party/directory/types.d.ts +43 -0
  565. package/dist/with-party/directory/user-envelope/api.d.ts +201 -0
  566. package/dist/with-party/directory/user-envelope/index.d.ts +12 -0
  567. package/dist/with-party/directory/user-envelope/storage.d.ts +54 -0
  568. package/dist/with-party/directory/visibility.d.ts +47 -0
  569. package/dist/with-party/policy/engine.d.ts +60 -0
  570. package/dist/with-party/policy/index.d.ts +15 -0
  571. package/dist/with-party/policy/noydb-facade.d.ts +39 -0
  572. package/dist/with-party/policy/presets.d.ts +38 -0
  573. package/dist/with-party/policy/storage.d.ts +31 -0
  574. package/dist/with-party/session/active.d.ts +34 -0
  575. package/dist/with-party/session/dev-unlock.d.ts +128 -0
  576. package/dist/with-party/session/index.d.ts +23 -0
  577. package/dist/with-party/session/session-policy.d.ts +92 -0
  578. package/dist/with-party/session/session.d.ts +131 -0
  579. package/dist/with-party/session/strategy.d.ts +42 -0
  580. package/dist/with-party/session/unlock-state.d.ts +47 -0
  581. package/dist/with-party/sync/index.d.ts +31 -0
  582. package/dist/with-party/tab-coordination.d.ts +73 -0
  583. package/dist/with-party/tab-write-relay.d.ts +39 -0
  584. package/dist/with-party/team/active.d.ts +13 -0
  585. package/dist/with-party/team/authenticators.d.ts +95 -0
  586. package/dist/with-party/team/deed.d.ts +97 -0
  587. package/dist/with-party/team/delegation.d.ts +88 -0
  588. package/dist/with-party/team/index.d.ts +38 -0
  589. package/dist/with-party/team/keyring.d.ts +318 -0
  590. package/dist/with-party/team/magic-link-grant.d.ts +152 -0
  591. package/dist/with-party/team/managed-passphrase.d.ts +280 -0
  592. package/dist/with-party/team/noydb-facade.d.ts +484 -0
  593. package/dist/with-party/team/peer-recover.d.ts +81 -0
  594. package/dist/with-party/team/presence.d.ts +81 -0
  595. package/dist/with-party/team/recovery.d.ts +191 -0
  596. package/dist/with-party/team/reserved-secret-collections.d.ts +41 -0
  597. package/dist/with-party/team/rotate-recover.d.ts +275 -0
  598. package/dist/with-party/team/shamir-recovery-provider.d.ts +15 -0
  599. package/dist/with-party/team/strategy.d.ts +9 -0
  600. package/dist/with-party/team/sync-active.d.ts +33 -0
  601. package/dist/with-party/team/sync-credentials.d.ts +113 -0
  602. package/dist/with-party/team/sync-strategy.d.ts +67 -0
  603. package/dist/with-party/team/sync-transaction.d.ts +39 -0
  604. package/dist/with-party/team/sync.d.ts +165 -0
  605. package/dist/with-party/team/tiers.d.ts +39 -0
  606. package/dist/with-party/team/wrapped-deks.d.ts +86 -0
  607. package/dist/with-pod/backup.d.ts +74 -0
  608. package/dist/with-pod/bundle.d.ts +414 -0
  609. package/dist/with-pod/format.d.ts +203 -0
  610. package/dist/with-pod/index.d.ts +20 -0
  611. package/dist/with-pod/pod-store.d.ts +54 -0
  612. package/dist/with-pod/ulid.d.ts +64 -0
  613. package/dist/with-shape/blobs/blob-compaction.d.ts +170 -0
  614. package/dist/with-shape/blobs/blob-set.d.ts +342 -0
  615. package/dist/with-shape/blobs/export-blobs.d.ts +110 -0
  616. package/dist/with-shape/blobs/import-external.d.ts +50 -0
  617. package/dist/with-shape/blobs/mime-magic.d.ts +48 -0
  618. package/dist/with-shape/blobs/object-projection.d.ts +70 -0
  619. package/dist/with-shape/introspection/describe.d.ts +237 -0
  620. package/dist/with-shape/introspection/field-meta.d.ts +61 -0
  621. package/dist/with-shape/introspection/fields.d.ts +14 -0
  622. package/dist/with-shape/introspection/index.d.ts +12 -0
  623. package/dist/with-shape/introspection/json-schema.d.ts +13 -0
  624. package/dist/with-shape/introspection/meta.d.ts +22 -0
  625. package/dist/with-shape/introspection/projection.d.ts +13 -0
  626. package/dist/with-shape/introspection/types.d.ts +154 -0
  627. package/dist/with-shape/introspection/walk.d.ts +50 -0
  628. package/dist/with-shape/links/lazy-handle.d.ts +36 -0
  629. package/dist/with-shape/links/link-set.d.ts +67 -0
  630. package/dist/with-shape/links/names.d.ts +65 -0
  631. package/dist/with-shape/links/vault-facade.d.ts +211 -0
  632. package/dist/with-shape/persisted-schemas/canonicalize.d.ts +11 -0
  633. package/dist/with-shape/persisted-schemas/derive.d.ts +29 -0
  634. package/dist/with-shape/persisted-schemas/index.d.ts +21 -0
  635. package/dist/with-shape/persisted-schemas/register.d.ts +66 -0
  636. package/dist/with-shape/persisted-schemas/storage.d.ts +61 -0
  637. package/dist/with-shape/persisted-schemas/types.d.ts +54 -0
  638. package/dist/with-shape/satellites/dead-filter.d.ts +21 -0
  639. package/dist/with-shape/satellites/declare.d.ts +60 -0
  640. package/dist/with-shape/satellites/existence.d.ts +5 -0
  641. package/dist/with-shape/satellites/fanout.d.ts +37 -0
  642. package/dist/with-shape/satellites/forget.d.ts +47 -0
  643. package/dist/with-shape/satellites/index.d.ts +3 -0
  644. package/dist/with-shape/satellites/joined.d.ts +19 -0
  645. package/dist/with-shape/satellites/marker.d.ts +10 -0
  646. package/dist/with-shape/satellites/post-register.d.ts +6 -0
  647. package/dist/with-shape/satellites/proxy.d.ts +37 -0
  648. package/dist/with-shape/satellites/raw-target.d.ts +14 -0
  649. package/dist/with-shape/satellites/registry.d.ts +19 -0
  650. package/dist/with-shape/satellites/types.d.ts +26 -0
  651. package/dist/with-shape/satellites/validate.d.ts +17 -0
  652. package/dist/with-shape/schema-update/client-registry.d.ts +35 -0
  653. package/dist/with-shape/schema-update/cutover.d.ts +5 -0
  654. package/dist/with-shape/schema-update/delta.d.ts +2 -0
  655. package/dist/with-shape/schema-update/dispatch.d.ts +3 -0
  656. package/dist/with-shape/schema-update/fence-controller.d.ts +62 -0
  657. package/dist/with-shape/schema-update/fence-watcher.d.ts +37 -0
  658. package/dist/with-shape/schema-update/fence.d.ts +15 -0
  659. package/dist/with-shape/schema-update/gate.d.ts +16 -0
  660. package/dist/with-shape/schema-update/index.d.ts +6 -0
  661. package/dist/with-shape/schema-update/store-coordination-provider.d.ts +29 -0
  662. package/dist/with-shape/schema-update/strategies.d.ts +12 -0
  663. package/dist/with-shape/schema-update/types.d.ts +53 -0
  664. package/dist/with-store/index.d.ts +15 -0
  665. package/dist/with-store/lazy/active.d.ts +12 -0
  666. package/dist/with-store/lazy/index.d.ts +14 -0
  667. package/dist/with-store/lazy/strategy.d.ts +9 -0
  668. package/dist/with-store/route-store.d.ts +259 -0
  669. package/dist/with-store/store-middleware.d.ts +189 -0
  670. package/dist/withdraw-accessible-CLMZEHQT.js +28 -0
  671. package/dist/withdraw-accessible-CLMZEHQT.js.map +1 -0
  672. package/package.json +56 -52
  673. package/dist/adapter/index.d.ts +0 -5
  674. package/dist/adapter/index.js +0 -15
  675. package/dist/aggregate/index.d.ts +0 -42
  676. package/dist/api-RW3KP7WU.js +0 -14
  677. package/dist/as/index.d.ts +0 -7
  678. package/dist/at/index.d.ts +0 -5
  679. package/dist/attestation/index.d.ts +0 -20
  680. package/dist/backup-XV3IOEGB.js +0 -217
  681. package/dist/backup-XV3IOEGB.js.map +0 -1
  682. package/dist/blobs/index.d.ts +0 -44
  683. package/dist/bundle/index.d.ts +0 -122
  684. package/dist/bundle-CH-H06dp.d.ts +0 -548
  685. package/dist/by/index.d.ts +0 -1
  686. package/dist/cargo/index.d.ts +0 -9
  687. package/dist/chunk-26LGBE4T.js +0 -42
  688. package/dist/chunk-26LGBE4T.js.map +0 -1
  689. package/dist/chunk-2P2HZEXU.js +0 -233
  690. package/dist/chunk-2P2HZEXU.js.map +0 -1
  691. package/dist/chunk-3YFXJ3ZP.js +0 -97
  692. package/dist/chunk-5LUY7UTV.js +0 -380
  693. package/dist/chunk-5LUY7UTV.js.map +0 -1
  694. package/dist/chunk-5N6CZTCY.js +0 -367
  695. package/dist/chunk-5O3AOPDT.js +0 -992
  696. package/dist/chunk-5O3AOPDT.js.map +0 -1
  697. package/dist/chunk-5R3ERCDH.js +0 -239
  698. package/dist/chunk-5R3ERCDH.js.map +0 -1
  699. package/dist/chunk-5R5JW2JT.js +0 -12502
  700. package/dist/chunk-5R5JW2JT.js.map +0 -1
  701. package/dist/chunk-5TDJ56JE.js +0 -32
  702. package/dist/chunk-5TDJ56JE.js.map +0 -1
  703. package/dist/chunk-62QYRORB.js +0 -320
  704. package/dist/chunk-62QYRORB.js.map +0 -1
  705. package/dist/chunk-6S7T6WC4.js +0 -111
  706. package/dist/chunk-6S7T6WC4.js.map +0 -1
  707. package/dist/chunk-76722EBH.js +0 -451
  708. package/dist/chunk-76722EBH.js.map +0 -1
  709. package/dist/chunk-AIWULCUO.js +0 -68
  710. package/dist/chunk-AIWULCUO.js.map +0 -1
  711. package/dist/chunk-AQTBSL7R.js +0 -181
  712. package/dist/chunk-AQTBSL7R.js.map +0 -1
  713. package/dist/chunk-AXRXJTE2.js +0 -59
  714. package/dist/chunk-AZAOEIKW.js +0 -155
  715. package/dist/chunk-BG3SPSR4.js +0 -53
  716. package/dist/chunk-BG3SPSR4.js.map +0 -1
  717. package/dist/chunk-BGIZAFY7.js +0 -1
  718. package/dist/chunk-CMGR4ZEW.js +0 -209
  719. package/dist/chunk-CWPPNPOH.js +0 -23
  720. package/dist/chunk-DFEMTNPJ.js +0 -1219
  721. package/dist/chunk-DFEMTNPJ.js.map +0 -1
  722. package/dist/chunk-DGDI2D4M.js +0 -79
  723. package/dist/chunk-DGDI2D4M.js.map +0 -1
  724. package/dist/chunk-EIZUR2XW.js +0 -36
  725. package/dist/chunk-FISN7WE4.js +0 -798
  726. package/dist/chunk-FISN7WE4.js.map +0 -1
  727. package/dist/chunk-GYGWYIOZ.js +0 -200
  728. package/dist/chunk-GYGWYIOZ.js.map +0 -1
  729. package/dist/chunk-HCIPRAGS.js +0 -45
  730. package/dist/chunk-I2NOIW44.js +0 -83
  731. package/dist/chunk-I2NOIW44.js.map +0 -1
  732. package/dist/chunk-I3TIKTJO.js +0 -132
  733. package/dist/chunk-I3TIKTJO.js.map +0 -1
  734. package/dist/chunk-IAGBDSCS.js +0 -40
  735. package/dist/chunk-IELYAOGG.js +0 -78
  736. package/dist/chunk-IELYAOGG.js.map +0 -1
  737. package/dist/chunk-IGUYVGGI.js +0 -205
  738. package/dist/chunk-IO6GRPT6.js +0 -34
  739. package/dist/chunk-IPB7FTQX.js +0 -273
  740. package/dist/chunk-IPB7FTQX.js.map +0 -1
  741. package/dist/chunk-ITNUCOXM.js +0 -148
  742. package/dist/chunk-ITNUCOXM.js.map +0 -1
  743. package/dist/chunk-IUEN57TV.js +0 -722
  744. package/dist/chunk-IUEN57TV.js.map +0 -1
  745. package/dist/chunk-JNUWZ6D3.js +0 -57
  746. package/dist/chunk-JNUWZ6D3.js.map +0 -1
  747. package/dist/chunk-K2WCO3NX.js +0 -1
  748. package/dist/chunk-KVOXU4T5.js +0 -30
  749. package/dist/chunk-KXGNJJXB.js +0 -135
  750. package/dist/chunk-LFLXAY2W.js +0 -414
  751. package/dist/chunk-LFLXAY2W.js.map +0 -1
  752. package/dist/chunk-LMTH2RM6.js +0 -129
  753. package/dist/chunk-LV7M27WM.js +0 -702
  754. package/dist/chunk-LV7M27WM.js.map +0 -1
  755. package/dist/chunk-LXQT4WMP.js +0 -684
  756. package/dist/chunk-LXQT4WMP.js.map +0 -1
  757. package/dist/chunk-M2YKN37S.js +0 -524
  758. package/dist/chunk-M2YKN37S.js.map +0 -1
  759. package/dist/chunk-M6OST55S.js +0 -14
  760. package/dist/chunk-MD3Y6J3L.js +0 -278
  761. package/dist/chunk-MD3Y6J3L.js.map +0 -1
  762. package/dist/chunk-MTMJVJ5W.js +0 -73
  763. package/dist/chunk-MTMJVJ5W.js.map +0 -1
  764. package/dist/chunk-NF5JWERG.js +0 -74
  765. package/dist/chunk-PKHL44ER.js +0 -124
  766. package/dist/chunk-PSMV73A5.js +0 -117
  767. package/dist/chunk-Q7SS3IME.js +0 -120
  768. package/dist/chunk-Q7SS3IME.js.map +0 -1
  769. package/dist/chunk-QHJW5EXU.js +0 -54
  770. package/dist/chunk-RUEKROOS.js +0 -80
  771. package/dist/chunk-RUIMKQTA.js +0 -23
  772. package/dist/chunk-RUIMKQTA.js.map +0 -1
  773. package/dist/chunk-SKF73JOP.js +0 -355
  774. package/dist/chunk-SM3AVUHC.js +0 -42
  775. package/dist/chunk-SMXWYP24.js +0 -155
  776. package/dist/chunk-SRB2XEWB.js +0 -148
  777. package/dist/chunk-SRB2XEWB.js.map +0 -1
  778. package/dist/chunk-TA66UMI4.js +0 -123
  779. package/dist/chunk-TEILUWOI.js +0 -664
  780. package/dist/chunk-TEILUWOI.js.map +0 -1
  781. package/dist/chunk-TJYQIGAP.js +0 -82
  782. package/dist/chunk-TJYQIGAP.js.map +0 -1
  783. package/dist/chunk-UAG5KWVA.js +0 -367
  784. package/dist/chunk-UDRIWL7A.js +0 -382
  785. package/dist/chunk-UIU2THRG.js +0 -1937
  786. package/dist/chunk-UIU2THRG.js.map +0 -1
  787. package/dist/chunk-UPJNJGGA.js +0 -572
  788. package/dist/chunk-UPJNJGGA.js.map +0 -1
  789. package/dist/chunk-UV5MFVO3.js +0 -21
  790. package/dist/chunk-V7RWQRG7.js +0 -430
  791. package/dist/chunk-VCTFO5CO.js +0 -71
  792. package/dist/chunk-VFQGRQIH.js +0 -97
  793. package/dist/chunk-VFQGRQIH.js.map +0 -1
  794. package/dist/chunk-WWGT2MDV.js +0 -762
  795. package/dist/chunk-WWGT2MDV.js.map +0 -1
  796. package/dist/chunk-WYSO2NIH.js +0 -30
  797. package/dist/chunk-XXYIOFUB.js +0 -164
  798. package/dist/chunk-Y22T3KQE.js +0 -261
  799. package/dist/chunk-Y22T3KQE.js.map +0 -1
  800. package/dist/chunk-ZCGAHGUS.js +0 -230
  801. package/dist/chunk-ZYUC53LT.js +0 -1370
  802. package/dist/chunk-ZYUC53LT.js.map +0 -1
  803. package/dist/collection-facade-GQAOGJP2.js +0 -33
  804. package/dist/consent/index.d.ts +0 -23
  805. package/dist/crdt/index.d.ts +0 -34
  806. package/dist/decrypt-partition-IHtxEnTi.d.ts +0 -21
  807. package/dist/delegation-UL5HKLER.js +0 -19
  808. package/dist/derivations/index.d.ts +0 -70
  809. package/dist/describe/index.d.ts +0 -1
  810. package/dist/describe/index.js +0 -1
  811. package/dist/describe-aBkJR2sd.d.ts +0 -131
  812. package/dist/dev-unlock-C9Ro3v_O.d.ts +0 -263
  813. package/dist/discriminant-BN9REW3o.d.ts +0 -60
  814. package/dist/enclave-UL5LW66V.js +0 -88
  815. package/dist/executor-2FWQRLMG.js +0 -15
  816. package/dist/executor-QZ7BXICW.js +0 -9
  817. package/dist/executor-Z5ZLJVTV.js +0 -9
  818. package/dist/export-accessible-KRV5W4GH.js +0 -17
  819. package/dist/extract-partition-GLKBOXFQ.js +0 -30
  820. package/dist/fanout-sidecar-GF3DJ6KR.js +0 -71
  821. package/dist/fanout-sidecar-GF3DJ6KR.js.map +0 -1
  822. package/dist/forget/index.d.ts +0 -36
  823. package/dist/guards/index.d.ts +0 -35
  824. package/dist/hash-Cp5uwiox.d.ts +0 -67
  825. package/dist/history/index.d.ts +0 -61
  826. package/dist/i18n/index.d.ts +0 -37
  827. package/dist/in/index.d.ts +0 -5
  828. package/dist/index-B9QdHytu.d.ts +0 -123
  829. package/dist/index-BF9_96A5.d.ts +0 -123
  830. package/dist/index-BzUo1B6n.d.ts +0 -20730
  831. package/dist/indexing/index.d.ts +0 -39
  832. package/dist/issue-Y6UVIR43.js +0 -13
  833. package/dist/kernel/index.d.ts +0 -32
  834. package/dist/kernel/index.js +0 -53
  835. package/dist/ledger-RYI35CDS.js +0 -36
  836. package/dist/liberate-CRPZEV7O.js +0 -18
  837. package/dist/materialized-views/index.d.ts +0 -173
  838. package/dist/mime-magic-CGhw37_E.d.ts +0 -103
  839. package/dist/noydb-367AM4HT.js +0 -50
  840. package/dist/on/index.d.ts +0 -5
  841. package/dist/overlay-views/index.d.ts +0 -98
  842. package/dist/periods/index.d.ts +0 -20
  843. package/dist/pod/index.d.ts +0 -63
  844. package/dist/policy-IXK4FVXP.js +0 -41
  845. package/dist/portability/index.d.ts +0 -20
  846. package/dist/public-envelope-JHDQCPSX.js +0 -32
  847. package/dist/query/index.d.ts +0 -5
  848. package/dist/read-only-facade-5ADRJVTM.js +0 -8
  849. package/dist/registry-45RJNWGU.js +0 -9
  850. package/dist/registry-5GRV5VXI.js +0 -13
  851. package/dist/registry-WEUCHBO4.js +0 -11
  852. package/dist/request-withdrawal-GBPH2FDY.js +0 -25
  853. package/dist/revoke-TUFRGI6S.js +0 -18
  854. package/dist/sealed-record/index.d.ts +0 -69
  855. package/dist/session/index.d.ts +0 -44
  856. package/dist/shadow/index.d.ts +0 -15
  857. package/dist/signer-PNKTBVF7.js +0 -19
  858. package/dist/snapshots/index.d.ts +0 -26
  859. package/dist/stale-3JWHNDIY.js +0 -14
  860. package/dist/store-coordination-provider-3I7XWZZK.js +0 -142
  861. package/dist/subject-index-O75wKshW.d.ts +0 -362
  862. package/dist/sync/index.d.ts +0 -41
  863. package/dist/team/index.d.ts +0 -116
  864. package/dist/tiers/index.d.ts +0 -5
  865. package/dist/to/index.d.ts +0 -5
  866. package/dist/transition-guard-C7ol6oPw.d.ts +0 -165
  867. package/dist/tx/index.d.ts +0 -35
  868. package/dist/ui/index.d.ts +0 -1
  869. package/dist/ulid-DRH25k3y.d.ts +0 -66
  870. package/dist/util/index.d.ts +0 -79
  871. package/dist/vault-diff-B5fYNBL7.d.ts +0 -147
  872. package/dist/with/index.d.ts +0 -38
  873. package/dist/with-materialized-view-6p0Fk8bL.d.ts +0 -27
  874. package/dist/with-overlayed-view-BJ6mXGMd.d.ts +0 -12
  875. package/dist/with-rollup-BvQo3ROo.d.ts +0 -47
  876. package/dist/withdraw-accessible-FFS46EOD.js +0 -22
  877. /package/dist/{adapter/index.js.map → api-YGMINAET.js.map} +0 -0
  878. /package/dist/{chunk-V7RWQRG7.js.map → chunk-3CNQ7FQ3.js.map} +0 -0
  879. /package/dist/{chunk-NF5JWERG.js.map → chunk-3MSQLQNZ.js.map} +0 -0
  880. /package/dist/{chunk-IO6GRPT6.js.map → chunk-4R4Q64W5.js.map} +0 -0
  881. /package/dist/{chunk-SMXWYP24.js.map → chunk-5XIPOCQC.js.map} +0 -0
  882. /package/dist/{chunk-IGUYVGGI.js.map → chunk-6QILBDZU.js.map} +0 -0
  883. /package/dist/{chunk-AZAOEIKW.js.map → chunk-7E67FJ33.js.map} +0 -0
  884. /package/dist/{chunk-PSMV73A5.js.map → chunk-7NS43EXZ.js.map} +0 -0
  885. /package/dist/{chunk-CMGR4ZEW.js.map → chunk-A2Y6YFVN.js.map} +0 -0
  886. /package/dist/{chunk-HCIPRAGS.js.map → chunk-BCYQA5BK.js.map} +0 -0
  887. /package/dist/{chunk-LMTH2RM6.js.map → chunk-CB25ONKC.js.map} +0 -0
  888. /package/dist/{chunk-UV5MFVO3.js.map → chunk-CIKY6I4W.js.map} +0 -0
  889. /package/dist/{chunk-QHJW5EXU.js.map → chunk-D26JB3LZ.js.map} +0 -0
  890. /package/dist/{chunk-SM3AVUHC.js.map → chunk-DIRRS7WP.js.map} +0 -0
  891. /package/dist/{chunk-SKF73JOP.js.map → chunk-H44ZE4IE.js.map} +0 -0
  892. /package/dist/{chunk-UDRIWL7A.js.map → chunk-HFJIGWJC.js.map} +0 -0
  893. /package/dist/{chunk-ZCGAHGUS.js.map → chunk-KPGX66PM.js.map} +0 -0
  894. /package/dist/{chunk-5N6CZTCY.js.map → chunk-MCEKIAO4.js.map} +0 -0
  895. /package/dist/{chunk-CWPPNPOH.js.map → chunk-O2DYPAZY.js.map} +0 -0
  896. /package/dist/{chunk-KVOXU4T5.js.map → chunk-ODJWBC5I.js.map} +0 -0
  897. /package/dist/{chunk-VCTFO5CO.js.map → chunk-OFJ5GPNA.js.map} +0 -0
  898. /package/dist/{chunk-KXGNJJXB.js.map → chunk-PXWVF7MC.js.map} +0 -0
  899. /package/dist/{chunk-IAGBDSCS.js.map → chunk-Q3XSMOZM.js.map} +0 -0
  900. /package/dist/{chunk-AXRXJTE2.js.map → chunk-RKRGDAS7.js.map} +0 -0
  901. /package/dist/{chunk-XXYIOFUB.js.map → chunk-SRVQHVNX.js.map} +0 -0
  902. /package/dist/{chunk-M6OST55S.js.map → chunk-UFILRICG.js.map} +0 -0
  903. /package/dist/{chunk-3YFXJ3ZP.js.map → chunk-UTLEAJXC.js.map} +0 -0
  904. /package/dist/{chunk-TA66UMI4.js.map → chunk-VA4ZWLFY.js.map} +0 -0
  905. /package/dist/{chunk-UAG5KWVA.js.map → chunk-VR24ILCR.js.map} +0 -0
  906. /package/dist/{chunk-WYSO2NIH.js.map → chunk-XHV25KBM.js.map} +0 -0
  907. /package/dist/{chunk-PKHL44ER.js.map → chunk-YSXEFGND.js.map} +0 -0
  908. /package/dist/{chunk-EIZUR2XW.js.map → chunk-YXOUQ2H7.js.map} +0 -0
  909. /package/dist/{chunk-RUEKROOS.js.map → chunk-ZP5PL65C.js.map} +0 -0
  910. /package/dist/{describe → classified}/index.js.map +0 -0
  911. /package/dist/{api-RW3KP7WU.js.map → collection-facade-YE2O4J4O.js.map} +0 -0
  912. /package/dist/{chunk-BGIZAFY7.js.map → computed-W6MVAMWZ.js.map} +0 -0
  913. /package/dist/{chunk-K2WCO3NX.js.map → delegation-OPUU3R2E.js.map} +0 -0
  914. /package/dist/{collection-facade-GQAOGJP2.js.map → derive-BGUHU663.js.map} +0 -0
  915. /package/dist/{delegation-UL5HKLER.js.map → enclave-VXAQD4XJ.js.map} +0 -0
  916. /package/dist/{enclave-UL5LW66V.js.map → executor-GTVSUUBX.js.map} +0 -0
  917. /package/dist/{executor-2FWQRLMG.js.map → executor-GZWMTOXB.js.map} +0 -0
  918. /package/dist/{executor-QZ7BXICW.js.map → executor-XXGS4S3K.js.map} +0 -0
  919. /package/dist/{executor-Z5ZLJVTV.js.map → export-accessible-BMULIOYB.js.map} +0 -0
  920. /package/dist/{export-accessible-KRV5W4GH.js.map → extract-partition-JUQTWDXR.js.map} +0 -0
  921. /package/dist/{extract-partition-GLKBOXFQ.js.map → find-XRGCNGNN.js.map} +0 -0
  922. /package/dist/{issue-Y6UVIR43.js.map → issue-UB6AA5M6.js.map} +0 -0
  923. /package/dist/{kernel → lazy}/index.js.map +0 -0
  924. /package/dist/{ledger-RYI35CDS.js.map → ledger-FU6GH5EH.js.map} +0 -0
  925. /package/dist/{liberate-CRPZEV7O.js.map → liberate-YUN7W5QG.js.map} +0 -0
  926. /package/dist/{noydb-367AM4HT.js.map → link-set-MNADSH5M.js.map} +0 -0
  927. /package/dist/{policy-IXK4FVXP.js.map → noydb-6JLBZU4U.js.map} +0 -0
  928. /package/dist/{public-envelope-JHDQCPSX.js.map → policy-JTFOPPUU.js.map} +0 -0
  929. /package/dist/{read-only-facade-5ADRJVTM.js.map → public-envelope-NJVB7LPA.js.map} +0 -0
  930. /package/dist/{registry-45RJNWGU.js.map → read-only-facade-CHCKSEPD.js.map} +0 -0
  931. /package/dist/{registry-5GRV5VXI.js.map → register-VCKOBWKT.js.map} +0 -0
  932. /package/dist/{registry-WEUCHBO4.js.map → registry-72UKJ2L4.js.map} +0 -0
  933. /package/dist/{request-withdrawal-GBPH2FDY.js.map → registry-BZFLJNEH.js.map} +0 -0
  934. /package/dist/{revoke-TUFRGI6S.js.map → registry-YJEYSYI5.js.map} +0 -0
  935. /package/dist/{signer-PNKTBVF7.js.map → request-withdrawal-6MJRMFHF.js.map} +0 -0
  936. /package/dist/{stale-3JWHNDIY.js.map → revoke-4KUNSVJC.js.map} +0 -0
  937. /package/dist/{withdraw-accessible-FFS46EOD.js.map → satellites/index.js.map} +0 -0
  938. /package/dist/{store-coordination-provider-3I7XWZZK.js.map → store-coordination-provider-HPYVFJCV.js.map} +0 -0
@@ -0,0 +1,3147 @@
1
+ /**
2
+ * Core types — the {@link NoydbStore} interface, envelope format, roles, and
3
+ * all configuration shapes consumed by {@link createNoydb}.
4
+ *
5
+ * ## What lives here
6
+ *
7
+ * - **{@link NoydbStore}** — the 6-method contract every backend must implement
8
+ * (`get`, `put`, `delete`, `list`, `loadAll`, `saveAll`).
9
+ * - **{@link EncryptedEnvelope}** — the wire format stored by backends:
10
+ * `{ _noydb, _v, _ts, _iv, _data }`. Backends only ever see this shape.
11
+ * - **{@link Role} / {@link Permission}** — the access-control vocabulary
12
+ * (`owner`, `admin`, `operator`, `viewer`, `client`).
13
+ * - **{@link NoydbOptions}** — the full configuration object passed to
14
+ * {@link createNoydb}.
15
+ *
16
+ * ## Extending the store interface
17
+ *
18
+ * All optional store capabilities (`ping`, `listPage`, `listSince`,
19
+ * `presencePublish`, `presenceSubscribe`, `listVaults`) are additive extensions
20
+ * discovered via `'method' in store`. Implementing them unlocks features but
21
+ * is never required — core always falls back to the 6-method baseline.
22
+ *
23
+ * @module
24
+ */
25
+ import type { StandardSchemaV1 } from './schema.js';
26
+ import type { DeferredNumberingConfig } from '../with-commit/numbering/descriptor.js';
27
+ import type { SyncPolicy } from './sync-policy.js';
28
+ import type { BlobStrategy } from '../port/with/blob-strategy.js';
29
+ import type { ArchiveStrategy } from '../with-fork/archive/index.js';
30
+ import type { IndexStrategy } from '../with-lookup/indexing/strategy.js';
31
+ import type { AggregateStrategy } from '../with-lookup/aggregate/strategy.js';
32
+ import type { ConsentStrategy } from '../with-audit/consent/strategy.js';
33
+ import type { PeriodsStrategy } from '../with-audit/periods/strategy.js';
34
+ import type { ShadowStrategy } from '../with-fork/shadow/strategy.js';
35
+ import type { TxStrategy } from '../with-commit/tx/strategy.js';
36
+ import type { HistoryStrategy } from '../with-commit/history/strategy.js';
37
+ import type { ForgetStrategy } from '../with-audit/forget/strategy.js';
38
+ import type { SnapshotStrategy } from '../with-fork/snapshots/strategy.js';
39
+ import type { DerivationSkippedFrozen } from './via/dispatch.js';
40
+ import type { AttestationStrategy } from '../with-audit/attestation/strategy.js';
41
+ import type { ClassifiedStrategy } from '../port/with/classified-strategy.js';
42
+ import type { TiersStrategy } from '../with-audit/tiers/strategy.js';
43
+ import type { SealedRecordStrategy } from '../with-audit/sealed-record/strategy.js';
44
+ import type { PortabilityStrategy } from '../with-audit/portability/strategy.js';
45
+ import type { SequenceStrategy } from '../with-commit/sequence/strategy.js';
46
+ import type { CustodyStrategy } from '../with-party/custody/strategy.js';
47
+ import type { TeamStrategy } from '../port/with/team-strategy.js';
48
+ import type { BrokerStrategy } from '../port/with/broker-strategy.js';
49
+ import type { LazyStrategy } from '../port/with/lazy-strategy.js';
50
+ import type { SearchStrategy } from '../with-lookup/search/strategy.js';
51
+ import type { CargoStrategy } from '../with-cargo/strategy.js';
52
+ import type { Layer, I18nStrategy } from '../port/with/i18n-strategy.js';
53
+ import type { SessionStrategy } from '../with-party/session/strategy.js';
54
+ import type { SyncStrategy } from '../with-party/team/sync-strategy.js';
55
+ import type { GuardStrategyHandleAny } from '../with-audit/guards/types.js';
56
+ import type { DerivationStrategyHandle } from '../with-formula/derivations/types.js';
57
+ import type { UnlockedKeyring } from '../with-party/team/keyring.js';
58
+ import type { PassphrasePolicy } from './validation.js';
59
+ import type { PublicEnvelopeSchema } from '../with-party/directory/public-envelope/types.js';
60
+ import type { MaterializedViewStrategyHandle } from '../with-formula/materialized-views/types.js';
61
+ import type { OverlayedViewStrategyHandle } from '../with-formula/overlay-views/types.js';
62
+ import type { SealingKeyProvider, RecipientHint } from '../with-party/team/managed-passphrase.js';
63
+ import type { ShamirRecoveryProvider } from '../with-party/team/shamir-recovery-provider.js';
64
+ import type { ObjectProjection } from '../with-shape/blobs/object-projection.js';
65
+ import type { CoordinationProvider } from '../port/by/types.js';
66
+ import type { ScriptWarning } from '../port/with/i18n-strategy.js';
67
+ import type { ViaDescriptor } from './via/index.js';
68
+ import type { EnclaveKey } from './enclave/index.js';
69
+ /** Format version for encrypted record envelopes. */
70
+ export declare const NOYDB_FORMAT_VERSION: 1;
71
+ /** Format version for keyring files. */
72
+ export declare const NOYDB_KEYRING_VERSION: 1;
73
+ /** Format version for backup files. */
74
+ export declare const NOYDB_BACKUP_VERSION: 1;
75
+ /** Format version for sync metadata. */
76
+ export declare const NOYDB_SYNC_VERSION: 1;
77
+ /**
78
+ * Access role assigned to a user within a vault.
79
+ *
80
+ * Roles control both the operations a user can perform and which DEKs
81
+ * they receive in their keyring:
82
+ *
83
+ * | Role | Collections | Can grant/revoke | Can export |
84
+ * |-------------|-----------------|:----------------:|:----------:|
85
+ * | `owner` | all (rw) | Yes (all roles) | Yes |
86
+ * | `admin` | all (rw) | Yes (≤ admin) | Yes |
87
+ * | `custodian` | all (rw) | No (see below) | Yes |
88
+ * | `operator` | explicit (rw) | No | ACL-scoped |
89
+ * | `viewer` | all (ro) | No | Yes |
90
+ * | `client` | explicit (ro) | No | ACL-scoped |
91
+ *
92
+ * **`custodian` (FR-6 sovereign custody).** Operationally admin-rank —
93
+ * rw + access on every collection, receives all collection DEKs on grant
94
+ * — but is *provably non-owning*: it CANNOT grant, revoke, rotate keys,
95
+ * destructively withdraw/sever, or extract-and-sever a partition (rotate is
96
+ * blocked in `rotateKeys`, sever in `withdrawAccessibleData`, and extract in
97
+ * `extractPartition`). Only the (sealed Deed) **owner** may
98
+ * mint or remove a custodian; an admin cannot. This is the inalienability
99
+ * floor — a custodian can run the vault day-to-day yet never escalate to
100
+ * the owner credential.
101
+ */
102
+ export type Role = 'owner' | 'admin' | 'custodian' | 'operator' | 'viewer' | 'client';
103
+ /**
104
+ * Read-write or read-only access on a collection.
105
+ * Stored per-collection in the user's keyring.
106
+ */
107
+ export type Permission = 'rw' | 'ro';
108
+ /**
109
+ * Map of collection name → permission level for a user's keyring entry.
110
+ * `'*'` is the wildcard collection matching all collections in the vault.
111
+ */
112
+ export type Permissions = Record<string, Permission>;
113
+ /** The encrypted wrapper stored by stores. Stores only ever see this. */
114
+ export interface EncryptedEnvelope {
115
+ readonly _noydb: typeof NOYDB_FORMAT_VERSION;
116
+ readonly _v: number;
117
+ readonly _ts: string;
118
+ readonly _iv: string;
119
+ readonly _data: string;
120
+ /** User who created this version (unencrypted metadata). */
121
+ readonly _by?: string;
122
+ /**
123
+ * Opaque provenance source id — which party/registry wrote this version.
124
+ * Unencrypted; present only when the collection opts into `provenance: true`
125
+ * and a `source` is supplied to `put()`. Off by default (zero cost).
126
+ */
127
+ readonly _source?: string;
128
+ /** ISO-8601 timestamp the provenance source was recorded. Present alongside `_source`. */
129
+ readonly _sourceTs?: string;
130
+ /**
131
+ * Hierarchical access tier. Omitted → tier 0.
132
+ *
133
+ * Unencrypted on purpose — the store reads it to route the envelope
134
+ * to the right DEK slot without having to try-decrypt against every
135
+ * tier. Only leaks the tier of each record, not any value
136
+ * equivalence.
137
+ */
138
+ readonly _tier?: number;
139
+ /**
140
+ * User id who last elevated this record. Used by
141
+ * `demote()` to gate the reverse operation: only the original
142
+ * elevator or an owner can demote a record back down. Cleared on
143
+ * every successful demote so a later re-elevate requires the new
144
+ * actor to own the demotion right.
145
+ */
146
+ readonly _elevatedBy?: string;
147
+ /**
148
+ * Deterministic-encryption index. Map of field name →
149
+ * base64 deterministic ciphertext. Present only when the collection
150
+ * declares `deterministicFields` and the feature is acknowledged. The
151
+ * field names are unencrypted (they're the index keys); the values
152
+ * are AES-GCM ciphertext with an HKDF-derived deterministic IV.
153
+ *
154
+ * Enables blind equality search (`collection.findByDet(field,
155
+ * value)`) without decrypting every record. Leaks equality as a known
156
+ * side channel.
157
+ */
158
+ readonly _det?: Record<string, string>;
159
+ /**
160
+ * Structural group-encryption. Map of sensitive field name →
161
+ * per-field sealed ciphertext in `iv:data` form (same shape as a `_det`
162
+ * slot). Present only when the collection declares `sensitive` fields and
163
+ * at least one is present on the record. Each field is encrypted under its
164
+ * own HKDF-derived per-field key (`deriveSealedFieldKey`, domain-separated
165
+ * by `<collection>/sealed/<field>`), and is kept OUT of the open `_data`
166
+ * blob — so a reader who can open `_data` still cannot see sealed fields
167
+ * without re-deriving each field key. With no sensitive fields declared the
168
+ * map is absent and `_data` is unchanged (byte-identical to legacy output).
169
+ */
170
+ readonly _sealed?: Record<string, string>;
171
+ /**
172
+ * Verify-digest slots (classified stage 2). Map of digest-only field name →
173
+ * AES-256-GCM `iv:data` blob sealed under the HKDF(CEK) vdig slot key with
174
+ * AAD ['noydb-classify-vdig', collection, recordId, field]. The store sees
175
+ * only ciphertext; only the enclave verify path can read the digest. At most
176
+ * one of `_sealed[field]` / `_vdig[field]` exists per field (I4).
177
+ */
178
+ readonly _vdig?: Record<string, string>;
179
+ /**
180
+ * Equatable blind-index tags (classified slice 2b). Map of digest-only field
181
+ * name → base64 33-byte tag (1-byte cost/version discriminator ‖ 32-byte keyed
182
+ * MAC), CURRENT VALUE ONLY (the _vdig ring is never indexed). This is the ONLY
183
+ * store-visible classified artifact: a keyed MAC, comparable without a key
184
+ * ceremony, with NO inline cryptographic integrity by construction. Invariant:
185
+ * _bidx[field] present ⇒ _vdig[field] present. Confirm-by-verify (findByDigest)
186
+ * makes any read-side orphan/splice unreturnable.
187
+ */
188
+ readonly _bidx?: Record<string, string>;
189
+ /**
190
+ * Per-record content-encryption key (CEK), base64 AES-KW-wrapped under
191
+ * the collection (or tier) DEK. Present only on records written by a
192
+ * collection opened with `perRecordKeys: true`. When present, the body
193
+ * (`_iv`/`_data`) is encrypted under the unwrapped CEK rather than the
194
+ * collection DEK directly.
195
+ *
196
+ * Presence is the format discriminant: `_cek` absent → legacy body
197
+ * keyed off the collection DEK (read unchanged); `_cek` present →
198
+ * unwrap under the collection DEK, then decrypt the body under the CEK.
199
+ *
200
+ * The CEK is stable across every version of a record (insert mints it;
201
+ * updates and history snapshots reuse it), so all `_history` envelopes
202
+ * for a record carry the same `_cek`. This is the foundation for
203
+ * per-record erasure and record-scoped sealing.
204
+ *
205
+ * `_det` slots are deliberately NOT keyed off the CEK — they remain
206
+ * keyed to the collection DEK so blind-equality search keeps working
207
+ * across records.
208
+ */
209
+ readonly _cek?: string;
210
+ /**
211
+ * Debug-plaintext marker. Present only on records written by a vault opened
212
+ * with `debugPlaintext: true` (which requires `encrypt: false`). When set,
213
+ * the record's own fields are inlined as top-level keys on this envelope
214
+ * (beside the reserved `_`-prefixed metadata) and `_data` is empty — so
215
+ * native store tooling (jq, S3 console) reads the record directly. The read
216
+ * path reconstructs the record from the non-`_` keys; the marker makes a
217
+ * debug envelope self-describing, so a classic plaintext reader handles it too.
218
+ */
219
+ readonly _debug?: typeof NOYDB_FORMAT_VERSION;
220
+ /**
221
+ * #589: this envelope is a delete marker (ordinary `collection.delete()` under
222
+ * sync). Empty `_data`, no `_cek`, but version-ordered — a higher-`_v` re-create
223
+ * resurrects the id. Distinct from a forget crypto-shred tombstone, which is
224
+ * terminal. Reads treat it as absent.
225
+ */
226
+ readonly _del?: true;
227
+ }
228
+ /** Spine policy for one digest-only classified field — the enclave-consumable
229
+ * projection of a ClassifiedFieldSpec (the enclave never imports with-*). */
230
+ export interface VdigFieldPolicy {
231
+ readonly normalize: 'password' | 'secret-answer';
232
+ /** Ring size for reuse refusal; 0 = no ring. Cap 8 (spec Q4). */
233
+ readonly notLastN: number;
234
+ readonly rotateDays?: number;
235
+ /** default false — refused unless the double door is open (R8) */
236
+ readonly equatable: boolean;
237
+ }
238
+ /**
239
+ * The persisted classified-fields config marker (C-A / R10). Reuses the
240
+ * stage-2 persisted-schema record; this is the shape of the marker stored
241
+ * there.
242
+ */
243
+ export interface ClassifiedMarker {
244
+ /** field names declared digest-only (have _vdig); non-empty ⇒ writes need the classified codec */
245
+ readonly digestOnly: readonly string[];
246
+ /** field names additionally declared equatable (have _bidx when covered) */
247
+ readonly equatable: readonly string[];
248
+ }
249
+ /** Verdict-only egress of the enclave oracle (spec §3). */
250
+ export interface ClassifiedVerdict {
251
+ readonly ok: boolean;
252
+ /** I1: present ONLY when ok === true — never computed for a false verdict. */
253
+ readonly mustRotate?: true;
254
+ }
255
+ /**
256
+ * Opaque access gate for a sealed (`sensitive`) field returned by a public
257
+ * read (the access layer). The handle carries only the per-field
258
+ * **ciphertext** — the plaintext is never materialised into the working-set
259
+ * cache. Call {@link Sealed.reveal} to decrypt the value on demand.
260
+ *
261
+ * A handle is intentionally NOT usable as `V`: it serialises to a non-leaking
262
+ * marker (`JSON.stringify` / structured logging emit `'[sealed]'`, never the
263
+ * value) and exposes no synchronous accessor.
264
+ */
265
+ export interface Sealed<V> {
266
+ /** Discriminant — always `true`, lets callers narrow a field to a handle. */
267
+ readonly sealed: true;
268
+ /** Decrypt and return the underlying value. */
269
+ reveal(): Promise<V>;
270
+ }
271
+ /**
272
+ * The shape a public read returns for a collection that declares `sensitive`
273
+ * fields `S`: every sealed field becomes an opaque {@link Sealed} handle while
274
+ * the rest of the record is unchanged. The `[S] extends [never]` guard collapses
275
+ * `SealedView<T, never>` to exactly `T`, so collections with no sensitive fields
276
+ * are unaffected — a plain `Omit<T, never>` is *not* a faithful identity for
277
+ * generic intersection record types (it can degrade intersection-only members to
278
+ * `unknown`), which would break consumers like the derivation/MV `_derivedFrom` /
279
+ * `_materializedFrom` reads.
280
+ */
281
+ export type SealedView<T, S extends keyof T> = [S] extends [never] ? T : Omit<T, S> & {
282
+ readonly [K in S]: Sealed<T[K]>;
283
+ };
284
+ /**
285
+ * The type of a field-name argument to the query/scan DSL (`where`, `orderBy`,
286
+ * …) for a collection whose sealed (`sensitive`) fields are `S`.
287
+ *
288
+ * Guarded so the common case is unchanged: with **no** sensitive fields
289
+ * (`S = never`) it is exactly `string` — collections that don't opt into
290
+ * `sensitive` keep today's permissive DSL, zero churn. Once a field is
291
+ * declared `sensitive`, the DSL narrows to the non-sensitive field names, so
292
+ * `where('ssn', …)` becomes a compile error. TypeScript cannot subtract a
293
+ * literal from `string`, so refusing a sensitive name necessarily means
294
+ * narrowing to the known field-name union — this is intentional and only
295
+ * affects collections that opted in.
296
+ *
297
+ * When `Q` (the indexed-field set) is given, `where()` is additionally
298
+ * restricted to `Q` minus any sensitive fields — the escape hatch for
299
+ * non-indexed filters is `scan()`. `Q = never` (the default) preserves the
300
+ * existing 2-param behaviour exactly (zero churn).
301
+ */
302
+ export type QueryField<T, S extends keyof T = never, Q extends keyof T & string = never> = [
303
+ Q
304
+ ] extends [never] ? ([S] extends [never] ? string : Exclude<keyof T & string, S>) : Exclude<Q, S>;
305
+ /**
306
+ * The type of a field-name reference in a collection's index-declaration
307
+ * options (`indexes`, `deterministicFields`, `textIndexes`). Same guarded
308
+ * narrowing as {@link QueryField}: permissive `string` until a field is
309
+ * declared `sensitive`, then the sensitive names are refused (a plaintext
310
+ * secondary index over a sealed field defeats non-residency). Kept distinct
311
+ * from `QueryField` so the two DSL surfaces can diverge later without coupling.
312
+ *
313
+ * When `Q` (the indexed-field set) is given, the `indexes` option is
314
+ * additionally restricted to `Q` minus any sensitive fields — declaring `Q`
315
+ * but listing a different field in `indexes` becomes a compile error.
316
+ * `Q = never` (the default) preserves the existing 2-param behaviour.
317
+ */
318
+ export type IndexFieldName<T, S extends keyof T = never, Q extends keyof T & string = never> = [
319
+ Q
320
+ ] extends [never] ? ([S] extends [never] ? string : Exclude<keyof T & string, S>) : Exclude<Q, S>;
321
+ /**
322
+ * Generic form of the runtime `IndexDef` (see `indexing/eager-indexes.ts`)
323
+ * parameterised by the allowed field-name set `F`. Used to refuse `sensitive`
324
+ * fields in the `indexes` collection option at compile time while leaving the
325
+ * runtime `IndexDef` (string-based) untouched. `IndexDefFor<string>` is
326
+ * structurally identical to `IndexDef`, which is why `vault.collection` can cast
327
+ * the narrowed public option to `IndexDef[]` at the runtime boundary (through
328
+ * `unknown`, solely to drop the `readonly`).
329
+ * **Keep this in sync with `IndexDef`** — if `IndexDef` gains a new union member,
330
+ * add it here too, or that boundary cast will silently admit shapes the runtime
331
+ * machinery does not narrow.
332
+ */
333
+ export type IndexDefFor<F extends string> = F | {
334
+ readonly fields: readonly F[];
335
+ readonly unique?: boolean;
336
+ } | readonly F[];
337
+ /**
338
+ * The type of the `sensitive` collection option, conditional on whether the
339
+ * caller opted into compile-time refusal via an explicit second generic.
340
+ * With no 2nd generic (`S = never`) it accepts any field array — runtime
341
+ * sealing only, no compile refusal, non-breaking. With `S` given, it is
342
+ * `readonly S[]`, which ties the runtime array to the declared sensitive
343
+ * union so the two cannot drift.
344
+ */
345
+ export type SensitiveOpt<T, S extends keyof T> = [S] extends [never] ? readonly (keyof T & string)[] : readonly S[];
346
+ /**
347
+ * The type of the `moneyFields` collection option, conditional on whether the
348
+ * caller opted into compile-time money-field typing via the 4th generic `M`.
349
+ * Typed against the opaque {@link ViaDescriptor} marker rather than the
350
+ * concrete `MoneyDescriptor` — the kernel never inspects a Via feature's
351
+ * descriptor shape, only its declaring service does.
352
+ * A `money()` descriptor structurally satisfies `ViaDescriptor` (it carries
353
+ * `_viaBrand: 'money'`), so this stays publicly assignable from `money()`
354
+ * call sites. With no `M` (`M = never`) it accepts any
355
+ * `Record<string, ViaDescriptor>` — runtime money only, no compile-level
356
+ * narrowing, non-breaking. With `M` given, it is `Record<M, ViaDescriptor>`,
357
+ * tying the runtime map to the declared money-field union so the two cannot
358
+ * drift.
359
+ */
360
+ export type MoneyFieldsOpt<T, M extends keyof T & string = never> = [
361
+ M
362
+ ] extends [never] ? Record<string, ViaDescriptor> : Record<M, ViaDescriptor>;
363
+ /**
364
+ * Concrete {@link Sealed} handle. Holds the reveal closure (which captures the
365
+ * field's ciphertext blob and the unseal routine) in a private field, so it is
366
+ * invisible to `JSON.stringify`, `util.inspect`, and `Object.keys`. `toJSON`
367
+ * returns the marker `'[sealed]'` — a handle can never leak its value through
368
+ * serialisation or logging because the plaintext is not stored on it at all.
369
+ */
370
+ export declare class SealedHandle<V> implements Sealed<V> {
371
+ #private;
372
+ readonly sealed: true;
373
+ constructor(reveal: () => Promise<V>);
374
+ reveal(): Promise<V>;
375
+ /** Non-leaking serialisation marker — never the underlying value. */
376
+ toJSON(): string;
377
+ }
378
+ /**
379
+ * Handover-capable provider. Implemented additionally by asymmetric/granted
380
+ * providers (cloud-KMS asymmetric, Azure RSA Key Vault, AWS KMS with grant).
381
+ * Self-only providers (macOS Keychain, env-var, WebAuthn-PRF) do NOT
382
+ * implement this — the §11.2 capability matrix lives in the type system.
383
+ *
384
+ * Per foundation §11.4. A function that requires recipient-target sealing
385
+ * takes `RecipientSealer`, not `SealingKeyProvider` — the compiler rejects
386
+ * passing a self-only provider at the spec site.
387
+ */
388
+ export interface RecipientSealer {
389
+ readonly id: string;
390
+ /** Produce hint material a sender uses to seal-for-this-recipient. */
391
+ publishRecipientHint(): Promise<RecipientHint>;
392
+ /**
393
+ * Seal plaintext for the recipient described by `hint`. Returns opaque
394
+ * bytes — same contract as `SealingKeyProvider.seal()`. The bundle
395
+ * layer base64-encodes the bytes into `SealedAutoUnlockEntry.sealed`
396
+ * without inspecting them.
397
+ */
398
+ sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array>;
399
+ }
400
+ /**
401
+ * Thin delivery envelope persisted at
402
+ * `_sealed_cek/<collection>/<id>/<pid>`. The grantor writes one per
403
+ * (record, recipient host) pair. `payload` is the base64 of the bytes returned
404
+ * by {@link RecipientSealer.sealForRecipient} over a UTF-8
405
+ * `JSON.stringify({@link SealedCekBinding})`.
406
+ *
407
+ * `expiresAt` is duplicated here for a cheap pre-unseal reject, but is NOT
408
+ * authoritative — the binding inside `payload` carries the expiry the host
409
+ * verifies after unsealing, so a tampered delivery envelope cannot extend a
410
+ * grant.
411
+ */
412
+ export interface SealedCekDeliveryEnvelope {
413
+ /** Envelope schema version. */
414
+ readonly v: 1;
415
+ /** Magic marker for forensics + format detection. */
416
+ readonly _noydb_sealed_cek: 1;
417
+ /** Recipient host provider id; matches the sealer's `.id` / hint `pid`. */
418
+ readonly pid: string;
419
+ /** base64 of the sealed {@link SealedCekBinding} bytes. */
420
+ readonly payload: string;
421
+ /** Fast-path expiry hint (ISO 8601). Authoritative copy is inside `payload`. */
422
+ readonly expiresAt: string;
423
+ }
424
+ /**
425
+ * The plaintext struct sealed for the recipient host. After the host unseals
426
+ * `SealedCekDeliveryEnvelope.payload` it parses this and MUST verify:
427
+ * - `collection` + `id` match the record envelope it is decrypting, and
428
+ * - `expiresAt` has not passed (authoritative expiry check).
429
+ *
430
+ * `cek` is the base64 of the raw 32-byte AES-256-GCM record CEK.
431
+ */
432
+ export interface SealedCekBinding {
433
+ /** Collection the CEK belongs to. */
434
+ readonly collection: string;
435
+ /** Record id the CEK belongs to. */
436
+ readonly id: string;
437
+ /** base64 of the raw AES-256-GCM CEK bytes. */
438
+ readonly cek: string;
439
+ /** Authoritative expiry (ISO 8601). */
440
+ readonly expiresAt: string;
441
+ }
442
+ /**
443
+ * Placeholder returned by `getAtTier()` in `'ghost'` mode when a
444
+ * record is at a tier the caller cannot decrypt. Record existence is
445
+ * advertised — the id and tier are visible — but contents are
446
+ * withheld. `canElevateFrom` lists user ids authorized to elevate
447
+ * access for this caller when known; absent when the workflow is
448
+ * not configured.
449
+ */
450
+ export interface GhostRecord {
451
+ readonly _ghost: true;
452
+ readonly _tier: number;
453
+ readonly canElevateFrom?: readonly string[];
454
+ }
455
+ /** Control what lower-tier reads see above their clearance. */
456
+ export type TierMode = 'invisibility' | 'ghost';
457
+ /**
458
+ * Event emitted when a record at a tier above the caller's inherent
459
+ * clearance is read or written successfully (via elevation or
460
+ * delegation). Always written to the ledger; subscribers get a
461
+ * real-time feed.
462
+ */
463
+ export interface CrossTierAccessEvent {
464
+ readonly actor: string;
465
+ readonly collection: string;
466
+ readonly id: string;
467
+ readonly tier: number;
468
+ /** How the caller gained tier access: they elevated it, or a delegation is active. */
469
+ readonly authorization: 'elevation' | 'delegation' | 'inherent';
470
+ readonly op: 'get' | 'put' | 'elevate' | 'demote';
471
+ readonly ts: string;
472
+ /**
473
+ * When `authorization === 'elevation'`, the audit reason string the
474
+ * caller passed to `vault.elevate(...)`. Empty for inherent /
475
+ * delegation paths.
476
+ */
477
+ readonly reason?: string;
478
+ /**
479
+ * When `authorization === 'elevation'`, the tier the caller's
480
+ * keyring effectively held BEFORE elevation. Useful for audit
481
+ * dashboards distinguishing "operator elevating to 2" from
482
+ * "inherent tier-2 write."
483
+ */
484
+ readonly elevatedFrom?: number;
485
+ }
486
+ /**
487
+ * A single deterministic-ciphertext index slot on an envelope. Stored
488
+ * as `iv:data` (both base64, colon-separated) so a single string per
489
+ * field keeps the envelope compact.
490
+ */
491
+ export type DeterministicCipher = string;
492
+ /** All records across all collections for a compartment. */
493
+ export type VaultSnapshot = Record<string, Record<string, EncryptedEnvelope>>;
494
+ /**
495
+ * Result of a single page fetch via the optional `listPage` adapter extension.
496
+ *
497
+ * `items` carries the actual encrypted envelopes (not just ids) so the
498
+ * caller can decrypt and emit a single record without an extra `get()`
499
+ * round-trip per id. `nextCursor` is `null` on the final page.
500
+ */
501
+ export interface ListPageResult {
502
+ /** Encrypted envelopes for this page, in adapter-defined order. */
503
+ items: Array<{
504
+ id: string;
505
+ envelope: EncryptedEnvelope;
506
+ }>;
507
+ /** Opaque cursor for the next page, or `null` if this was the last page. */
508
+ nextCursor: string | null;
509
+ }
510
+ export interface NoydbStore {
511
+ /**
512
+ * Optional human-readable store name (e.g. 'memory', 'file', 'dynamo').
513
+ * Used in diagnostic messages and the listPage fallback warning. Stores
514
+ * are encouraged to set this so logs are clearer about which backend is
515
+ * involved when something goes wrong.
516
+ */
517
+ name?: string;
518
+ /**
519
+ * Optional declared store capabilities (CAS atomicity, native tx, blob
520
+ * size limits, auth). Consumers that require a capability — e.g.
521
+ * `vault.sequence().next()` needs `casAtomic` — read it here.
522
+ */
523
+ capabilities?: StoreCapabilities;
524
+ /** Get a single record. Returns null if not found. */
525
+ get(vault: string, collection: string, id: string): Promise<EncryptedEnvelope | null>;
526
+ /** Put a record. Throws ConflictError if expectedVersion doesn't match. */
527
+ put(vault: string, collection: string, id: string, envelope: EncryptedEnvelope, expectedVersion?: number): Promise<void>;
528
+ /** Delete a record. */
529
+ delete(vault: string, collection: string, id: string): Promise<void>;
530
+ /** List all record IDs in a collection. */
531
+ list(vault: string, collection: string): Promise<string[]>;
532
+ /** Load all records for a vault (initial hydration). */
533
+ loadAll(vault: string): Promise<VaultSnapshot>;
534
+ /** Save all records for a vault (bulk write / restore). */
535
+ saveAll(vault: string, data: VaultSnapshot): Promise<void>;
536
+ /** Optional connectivity check for sync engine. */
537
+ ping?(): Promise<boolean>;
538
+ /**
539
+ * The store's authoritative time as a bounded-uncertainty interval.
540
+ * Present iff `capabilities.serverWriteTime` is true. Monotonic
541
+ * non-decreasing across calls on a single store.
542
+ */
543
+ getStoreTime?(): Promise<StoreTime>;
544
+ /**
545
+ * Optional: list record IDs in a collection that have `_ts` after `since`.
546
+ * Used by partial sync (`pull({ modifiedSince })`). Stores that omit this
547
+ * fall back to a full `loadAll` + client-side timestamp filter.
548
+ */
549
+ listSince?(vault: string, collection: string, since: string): Promise<string[]>;
550
+ /**
551
+ * Optional pagination extension. Stores that implement `listPage` get
552
+ * the streaming `Collection.scan()` fast path; stores that don't are
553
+ * silently fallen back to a full `loadAll()` + slice (with a one-time
554
+ * console.warn).
555
+ *
556
+ * `cursor` is opaque to the core — each store encodes its own paging
557
+ * state (DynamoDB: base64 LastEvaluatedKey JSON; S3: ContinuationToken;
558
+ * memory/file/browser: numeric offset of a sorted id list). Pass
559
+ * `undefined` to start from the beginning.
560
+ *
561
+ * `limit` is a soft upper bound on `items.length`. Stores MAY return
562
+ * fewer items even when more exist (e.g. if the underlying store has
563
+ * its own page size cap), and MUST signal "no more pages" by returning
564
+ * `nextCursor: null`.
565
+ *
566
+ * The 6-method core contract is unchanged — this is an additive
567
+ * extension discovered via `'listPage' in adapter`.
568
+ */
569
+ listPage?(vault: string, collection: string, cursor?: string, limit?: number): Promise<ListPageResult>;
570
+ /**
571
+ * Optional pub/sub for real-time presence.
572
+ * Publish an encrypted payload to a presence channel.
573
+ * Falls back to storage-based polling when absent.
574
+ */
575
+ presencePublish?(channel: string, payload: string): Promise<void>;
576
+ /**
577
+ * Optional pub/sub for real-time presence.
578
+ * Subscribe to a presence channel. Returns an unsubscribe function.
579
+ * Falls back to storage-based polling when absent.
580
+ */
581
+ presenceSubscribe?(channel: string, callback: (payload: string) => void): () => void;
582
+ /**
583
+ * Optional cross-vault enumeration extension.
584
+ *
585
+ * Returns the names of every top-level vault the store
586
+ * currently stores. Used by `Noydb.listAccessibleVaults()` to
587
+ * enumerate the universe of vaults before filtering down to
588
+ * the ones the calling principal can actually unwrap.
589
+ *
590
+ * **Why this is optional:** the storage shape of compartments
591
+ * differs across backends. Memory and file stores store
592
+ * vaults as top-level keys / directories and can enumerate
593
+ * them in O(1) calls. DynamoDB stores everything in a single table
594
+ * keyed by `(compartment#collection, id)` — enumerating compartments
595
+ * requires either a Scan (expensive, eventually consistent, leaks
596
+ * ciphertext metadata) or a dedicated GSI that the consumer
597
+ * provisioned. S3 needs a prefix list (cheap if enabled, ACL-sensitive
598
+ * otherwise). Browser localStorage can scan keys by prefix.
599
+ *
600
+ * Stores that cannot implement `listVaults` cheaply or
601
+ * cleanly should omit it. Core surfaces a `StoreCapabilityError`
602
+ * with a clear message when a caller invokes
603
+ * `listAccessibleVaults()` against a store that doesn't
604
+ * provide this method, so consumers know to either upgrade their
605
+ * store, provide a candidate list explicitly to `queryAcross()`,
606
+ * or fall back to maintaining the compartment index out of band.
607
+ *
608
+ * **Privacy note:** `listVaults` returns *every* compartment
609
+ * the store has, not just the ones the caller can access. The
610
+ * existence-leak filtering (returning only compartments whose
611
+ * keyring the caller can unwrap) happens in core, not in the
612
+ * store. The store is trusted to know its own contents — that
613
+ * is not a leak in the threat model. The leak the API guards
614
+ * against is the *return value* of `listAccessibleVaults()`
615
+ * exposing existence to a downstream observer who only sees that
616
+ * function's output.
617
+ *
618
+ * The 6-method core contract is unchanged — this is an additive
619
+ * extension discovered via `'listVaults' in store`.
620
+ */
621
+ listVaults?(): Promise<string[]>;
622
+ /**
623
+ * Optional: generate a presigned URL for direct client download.
624
+ * Only meaningful for object stores (S3, GCS) that support URL signing.
625
+ * Returns a time-limited URL that fetches the encrypted envelope directly.
626
+ * The caller must decrypt client-side (the URL returns ciphertext).
627
+ */
628
+ presignUrl?(vault: string, collection: string, id: string, expiresInSeconds?: number): Promise<string>;
629
+ /**
630
+ * Optional: estimate current storage usage.
631
+ * Returns `{ usedBytes, quotaBytes }` or null if the store cannot estimate.
632
+ * Used by quota-aware routing to detect overflow conditions.
633
+ */
634
+ estimateUsage?(): Promise<{
635
+ usedBytes: number;
636
+ quotaBytes: number;
637
+ } | null>;
638
+ /**
639
+ * Optional multi-record atomic write.
640
+ *
641
+ * When present, `db.transaction(async (tx) => { ... })` uses this to
642
+ * commit every staged op in one storage-layer transaction — either
643
+ * all ops land or none do, regardless of which records they touch.
644
+ * Every `TxOp.expectedVersion` (when set) must be honored atomically
645
+ * alongside the write; any violation throws `ConflictError` and the
646
+ * whole batch fails.
647
+ *
648
+ * Stores that omit this fall through to the hub's per-record OCC
649
+ * fallback: pre-flight CAS check, then sequential `put`/`delete`
650
+ * with best-effort unwind on mid-batch failure (see
651
+ * `runTransaction` for the exact semantics and crash window).
652
+ *
653
+ * Native implementations: `to-memory` (single Map mutation),
654
+ * `to-dynamo` (`TransactWriteItems`), `to-browser-idb` (one
655
+ * `readwrite` transaction). File / S3 cannot implement this
656
+ * atomically and should omit the method.
657
+ */
658
+ tx?(ops: readonly TxOp[]): Promise<void>;
659
+ }
660
+ /**
661
+ * A single staged operation inside a `db.transaction(fn)` commit. The
662
+ * hub assembles `TxOp[]` from the user's `tx.collection().put/delete`
663
+ * calls, encrypts any `record` values into `envelope`, and hands the
664
+ * array to `NoydbStore.tx()` when the store supports atomic batch
665
+ * writes. Stores that implement `tx()` MUST honor every
666
+ * `expectedVersion` atomically against the stored envelope version.
667
+ */
668
+ export interface TxOp {
669
+ readonly type: 'put' | 'delete';
670
+ readonly vault: string;
671
+ readonly collection: string;
672
+ readonly id: string;
673
+ /** Populated for `type: 'put'` — the encrypted envelope to write. */
674
+ readonly envelope?: EncryptedEnvelope;
675
+ /** Optional per-record CAS. Mismatch must throw `ConflictError`. */
676
+ readonly expectedVersion?: number;
677
+ }
678
+ /** Type-safe helper for creating store factories. */
679
+ export declare function createStore<TOptions>(factory: (options: TOptions) => NoydbStore): (options: TOptions) => NoydbStore;
680
+ /**
681
+ * Interchange formats `@noy-db/as-*` packages can produce. `'*'` is a
682
+ * wildcard granting every current + future plaintext format.
683
+ */
684
+ export type ExportFormat = 'xlsx' | 'csv' | 'json' | 'ndjson' | 'xml' | 'sql' | 'pdf' | 'blob' | 'zip' | '*';
685
+ /**
686
+ * Owner-granted export capability on a keyring.
687
+ *
688
+ * Two independent dimensions:
689
+ *
690
+ * - `plaintext` — per-format allowlist for record formatters + blob
691
+ * extractors that emit plaintext bytes (`as-xlsx`, `as-csv`,
692
+ * `as-blob`, `as-zip`, …). **Defaults to empty** for every role;
693
+ * the owner/admin must positively grant per-format (or `'*'`).
694
+ * - `bundle` — boolean for `.noydb` encrypted container export
695
+ * (`as-noydb`). **Default policy: on for owner/admin, off for
696
+ * operator/viewer/client** — applied when the field is absent or
697
+ * undefined (see `hasExportCapability`).
698
+ */
699
+ export interface ExportCapability {
700
+ readonly plaintext?: readonly ExportFormat[];
701
+ readonly bundle?: boolean;
702
+ }
703
+ /**
704
+ * Owner-granted import capability on a keyring (sibling of
705
+ * `ExportCapability`, issue ).
706
+ *
707
+ * Two independent dimensions:
708
+ *
709
+ * - `plaintext` — per-format allowlist for `as-*` readers that ingest
710
+ * plaintext bytes (`as-csv`, `as-json`, `as-ndjson`, `as-zip`, …).
711
+ * Defaults to empty for every role; the owner/admin must positively
712
+ * grant per-format (or `'*'`).
713
+ * - `bundle` — boolean gate for `.noydb` bundle import. **Defaults to
714
+ * `false` for every role**, including owner/admin. Import is more
715
+ * dangerous than export (corrupts vs leaks), so the policy is
716
+ * default-closed across the board — the owner explicitly opts a
717
+ * keyring in via `db.grant({ importCapability: { bundle: true } })`.
718
+ */
719
+ export interface ImportCapability {
720
+ readonly plaintext?: readonly ExportFormat[];
721
+ readonly bundle?: boolean;
722
+ }
723
+ /**
724
+ * Forward-declared on-disk shape for `VaultPolicy` — the actual policy
725
+ * model is declared further down in this file (#9), see {@link VaultPolicy}.
726
+ * Declared here as an `unknown`-typed map (rather than `VaultPolicy` itself)
727
+ * so the `KeyringFile.policy` field can still round-trip foreign/older
728
+ * documents that don't strictly satisfy the current shape.
729
+ *
730
+ * @internal
731
+ */
732
+ export type VaultPolicyOnDisk = Record<string, unknown>;
733
+ /**
734
+ * Recovery profile enrolled at vault creation.
735
+ *
736
+ * - `paper` — `on-recovery` codes (the standard end-to-end profile).
737
+ * - `shamir` / `multi-channel` / `admin-mediated` — API surface ships;
738
+ * per-profile dispatch lands in follow-up issues. Calling
739
+ * `db.recoverPassphrase` against these throws
740
+ * {@link RecoveryProfileNotImplementedError}.
741
+ */
742
+ export type RecoveryEnrollment = {
743
+ readonly profile: 'paper';
744
+ /** Number of single-use codes to print at enrollment. */
745
+ readonly codes: number;
746
+ } | {
747
+ readonly profile: 'shamir';
748
+ readonly k: number;
749
+ readonly n: number;
750
+ readonly trustees: ReadonlyArray<string>;
751
+ } | {
752
+ readonly profile: 'multi-channel';
753
+ readonly email?: string;
754
+ readonly pin?: boolean;
755
+ readonly paperCodes?: number;
756
+ } | {
757
+ readonly profile: 'admin-mediated';
758
+ readonly grantorUserId: string;
759
+ };
760
+ /**
761
+ * One tier-2 authenticator slot inside a keyring file. Each slot
762
+ * independently wraps the SAME KEK under a method-specific derived key
763
+ * (LUKS pattern). Adding or removing a slot is a constant-time keyring
764
+ * write — no DEK re-keying required.
765
+ *
766
+ * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/session-tiers.md → Tier 2 — Authenticate (multi-slot)
767
+ */
768
+ /**
769
+ * Shared fields across all authenticator slot variants. The variant
770
+ * (`KeyringAuthenticatorWrappingKEK` vs `KeyringAuthenticatorWrappingDEKs`)
771
+ * carries the actual wrapped material; everything below is identity +
772
+ * metadata only.
773
+ */
774
+ interface KeyringAuthenticatorBase {
775
+ /** Caller-chosen identifier — e.g. `'webauthn-yubikey-blue'`, `'oidc-google'`, `'password'`. */
776
+ readonly id: string;
777
+ /** Method family — selects which `@noy-db/on-*` package handles unlock. */
778
+ readonly method: 'webauthn' | 'oidc' | 'password';
779
+ /** ISO-8601 timestamp at which the slot was added. */
780
+ readonly enrolled_at: string;
781
+ /**
782
+ * Which session tier ENROLLED this slot. Tier 1 enrolls a fresh slot;
783
+ * tier 2 may add a sibling slot when the active policy permits.
784
+ */
785
+ readonly enrolled_via_tier: 1 | 2;
786
+ /**
787
+ * Method-specific metadata: WebAuthn cred id, OIDC issuer/sub, PBKDF2
788
+ * salt for `on-password`, etc. The schema is open by design — the
789
+ * `@noy-db/on-*` package owns the contents.
790
+ */
791
+ readonly meta: Record<string, unknown>;
792
+ }
793
+ /**
794
+ * Slot that wraps the KEK directly under a method-derived AES-KW key.
795
+ * Used by ceremonies where the on-* package can produce/recover an
796
+ * extractable KEK from its own credential — WebAuthn (PRF-derived
797
+ * wrapping key) and split-key OIDC.
798
+ *
799
+ * `wrapKind` is optional/absent on older slots — those
800
+ * legacy slots are treated as wrap-KEK by default at unlock time.
801
+ */
802
+ export interface KeyringAuthenticatorWrappingKEK extends KeyringAuthenticatorBase {
803
+ readonly wrapKind?: 'kek';
804
+ /** Base64 wrapped-KEK ciphertext under the method-derived key. */
805
+ readonly wrapped_kek: string;
806
+ /** XOR guard — wrap-KEK slots must NOT carry wrap-DEKs material. */
807
+ readonly wrapped_deks?: never;
808
+ /** XOR guard — wrap-KEK slots must NOT carry wrap-DEKs material. */
809
+ readonly iv?: never;
810
+ }
811
+ /**
812
+ * Slot that wraps the DEK set (not the KEK) under a method-derived
813
+ * AES-GCM key — sidesteps the non-extractable-KEK constraint by
814
+ * encrypting the serialized `{ deks: { collection: rawDekBase64 } }`
815
+ * directly. Mirrors the format used by `mintPaperRecoveryEntry`
816
+ * (`PaperRecoveryEntry`) and `@noy-db/on-pin`'s `PinResumeState` —
817
+ * the unified wrap-DEKs primitive across tier-0 / tier-2 / tier-3.
818
+ *
819
+ * Trade-off: a slot of this kind reconstructs `UnlockedKeyring` with
820
+ * `kek: null` after unlock. That is semantically correct for tier-2
821
+ * (sensitive ops like `enrollAuthenticator` / `rotatePassphrase`
822
+ * require a tier-1 unlock anyway) and matches how `@noy-db/on-pin`
823
+ * already behaves at tier 3.
824
+ *
825
+ * @see `mintPaperRecoveryEntry` in `team/recovery.ts` — same shape on
826
+ * a different on-disk path (`_meta/recovery-paper`).
827
+ */
828
+ export interface KeyringAuthenticatorWrappingDEKs extends KeyringAuthenticatorBase {
829
+ readonly wrapKind: 'deks';
830
+ /** Base64 AES-GCM ciphertext of `{ deks: { collection: base64rawDek } }`. */
831
+ readonly wrapped_deks: string;
832
+ /** Base64 AES-GCM IV used for the `wrapped_deks` ciphertext. */
833
+ readonly iv: string;
834
+ /** XOR guard — wrap-DEKs slots must NOT carry wrap-KEK material. */
835
+ readonly wrapped_kek?: never;
836
+ }
837
+ /**
838
+ * Discriminated union over the two wrap-format variants. Reads from
839
+ * disk should always go through this type so the variant is preserved.
840
+ *
841
+ * Discriminator: `wrapKind`. Absent → wrap-KEK (legacy / WebAuthn /
842
+ * OIDC). Present and `'deks'` → wrap-DEKs (password / future on-* that
843
+ * want to sidestep extractable-KEK).
844
+ *
845
+ * The type-level XOR enforces "exactly one of `wrapped_kek` /
846
+ * `wrapped_deks` is present" — a structural guarantee that the runtime
847
+ * dispatch is safe.
848
+ */
849
+ export type KeyringAuthenticator = KeyringAuthenticatorWrappingKEK | KeyringAuthenticatorWrappingDEKs;
850
+ export interface KeyringFile {
851
+ readonly _noydb_keyring: typeof NOYDB_KEYRING_VERSION;
852
+ readonly user_id: string;
853
+ readonly display_name: string;
854
+ readonly role: Role;
855
+ readonly permissions: Permissions;
856
+ readonly deks: Record<string, string>;
857
+ readonly salt: string;
858
+ readonly created_at: string;
859
+ readonly granted_by: string;
860
+ /**
861
+ * Passphrase canary — base64 AES-KW-wrapped form of a known constant
862
+ * 256-bit value, wrapped under the keyring's KEK.
863
+ *
864
+ * Optional: older keyrings load with no canary and fall back to
865
+ * the multi-DEK corruption heuristic. Newer keyrings
866
+ * carry one and let `loadKeyring` distinguish wrong-passphrase
867
+ * from corruption even when ALL DEKs (including a single-DEK keyring's
868
+ * sole DEK) are corrupted.
869
+ *
870
+ * AES-KW is deterministic — every write site mints fresh on each
871
+ * persist; same KEK + same constant input always produces the same
872
+ * ciphertext, so this round-trips without state.
873
+ */
874
+ readonly canary?: string;
875
+ /**
876
+ * Tier-2 authenticator slots (multi-slot keyring extension).
877
+ * Optional / append-only: keyring files written before the
878
+ * extension load with an empty list. Each slot independently wraps
879
+ * the same KEK; any one of them unlocks.
880
+ *
881
+ * @see KeyringAuthenticator
882
+ */
883
+ readonly authenticators?: readonly KeyringAuthenticator[];
884
+ /**
885
+ * Per-keyring policy override (reserved). The on-disk format
886
+ * accepts the field for forward compatibility with the Option C
887
+ * merge engine deferred to a later release; v1.0 reads only the
888
+ * vault-level `_meta/policy` document, so this field is parsed and
889
+ * round-tripped but never enforced.
890
+ */
891
+ readonly policy?: VaultPolicyOnDisk;
892
+ /**
893
+ * Optional — authorization spec capability bits. Absent on keyrings written
894
+ * before the RFC implementation. Loading falls back to role-based
895
+ * defaults (owner/admin get bundle-on, everyone else off).
896
+ */
897
+ readonly export_capability?: ExportCapability;
898
+ /**
899
+ * Optional bundle-slot expiry. ISO-8601 timestamp; past
900
+ * the cutoff `loadKeyring` throws `KeyringExpiredError` before any
901
+ * DEK unwrap is attempted. Useful for time-boxed audit access:
902
+ * "this slot works for 30 days then becomes opaque to its holder."
903
+ *
904
+ * Absent on live keyrings written via `db.grant()` — the field is
905
+ * meaningful for `BundleRecipient` slots produced by
906
+ * `writePod({ recipients: [...] })`. Setting it on a live
907
+ * keyring is allowed but unusual.
908
+ */
909
+ readonly expires_at?: string;
910
+ /**
911
+ * Optional — issue import-capability bits. Absent on keyrings
912
+ * written before landed. Loading falls back to default-closed
913
+ * for every role and every format.
914
+ */
915
+ readonly import_capability?: ImportCapability;
916
+ /**
917
+ * hierarchical access clearance. Absent → 0 (advisory;
918
+ * the real check is whether the DEK map carries a `collection#tier`
919
+ * entry for the requested tier). Owners and admins default to the
920
+ * highest tier they have DEKs for at grant time.
921
+ */
922
+ readonly clearance?: number;
923
+ }
924
+ export interface VaultBackup {
925
+ readonly _noydb_backup: typeof NOYDB_BACKUP_VERSION;
926
+ readonly _compartment: string;
927
+ readonly _exported_at: string;
928
+ readonly _exported_by: string;
929
+ readonly keyrings: Record<string, KeyringFile>;
930
+ readonly collections: VaultSnapshot;
931
+ /**
932
+ * Internal collections (`_ledger`, `_ledger_deltas`, `_history`, `_sync`, …)
933
+ * captured alongside the data collections. Optional for backwards
934
+ * compat with backups, which only stored data collections —
935
+ * loading a backup leaves the ledger empty (and `verifyBackupIntegrity`
936
+ * skips the chain check, surfacing only a console warning).
937
+ */
938
+ readonly _internal?: VaultSnapshot;
939
+ /**
940
+ * Verifiable-backup metadata. Embeds the ledger head at
941
+ * dump time so `load()` can cross-check that the loaded chain matches
942
+ * exactly what was exported. A backup whose chain has been tampered
943
+ * with — either by modifying ledger entries or by modifying data
944
+ * envelopes that the chain references — fails this check.
945
+ *
946
+ * Optional for backwards compat with backups; missing means
947
+ * "legacy backup, load with a warning, no integrity check".
948
+ */
949
+ readonly ledgerHead?: {
950
+ /** Hex sha256 of the canonical JSON of the last ledger entry. */
951
+ readonly hash: string;
952
+ /** Sequential index of the last ledger entry. */
953
+ readonly index: number;
954
+ /** ISO timestamp captured at dump time. */
955
+ readonly ts: string;
956
+ };
957
+ }
958
+ /**
959
+ * Options for `Vault.exportStream()` and `Vault.exportJSON()`.
960
+ *
961
+ * The defaults match the most common consumer pattern: one chunk per
962
+ * collection, no ledger metadata. Per-record streaming and ledger-head
963
+ * inclusion are opt-in because both add structure most consumers don't
964
+ * need.
965
+ */
966
+ export interface ExportStreamOptions {
967
+ /**
968
+ * `'collection'` (default) yields one chunk per collection with all
969
+ * records bundled in `chunk.records`. `'record'` yields one chunk per
970
+ * record, useful for arbitrarily large collections that should never
971
+ * be materialized as a single array.
972
+ */
973
+ readonly granularity?: 'collection' | 'record';
974
+ /**
975
+ * When `true`, every chunk includes the current compartment ledger
976
+ * head under `chunk.ledgerHead`. The value is identical across every
977
+ * chunk in a single export (one ledger per compartment). Forward-
978
+ * compatible with future partition work where the head would become
979
+ * per-partition. Default: `false`.
980
+ */
981
+ readonly withLedgerHead?: boolean;
982
+ /**
983
+ * Export locale (BCP 47, e.g. `'th'`). When set, records are read at this
984
+ * locale through the **`export` layer**: `i18nText` fields collapse to
985
+ * the locale string (honoring each field's `export`-layer `onMissing` policy)
986
+ * and `dictKey`/`staticDict` `<field>Label`s are resolved — a single-locale
987
+ * export. The raw `dictionaries` snapshot is then redundant and omitted. This
988
+ * applies to BOTH `exportStream()` and `exportJSON()`.
989
+ *
990
+ * Default: `undefined` — raw `{locale}` maps + the `_dictionaries` snapshot
991
+ * (a full, all-locale backup; format packages apply their own locale strategy).
992
+ */
993
+ readonly resolveLabels?: string;
994
+ }
995
+ /**
996
+ * One chunk yielded by `Vault.exportStream()`.
997
+ *
998
+ * `granularity: 'collection'` yields one chunk per collection with the
999
+ * full record array in `records`. `granularity: 'record'` yields one
1000
+ * chunk per record with `records` containing exactly one element — the
1001
+ * `schema` and `refs` metadata is repeated on every chunk so consumers
1002
+ * doing per-record streaming don't have to thread state across yields.
1003
+ */
1004
+ export interface ExportChunk<T = unknown> {
1005
+ /** Collection name (no leading underscore — internal collections are filtered out). */
1006
+ readonly collection: string;
1007
+ /**
1008
+ * Standard Schema validator attached to the collection at `collection()`
1009
+ * construction time, or `null` if no schema was provided. Surfaced so
1010
+ * downstream serializers (`@noy-db/as-*` packages, custom
1011
+ * exporters) can produce schema-aware output (typed CSV headers, XSD
1012
+ * generation, etc.) without poking at collection internals.
1013
+ */
1014
+ readonly schema: StandardSchemaV1<unknown, T> | null;
1015
+ /**
1016
+ * Foreign-key references declared on the collection via the `refs`
1017
+ * option, as the `{ field → { target, mode } }` map produced by
1018
+ * `RefRegistry.getOutbound`. Empty object when no refs were declared.
1019
+ */
1020
+ readonly refs: Record<string, {
1021
+ readonly target: string;
1022
+ readonly mode: 'strict' | 'warn' | 'cascade';
1023
+ }>;
1024
+ /**
1025
+ * Decrypted, ACL-scoped, schema-validated records. Length 1 in
1026
+ * `granularity: 'record'` mode, full collection in `granularity: 'collection'`
1027
+ * mode. Records are returned by reference from the collection's eager
1028
+ * cache where applicable — consumers must treat them as immutable.
1029
+ */
1030
+ readonly records: T[];
1031
+ /**
1032
+ * Dictionary snapshots for every `dictKey` field declared on this
1033
+ * collection. Captured once at stream-start and held
1034
+ * constant across all chunks within the same export — a rename
1035
+ * mid-export does not change the snapshot. `undefined` when the
1036
+ * collection has no `dictKeyFields`.
1037
+ *
1038
+ * Shape: `{ [fieldName]: { [stableKey]: { [locale]: label } } }`
1039
+ *
1040
+ * @example
1041
+ * ```ts
1042
+ * chunk.dictionaries?.status?.paid?.th // → 'ชำระแล้ว'
1043
+ * ```
1044
+ */
1045
+ readonly dictionaries?: Record<string, // field name
1046
+ Record<string, Record<string, string>>>;
1047
+ /**
1048
+ * Vault ledger head at export time. Present only when
1049
+ * `exportStream({ withLedgerHead: true })` was called. Identical
1050
+ * across every chunk in the same export — included on every chunk
1051
+ * for forward-compatibility with future per-partition ledgers, where
1052
+ * the value will differ per chunk.
1053
+ */
1054
+ readonly ledgerHead?: {
1055
+ readonly hash: string;
1056
+ readonly index: number;
1057
+ readonly ts: string;
1058
+ };
1059
+ }
1060
+ export interface DirtyEntry {
1061
+ readonly vault: string;
1062
+ readonly collection: string;
1063
+ readonly id: string;
1064
+ readonly action: 'put' | 'delete';
1065
+ readonly version: number;
1066
+ readonly timestamp: string;
1067
+ }
1068
+ export interface SyncMetadata {
1069
+ readonly _noydb_sync: typeof NOYDB_SYNC_VERSION;
1070
+ readonly last_push: string | null;
1071
+ readonly last_pull: string | null;
1072
+ readonly dirty: DirtyEntry[];
1073
+ }
1074
+ export interface Conflict {
1075
+ readonly vault: string;
1076
+ readonly collection: string;
1077
+ readonly id: string;
1078
+ readonly local: EncryptedEnvelope;
1079
+ readonly remote: EncryptedEnvelope;
1080
+ readonly localVersion: number;
1081
+ readonly remoteVersion: number;
1082
+ /**
1083
+ * Present only when the collection uses `conflictPolicy: 'manual'`.
1084
+ * Call `resolve(winner)` to commit the winning envelope, or
1085
+ * `resolve(null)` to defer (conflict stays queued for the next sync).
1086
+ * Called synchronously inside the `sync:conflict` event handler.
1087
+ */
1088
+ readonly resolve?: (winner: EncryptedEnvelope | null) => void;
1089
+ }
1090
+ /**
1091
+ * #590: sync suppressed a live envelope because a crypto-shred tombstone is
1092
+ * terminal for its record id. Reported on push/pull results (`erasures`) and
1093
+ * via the `'sync:erasure'` event; conflict resolvers are never consulted for
1094
+ * tombstone pairs.
1095
+ */
1096
+ export interface ErasureEnforcement {
1097
+ readonly vault: string;
1098
+ readonly collection: string;
1099
+ readonly id: string;
1100
+ /** The winning tombstone (as stored after enforcement). */
1101
+ readonly tombstone: EncryptedEnvelope;
1102
+ /** The live envelope that lost: a suppressed dirty local edit, or the remote copy destroyed by re-assertion. */
1103
+ readonly suppressed: EncryptedEnvelope;
1104
+ readonly direction: 'pull' | 'push';
1105
+ }
1106
+ /**
1107
+ * A same-device cross-tab write conflict: another tab overwrote a
1108
+ * document this tab had written, having diverged from an older base. Records
1109
+ * are decrypted (cross-tab handlers reconcile in plaintext). `base` is the
1110
+ * common ancestor from history, or null when history is unavailable.
1111
+ */
1112
+ export interface WriteConflict {
1113
+ readonly vault: string;
1114
+ readonly collection: string;
1115
+ readonly docId: string;
1116
+ readonly local: unknown;
1117
+ readonly remote: unknown;
1118
+ readonly base: unknown;
1119
+ readonly localVersion: number;
1120
+ readonly remoteVersion: number;
1121
+ readonly baseVersion: number;
1122
+ }
1123
+ export type ConflictStrategy = 'local-wins' | 'remote-wins' | 'version' | ((conflict: Conflict) => 'local' | 'remote');
1124
+ /**
1125
+ * Collection-level conflict policy.
1126
+ * Overrides the db-level `conflict` option for the specific collection.
1127
+ *
1128
+ * - `'last-writer-wins'` — higher `_ts` wins (timestamp LWW).
1129
+ * - `'first-writer-wins'` — lower `_v` wins (earlier version is preserved).
1130
+ * - `'manual'` — emits `sync:conflict` with a `resolve` callback. Call
1131
+ * `resolve(winner)` synchronously to commit or `resolve(null)` to defer.
1132
+ * - Custom fn — synchronous `(local: T, remote: T) => T`. Must be pure.
1133
+ *
1134
+ * **Delete-vs-edit caveat:** `'last-writer-wins'`, `'first-writer-wins'`,
1135
+ * and `'manual'` compare/hand over raw envelopes, so an edit CAN win over
1136
+ * a delete marker (a later `_ts`, an earlier `_v`, or the app's own
1137
+ * `resolve()` choice). A custom fn, and the CRDT merge modes `'lww-map'`/
1138
+ * `'rga'` (`crdtStrategy`), CANNOT: their shared resolver wrapper decrypts
1139
+ * both sides first and short-circuits to whichever side is the
1140
+ * shredded/tombstoned one *before* the merge function (or CRDT merge)
1141
+ * ever runs — delete unconditionally wins. CRDT mode `'yjs'` is the
1142
+ * exception among CRDT modes: it never decrypts and falls back to a
1143
+ * plain higher-`_v`-wins compare, so an edit can beat a delete there too.
1144
+ */
1145
+ export type ConflictPolicy<T> = 'last-writer-wins' | 'first-writer-wins' | 'manual' | ((local: T, remote: T) => T);
1146
+ /**
1147
+ * Envelope-level resolver registered per collection with the SyncEngine.
1148
+ * Receives the `id` of the conflicting record and both envelopes.
1149
+ * Returns the winning envelope, or `null` to defer resolution.
1150
+ * @internal
1151
+ */
1152
+ export type CollectionConflictResolver = (id: string, local: EncryptedEnvelope, remote: EncryptedEnvelope) => Promise<EncryptedEnvelope | null>;
1153
+ /** Options for targeted push operations. */
1154
+ export interface PushOptions {
1155
+ /** Only push records belonging to these collections. Omit to push all dirty. */
1156
+ collections?: string[];
1157
+ }
1158
+ /** Options for targeted pull operations. */
1159
+ export interface PullOptions {
1160
+ /** Only pull these collections. Omit to pull all. */
1161
+ collections?: string[];
1162
+ /**
1163
+ * Only pull records with `_ts` strictly after this ISO timestamp.
1164
+ * Stores that implement `listSince` use it directly; others fall back
1165
+ * to a full scan with client-side filtering.
1166
+ */
1167
+ modifiedSince?: string;
1168
+ }
1169
+ export interface PushResult {
1170
+ readonly pushed: number;
1171
+ readonly conflicts: Conflict[];
1172
+ readonly errors: Error[];
1173
+ /** #590: tombstone enforcements applied during this run (never resolver-visible). */
1174
+ readonly erasures?: ErasureEnforcement[];
1175
+ }
1176
+ export interface PullResult {
1177
+ readonly pulled: number;
1178
+ readonly conflicts: Conflict[];
1179
+ readonly errors: Error[];
1180
+ /** #590: tombstone enforcements applied during this run (never resolver-visible). */
1181
+ readonly erasures?: ErasureEnforcement[];
1182
+ }
1183
+ /** Result of a sync transaction commit. */
1184
+ export interface SyncTransactionResult {
1185
+ readonly status: 'committed' | 'conflict';
1186
+ readonly pushed: number;
1187
+ readonly conflicts: Conflict[];
1188
+ /** #590: staged writes suppressed by tombstone enforcement during commit. */
1189
+ readonly erasures?: ErasureEnforcement[];
1190
+ }
1191
+ export interface SyncStatus {
1192
+ readonly dirty: number;
1193
+ readonly lastPush: string | null;
1194
+ readonly lastPull: string | null;
1195
+ readonly online: boolean;
1196
+ }
1197
+ export type SyncTargetRole = 'sync-peer' | 'backup' | 'archive';
1198
+ /**
1199
+ * A sync target with role and optional per-target policy.
1200
+ *
1201
+ * | Role | Direction | Conflict resolution | Typical use |
1202
+ * |-------------|---------------|---------------------|--------------------------|
1203
+ * | `sync-peer` | Bidirectional | ConflictStrategy | DynamoDB live sync |
1204
+ * | `backup` | Push-only | N/A (receives merged)| S3 dump, Google Drive |
1205
+ * | `archive` | Push-only | N/A | IPFS, Git tags, S3 Lock |
1206
+ */
1207
+ export interface SyncTarget {
1208
+ /** The store to sync with. */
1209
+ readonly store: NoydbStore;
1210
+ /** Role determines sync direction and conflict handling. */
1211
+ readonly role: SyncTargetRole;
1212
+ /** Per-target sync policy. Inherits store-category default when absent. */
1213
+ readonly policy?: SyncPolicy;
1214
+ /** Human-readable label for DevTools and audit logs. */
1215
+ readonly label?: string;
1216
+ }
1217
+ export interface ChangeEvent {
1218
+ readonly vault: string;
1219
+ readonly collection: string;
1220
+ readonly id: string;
1221
+ readonly action: 'put' | 'delete';
1222
+ }
1223
+ export interface NoydbEventMap {
1224
+ 'change': ChangeEvent;
1225
+ 'error': Error;
1226
+ /**
1227
+ * Same-instance signal that this vault's schema-fence state changed.
1228
+ * For UI integration. Cross-client coordination goes
1229
+ * through the store, not this event.
1230
+ */
1231
+ 'schema:fence-changed': {
1232
+ vault: string;
1233
+ currentSchemaVersion: number;
1234
+ fenceState: 'normal' | 'draining' | 'migrating' | 'complete';
1235
+ };
1236
+ 'sync:push': PushResult;
1237
+ 'sync:pull': PullResult;
1238
+ 'sync:erasure': ErasureEnforcement;
1239
+ 'sync:conflict': Conflict;
1240
+ 'write:conflict': WriteConflict;
1241
+ 'sync:online': void;
1242
+ 'sync:offline': void;
1243
+ 'sync:backup-error': {
1244
+ vault: string;
1245
+ target: string;
1246
+ error: Error;
1247
+ };
1248
+ 'history:save': {
1249
+ vault: string;
1250
+ collection: string;
1251
+ id: string;
1252
+ version: number;
1253
+ };
1254
+ 'history:prune': {
1255
+ vault: string;
1256
+ collection: string;
1257
+ id: string;
1258
+ pruned: number;
1259
+ };
1260
+ /**
1261
+ * A non-fatal i18n script violation under `onScriptViolation: 'warn' | 'filter'`.
1262
+ * 'warn' stored the value as-is; 'filter' stripped disallowed characters
1263
+ * (the event is the only signal the stored data was mutated). 'reject'
1264
+ * throws `ScriptViolationError` and emits nothing.
1265
+ */
1266
+ 'i18n:script-violation': {
1267
+ vault: string;
1268
+ collection: string;
1269
+ id: string;
1270
+ mode: 'warn' | 'filter';
1271
+ warning: ScriptWarning;
1272
+ };
1273
+ /**
1274
+ * Emitted when a persisted-index side-car put/delete fails after the
1275
+ * main record write already succeeded. The main record is durable; the
1276
+ * index mirror may have drifted. Operators reconcile via
1277
+ * `collection.reconcileIndex(field)`.
1278
+ */
1279
+ 'index:write-partial': {
1280
+ vault: string;
1281
+ collection: string;
1282
+ id: string;
1283
+ action: 'put' | 'delete';
1284
+ error: Error;
1285
+ };
1286
+ /**
1287
+ * emitted by `Collection.ensurePersistedIndexesLoaded()`
1288
+ * once per field on first lazy-mode query when
1289
+ * `reconcileOnOpen: 'auto' | 'dry-run'` is configured. `applied` is
1290
+ * `0` in `'dry-run'` mode. `skipped` is reserved for a future
1291
+ * drift-stamp optimization that short-circuits the reconcile when
1292
+ * the mirror version matches what's on disk — currently always
1293
+ * `false` (the full reconcile runs every session).
1294
+ */
1295
+ 'index:reconciled': {
1296
+ vault: string;
1297
+ collection: string;
1298
+ field: string;
1299
+ missing: readonly string[];
1300
+ stale: readonly string[];
1301
+ applied: number;
1302
+ skipped: boolean;
1303
+ };
1304
+ /**
1305
+ * #638 Task 5 — a dispatch-driven derivation/rollup/MV output write targeted a row whose
1306
+ * period is closed. The write is SKIPPED (the historical value stands); the SOURCE write
1307
+ * that triggered the recompute still succeeded. See `kernel/via/dispatch.ts#putDerivedOutput`.
1308
+ * `source.id` may be a non-record sentinel (e.g. `'refreshView'`) for manual bulk-refresh-
1309
+ * triggered skips, not a real source record id.
1310
+ */
1311
+ 'derivation:skipped-frozen': DerivationSkippedFrozen;
1312
+ /**
1313
+ * #654 — an ordinary-delete lookup-ref `cascade`/`nullify` propagation edge whose compare-key
1314
+ * could not be resolved from the backing row (matrix custom-key row unreadable — corruption
1315
+ * class). The delete itself proceeds (only `restrict` edges fail closed, via
1316
+ * `RestrictRefUnresolvableError`); this edge's propagation is skipped and reported here instead
1317
+ * of silently dropped — the ordinary-delete counterpart of the forget path's
1318
+ * `ForgetResult.lookupReferencesResidue` channel. `residue` entries are `backing:key:
1319
+ * collection.field`, one per un-propagated edge (see `VaultLinks.applyLookupRefsPropagation`).
1320
+ */
1321
+ 'lookup:propagation-residue': {
1322
+ vault: string;
1323
+ dimension: string;
1324
+ key: string;
1325
+ residue: readonly string[];
1326
+ };
1327
+ /**
1328
+ * #640 rider (#644 item 3) — the sync/cutover/restore dispatch wave's per-id recompute failed
1329
+ * (a genuine decrypt failure, a derive()/executor bug, a schema violation on the output, ...).
1330
+ * ADDITIVE to the existing `console.warn` in `runGraphDispatchWave` — never replaces it, so no
1331
+ * listener-dependent silence. One event per failed (collection, id); the wave still isolates
1332
+ * the failure to just that one record. See `kernel/via/dispatch.ts#runGraphDispatchWave`.
1333
+ */
1334
+ 'derivation:wave-error': {
1335
+ collection: string;
1336
+ id: string;
1337
+ error: unknown;
1338
+ };
1339
+ }
1340
+ export interface GrantOptions {
1341
+ readonly userId: string;
1342
+ readonly displayName: string;
1343
+ readonly role: Role;
1344
+ readonly passphrase: string;
1345
+ readonly permissions?: Permissions;
1346
+ /**
1347
+ * Optional `@noy-db/as-*` export capability. Omit or
1348
+ * leave undefined to apply role-based defaults (see
1349
+ * `hasExportCapability` and `ExportCapability`).
1350
+ */
1351
+ readonly exportCapability?: ExportCapability;
1352
+ /**
1353
+ * Optional `@noy-db/as-*` import capability (issue ). Omit or
1354
+ * leave undefined for default-closed semantics — no plaintext format
1355
+ * is grantable until positively listed; bundle import is denied.
1356
+ */
1357
+ readonly importCapability?: ImportCapability;
1358
+ /**
1359
+ * Skip phrase-format strength validation (issue #7). Defaults to
1360
+ * false — `grant()` rejects phrases that don't meet the configured
1361
+ * `PassphrasePolicy`. Test fixtures and CLI scripts pass `true`.
1362
+ */
1363
+ readonly allowWeakPassphrase?: boolean;
1364
+ /**
1365
+ * Initial user-envelope payload for the new principal. Sealed under
1366
+ * the same vault DEK (the reserved `_users` collection's DEK) and
1367
+ * persisted alongside the keyring during grant.
1368
+ *
1369
+ * **Bootstrap-only.** Once the new user activates and writes their
1370
+ * own envelope, the own-only write rule kicks in — admins cannot
1371
+ * edit a teammate's envelope after activation. Use this field for
1372
+ * pre-fill at invite time (e.g. "displayName: Bob, locale: en-US")
1373
+ * and let the user take over from there.
1374
+ *
1375
+ * Hub does not introspect the payload; it is JSON-serialized and
1376
+ * encrypted opaquely. Apps own the schema.
1377
+ *
1378
+ * @see docs/superpowers/specs/2026-05-05-user-envelope-design.md → Lifecycle
1379
+ */
1380
+ readonly initialProfile?: unknown;
1381
+ }
1382
+ /**
1383
+ * Caller payload for `db.updateUser`. Mutate one or more
1384
+ * identity fields on an existing keyring without rotating any keys.
1385
+ *
1386
+ * `role`, `displayName`, and `permissions` live in the plaintext header
1387
+ * of `_keyring/<userId>` (the sync engine reads them without keys).
1388
+ * Mutating them is a JSON header swap — no DEK rewrap, no KEK
1389
+ * required, no authenticator slots touched. Tier-2 slots and recovery
1390
+ * enrollments survive unchanged. Last-write-wins through the existing
1391
+ * keyring put (same concurrency story as `db.grant` / `db.revoke`).
1392
+ *
1393
+ * Top-level fields are partial-merge: absent fields are not modified.
1394
+ * `null` on `displayName` clears the field (stored as the empty string;
1395
+ * UI consumers typically render the empty case by falling back to the
1396
+ * user id). `undefined` / absent leaves the field untouched. Mirrors
1397
+ * the `null`-as-clear convention `UserApi.updateMe` uses.
1398
+ *
1399
+ * `permissions`, however, is a **full replacement** at the map level —
1400
+ * passing `{ invoices: 'rw' }` REPLACES the entire permissions map,
1401
+ * silently dropping any other entries. To partially update, read the
1402
+ * current keyring and merge: `permissions: { ...current, invoices: 'rw' }`.
1403
+ * To clear all permissions, pass `permissions: {}` explicitly.
1404
+ *
1405
+ * Role-elevation guard: the same hierarchy as `db.grant`. Admins can
1406
+ * change `admin` / `operator` / `viewer` / `client` to and from each
1407
+ * other; admins cannot promote to or demote from `owner`. Owners can
1408
+ * do anything. Non-admin callers (operator/viewer/client) cannot call
1409
+ * `db.updateUser` at all — for self-displayName changes, use
1410
+ * `vault.user.updateMe` (the user-envelope API).
1411
+ */
1412
+ export interface UpdateUserOptions {
1413
+ readonly userId: string;
1414
+ readonly role?: Role;
1415
+ readonly displayName?: string | null;
1416
+ readonly permissions?: Permissions;
1417
+ }
1418
+ export interface RevokeOptions {
1419
+ readonly userId: string;
1420
+ readonly rotateKeys?: boolean;
1421
+ /**
1422
+ * Cascade behavior when the revoked user is an admin who has granted
1423
+ * other admins.
1424
+ *
1425
+ * - `'strict'` (default) — recursively revoke every admin that the
1426
+ * target (transitively) granted. The cascade walks the
1427
+ * `granted_by` field on each keyring file and stops at non-admin
1428
+ * leaves. All affected collections are accumulated and rotated in
1429
+ * a single pass at the end, so cascade cost is O(records in
1430
+ * affected collections), not O(records × cascade depth).
1431
+ *
1432
+ * - `'warn'` — leave the descendant admins in place but emit a
1433
+ * `console.warn` listing them. Useful for diagnostic dry runs and
1434
+ * for environments where the operator wants to clean up the
1435
+ * delegation tree manually.
1436
+ *
1437
+ * No effect when the target is not an admin (operators, viewers, and
1438
+ * clients cannot grant other users, so they have no delegation
1439
+ * subtree to cascade through). Defaults to `'strict'`.
1440
+ */
1441
+ readonly cascade?: 'strict' | 'warn';
1442
+ }
1443
+ /**
1444
+ * One entry returned by `Noydb.listAccessibleVaults()`. Carries
1445
+ * the compartment id and the role the calling principal holds in it,
1446
+ * so the consumer can decide how to fan out without re-checking
1447
+ * permissions per vault.
1448
+ */
1449
+ export interface AccessibleVault {
1450
+ readonly id: string;
1451
+ readonly role: Role;
1452
+ }
1453
+ /**
1454
+ * Options for `Noydb.listAccessibleVaults()`.
1455
+ */
1456
+ export interface ListAccessibleVaultsOptions {
1457
+ /**
1458
+ * Minimum role the caller must hold to include a vault in the
1459
+ * result. Vaults where the caller's role is strictly *below*
1460
+ * this threshold are silently excluded. Defaults to `'client'`,
1461
+ * which means "every vault I can unwrap is returned." Set to
1462
+ * `'admin'` for "vaults where I can grant/revoke," or
1463
+ * `'owner'` for "vaults I own."
1464
+ *
1465
+ * The privilege ordering used:
1466
+ * `client (1) < viewer (2) < operator (3) < admin (4) < owner (5)`
1467
+ *
1468
+ * Note: `viewer` and `client` are conceptually peers in the ACL
1469
+ * (neither can grant), but `viewer` has read-all access while
1470
+ * `client` has only explicit-collection read. The numeric order
1471
+ * reflects "how much can this principal see," not "how much can
1472
+ * this principal modify."
1473
+ */
1474
+ readonly minRole?: Role;
1475
+ }
1476
+ /**
1477
+ * Options for `Noydb.queryAcross()`.
1478
+ */
1479
+ export interface QueryAcrossOptions {
1480
+ /**
1481
+ * Maximum number of compartments to process in parallel. Defaults
1482
+ * to `1` (sequential) — conservative because the per-compartment
1483
+ * callback typically does its own I/O and an unbounded fan-out can
1484
+ * exhaust adapter connections (DynamoDB throughput, S3 socket
1485
+ * limits, browser fetch concurrency).
1486
+ *
1487
+ * Set to `4` or `8` for cloud-backed compartments where parallelism
1488
+ * is the whole point of fanning out. Set to `1` (default) for local
1489
+ * adapters where the disk I/O serializes anyway.
1490
+ */
1491
+ readonly concurrency?: number;
1492
+ /**
1493
+ * Open shards non-creatingly — a missing grant throws instead of
1494
+ * self-provisioning. Default: `true` (create iff the vault has no
1495
+ * `_keyring/*`). Pass `false` for strict open-existing semantics
1496
+ * (e.g. federation read fan-out where shards are pre-provisioned
1497
+ * and an absent grant should fail closed).
1498
+ */
1499
+ readonly create?: boolean;
1500
+ }
1501
+ /**
1502
+ * One entry in the array returned by `Noydb.queryAcross()`. Either
1503
+ * `result` is set (callback succeeded for this compartment) or
1504
+ * `error` is set (callback threw, or compartment failed to open).
1505
+ *
1506
+ * Per-compartment errors do **not** abort the overall fan-out — every
1507
+ * compartment is given a chance to run its callback, and the
1508
+ * partition between success and failure is exposed in the return
1509
+ * value. Consumers that want fail-fast semantics can check
1510
+ * `r.error !== undefined` and short-circuit themselves.
1511
+ */
1512
+ export type QueryAcrossResult<T> = {
1513
+ readonly vault: string;
1514
+ readonly result: T;
1515
+ readonly error?: undefined;
1516
+ } | {
1517
+ readonly vault: string;
1518
+ readonly result?: undefined;
1519
+ readonly error: Error;
1520
+ };
1521
+ export interface UserInfo {
1522
+ readonly userId: string;
1523
+ readonly displayName: string;
1524
+ readonly role: Role;
1525
+ readonly permissions: Permissions;
1526
+ readonly createdAt: string;
1527
+ readonly grantedBy: string;
1528
+ }
1529
+ /**
1530
+ * Operations that a session policy can require re-authentication for.
1531
+ * Passed as the `requireReAuthFor` array in `SessionPolicy`.
1532
+ */
1533
+ export type ReAuthOperation = 'export' | 'grant' | 'revoke' | 'rotate' | 'changeSecret';
1534
+ /**
1535
+ * Session policy controlling lifetime, re-auth requirements, and
1536
+ * background-lock behavior.
1537
+ *
1538
+ * All timeout values are in milliseconds. `undefined` means "no limit."
1539
+ * The policy is evaluated lazily — it does not start timers itself;
1540
+ * enforcement happens at the Noydb call site.
1541
+ */
1542
+ export interface SessionPolicy {
1543
+ /**
1544
+ * Idle timeout in ms. If no NOYDB operation is performed for this
1545
+ * duration, the session is revoked on the next operation attempt
1546
+ * (which will throw `SessionExpiredError`). The idle clock resets
1547
+ * on every successful operation.
1548
+ *
1549
+ * Default: `undefined` (no idle timeout).
1550
+ */
1551
+ readonly idleTimeoutMs?: number;
1552
+ /**
1553
+ * Absolute timeout in ms from session creation. After this duration
1554
+ * the session is unconditionally revoked regardless of activity.
1555
+ *
1556
+ * Default: `undefined` (no absolute timeout).
1557
+ */
1558
+ readonly absoluteTimeoutMs?: number;
1559
+ /**
1560
+ * Operations that require the user to re-authenticate (re-enter their
1561
+ * passphrase or perform a fresh WebAuthn assertion) before proceeding,
1562
+ * even if the session is still alive.
1563
+ *
1564
+ * Common pattern: `requireReAuthFor: ['export', 'grant']` — allow
1565
+ * read/write operations in the background but demand a fresh credential
1566
+ * for high-risk mutations.
1567
+ *
1568
+ * Default: `[]` (no extra re-auth requirements).
1569
+ */
1570
+ readonly requireReAuthFor?: readonly ReAuthOperation[];
1571
+ /**
1572
+ * If `true`, the session is revoked when the page goes to the background
1573
+ * (visibilitychange event, `document.hidden === true`). Useful for
1574
+ * high-sensitivity deployments where leaving the tab is treated as
1575
+ * a session boundary.
1576
+ *
1577
+ * No-op in non-browser environments (Node.js, workers without document).
1578
+ * Default: `false`.
1579
+ */
1580
+ readonly lockOnBackground?: boolean;
1581
+ }
1582
+ /**
1583
+ * Locale-aware read options. Pass to `Collection.get()`, `list()`,
1584
+ * `query()`, and `scan()` to trigger per-record locale resolution for
1585
+ * `dictKey` and `i18nText` fields.
1586
+ *
1587
+ * - **`locale: 'raw'`** — skip resolution for `i18nText` fields and
1588
+ * return the full `{ [locale]: string }` map. Dict key fields still
1589
+ * return the stable key (no `<field>Label` added).
1590
+ * - **`fallback`** — single locale code or ordered list. Use `'any'` as
1591
+ * the last element to fall back to any present translation.
1592
+ *
1593
+ * When neither the call-level locale nor the compartment's default locale
1594
+ * is set, reading a record with `i18nText` fields throws
1595
+ * `LocaleNotSpecifiedError`.
1596
+ */
1597
+ export interface LocaleReadOptions {
1598
+ /**
1599
+ * The target locale code (e.g. `'th'`), or `'raw'` to return the full
1600
+ * language map without resolution.
1601
+ */
1602
+ readonly locale?: string;
1603
+ /**
1604
+ * Fallback locale or ordered fallback chain. Use `'any'` as the last
1605
+ * element to fall back to any present translation.
1606
+ */
1607
+ readonly fallback?: string | readonly string[];
1608
+ /**
1609
+ * @internal — the resolution layer this read belongs to (`'read'` by
1610
+ * default). Threaded by layer-tagged read facades (guard / derivation)
1611
+ * so `applyI18nLocale` and dictKey `resolvePolicy` select that layer's
1612
+ * `onMissing` policy instead of the `'read'` policy. Not part of the
1613
+ * public read API — callers select policy via the field's `onMissing`
1614
+ * map, not by setting this.
1615
+ */
1616
+ readonly _layer?: Layer;
1617
+ }
1618
+ /**
1619
+ * Context passed to the consumer-supplied `plaintextTranslator` function.
1620
+ * The hook receives the source text plus enough metadata to route it to the
1621
+ * right translation service and record what it did.
1622
+ */
1623
+ export interface PlaintextTranslatorContext {
1624
+ /** The plaintext string to translate. */
1625
+ readonly text: string;
1626
+ /** BCP 47 source locale (the locale the text is written in). */
1627
+ readonly from: string;
1628
+ /** BCP 47 target locale to translate into. */
1629
+ readonly to: string;
1630
+ /** The schema field name that triggered the translation. */
1631
+ readonly field: string;
1632
+ /** The collection the record is being put into. */
1633
+ readonly collection: string;
1634
+ }
1635
+ /**
1636
+ * A consumer-supplied async function that translates a single string
1637
+ * from one locale to another. noy-db ships no built-in translator.
1638
+ *
1639
+ * **Security:** this function receives plaintext. The consumer is
1640
+ * responsible for the data policy of whatever service it calls. See
1641
+ * `NOYDB_SPEC.md § Zero-Knowledge Storage` and the `plaintextTranslator`
1642
+ * JSDoc on `NoydbOptions` for the full invariant statement.
1643
+ */
1644
+ export type PlaintextTranslatorFn = (ctx: PlaintextTranslatorContext) => Promise<string>;
1645
+ /**
1646
+ * One entry in the in-process translator audit log. Cleared when
1647
+ * `db.close()` is called — same lifetime as the KEK and DEKs.
1648
+ *
1649
+ * Deliberately omits any content hash or translated-text fingerprint
1650
+ * to prevent correlation attacks on the audit trail.
1651
+ */
1652
+ export interface TranslatorAuditEntry {
1653
+ readonly type: 'translator-invocation';
1654
+ /** Schema field name that was translated. */
1655
+ readonly field: string;
1656
+ /** Collection the record belongs to. */
1657
+ readonly collection: string;
1658
+ /** Source locale. */
1659
+ readonly fromLocale: string;
1660
+ /** Target locale. */
1661
+ readonly toLocale: string;
1662
+ /**
1663
+ * Consumer-provided translator name from
1664
+ * `NoydbOptions.plaintextTranslatorName`. Defaults to `'anonymous'`
1665
+ * when not supplied.
1666
+ */
1667
+ readonly translatorName: string;
1668
+ /** ISO 8601 timestamp of the invocation. */
1669
+ readonly timestamp: string;
1670
+ /**
1671
+ * `true` when the result was served from the in-process cache rather
1672
+ * than by calling the translator function. Present only on cache hits
1673
+ * so the absence of the field also communicates a cache miss.
1674
+ */
1675
+ readonly cached?: true;
1676
+ }
1677
+ /**
1678
+ * A presence peer entry. `lastSeen` is an ISO timestamp set by core on each
1679
+ * `update()` call. Stale entries (lastSeen older than `staleMs`) are filtered
1680
+ * before delivering to the subscriber callback.
1681
+ */
1682
+ export interface PresencePeer<P> {
1683
+ readonly userId: string;
1684
+ readonly payload: P;
1685
+ readonly lastSeen: string;
1686
+ }
1687
+ /** Per-collection CRDT mode. */
1688
+ export type CrdtMode = 'lww-map' | 'rga' | 'yjs';
1689
+ /**
1690
+ * Per-field last-write-wins registers.
1691
+ * Each field carries its latest value and the ISO timestamp of the last write.
1692
+ * Merge: for each field, keep the entry with the lexicographically higher `ts`.
1693
+ */
1694
+ export interface LwwMapState {
1695
+ readonly _crdt: 'lww-map';
1696
+ readonly fields: Record<string, {
1697
+ readonly v: unknown;
1698
+ readonly ts: string;
1699
+ }>;
1700
+ }
1701
+ /**
1702
+ * Simplified Replicated Growable Array.
1703
+ * Items are assigned stable NID (noy-db id) strings on first insertion.
1704
+ * Deleted items are tracked as tombstones so concurrent removals commute.
1705
+ *
1706
+ * The resolved snapshot is the ordered list of non-tombstoned `v` values.
1707
+ */
1708
+ export interface RgaState {
1709
+ readonly _crdt: 'rga';
1710
+ readonly items: ReadonlyArray<{
1711
+ readonly nid: string;
1712
+ readonly v: unknown;
1713
+ }>;
1714
+ readonly tombstones: readonly string[];
1715
+ }
1716
+ /**
1717
+ * Yjs binary state marker. `update` is base64(Y.encodeStateAsUpdate()).
1718
+ * Core stores and retrieves the blob opaquely. `@noy-db/yjs` is responsible
1719
+ * for encoding, decoding, and merging via `Y.mergeUpdates`.
1720
+ * Core falls back to last-write-wins (higher `_v`) for conflict resolution.
1721
+ */
1722
+ export interface YjsState {
1723
+ readonly _crdt: 'yjs';
1724
+ /** base64-encoded Y.encodeStateAsUpdate() bytes. */
1725
+ readonly update: string;
1726
+ }
1727
+ export type CrdtState = LwwMapState | RgaState | YjsState;
1728
+ /**
1729
+ * Seam interface. `@internal`.
1730
+ *
1731
+ * @internal
1732
+ */
1733
+ export interface CrdtStrategy {
1734
+ buildLwwMapState(record: Record<string, unknown>, previous: LwwMapState | undefined, now: string): LwwMapState;
1735
+ buildRgaState(items: readonly unknown[], previous: RgaState | undefined, idGen: () => string): RgaState;
1736
+ mergeCrdtStates(local: CrdtState, remote: CrdtState): CrdtState;
1737
+ resolveCrdtSnapshot(state: CrdtState): unknown;
1738
+ }
1739
+ /**
1740
+ * Second store shape for blob-store backends (Drive, WebDAV, Git, iCloud)
1741
+ * that operate on whole-vault bundles rather than per-record KV.
1742
+ *
1743
+ * Implement `readBundle` / `writeBundle` instead of the six-method KV
1744
+ * contract. Use `wrapBundleStore()` from `@noy-db/hub` to convert to a
1745
+ * `NoydbStore` that the rest of the API consumes transparently.
1746
+ *
1747
+ * Named `NoydbPodStore` (not `NoydbBundleAdapter`) for consistency
1748
+ * with the hub / to-* / in-* rename. Concrete implementations ship
1749
+ * in `@noy-db/to-*` packages starting in.
1750
+ */
1751
+ export interface NoydbPodStore {
1752
+ /** Discriminant for engine auto-detection of store shape. */
1753
+ readonly kind: 'bundle';
1754
+ /** Human-readable name for diagnostics (e.g. `'drive'`, `'webdav'`). */
1755
+ readonly name?: string;
1756
+ /**
1757
+ * Read the entire vault as raw bytes. Returns `null` if no bundle exists
1758
+ * yet (first open of a brand-new vault).
1759
+ */
1760
+ readBundle(vaultId: string): Promise<{
1761
+ bytes: Uint8Array;
1762
+ version: string;
1763
+ } | null>;
1764
+ /**
1765
+ * Write the entire vault as raw bytes. `expectedVersion` is the version
1766
+ * token from the last `readBundle` (or `null` for a first write).
1767
+ * Implementations MUST reject the write if the stored version has advanced
1768
+ * past `expectedVersion` — throw `PodVersionConflictError`.
1769
+ * Returns the new version token on success.
1770
+ */
1771
+ writeBundle(vaultId: string, bytes: Uint8Array, expectedVersion: string | null): Promise<{
1772
+ version: string;
1773
+ }>;
1774
+ /** Delete a vault bundle. Idempotent — no-op if the bundle does not exist. */
1775
+ deleteBundle(vaultId: string): Promise<void>;
1776
+ /** List all vault bundles managed by this store. */
1777
+ listBundles(): Promise<Array<{
1778
+ vaultId: string;
1779
+ version: string;
1780
+ size: number;
1781
+ }>>;
1782
+ }
1783
+ /** @deprecated Use `NoydbPodStore`. */
1784
+ export type NoydbBundleStore = NoydbPodStore;
1785
+ /**
1786
+ * Content-addressed blob object stored in the vault-level blob index.
1787
+ * Identified by HMAC-SHA-256(blobDEK, plaintext) — opaque to the store.
1788
+ *
1789
+ * Shared across all collections within a vault for deduplication: two
1790
+ * records that attach identical byte content reference the same `eTag`
1791
+ * and share a single set of encrypted chunks in `_blob_chunks`.
1792
+ */
1793
+ export interface BlobObject {
1794
+ /** HMAC-SHA-256 hex of the original plaintext bytes, keyed by `_blob` DEK. */
1795
+ readonly eTag: string;
1796
+ /** Original uncompressed size in bytes. */
1797
+ readonly size: number;
1798
+ /** Compressed size in bytes (the payload that is actually encrypted and chunked). */
1799
+ readonly compressedSize: number;
1800
+ /** Compression algorithm applied before encryption. */
1801
+ readonly compression: 'gzip' | 'none';
1802
+ /** Raw chunk size in bytes used at write time. Readers MUST use this value. */
1803
+ readonly chunkSize: number;
1804
+ /** Total number of chunks written. Reader expects exactly this many. */
1805
+ readonly chunkCount: number;
1806
+ /** MIME type if provided or auto-detected at upload time. */
1807
+ readonly mimeType?: string;
1808
+ /** ISO timestamp of first upload. */
1809
+ readonly createdAt: string;
1810
+ /** Live reference count — slots + published versions pointing to this blob. */
1811
+ readonly refCount: number;
1812
+ /**
1813
+ * Base64 AES-KW-wrapped per-blob **content CEK** (wrapped under the `_blob`
1814
+ * DEK). Present on erasable-collection blobs (`perRecordKeys`): the chunks
1815
+ * are encrypted under this content CEK rather than directly under the `_blob`
1816
+ * DEK, so deleting this BlobObject at `refCount → 0` crypto-shreds the chunks
1817
+ * (they become permanently undecryptable). Absent → legacy blob, chunks
1818
+ * decrypt directly under the `_blob` DEK (read unchanged). See
1819
+ * docs/superpowers/specs/2026-06-13-per-blob-cek-design.md.
1820
+ */
1821
+ readonly _cek?: string;
1822
+ /**
1823
+ * Transient migration marker. Present only while a legacy
1824
+ * blob is being migrated to a content CEK: it holds the wrapped content CEK
1825
+ * BEFORE the chunks have been re-encrypted under it. Readers **ignore**
1826
+ * `_cekPending` (they key off `_cek`), so the blob stays readable under the
1827
+ * `_blob` DEK during migration AND the content CEK survives a crash → a
1828
+ * re-run resumes and promotes `_cekPending` → `_cek`. Never set on a settled blob.
1829
+ */
1830
+ readonly _cekPending?: string;
1831
+ /**
1832
+ * Hint indicating which store holds the chunk data.
1833
+ * Used by `routeStore` size-tiered routing: `'default'` for small blobs
1834
+ * stored inline (e.g. DynamoDB), `'blobs'` for large blobs in the overflow
1835
+ * store (e.g. S3). Absent when no routing is configured.
1836
+ */
1837
+ readonly storeHint?: 'default' | 'blobs';
1838
+ }
1839
+ /**
1840
+ * Slot record — mutable metadata linking a named slot on a record
1841
+ * to a `BlobObject` via its eTag.
1842
+ *
1843
+ * Multiple slots (even across different records) may reference the same
1844
+ * `eTag` — the underlying chunks are shared. Updating metadata creates
1845
+ * a new envelope version (`_v++`) while the blob data is unchanged.
1846
+ */
1847
+ export interface SlotRecord {
1848
+ /**
1849
+ * Reference to the `BlobObject` in `_blob_index` (chunk-based blobs).
1850
+ * Empty string (`''`) for an `external` slot, whose bytes live in the
1851
+ * `ObjectProjection` rather than `_blob_chunks` — read `external` instead.
1852
+ */
1853
+ readonly eTag: string;
1854
+ /**
1855
+ * External-projection reference. Present when the blob field is declared
1856
+ * `external`: the raw bytes live in the vault's `ObjectProjection` at `key`
1857
+ * (unencrypted), not in `_blob_chunks`. This slot record (in the encrypted
1858
+ * collection) remains the catalog entry — the anchoring invariant.
1859
+ */
1860
+ readonly external?: {
1861
+ readonly key: string;
1862
+ readonly contentType?: string;
1863
+ readonly public?: boolean;
1864
+ /** Opaque-token backlink stamped on the object (when `backlink:'opaque-token'`). */
1865
+ readonly backlink?: string;
1866
+ /**
1867
+ * Secondary metadata store synced from the object / its processing pipeline
1868
+ * (e.g. video `duration`, image `width`/`height`, arbitrary metatags).
1869
+ * Populated via `BlobSet.setExternalMeta()` — typically an AWS-side callback.
1870
+ */
1871
+ readonly meta?: Record<string, unknown>;
1872
+ };
1873
+ /** User-visible filename for the slot. */
1874
+ readonly filename: string;
1875
+ /** Original uncompressed size in bytes (denormalized from `BlobObject`). */
1876
+ readonly size: number;
1877
+ /** MIME type. Takes precedence over the MIME type stored in `BlobObject`. */
1878
+ readonly mimeType?: string;
1879
+ /** ISO timestamp of the upload that set this slot. */
1880
+ readonly uploadedAt: string;
1881
+ /** User ID of the uploader, if available. */
1882
+ readonly uploadedBy?: string;
1883
+ }
1884
+ /** Result of `BlobSet.list()` — slot record plus its named slot key. */
1885
+ export interface SlotInfo extends SlotRecord {
1886
+ /** The slot name (key in the record's slot map). */
1887
+ readonly name: string;
1888
+ }
1889
+ /**
1890
+ * Explicitly published version snapshot — an independent reference to a
1891
+ * blob at a specific point in time.
1892
+ */
1893
+ export interface VersionRecord {
1894
+ /** User-defined label (e.g. `'issued-2025-01'`, `'amendment-2025-02'`). */
1895
+ readonly label: string;
1896
+ /** eTag of the blob snapshot at publish time — independent of the current slot. */
1897
+ readonly eTag: string;
1898
+ /** ISO timestamp when the version was published. */
1899
+ readonly publishedAt: string;
1900
+ /** User ID of the publisher, if available. */
1901
+ readonly publishedBy?: string;
1902
+ }
1903
+ /** Options for `BlobSet.put()`. */
1904
+ export interface BlobPutOptions {
1905
+ /** MIME type hint. If omitted, auto-detected from magic bytes. */
1906
+ mimeType?: string;
1907
+ /**
1908
+ * Raw chunk size in bytes. Priority: this value > store.maxBlobBytes > 256 KB.
1909
+ */
1910
+ chunkSize?: number;
1911
+ /**
1912
+ * Whether to gzip-compress bytes before encrypting. Default: `true`.
1913
+ * Auto-set to `false` for pre-compressed MIME types (JPEG, PNG, ZIP, etc.).
1914
+ */
1915
+ compress?: boolean;
1916
+ /** User ID to record as `uploadedBy`. Defaults to the Noydb session user. */
1917
+ uploadedBy?: string;
1918
+ /**
1919
+ * User-visible filename to store on the slot. Defaults to the slot name.
1920
+ * Differs from the slot name when the caller wants a display/download name
1921
+ * (e.g. slot `attachment` holding `invoice-2024.pdf`); this is the value
1922
+ * that the L1 lexical index tokenizes for blob fields.
1923
+ */
1924
+ filename?: string;
1925
+ }
1926
+ /** Options for `BlobSet.response()` and `BlobSet.responseVersion()`. */
1927
+ export interface BlobResponseOptions {
1928
+ /**
1929
+ * When `true`, sets `Content-Disposition: inline; filename="..."` so
1930
+ * the browser renders the file in the tab. Default (`false`) sets
1931
+ * `attachment; filename="..."` which triggers a download.
1932
+ */
1933
+ inline?: boolean;
1934
+ /** Override the filename in the Content-Disposition header. */
1935
+ filename?: string;
1936
+ }
1937
+ export type StoreAuthKind = 'none' | 'filesystem' | 'api-key' | 'iam' | 'oauth' | 'kerberos' | 'browser-origin';
1938
+ export interface StoreAuth {
1939
+ kind: StoreAuthKind | StoreAuthKind[];
1940
+ required: boolean;
1941
+ flow: 'static' | 'oauth' | 'kerberos' | 'implicit';
1942
+ }
1943
+ /** Vendor-neutral short-lived store credentials. `kind` is the credential-PAYLOAD
1944
+ * discriminator — orthogonal to StoreAuthKind ('iam'|'api-key'|…), which is unchanged. */
1945
+ export type StoreCredentials = {
1946
+ readonly kind: 'aws';
1947
+ readonly accessKeyId: string;
1948
+ readonly secretAccessKey: string;
1949
+ readonly sessionToken?: string;
1950
+ readonly expiresAt?: string;
1951
+ } | {
1952
+ readonly kind: 'token';
1953
+ readonly token: string;
1954
+ readonly expiresAt?: string;
1955
+ };
1956
+ /** Refresh hook a store calls when it has no credentials or they are near expiry. */
1957
+ export type StoreCredentialSource = () => Promise<StoreCredentials>;
1958
+ /**
1959
+ * The store's authoritative clock as a bounded-uncertainty interval
1960
+ * (Spanner TrueTime model). True time is provably within [earliest, latest];
1961
+ * `latest - earliest` is the clock-uncertainty bound ε. Used by deferred
1962
+ * numbering to order records by store-commit-time and to commit-wait. Never
1963
+ * the client wall clock.
1964
+ */
1965
+ export interface StoreTime {
1966
+ readonly earliest: number;
1967
+ readonly latest: number;
1968
+ }
1969
+ export interface StoreCapabilities {
1970
+ /**
1971
+ * true — the store's expectedVersion check and write are atomic at the
1972
+ * storage layer. Two concurrent puts with the same expectedVersion will
1973
+ * produce exactly one success and one ConflictError.
1974
+ * false — check and write are separate operations with a race window.
1975
+ */
1976
+ casAtomic: boolean;
1977
+ /**
1978
+ * true — the store exposes an authoritative {@link NoydbStore.getStoreTime}
1979
+ * clock and records are ordered by store-commit-time. Required for
1980
+ * `withDeferredNumbering`. Absent/false — the store cannot back deferred
1981
+ * numbering (use CAS `sequence().next()` or per-series).
1982
+ */
1983
+ serverWriteTime?: boolean;
1984
+ /**
1985
+ * Advisory geographic region this store serves (e.g. `'eu'`, `'us'`).
1986
+ * Purely declarative — no behavior change for stores that omit it. The
1987
+ * federation data-residency guard compares this against a
1988
+ * `sharding.regionOf(record)` to refuse non-compliant shard placement.
1989
+ */
1990
+ region?: string;
1991
+ auth: StoreAuth;
1992
+ /**
1993
+ * true — the store implements {@link NoydbStore.tx} and commits
1994
+ * every op atomically at the storage layer. The hub's
1995
+ * `db.transaction(fn)` will delegate to `tx(ops)` and surface a
1996
+ * single pass/fail outcome. false (or absent) — no native
1997
+ * multi-record atomicity; the hub falls back to per-record OCC
1998
+ * with best-effort unwind on partial failure.
1999
+ */
2000
+ txAtomic?: boolean;
2001
+ /**
2002
+ * Maximum raw bytes per blob chunk record.
2003
+ * `undefined` — no limit (S3, file, IDB); blob stored as single chunk.
2004
+ * `256 * 1024` — DynamoDB (400 KB item limit minus envelope overhead).
2005
+ * `5 * 1024 * 1024` — localStorage quota safety.
2006
+ */
2007
+ maxBlobBytes?: number;
2008
+ /**
2009
+ * true — the store is a tiered router (`routeStore`) with a cold route,
2010
+ * so `compact(vault, { before })` can relocate records hot → cold and
2011
+ * reads fall through to cold. `vault.archivePeriod()` requires this.
2012
+ */
2013
+ coldArchival?: boolean;
2014
+ }
2015
+ export interface NoydbOptions {
2016
+ /** The ciphertext store. Optional — defaults to the built-in `memoryStore()` (non-persistent). */
2017
+ readonly store?: NoydbStore;
2018
+ /**
2019
+ * tree-shake seam — optional blob strategy. Pass `withBlobs()`
2020
+ * from `@noy-db/hub/blobs` to enable `collection.blob(id)` storage.
2021
+ * When omitted, hub's blob machinery stays out of the bundle (ESM
2022
+ * tree-shaking) and `collection.blob(id)` throws with a pointer at
2023
+ * the subpath. `BlobStrategy` is `@internal` — users only construct
2024
+ * it via the subpath factory.
2025
+ *
2026
+ * @internal
2027
+ */
2028
+ readonly blobStrategy?: BlobStrategy;
2029
+ /**
2030
+ * Cold-storage archival target. `withArchive({ store })` designates a
2031
+ * second store that holds archived record envelopes. Enables
2032
+ * `vault.archive()` / `vault.restore()` / `vault.listArchived()`.
2033
+ */
2034
+ readonly archiveStrategy?: ArchiveStrategy;
2035
+ /**
2036
+ * tree-shake seam — optional indexing strategy. Pass
2037
+ * `withIndexing()` from `@noy-db/hub/indexing` to enable eager-mode
2038
+ * `==/in` fast-paths, lazy-mode `.lazyQuery()`, rebuild/reconcile,
2039
+ * and auto-reconcile. When omitted, indexing code never reaches the
2040
+ * bundle; `.lazyQuery()` throws with a pointer at the subpath, and
2041
+ * eager-mode collections fall back to linear scans regardless of
2042
+ * `indexes: [...]` declarations. `IndexStrategy` is `@internal` —
2043
+ * users only construct it via the subpath factory.
2044
+ *
2045
+ * @internal
2046
+ */
2047
+ readonly indexStrategy?: IndexStrategy;
2048
+ /**
2049
+ * tree-shake seam — optional aggregate strategy. Pass
2050
+ * `withAggregate()` from `@noy-db/hub/aggregate` to enable
2051
+ * `.aggregate()` and `.groupBy()` on Query. When omitted, those
2052
+ * methods throw with a pointer at the subpath; the ~886 LOC of
2053
+ * Aggregation + GroupedQuery machinery never reaches the bundle.
2054
+ * Streaming `scan().aggregate()` works independently of this
2055
+ * strategy — it doesn't use the `Aggregation` class.
2056
+ *
2057
+ * @internal
2058
+ */
2059
+ readonly aggregateStrategy?: AggregateStrategy;
2060
+ /**
2061
+ * tree-shake seam — optional CRDT strategy. Required when
2062
+ * any collection is declared with `crdt: 'lww-map' | 'rga' | 'yjs'`;
2063
+ * otherwise the first put/sync-merge hitting the CRDT path throws.
2064
+ * When omitted, ~221 LOC of LWW-Map / RGA / merge helpers never
2065
+ * reach the bundle.
2066
+ *
2067
+ * @internal
2068
+ */
2069
+ readonly crdtStrategy?: CrdtStrategy;
2070
+ /**
2071
+ * tree-shake seam — strategy for the collection-level hierarchical-tier
2072
+ * operations. Pass `withTiers()` from `@noy-db/hub/tiers` to enable
2073
+ * `putAtTier`/`getAtTier`/`listAtTier`/`elevate`/`demote` on collections
2074
+ * declared with `{ tiers: [...] }`. When omitted, all five throw
2075
+ * `TiersNotEnabledError` and the tier read/write/re-key engine never
2076
+ * reaches the bundle.
2077
+ *
2078
+ * @internal
2079
+ */
2080
+ readonly tiersStrategy?: TiersStrategy;
2081
+ /**
2082
+ * tree-shake seam — optional consent-audit strategy. Pass
2083
+ * `withConsent()` from `@noy-db/hub/consent` to enable per-op audit
2084
+ * writes into `_consent_audit` when a consent scope is active.
2085
+ * When omitted, `vault.consentAudit()` returns `[]` and writes are
2086
+ * no-ops; the consent module's ~194 LOC never reaches the bundle.
2087
+ *
2088
+ * @internal
2089
+ */
2090
+ readonly consentStrategy?: ConsentStrategy;
2091
+ /**
2092
+ * tree-shake seam — optional periods strategy. Pass
2093
+ * `withPeriods()` from `@noy-db/hub/periods` to enable
2094
+ * `vault.closePeriod()` / `.openPeriod()` / write-guard on closed
2095
+ * periods. When omitted, `vault.listPeriods()` returns `[]` and
2096
+ * the write-guard is a no-op; the ~363 LOC of period validation +
2097
+ * ledger appending stay out of the bundle.
2098
+ *
2099
+ * @internal
2100
+ */
2101
+ readonly periodsStrategy?: PeriodsStrategy;
2102
+ /**
2103
+ * tree-shake seam — optional VaultFrame strategy. Pass
2104
+ * `withShadow()` from `@noy-db/hub/shadow` to enable
2105
+ * `vault.frame()`. Without it, calling `vault.frame()` throws.
2106
+ *
2107
+ * @internal
2108
+ */
2109
+ readonly shadowStrategy?: ShadowStrategy;
2110
+ /**
2111
+ * tree-shake seam — optional multi-record transactions. Pass
2112
+ * `withTransactions()` from `@noy-db/hub/tx` to enable
2113
+ * `db.transaction(fn)`. Without it, calling the method throws.
2114
+ *
2115
+ * @internal
2116
+ */
2117
+ readonly txStrategy?: TxStrategy;
2118
+ /**
2119
+ * tree-shake seam — optional history + ledger + time-machine.
2120
+ * Pass `withHistory()` from `@noy-db/hub/history` to enable
2121
+ * per-record version snapshots, the hash-chained audit ledger, JSON
2122
+ * Patch deltas, `vault.ledger()`, `vault.at()`, and the
2123
+ * `collection.history()` / `getVersion()` / `revert()` / `diff()` /
2124
+ * `clearHistory()` / `pruneRecordHistory()` read APIs. When omitted,
2125
+ * snapshots/prune/clear are silent no-ops, the read APIs throw with
2126
+ * a pointer at the subpath, and ~1,880 LOC stay out of the bundle.
2127
+ *
2128
+ * @internal
2129
+ */
2130
+ readonly historyStrategy?: HistoryStrategy;
2131
+ /**
2132
+ * GDPR right-to-erasure. Pass `withForgetCascade({ subjects })`
2133
+ * from `@noy-db/hub/forget` to declare which collections carry erasable
2134
+ * subject data and the record field naming the data subject. Enables
2135
+ * `vault.forget(subjectId)` crypto-shred (rewrite-to-tombstone of the live
2136
+ * record + every history version → body permanently undecryptable, single
2137
+ * `op:'forget'` ledger entry, chain still verifies). Each declared
2138
+ * collection is forced to `perRecordKeys: true`. When omitted (the
2139
+ * `NO_FORGET` default), `vault.forget()` throws
2140
+ * `ForgetStrategyNotConfiguredError` and no subject-index write hooks run.
2141
+ * Requires `historyStrategy` (the ledger) for the erasure-proof entry.
2142
+ */
2143
+ readonly forgetStrategy?: ForgetStrategy;
2144
+ /**
2145
+ * tree-shake seam — optional i18n strategy. Pass `withI18n()`
2146
+ * from `@noy-db/hub/i18n` to enable `i18nText`/`dictKey` field
2147
+ * resolution on reads, `i18nText` validation on writes, and
2148
+ * `vault.dictionary(name)`. When omitted, locale resolution is the
2149
+ * identity (raw values returned), the validators throw with a
2150
+ * pointer to the subpath, and ~854 LOC of dictionary + locale
2151
+ * machinery stay out of the bundle.
2152
+ *
2153
+ * @internal
2154
+ */
2155
+ readonly i18nStrategy?: I18nStrategy;
2156
+ /**
2157
+ * tree-shake seam — optional session-policy strategy. Pass
2158
+ * `withSession()` from `@noy-db/hub/session` to enable
2159
+ * `sessionPolicy` validation, `PolicyEnforcer` lifecycle (idle /
2160
+ * absolute timeouts, lockOnBackground), and global session-token
2161
+ * revocation. When omitted, setting `sessionPolicy` throws at
2162
+ * `createNoydb()` time, and ~495 LOC of policy + token machinery
2163
+ * stay out of the bundle.
2164
+ *
2165
+ * @internal
2166
+ */
2167
+ readonly sessionStrategy?: SessionStrategy;
2168
+ /**
2169
+ * tree-shake seam — optional sync engine + presence strategy.
2170
+ * Pass `withSync()` from `@noy-db/hub/sync` to enable
2171
+ * `db.push()` / `pull()` / replication, `db.transaction(vault)`
2172
+ * for sync-aware transactions, and `collection.presence()`. When
2173
+ * omitted, configuring `sync` / calling these surfaces throws with
2174
+ * a pointer at the subpath, and ~856 LOC of replication + presence
2175
+ * machinery stay out of the bundle. Keyring stays core; grant/
2176
+ * revoke/magic-link/delegation tree-shake via direct imports.
2177
+ *
2178
+ * @internal
2179
+ */
2180
+ readonly syncStrategy?: SyncStrategy;
2181
+ /**
2182
+ * Tree-shake seam — optional snapshot-lifecycle service. Pass
2183
+ * `withSnapshots({ store })` from `@noy-db/hub/snapshots` to enable
2184
+ * `db.snapshot()`, `db.listSnapshots()`, and `db.restoreSnapshot()`.
2185
+ * When omitted, all three methods throw with a pointer at the subpath.
2186
+ */
2187
+ readonly snapshotStrategy?: SnapshotStrategy;
2188
+ /**
2189
+ * Tree-shake seam — optional attestation capability. Pass
2190
+ * `withAttestation()` from `@noy-db/hub/attestation` to enable
2191
+ * `vault.issueAttestation()`, `vault.getDocumentSigningPublicKey()`,
2192
+ * `vault.revokeAttestation()`, `vault.unrevokeAttestation()`,
2193
+ * `vault.getRevokedDocIds()`, and `vault.publishRevocationList()`. When
2194
+ * omitted, all six throw `AttestationNotEnabledError` and the issue/revoke/
2195
+ * signer engines are tree-shaken out.
2196
+ */
2197
+ readonly attestationStrategy?: AttestationStrategy;
2198
+ /**
2199
+ * Tree-shake seam — optional classified-field capability. Pass
2200
+ * `withClassified()` from `@noy-db/hub/classified` to enable
2201
+ * `collection.reveal()`. When omitted, `reveal()` throws
2202
+ * `ClassifiedNotEnabledError` and the reveal engine is tree-shaken out.
2203
+ */
2204
+ readonly classifiedStrategy?: ClassifiedStrategy;
2205
+ /**
2206
+ * Tree-shake seam — optional sealed-record (grantor-side) capability. Pass
2207
+ * `withSealedRecord()` from `@noy-db/hub/sealed-record` to enable
2208
+ * `vault.sealRecordToHost()`, `vault.revokeSealedRecord()`, and
2209
+ * `vault.rotateRecordCek()`. When omitted, all three throw
2210
+ * `SealedRecordNotEnabledError` and the record-keys grantor engine is reached
2211
+ * only via opt-in. The host-side `openSealedRecord` opener stays ungated.
2212
+ */
2213
+ readonly sealedRecordStrategy?: SealedRecordStrategy;
2214
+ /**
2215
+ * Tree-shake seam — optional portability (data-sovereignty) capability. Pass
2216
+ * `withPortability()` from `@noy-db/hub/portability` to enable the
2217
+ * `vault.user.*` export/withdrawal surface (`exportMyAccessibleData`,
2218
+ * `unilateralWithdrawal`, `requestWithdrawal`, `listWithdrawalRequests`,
2219
+ * `approveWithdrawal`, `rejectWithdrawal`). When omitted, all six throw
2220
+ * `PortabilityNotEnabledError` and the export/withdraw/request engines are
2221
+ * reached only via opt-in.
2222
+ */
2223
+ readonly portabilityStrategy?: PortabilityStrategy;
2224
+ /**
2225
+ * Tree-shake seam — optional atomic-sequence capability. Pass
2226
+ * `withSequence()` from `@noy-db/hub` to enable `vault.sequence(name)`
2227
+ * (`.next()` / `.peek()` / `.seedTo()`). When omitted, `vault.sequence()`
2228
+ * throws `SequenceNotEnabledError` and the CAS `SequenceStore` engine is
2229
+ * reached only via opt-in. Deferred-numbering series (`numbering:
2230
+ * [withDeferredNumbering(...)]`) are a separate capability and stay live.
2231
+ */
2232
+ readonly sequenceStrategy?: SequenceStrategy;
2233
+ /**
2234
+ * Tree-shake seam — optional sovereign-custody (FR-6) capability. Pass
2235
+ * `withCustody()` from `@noy-db/hub` to enable minting / removing a
2236
+ * `custodian` (`db.grantCustodian` / `db.revokeCustodian` and the
2237
+ * `vault.custody.*` facade) plus the `vault.custody.liberate()` ceremony.
2238
+ * When omitted, those throw `CustodyNotEnabledError` and the liberate engine
2239
+ * is reached only via opt-in. The lower-level `liberateVault` free function
2240
+ * stays ungated (it has no createNoydb instance to gate against).
2241
+ */
2242
+ readonly custodyStrategy?: CustodyStrategy;
2243
+ /**
2244
+ * Tree-shake seam — optional multi-user team capability (#267
2245
+ * keyring-grant → team split). Pass `withTeam()` from `@noy-db/hub/team`
2246
+ * to enable `db.grant` / `db.revoke` / `db.rotate`. When omitted, those
2247
+ * throw `TeamNotEnabledError` and the keyring grant/revoke/rotate engines
2248
+ * are reached only via opt-in — the always-on floor is single-user.
2249
+ * Single-user primitives (owner keyring, unlock, `listUsers`,
2250
+ * `updateUser`, passphrase rotate/recover) stay ungated, as does the
2251
+ * `createDeedOwner` free function (no createNoydb instance to gate
2252
+ * against).
2253
+ */
2254
+ readonly teamStrategy?: TeamStrategy;
2255
+ /**
2256
+ * Tree-shake seam — optional credential-broker capability (#479). Pass
2257
+ * `brokerStrategy: withBroker(config)` from `@noy-db/hub/broker` to
2258
+ * enable `vault.broker()` (`.enroll()` / `.rotate()` /
2259
+ * `.credentialSource(profile?)`). When omitted, `vault.broker()` throws
2260
+ * `BrokerNotEnabledError` and the seed lifecycle + network/cache engine
2261
+ * are reached only via opt-in.
2262
+ */
2263
+ readonly brokerStrategy?: BrokerStrategy;
2264
+ /**
2265
+ * Opt-in seam — the `lazy` service (#267). Pass `withLazy()` from
2266
+ * `@noy-db/hub/lazy` to explicitly enable lazy mode's bounded-LRU
2267
+ * working set for collections declared with `prefetch: false`. When
2268
+ * omitted, `prefetch: false` still works via the deprecated implicit
2269
+ * back-compat path (identical behavior, one-time deprecation warn);
2270
+ * the implicit path will be removed at 1.0.
2271
+ */
2272
+ readonly lazyStrategy?: LazyStrategy;
2273
+ /**
2274
+ * Tree-shake seam — optional search / retrieval capability. Pass
2275
+ * `withSearch()` from `@noy-db/hub` to enable a collection's `search`
2276
+ * / `retrieve` / `similarTo` / `warmIndex` / `flushIndex` methods and the
2277
+ * put()-time embedding-vector compute for collections declaring `embeddings`.
2278
+ * When omitted, those throw `SearchNotEnabledError` and the search/retrieval
2279
+ * engine is reached only via opt-in. Embedding compute is paired with search
2280
+ * (a vector no gated retrieval could read would be dead weight).
2281
+ */
2282
+ readonly searchStrategy?: SearchStrategy;
2283
+ /**
2284
+ * Tree-shake seam — optional cargo (partition extraction) capability
2285
+ * (FR-6/FR-7). Pass `withCargo()` from `@noy-db/hub/cargo` to enable the
2286
+ * source-side `extractPartition(vault, …)` free function. When omitted, it
2287
+ * throws `CargoNotEnabledError` and the extraction crypto is reached only via
2288
+ * opt-in. The recipient-side `adoptPartition` / `decryptExtractedPartition`
2289
+ * free functions — and `diffVault` (shared import/merge infra) — operate
2290
+ * without a gated source instance and stay ungated.
2291
+ */
2292
+ readonly cargoStrategy?: CargoStrategy;
2293
+ /**
2294
+ * Optional guard strategies — collection-level write guards. Each
2295
+ * handle is the output of `withGuard()` from `@noy-db/hub/guards`.
2296
+ * Multiple guards per collection are allowed; they are dispatched
2297
+ * in registration order on `collection.put()`.
2298
+ */
2299
+ readonly guardStrategies?: ReadonlyArray<GuardStrategyHandleAny>;
2300
+ /**
2301
+ * Deferred-numbering series declared via `withDeferredNumbering(...)`.
2302
+ * `vault.sequence(series).next({ for })` then assigns gap-free serials at a
2303
+ * numbering pass (`vault.runNumberingPass(series)`) instead of via CAS.
2304
+ */
2305
+ readonly numbering?: ReadonlyArray<DeferredNumberingConfig>;
2306
+ /**
2307
+ * Optional derivation strategies — source-to-output projections that
2308
+ * fire on `collection.put()`. Each handle is the output of
2309
+ * `withDerivation()` from `@noy-db/hub/derivations`. The vault
2310
+ * validates the derivation graph for cycles on `openVault`; a cyclic
2311
+ * graph throws `DerivationCycleError`.
2312
+ */
2313
+ readonly derivationStrategies?: ReadonlyArray<DerivationStrategyHandle>;
2314
+ /**
2315
+ * Optional materialized-view strategies.
2316
+ * Each handle returned by `withMaterializedView()` from
2317
+ * `@noy-db/hub/materialized-views`. The vault runs unified cycle
2318
+ * detection across the MV + derivation graphs at `openVault`; a
2319
+ * cyclic graph throws `MaterializedViewCycleError`.
2320
+ */
2321
+ readonly materializedViewStrategies?: ReadonlyArray<MaterializedViewStrategyHandle>;
2322
+ /**
2323
+ * Optional overlay strategies. Each handle returned by
2324
+ * `withOverlayedView()` from `@noy-db/hub/overlay-views`. The vault
2325
+ * validates name uniqueness + base concreteness + overlay
2326
+ * availability at `openVault`; a clash throws one of the
2327
+ * `Overlay*Error` family.
2328
+ */
2329
+ readonly overlayedViewStrategies?: ReadonlyArray<OverlayedViewStrategyHandle>;
2330
+ /** Optional remote store(s) for sync. Accepts a single store, a SyncTarget, or an array. */
2331
+ readonly sync?: NoydbStore | SyncTarget | SyncTarget[];
2332
+ /** User identifier. */
2333
+ readonly user: string;
2334
+ /** Passphrase for key derivation. Required unless encrypt is false or `getKeyring` is provided. */
2335
+ readonly secret?: string;
2336
+ /**
2337
+ * Optional callback that returns an unlocked keyring for a given vault.
2338
+ * Use this to plug in WebAuthn / OIDC / Shamir / any unlock path that
2339
+ * produces an `UnlockedKeyring` outside the passphrase model.
2340
+ *
2341
+ * When set, `secret` MUST NOT also be set — `createNoydb` throws if both
2342
+ * are supplied. When neither is set (and `encrypt !== false`), `createNoydb`
2343
+ * also throws.
2344
+ *
2345
+ * The callback is called lazily, on the first operation that needs the
2346
+ * keyring for a given vault. Noydb caches the returned keyring per-vault
2347
+ * for the lifetime of the instance, so the callback is invoked at most
2348
+ * once per `(instance, vault)` pair (assuming the callback resolves
2349
+ * successfully). If the callback rejects, the rejection surfaces from the
2350
+ * first vault operation that triggered the unlock; subsequent operations
2351
+ * will retry the callback.
2352
+ *
2353
+ * @example
2354
+ * ```ts
2355
+ * import { createNoydb } from '@noy-db/hub'
2356
+ * import { unlockWebAuthn } from '@noy-db/on-webauthn'
2357
+ *
2358
+ * const enrollment = await loadEnrollment()
2359
+ * const db = await createNoydb({
2360
+ * store,
2361
+ * user: 'alice',
2362
+ * getKeyring: (vault) => unlockWebAuthn(enrollment),
2363
+ * })
2364
+ * ```
2365
+ *
2366
+ * Note: this callback is responsible for both the "open existing vault"
2367
+ * and the "create new vault" cases. Unlike the passphrase path, there is
2368
+ * no automatic `NoAccessError` → `createOwnerKeyring` fallback, because
2369
+ * the callback owner has the UI context to decide which path to run.
2370
+ * For first-time bootstrap, use a passphrase or recovery code, enroll
2371
+ * WebAuthn from the unlocked keyring, then swap to `getKeyring` on
2372
+ * subsequent sessions.
2373
+ */
2374
+ readonly getKeyring?: (vault: string) => Promise<UnlockedKeyring>;
2375
+ /**
2376
+ * Passphrase mode. Default `'standard'`.
2377
+ *
2378
+ * - `'standard'` — the legacy flow. `secret` supplies the
2379
+ * plaintext passphrase, the user knows it, and the policy gate
2380
+ * `rotate-passphrase` is enabled.
2381
+ * - `'managed'` — rubber-hose-resistant mode. Hub generates a
2382
+ * 256-bit random passphrase at first open and seals it under
2383
+ * the provided `sealingKey`. The user never sees or types the
2384
+ * passphrase, defeating the $5-wrench attack. Mutually
2385
+ * exclusive with `secret` and `getKeyring`.
2386
+ *
2387
+ * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/session-tiers.md → Managed-passphrase mode
2388
+ */
2389
+ readonly passphraseMode?: 'standard' | 'managed';
2390
+ /**
2391
+ * Provider that seals/unseals the auto-generated managed-mode
2392
+ * passphrase. Required when `passphraseMode === 'managed'`; ignored
2393
+ * otherwise. Implementations live in per-platform packages
2394
+ * (`@noy-db/seal-macos-keychain`, `@noy-db/seal-wincred`,
2395
+ * `@noy-db/seal-libsecret`, `@noy-db/seal-aws-kms`, …).
2396
+ */
2397
+ readonly sealingKey?: SealingKeyProvider;
2398
+ /** Required to use `profile: 'shamir'` recovery. Pass
2399
+ * `shamirRecoveryProvider()` from `@noy-db/on-shamir`. */
2400
+ readonly shamirRecovery?: ShamirRecoveryProvider;
2401
+ /** Auth method. Default: 'passphrase'. */
2402
+ readonly auth?: 'passphrase' | 'biometric';
2403
+ /** Enable encryption. Default: true. */
2404
+ readonly encrypt?: boolean;
2405
+ /**
2406
+ * Debug-only: lay plaintext records out as directly-inspectable store
2407
+ * objects (record fields inlined beside envelope metadata, `_debug: 1`) so
2408
+ * native store tooling can read them without unwrapping `_data`. Requires
2409
+ * `encrypt: false` — combining with encryption throws `DebugPlaintextError`
2410
+ * at construction. NEVER enable for production or client data.
2411
+ */
2412
+ readonly debugPlaintext?: boolean;
2413
+ /**
2414
+ * Object projection for direct-serve / external blob fields (`as-*`, e.g.
2415
+ * `@noy-db/as-aws-s3`). Blob fields declared `external` route their RAW bytes
2416
+ * to this projection as a single native object (servable from S3/CDN) instead
2417
+ * of the encrypted-chunk path; the encrypted record/slot stays the catalog.
2418
+ * Sees plaintext bytes — outside the zero-knowledge guarantee.
2419
+ */
2420
+ readonly objectStore?: ObjectProjection;
2421
+ /** Conflict resolution strategy. Default: 'version'. */
2422
+ readonly conflict?: ConflictStrategy;
2423
+ /**
2424
+ * Sync scheduling policy. Controls when push/pull fire.
2425
+ * Default inferred from store category: per-record → `on-change`,
2426
+ * bundle → `debounce 30s`.
2427
+ */
2428
+ readonly syncPolicy?: SyncPolicy;
2429
+ /**
2430
+ * @deprecated Use `syncPolicy` instead. Kept for backward compatibility.
2431
+ * When both are supplied, `syncPolicy` takes precedence.
2432
+ */
2433
+ readonly autoSync?: boolean;
2434
+ /**
2435
+ * @deprecated Use `syncPolicy` instead. Kept for backward compatibility.
2436
+ */
2437
+ readonly syncInterval?: number;
2438
+ /**
2439
+ * Session timeout in ms. Clears keys after inactivity. Default: none.
2440
+ * @deprecated Use `sessionPolicy.idleTimeoutMs` instead. This field is
2441
+ * still honored for backwards compatibility but `sessionPolicy` takes
2442
+ * precedence when both are supplied.
2443
+ */
2444
+ readonly sessionTimeout?: number;
2445
+ /**
2446
+ * Session policy controlling lifetime, re-auth requirements, and
2447
+ * background-lock behavior. When supplied, replaces the
2448
+ * legacy `sessionTimeout` field.
2449
+ */
2450
+ readonly sessionPolicy?: SessionPolicy;
2451
+ /**
2452
+ * Validate passphrase strength against the phrase format
2453
+ * on first-time keyring creation. When
2454
+ * `true`, weak phrases throw {@link WeakPassphraseError} from
2455
+ * `createNoydb()` / `db.rotatePassphrase()`. Default: `false` for
2456
+ * back-compat; planned to flip to `true` in a future major release.
2457
+ */
2458
+ readonly validatePassphrase?: boolean;
2459
+ /**
2460
+ * Vault-level policy gate document. When present, the hub
2461
+ * persists the merged policy at `_meta/policy` on first-time vault
2462
+ * creation and gates sensitive operations (`db.rotatePassphrase`,
2463
+ * `db.export*`, …) against it. Omitted ⇒ the engine uses
2464
+ * {@link PERSONAL_POLICY}. Use {@link STRICT_POLICY} for regulated
2465
+ * deployments.
2466
+ *
2467
+ * The on-disk document is the source of truth — the policy field
2468
+ * is only honored at vault creation; subsequent runs read from
2469
+ * `_meta/policy`. Use `db.updatePolicy()` to change it deliberately.
2470
+ *
2471
+ * Imported from `@noy-db/hub` as a type-only reference; the runtime
2472
+ * import lives in `policy/index.ts`.
2473
+ */
2474
+ readonly policy?: VaultPolicy;
2475
+ /**
2476
+ * Mandatory recovery profile enrollment. Vaults with
2477
+ * `recover-passphrase` enabled MUST register at least one profile
2478
+ * before being production-ready, otherwise `createNoydb()` throws
2479
+ * {@link RecoveryNotEnrolledError}. Set
2480
+ * `policy.gates['recover-passphrase'].enabled = false` to
2481
+ * deliberately opt out of recovery (passphrase loss = data loss).
2482
+ *
2483
+ * The `'paper'` profile is supported end-to-end. Other
2484
+ * profiles ship the API shape and throw
2485
+ * {@link RecoveryProfileNotImplementedError} during use.
2486
+ */
2487
+ readonly recovery?: ReadonlyArray<RecoveryEnrollment>;
2488
+ /**
2489
+ * When `true`, `createNoydb` rejects vaults with no recovery
2490
+ * entries persisted (per the spec's mandatory-enrollment
2491
+ * requirement). Default `false` for back-compat; planned to
2492
+ * flip to `true` in a future major release. Apps in regulated
2493
+ * environments should turn this on now.
2494
+ */
2495
+ readonly requireRecovery?: boolean;
2496
+ /**
2497
+ * What to do when `openVault` finds an existing keyring in the store that
2498
+ * cannot be decrypted with the supplied credentials (`InvalidKeyError`).
2499
+ *
2500
+ * - `'error'` (default) — propagate the error. The app must prompt the user
2501
+ * to supply the correct credentials or clear both the data and auth stores.
2502
+ * - `'reset'` — delete the stale keyring and re-initialise the vault from
2503
+ * scratch using the current credentials. Use this when the data store can
2504
+ * become detached from the auth store (e.g. the user cleared the IndexedDB
2505
+ * data records but not the keyring row, or a WebAuthn credential was rotated).
2506
+ * **All previously encrypted data is unrecoverable after a reset.**
2507
+ *
2508
+ * Only applies to the passphrase (`secret`) path. When `getKeyring` is used,
2509
+ * the callback is responsible for handling stale-keyring detection itself.
2510
+ */
2511
+ readonly onInvalidKey?: 'error' | 'reset';
2512
+ /**
2513
+ * Enable the public envelope service (`https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md`).
2514
+ * Pass `true` for the default schema (every standard field, 256 KB
2515
+ * icon cap, 200-char text cap), or a `PublicEnvelopeSchema` to
2516
+ * narrow what the owner can set. Off by default — vaults written
2517
+ * by hubs without this option carry no envelope, full stop.
2518
+ */
2519
+ readonly publicEnvelope?: true | PublicEnvelopeSchema;
2520
+ /** Audit history configuration. */
2521
+ readonly history?: HistoryConfig;
2522
+ /**
2523
+ * Consumer-supplied translation function for `i18nText` fields with
2524
+ * `autoTranslate: true`.
2525
+ *
2526
+ * ⚠ **`plaintextTranslator` receives unencrypted text.** Configuring
2527
+ * this hook causes plaintext to leave noy-db's zero-knowledge boundary
2528
+ * over whatever channel the consumer's implementation uses. noy-db ships
2529
+ * no built-in translator and adds no translator SDKs as dependencies.
2530
+ * The consumer chooses and owns the data policy of the external service.
2531
+ *
2532
+ * Per-field opt-in via `autoTranslate: true` on `i18nText()`. Calling
2533
+ * `put()` on a collection with `autoTranslate: true` fields while this
2534
+ * option is absent throws `TranslatorNotConfiguredError`.
2535
+ *
2536
+ * See `NOYDB_SPEC.md § Zero-Knowledge Storage` for the invariant text.
2537
+ */
2538
+ readonly plaintextTranslator?: PlaintextTranslatorFn;
2539
+ /**
2540
+ * Human-readable name for the translator, recorded in the in-process
2541
+ * audit log (e.g. `'deepl-pro-with-dpa'`, `'self-hosted-llama-7b'`).
2542
+ * Defaults to `'anonymous'` when not supplied.
2543
+ */
2544
+ readonly plaintextTranslatorName?: string;
2545
+ /**
2546
+ * Drain-barrier coordination transport for the schema fence.
2547
+ * When omitted, the kernel uses a {@link CoordinationProvider} backed by the
2548
+ * primary store (`StoreCoordinationProvider`), reproducing today's
2549
+ * store-polling fence behavior byte-for-byte. `@noy-db/by-tabs` /
2550
+ * `@noy-db/by-peer` inject a real-time push transport here; an external
2551
+ * orchestrator (`@klum-db/lobby`) drives it through the `Noydb` handle.
2552
+ *
2553
+ * @internal
2554
+ */
2555
+ readonly coordinationStrategy?: CoordinationProvider;
2556
+ /**
2557
+ * Pre-resolved factory for the `vault.user` per-principal user-envelope
2558
+ * API. `createNoydb()` always resolves this itself (dynamically
2559
+ * importing `with-party/directory/user-envelope/api.js`) before
2560
+ * constructing `Noydb` — mirrors the {@link coordinationStrategy}
2561
+ * pre-resolve above. There is no supported way to override it; it exists
2562
+ * as an options-bag field only so `createNoydb()` can thread the
2563
+ * pre-resolved value into the constructor without a second parameter.
2564
+ *
2565
+ * @internal
2566
+ */
2567
+ readonly userApiFactory?: UserApiFactory;
2568
+ /**
2569
+ * Pre-resolved factory for the `NoydbPolicy` service (vault-policy
2570
+ * read/update/bootstrap + session-policy enforcer wiring).
2571
+ * `createNoydb()` always resolves this itself (dynamically importing
2572
+ * `with-party/policy/index.js`) before constructing `Noydb` — mirrors the
2573
+ * {@link coordinationStrategy} / {@link userApiFactory} pre-resolves
2574
+ * above. There is no supported way to override it.
2575
+ *
2576
+ * @internal
2577
+ */
2578
+ readonly policyFactory?: NoydbPolicyFactory;
2579
+ /**
2580
+ * Pre-resolved policy-gate engine function (`checkGate`).
2581
+ * `createNoydb()` always resolves this itself (dynamically importing
2582
+ * `with-party/policy/index.js`) before constructing `Noydb` — same
2583
+ * pre-resolve pattern as {@link policyFactory}.
2584
+ *
2585
+ * @internal
2586
+ */
2587
+ readonly policyCheckGateFn?: PolicyCheckGateFn;
2588
+ /**
2589
+ * Stable id for the session that owns this instance's writers (one user's
2590
+ * writers across vaults). Tags every {@link WriterPresence} the fence
2591
+ * watcher reports. Defaults to a fresh ULID per `Noydb` instance.
2592
+ *
2593
+ * @internal
2594
+ */
2595
+ readonly sessionId?: string;
2596
+ }
2597
+ /** History configuration. */
2598
+ export interface HistoryConfig {
2599
+ /** Enable history tracking. Default: true. */
2600
+ readonly enabled?: boolean;
2601
+ /** Maximum history entries per record. Oldest pruned on overflow. Default: unlimited. */
2602
+ readonly maxVersions?: number;
2603
+ /**
2604
+ * Participate in the vault-wide hash-chained tamper ledger. Default:
2605
+ * `true` (every write of this collection appends a ledger entry when
2606
+ * `withHistory()` is active). Set `false` to exclude this collection's
2607
+ * writes from the chain — its puts/deletes leave no ledger entry,
2608
+ * confining tamper-evidence to the collections where it carries weight.
2609
+ * Independent of `enabled`, which gates per-record snapshots. Has no
2610
+ * effect when `withHistory()` is not active (there is no ledger).
2611
+ */
2612
+ readonly ledger?: boolean;
2613
+ }
2614
+ /** Options for querying history. */
2615
+ export interface HistoryOptions {
2616
+ /** Start date (inclusive), ISO 8601. */
2617
+ readonly from?: string;
2618
+ /** End date (inclusive), ISO 8601. */
2619
+ readonly to?: string;
2620
+ /** Maximum entries to return. */
2621
+ readonly limit?: number;
2622
+ }
2623
+ /** Options for pruning history. */
2624
+ export interface PruneOptions {
2625
+ /** Keep only the N most recent versions. */
2626
+ readonly keepVersions?: number;
2627
+ /** Delete versions older than this date, ISO 8601. */
2628
+ readonly beforeDate?: string;
2629
+ }
2630
+ /** A decrypted history entry. */
2631
+ export interface HistoryEntry<T> {
2632
+ readonly version: number;
2633
+ readonly timestamp: string;
2634
+ readonly userId: string;
2635
+ readonly record: T;
2636
+ }
2637
+ /** Per-item options for `Collection.putMany()`. */
2638
+ export interface PutManyItemOptions {
2639
+ /**
2640
+ * Optimistic-concurrency check: fail this item if the stored version
2641
+ * is not `expectedVersion`. Honored only in `atomic: true` mode;
2642
+ * ignored in the default best-effort loop.
2643
+ */
2644
+ readonly expectedVersion?: number;
2645
+ }
2646
+ /**
2647
+ * Batch-level options for `Collection.putMany()` and `deleteMany()`.
2648
+ *
2649
+ * `atomic: true` switches the call from best-effort loop
2650
+ * to all-or-nothing: a pre-flight CAS check runs first, then every op
2651
+ * is executed; any mid-batch failure triggers a best-effort revert.
2652
+ * On failure in atomic mode the whole call throws — you won't get a
2653
+ * partial `PutManyResult`. On success the result mirrors the default
2654
+ * loop's shape.
2655
+ */
2656
+ export interface PutManyOptions {
2657
+ readonly atomic?: boolean;
2658
+ }
2659
+ /** Result of `Collection.putMany()`. */
2660
+ export interface PutManyResult {
2661
+ /** `true` iff every entry succeeded. */
2662
+ readonly ok: boolean;
2663
+ /** IDs that were successfully written. */
2664
+ readonly success: readonly string[];
2665
+ /** Entries that failed, with the error that prevented each write. */
2666
+ readonly failures: ReadonlyArray<{
2667
+ readonly id: string;
2668
+ readonly error: Error;
2669
+ }>;
2670
+ }
2671
+ /** Result of `Collection.deleteMany()`. Same shape as `PutManyResult`. */
2672
+ export interface DeleteManyResult {
2673
+ readonly ok: boolean;
2674
+ readonly success: readonly string[];
2675
+ readonly failures: ReadonlyArray<{
2676
+ readonly id: string;
2677
+ readonly error: Error;
2678
+ }>;
2679
+ }
2680
+ /**
2681
+ * Thin reader view of a user envelope. The on-disk shape is the standard
2682
+ * {@link EncryptedEnvelope}; this is what callers see after the storage
2683
+ * layer has decrypted the payload.
2684
+ *
2685
+ * Hub commits to the `keyringId` ⇔ `userId` identity and the `_v` / `_ts`
2686
+ * envelope metadata. The `data` payload is fully app-defined — hub does
2687
+ * not introspect, validate, or reserve any keys inside it.
2688
+ */
2689
+ export interface UserEnvelope<T> {
2690
+ /** The principal id this envelope belongs to. Equals the keyring `user_id`. */
2691
+ readonly keyringId: string;
2692
+ /** App-owned payload. Opaque to hub. */
2693
+ readonly data: T;
2694
+ /** Optimistic-concurrency version. Increments on every write. */
2695
+ readonly _v: number;
2696
+ /** ISO timestamp of the last write. */
2697
+ readonly _ts: string;
2698
+ }
2699
+ /**
2700
+ * Recursive partial. Used for `updateMe(patch)` so callers can hand in
2701
+ * deeply-nested partial shapes and have them deep-merged onto the
2702
+ * current envelope.
2703
+ */
2704
+ export type DeepPartial<T> = T extends object ? {
2705
+ [P in keyof T]?: DeepPartial<T[P]>;
2706
+ } : T;
2707
+ /**
2708
+ * Recursive partial with `null` allowed at every level — used by
2709
+ * `updateMe` to express deletion intent in addition to merge.
2710
+ *
2711
+ * Semantics inside `updateMe`:
2712
+ * - `undefined` (or absent key) — skip; source value preserved
2713
+ * - `null` — delete the key from the resulting envelope
2714
+ * - any other value — overwrite (deep-merge for plain objects,
2715
+ * replace for primitives / arrays)
2716
+ *
2717
+ * Matches lodash `_.merge` behavior on `null` and Firestore's
2718
+ * `FieldValue.delete()` semantics. Loosened from `DeepPartial<T>`.
2719
+ * Consumers wanting the original "merge-only" surface can keep
2720
+ * importing `DeepPartial` and avoid passing `null`.
2721
+ */
2722
+ export type DeepPartialOrNull<T> = T extends object ? {
2723
+ [P in keyof T]?: DeepPartialOrNull<T[P]> | null;
2724
+ } : T;
2725
+ /** Cancel a previously-registered subscription. */
2726
+ export type Unsubscribe = () => void;
2727
+ /**
2728
+ * Optional factor-proof bundle threaded into gated user-envelope
2729
+ * operations. Same shape as `Noydb.checkGate(vault, gate, presented)`
2730
+ * accepts elsewhere — apps that have already presented a TOTP/email-OTP
2731
+ * for this session pass it here to satisfy tightened policies.
2732
+ */
2733
+ export interface UserEnvelopePresented {
2734
+ readonly factors?: readonly FactorProof[];
2735
+ readonly sharedDevice?: boolean;
2736
+ }
2737
+ /**
2738
+ * Callback used by `UserApi` to validate the active session against a
2739
+ * policy gate. Provided by the `Vault` constructor; in production this
2740
+ * delegates to `Noydb.checkGate(vault, gate, presented)`. In tests, a
2741
+ * no-op stub is fine.
2742
+ */
2743
+ export type UserEnvelopeCheckGate = (gate: 'edit-own-profile' | 'view-team-profiles' | 'client-unilateral-withdraw' | 'user-request-withdrawal' | 'approve-user-withdrawal', presented?: UserEnvelopePresented) => Promise<void>;
2744
+ /**
2745
+ * Reactive handle returned by `live()`. `current` is the most recently
2746
+ * observed value; `subscribe(cb)` fires on subsequent local writes.
2747
+ * `stop()` releases the underlying subscription.
2748
+ */
2749
+ export interface LiveUserEnvelope<T> {
2750
+ current(): UserEnvelope<T> | null;
2751
+ subscribe(cb: (env: UserEnvelope<T> | null) => void): Unsubscribe;
2752
+ stop(): void;
2753
+ }
2754
+ /**
2755
+ * The 2nd positional parameter of a {@link PortabilityStrategy} method
2756
+ * (index 1, right after the leading `vault` argument).
2757
+ */
2758
+ type PortabilityParam1<K extends keyof PortabilityStrategy> = Parameters<PortabilityStrategy[K]>[1];
2759
+ /**
2760
+ * The 3rd positional parameter (index 2) — only present on
2761
+ * `approveWithdrawal` / `rejectWithdrawal` (requestId is index 1 there).
2762
+ */
2763
+ type PortabilityParam2<K extends keyof PortabilityStrategy> = Parameters<PortabilityStrategy[K]>[2];
2764
+ type PortabilityReturn<K extends keyof PortabilityStrategy> = ReturnType<PortabilityStrategy[K]>;
2765
+ /**
2766
+ * Public `vault.user.*` API surface — the CONTRACT. The implementation
2767
+ * (`UserApi`) lives at `with-party/directory/user-envelope/api.ts` and
2768
+ * `implements` this interface; `createNoydb()` wires it in via the
2769
+ * pre-resolved {@link UserApiFactory}.
2770
+ *
2771
+ * Three families:
2772
+ * - Write-self: `me` / `updateMe` / `setMe` — always target the writer's
2773
+ * own keyringId. **Own-only write rule** is structural — no method
2774
+ * exists to write someone else's envelope.
2775
+ * - Read-anyone: `get` / `list` — read other principals' envelopes
2776
+ * (subject to `view-team-profiles` policy gate).
2777
+ * - Reactive: `subscribe` / `live` — in-process event emission on local
2778
+ * writes. Cross-instance updates land via the team/sync engine and
2779
+ * surface to subscribers when the sync diff replays through this API.
2780
+ *
2781
+ * @see docs/superpowers/specs/2026-05-05-user-envelope-design.md
2782
+ */
2783
+ export interface VaultUserApi {
2784
+ requestWithdrawal(opts?: PortabilityParam1<'requestWithdrawal'>): PortabilityReturn<'requestWithdrawal'>;
2785
+ listWithdrawalRequests(opts?: PortabilityParam1<'listWithdrawalRequests'>): PortabilityReturn<'listWithdrawalRequests'>;
2786
+ approveWithdrawal(requestId: PortabilityParam1<'approveWithdrawal'>, opts?: PortabilityParam2<'approveWithdrawal'>): PortabilityReturn<'approveWithdrawal'>;
2787
+ rejectWithdrawal(requestId: PortabilityParam1<'rejectWithdrawal'>, opts?: PortabilityParam2<'rejectWithdrawal'>): PortabilityReturn<'rejectWithdrawal'>;
2788
+ unilateralWithdrawal(opts: PortabilityParam1<'withdrawAccessibleData'>): PortabilityReturn<'withdrawAccessibleData'>;
2789
+ exportMyAccessibleData(opts?: PortabilityParam1<'exportAccessibleData'>): PortabilityReturn<'exportAccessibleData'>;
2790
+ me<T = unknown>(): Promise<UserEnvelope<T> | null>;
2791
+ updateMe<T extends object = Record<string, unknown>>(patch: DeepPartialOrNull<T>, presented?: UserEnvelopePresented): Promise<UserEnvelope<T>>;
2792
+ setMe<T = unknown>(payload: T, presented?: UserEnvelopePresented): Promise<UserEnvelope<T>>;
2793
+ getMyVisibility(): Promise<{
2794
+ readonly hidden: boolean;
2795
+ }>;
2796
+ setMyVisibility(visibility: {
2797
+ readonly hidden: boolean;
2798
+ }): Promise<void>;
2799
+ get<T = unknown>(keyringId: string, presented?: UserEnvelopePresented): Promise<UserEnvelope<T> | null>;
2800
+ list<T = unknown>(presented?: UserEnvelopePresented): Promise<UserEnvelope<T>[]>;
2801
+ subscribe<T = unknown>(keyringId: string, cb: (env: UserEnvelope<T> | null) => void): Unsubscribe;
2802
+ live<T = unknown>(keyringId: string): LiveUserEnvelope<T>;
2803
+ }
2804
+ /**
2805
+ * Constructor dependencies for `UserApi` (the {@link VaultUserApi}
2806
+ * implementation). Built by `Vault`'s constructor and passed to the
2807
+ * pre-resolved {@link UserApiFactory}.
2808
+ */
2809
+ export interface UserApiDeps {
2810
+ readonly adapter: NoydbStore;
2811
+ readonly vaultName: string;
2812
+ /** The writer's own keyringId. Frozen at construction time. */
2813
+ readonly writerKeyringId: string;
2814
+ readonly getDek: () => Promise<EnclaveKey>;
2815
+ /**
2816
+ * Policy-gate validator. When omitted, gates are skipped — useful
2817
+ * for low-level tests that exercise the storage layer directly.
2818
+ * Production paths always wire the Noydb-backed implementation.
2819
+ */
2820
+ readonly checkGate?: UserEnvelopeCheckGate;
2821
+ /**
2822
+ * Noydb-backed `exportMyAccessibleData`, injected by the Vault
2823
+ * (which holds the keyring + bundle machinery). Omitted in low-level tests.
2824
+ */
2825
+ readonly exportAccessible?: (opts: PortabilityParam1<'exportAccessibleData'>) => PortabilityReturn<'exportAccessibleData'>;
2826
+ /**
2827
+ * Noydb-backed `unilateralWithdrawal`, injected by the Vault.
2828
+ * Destructive — extract + dispose (delete | freeze). Omitted in low-level tests.
2829
+ */
2830
+ readonly unilateralWithdraw?: (opts: PortabilityParam1<'withdrawAccessibleData'>) => PortabilityReturn<'withdrawAccessibleData'>;
2831
+ /**
2832
+ * Noydb-backed two-party withdrawal ceremony, injected by the
2833
+ * Vault. requestWithdraw = requester side; the rest = owner side.
2834
+ */
2835
+ readonly requestWithdraw?: (opts: PortabilityParam1<'requestWithdrawal'>) => PortabilityReturn<'requestWithdrawal'>;
2836
+ readonly listWithdrawals?: (opts: PortabilityParam1<'listWithdrawalRequests'>) => PortabilityReturn<'listWithdrawalRequests'>;
2837
+ readonly approveWithdraw?: (requestId: PortabilityParam1<'approveWithdrawal'>, opts: PortabilityParam2<'approveWithdrawal'>) => PortabilityReturn<'approveWithdrawal'>;
2838
+ readonly rejectWithdraw?: (requestId: PortabilityParam1<'rejectWithdrawal'>, opts: PortabilityParam2<'rejectWithdrawal'>) => PortabilityReturn<'rejectWithdrawal'>;
2839
+ }
2840
+ /**
2841
+ * Factory that builds the `vault.user` API implementation from its
2842
+ * dependencies. `createNoydb()` pre-resolves the real implementation
2843
+ * (`with-party/directory/user-envelope/api.js#createUserApi`) via a
2844
+ * dynamic import before constructing `Noydb`, so `Vault`'s constructor
2845
+ * can call it synchronously — the two sync `subscribe`/`live` methods on
2846
+ * `VaultUserApi` are why `vault.user` must be built synchronously.
2847
+ */
2848
+ export type UserApiFactory = (deps: UserApiDeps) => VaultUserApi;
2849
+ /**
2850
+ * A single factor surface — the proof an actor presents at gate time.
2851
+ *
2852
+ * | Kind | Source | Off-device? |
2853
+ * |---|---|---|
2854
+ * | `totp` | RFC 6238 authenticator app (Google Auth, 1Password) | yes |
2855
+ * | `email-otp` | one-time code mailed to the user | yes |
2856
+ * | `recovery` | printable Base32 code (`@noy-db/on-recovery`) | yes (paper) |
2857
+ * | `shamir` | k-of-n threshold share (`@noy-db/on-shamir`) | yes |
2858
+ * | `webauthn-roaming` | hardware key (YubiKey, SoloKey, Titan) | yes (key portable) |
2859
+ * | `webauthn-platform` | platform passkey (Touch ID, Face ID, Hello) | no (device-bound) |
2860
+ * | `password` | tier-2 password (`@noy-db/on-password`) | no |
2861
+ * | `pin` | tier-3 quick-resume PIN (`@noy-db/on-pin`) | no |
2862
+ *
2863
+ * Off-device kinds (TOTP, email-OTP, recovery, shamir, roaming WebAuthn)
2864
+ * are the strongest factor proofs because they require something
2865
+ * separate from the device the user just unlocked. Platform / password /
2866
+ * PIN are useful for "fresh proof of *this* user" but don't bind across
2867
+ * devices — policies can require ANY of them or insist on a count of 2
2868
+ * to force a mix.
2869
+ *
2870
+ * `webauthn-platform`, `password`, `pin` — for consumers with no
2871
+ * off-device infrastructure (no TOTP, no email-OTP, paper recovery not
2872
+ * enrolled) who want to require "any second factor I have wired"
2873
+ * without losing the freshness guarantee.
2874
+ */
2875
+ export type FactorKind = 'totp' | 'email-otp' | 'recovery' | 'shamir' | 'webauthn-roaming' | 'webauthn-platform' | 'password' | 'pin';
2876
+ /**
2877
+ * One factor requirement entry. The default is "any one of the listed
2878
+ * factors, fresh within the last 5 minutes". Bumping `count` requires N
2879
+ * distinct fresh proofs; bumping `freshnessMs` widens the acceptance
2880
+ * window.
2881
+ */
2882
+ export interface FactorRequirement {
2883
+ readonly anyOf: ReadonlyArray<FactorKind>;
2884
+ /** Number of distinct factors required. Default 1. */
2885
+ readonly count?: number;
2886
+ /** How recent each proof must be. Default 5 minutes. */
2887
+ readonly freshnessMs?: number;
2888
+ }
2889
+ /** Soft signals layered on top of the gate verdict — never block on their own. */
2890
+ export interface WarningRules {
2891
+ /** Behavior on shared-device tier-1 ops. `'block'` raises a `PolicyDeniedError`. */
2892
+ readonly sharedDevice?: 'warn' | 'block';
2893
+ /** Behavior on weak tier-2 (e.g. password-only) for sensitive ops. */
2894
+ readonly weakAuthenticator?: 'warn' | 'block';
2895
+ }
2896
+ /**
2897
+ * Policy applied to one named gate. `enabled: false` disables the
2898
+ * action entirely (useful in managed-passphrase mode where rotation is
2899
+ * impossible by construction).
2900
+ */
2901
+ export interface GatePolicy {
2902
+ /** Minimum tier the active session must hold. */
2903
+ readonly minTier: 1 | 2 | 3;
2904
+ /** Extra freshness-bound proofs required at gate time. */
2905
+ readonly factors?: ReadonlyArray<FactorRequirement>;
2906
+ readonly warn?: WarningRules;
2907
+ readonly enabled?: boolean;
2908
+ }
2909
+ /**
2910
+ * Built-in gate names. App-defined gates live in the `app:*` namespace
2911
+ * and use the same engine; the engine treats unknown names with no
2912
+ * configured policy as "no gate" (no-op).
2913
+ */
2914
+ export type BuiltInGateName = 'rotate-passphrase' | 'recover-passphrase' | 'enroll-authenticator' | 'remove-authenticator'
2915
+ /**
2916
+ * Authorize a deliberate paper-recovery-code regeneration —
2917
+ * `db.rotateRecovery`. Symmetric to `rotate-passphrase` for
2918
+ * the case where the user remembers their passphrase but wants a
2919
+ * fresh sheet (lost the printout, suspect compromise of the off-site
2920
+ * copy). PERSONAL allows tier-1; STRICT requires an off-device
2921
+ * factor so a stolen unlocked laptop cannot silently mint a new
2922
+ * sheet for an attacker.
2923
+ */
2924
+ | 'rotate-recovery'
2925
+ /**
2926
+ * Authorize a meta-only mutation on an existing authenticator slot —
2927
+ * `db.updateAuthenticator`. The slot's wrap material, id, and
2928
+ * method are immutable through this gate; only the `meta` blob
2929
+ * (nicknames, method-specific labels) can change. Anti-slot-swap
2930
+ * guard is preserved structurally regardless of this gate's
2931
+ * settings.
2932
+ */
2933
+ | 'update-authenticator' | 'rotate-unlock' | 'enroll-user' | 'revoke-user' | 'export-bundle' | 'export-plaintext' | 'view-user-auth'
2934
+ /** Authorize a write to one's own user envelope. */
2935
+ | 'edit-own-profile'
2936
+ /** Authorize reading other principals' user envelopes. */
2937
+ | 'view-team-profiles'
2938
+ /**
2939
+ * Authorize an atomic peer-recovery — `db.recoverUser`.
2940
+ * Distinct from `revoke-user` because peer-recovery is intentional
2941
+ * re-issuance of someone's keyring under a temp passphrase, NOT
2942
+ * removal. Allows owner→owner natively (matches the threat model:
2943
+ * a co-owner explicitly recovering another co-owner). Ships with a
2944
+ * factor-proof default in `STRICT_POLICY` so the issuer must
2945
+ * affirmatively prove identity at the moment of recovery.
2946
+ */
2947
+ | 'peer-recover-user'
2948
+ /**
2949
+ * Authorize a post-grant identity mutation — `db.updateUser`.
2950
+ * Covers `role`, `displayName`, `permissions` changes on an existing
2951
+ * keyring. Pure plaintext-header rewrite — no DEKs touched, no KEK
2952
+ * required. The role-elevation guard inside the implementation
2953
+ * mirrors `db.grant`'s hierarchy (admin cannot promote to owner)
2954
+ * regardless of this gate's settings.
2955
+ */
2956
+ | 'update-user'
2957
+ /**
2958
+ * Authorize a non-owner's self-service **destructive** withdrawal —
2959
+ * `vault.user.unilateralWithdrawal`. The actor exports their
2960
+ * own re-keyed copy and then removes (delete-closure) or freezes the
2961
+ * source records. Because it both egresses data AND destroys the
2962
+ * firm's live copy, it MUST fail closed: undefined in a policy = denied.
2963
+ * Hosts opt in explicitly (and typically pin `minTier`/factor proofs).
2964
+ */
2965
+ | 'client-unilateral-withdraw'
2966
+ /**
2967
+ * Authorize FILING a two-party withdrawal request —
2968
+ * `vault.user.requestWithdrawal`. Non-destructive (writes a
2969
+ * pending request only); enabled by default so a read-only client can ask.
2970
+ */
2971
+ | 'user-request-withdrawal'
2972
+ /**
2973
+ * Authorize DECIDING a two-party withdrawal request (approve/reject) —
2974
+ * `vault.user.approveWithdrawal` / `rejectWithdrawal`. The approve
2975
+ * path is destructive (extract-and-dispose under firm authority), so it
2976
+ * defaults to a tier-2 floor; owner/admin role is enforced structurally.
2977
+ */
2978
+ | 'approve-user-withdrawal'
2979
+ /**
2980
+ * Authorize minting a **custodian** — `db.grantCustodian` (FR-6). The
2981
+ * custodian is the de-facto operational authority on a sealed-owner (Deed)
2982
+ * vault, so granting one is an ownership-level act: this gate MUST fail
2983
+ * closed (undefined in a policy = denied) and owner-only role is enforced
2984
+ * structurally. Hosts opt in explicitly, typically pinning factor proofs.
2985
+ */
2986
+ | 'grant-custodian'
2987
+ /**
2988
+ * Authorize the audited **Liberate** ceremony — `vault.custody.liberate`
2989
+ * (FR-6). The custodian (holding the live DEKs) claims ownership of a
2990
+ * sealed-owner vault under a recorded legal basis, minting a NEW owner
2991
+ * keyring. Destructive-of-the-old-ownership and irreversible, so it MUST
2992
+ * fail closed (undefined = denied); the caller-is-custodian check is
2993
+ * enforced structurally in the ceremony.
2994
+ */
2995
+ | 'liberate-vault';
2996
+ /** Either a built-in gate name or an `app:*` custom gate. */
2997
+ export type GateName = BuiltInGateName | `app:${string}`;
2998
+ /**
2999
+ * Top-level policy object. Persisted at `_meta/policy` once at vault
3000
+ * creation. The `passphrase` block configures the strength rules
3001
+ * applied at every passphrase ingress; `gates` configures
3002
+ * the action-level requirements.
3003
+ */
3004
+ export interface VaultPolicy {
3005
+ readonly passphrase?: PassphrasePolicy;
3006
+ readonly gates: Partial<Record<GateName, GatePolicy>>;
3007
+ }
3008
+ /** Concrete proof an actor presents to {@link checkGate}. */
3009
+ export interface FactorProof {
3010
+ readonly kind: FactorKind;
3011
+ /** ISO-8601 timestamp the proof was minted at. Compared against `freshnessMs`. */
3012
+ readonly mintedAt?: string;
3013
+ /** Method-specific payload. The engine treats it as opaque — verification is delegated. */
3014
+ readonly payload?: unknown;
3015
+ }
3016
+ /**
3017
+ * Bundle of factor proofs + session-context flags passed to a gated
3018
+ * Noydb method. Used as the optional last parameter of every method
3019
+ * that runs through `checkGate`: `db.grant`, `db.revoke`, `db.updateUser`,
3020
+ * `db.enrollAuthenticator`, `db.removeAuthenticator`, `db.updateAuthenticator`,
3021
+ * `db.enrollWebAuthn`, `db.rotatePassphrase`, `db.recoverPassphrase`,
3022
+ * `db.recoverUser`, `db.enrollUnlock`, `db.describeUserAuth`,
3023
+ * `db.describeAllUsersAuth`.
3024
+ *
3025
+ * Previously this type was inlined at every call site as
3026
+ * `{ factors?: ReadonlyArray<FactorProof>; sharedDevice?: boolean }`
3027
+ * and parameter names alternated between `factors` and `presented`.
3028
+ * Now exported so consumers can name their helpers and so the param
3029
+ * name converges to `factors` everywhere.
3030
+ */
3031
+ export interface FactorProofBundle {
3032
+ readonly factors?: ReadonlyArray<FactorProof>;
3033
+ readonly sharedDevice?: boolean;
3034
+ }
3035
+ /** Active session tier — what the engine compares against `gate.minTier`. */
3036
+ export type ActiveTier = 1 | 2 | 3;
3037
+ /**
3038
+ * Caller-supplied context for the policy engine's `checkGate`/`describeGate`.
3039
+ * Structural mirror of `with-party/policy/engine.ts`'s `CheckGateContext` —
3040
+ * duplicated here (rather than imported) because the kernel spine may not
3041
+ * statically import a with-* service; see {@link PolicyCheckGateFn}.
3042
+ */
3043
+ export interface PolicyCheckGateContext {
3044
+ /** Tier the active session currently holds. */
3045
+ readonly activeTier: ActiveTier;
3046
+ /** Proofs the actor is presenting for this gate. */
3047
+ readonly factors?: ReadonlyArray<FactorProof>;
3048
+ /**
3049
+ * If the host knows the actor is on a shared device, set this to
3050
+ * `true` so the engine can apply `warn.sharedDevice` rules. Defaults
3051
+ * to `false`.
3052
+ */
3053
+ readonly sharedDevice?: boolean;
3054
+ /**
3055
+ * Override `now()` for tests. Defaults to `Date.now()`.
3056
+ * @internal
3057
+ */
3058
+ readonly now?: number;
3059
+ }
3060
+ /**
3061
+ * Structural type of the policy engine's `checkGate` function. The real
3062
+ * implementation lives at `with-party/policy/engine.ts#checkGate`;
3063
+ * `createNoydb()` pre-resolves it via a dynamic import (mirrors
3064
+ * {@link UserApiFactory}) so `Noydb.checkGate` can call it without the
3065
+ * spine statically importing the service.
3066
+ */
3067
+ export type PolicyCheckGateFn = (policy: VaultPolicy, gate: GateName, context: PolicyCheckGateContext) => Promise<void>;
3068
+ /**
3069
+ * Public `NoydbPolicy` surface — the CONTRACT. The implementation
3070
+ * (`NoydbPolicy` class) lives at `with-party/policy/noydb-facade.ts`;
3071
+ * `createNoydb()` wires it in via the pre-resolved {@link NoydbPolicyFactory}.
3072
+ */
3073
+ export interface NoydbPolicyApi {
3074
+ /**
3075
+ * Touch the policy enforcer for a vault (records activity, resets
3076
+ * idle timer). Also touches the legacy session timer. No-op if no enforcer.
3077
+ */
3078
+ touchPolicy(vault?: string): void;
3079
+ /**
3080
+ * Check that a policy-guarded operation is permitted.
3081
+ * Throws `SessionPolicyError` if re-auth is required.
3082
+ */
3083
+ checkPolicyOperation(vault: string, op: ReAuthOperation): void;
3084
+ /**
3085
+ * Read the active policy for a vault. Loads from `_meta/policy` on
3086
+ * first call; subsequent calls hit the in-memory cache. Throws
3087
+ * `ValidationError` if the vault has not been opened.
3088
+ */
3089
+ getPolicy(vault: string): Promise<VaultPolicy>;
3090
+ /**
3091
+ * Replace the policy document at `_meta/policy` and update the
3092
+ * in-memory cache. Gated by the `enroll-user` policy (a policy
3093
+ * change is fundamentally a privilege-management action).
3094
+ */
3095
+ updatePolicy(vault: string, override: Partial<VaultPolicy>): Promise<VaultPolicy>;
3096
+ /** Read or persist the vault policy at `_meta/policy` on first open. */
3097
+ bootstrapPolicy(vault: string, opts?: {
3098
+ skipManagedCheck?: boolean;
3099
+ }): Promise<void>;
3100
+ }
3101
+ /**
3102
+ * Constructor dependencies for `NoydbPolicy` (the {@link NoydbPolicyApi}
3103
+ * implementation). Everything the policy/session-policy methods touch on
3104
+ * the owning `Noydb` instance's `this.*`.
3105
+ *
3106
+ * The `policyEnforcers` map is typed structurally (rather than importing
3107
+ * `PolicyEnforcer` from `with-party/session/session-policy.ts`) so this
3108
+ * spine-resident interface never needs a with-* import; the real
3109
+ * `PolicyEnforcer` class satisfies this shape.
3110
+ */
3111
+ export interface NoydbPolicyDeps {
3112
+ /** In-memory vault-policy cache (Noydb-resident; read/written by reference). */
3113
+ readonly policyCache: Map<string, VaultPolicy>;
3114
+ /** Per-vault session-policy enforcers (Noydb-resident; read/written by reference). */
3115
+ readonly policyEnforcers: Map<string, {
3116
+ touch(): void;
3117
+ destroy(): void;
3118
+ checkOperation(op: ReAuthOperation): void;
3119
+ }>;
3120
+ /** The ciphertext store. */
3121
+ readonly store: NoydbStore;
3122
+ /** Whether records are encrypted (`options.encrypt !== false`). */
3123
+ readonly encrypted: boolean;
3124
+ /** The configured session policy, or undefined. */
3125
+ readonly sessionPolicy: SessionPolicy | undefined;
3126
+ /** The developer-supplied default policy, or undefined. */
3127
+ readonly policyOption: VaultPolicy | undefined;
3128
+ /** Whether the owning instance has been closed. */
3129
+ isClosed(): boolean;
3130
+ /** Reset the kernel-resident idle/session timer. */
3131
+ resetSessionTimer(): void;
3132
+ /** Managed-recovery enrolment check (kernel-resident; called on bootstrap). */
3133
+ assertRecoveryEnrolled(vault: string, policy: VaultPolicy, opts?: {
3134
+ skipManagedCheck?: boolean;
3135
+ }): Promise<void>;
3136
+ /** Evict the keyring + vault caches when a session is revoked. */
3137
+ onSessionRevoke(vault: string): void;
3138
+ }
3139
+ /**
3140
+ * Factory that builds the `NoydbPolicy` service implementation from its
3141
+ * dependencies. `createNoydb()` pre-resolves the real implementation
3142
+ * (`with-party/policy/noydb-facade.js#createNoydbPolicy`) via a dynamic
3143
+ * import before constructing `Noydb`, so the constructor can call it
3144
+ * synchronously — mirrors {@link UserApiFactory}.
3145
+ */
3146
+ export type NoydbPolicyFactory = (deps: NoydbPolicyDeps) => NoydbPolicyApi;
3147
+ export {};