@noy-db/hub 0.6.0-pre.2 → 0.6.0-pre.21

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 (499) hide show
  1. package/CHANGELOG.md +5234 -0
  2. package/codemods/0.4.0-pre.json +699 -0
  3. package/codemods/0.6.0-pre.json +211 -0
  4. package/dist/api-EYNT6KGS.js +20 -0
  5. package/dist/attestation/index.js +19 -19
  6. package/dist/{backup-YYBE5RPC.js → backup-FSC36VWC.js} +36 -18
  7. package/dist/backup-FSC36VWC.js.map +1 -0
  8. package/dist/blobs/index.js +13 -13
  9. package/dist/broker/index.js +12 -12
  10. package/dist/cargo/index.js +33 -33
  11. package/dist/{chunk-35EBKWQU.js → chunk-2LFOMUEA.js} +4 -4
  12. package/dist/{chunk-OF3L2SD6.js → chunk-32B7VCKU.js} +2 -2
  13. package/dist/{chunk-MSWYQLMQ.js → chunk-3B6S6RSI.js} +2 -2
  14. package/dist/{chunk-PJNTR2NV.js → chunk-3ENNPCIW.js} +7 -10
  15. package/dist/chunk-3ENNPCIW.js.map +1 -0
  16. package/dist/{chunk-7F4DBNSP.js → chunk-3O72ZD2E.js} +3 -3
  17. package/dist/{chunk-FNSMZQS4.js → chunk-3PMFMUFX.js} +2 -2
  18. package/dist/{chunk-WQDTCJ6W.js → chunk-45YHJ3GV.js} +11 -3
  19. package/dist/{chunk-WQDTCJ6W.js.map → chunk-45YHJ3GV.js.map} +1 -1
  20. package/dist/{chunk-NIVEDYJZ.js → chunk-4A34KWOU.js} +31 -49
  21. package/dist/chunk-4A34KWOU.js.map +1 -0
  22. package/dist/{chunk-ZJADGNYF.js → chunk-4AOERLTV.js} +1 -1
  23. package/dist/chunk-4AOERLTV.js.map +1 -0
  24. package/dist/{chunk-EDXAQ6JI.js → chunk-4N5Q23KV.js} +87 -34
  25. package/dist/chunk-4N5Q23KV.js.map +1 -0
  26. package/dist/{chunk-VV4NSB7P.js → chunk-4OQZNXQG.js} +15 -24
  27. package/dist/chunk-4OQZNXQG.js.map +1 -0
  28. package/dist/{chunk-FAXZQ5UF.js → chunk-4RAS6HN6.js} +2 -2
  29. package/dist/{chunk-C2OOEM57.js → chunk-4YL2LMXK.js} +92 -35
  30. package/dist/chunk-4YL2LMXK.js.map +1 -0
  31. package/dist/{chunk-EP7VPR7Y.js → chunk-5Q7AJ7DN.js} +11 -8
  32. package/dist/chunk-5Q7AJ7DN.js.map +1 -0
  33. package/dist/{chunk-VMCCGUQB.js → chunk-6JPGVL7X.js} +2 -2
  34. package/dist/{chunk-PRDRGL73.js → chunk-6KTVJ5ZZ.js} +17 -14
  35. package/dist/chunk-6KTVJ5ZZ.js.map +1 -0
  36. package/dist/{chunk-4MC5JRRX.js → chunk-6WO62AJW.js} +14 -15
  37. package/dist/chunk-6WO62AJW.js.map +1 -0
  38. package/dist/{chunk-WLYIROCJ.js → chunk-6YD5SYQS.js} +2 -2
  39. package/dist/{chunk-YAWK6AWF.js → chunk-7KAE7CQ2.js} +2 -2
  40. package/dist/{chunk-MWKDOHEF.js → chunk-7LNE2N2V.js} +17 -10
  41. package/dist/chunk-7LNE2N2V.js.map +1 -0
  42. package/dist/{chunk-5PR33AC4.js → chunk-7PJ3BKHS.js} +20 -17
  43. package/dist/chunk-7PJ3BKHS.js.map +1 -0
  44. package/dist/{chunk-JXIDGFKS.js → chunk-A4TOGAUW.js} +4 -2
  45. package/dist/chunk-A4TOGAUW.js.map +1 -0
  46. package/dist/{chunk-VCETL77O.js → chunk-AU3AUJIZ.js} +27 -7
  47. package/dist/chunk-AU3AUJIZ.js.map +1 -0
  48. package/dist/{chunk-NKH7GSIH.js → chunk-AUPSEJ7O.js} +4 -4
  49. package/dist/{chunk-CCZJJ4I2.js → chunk-B6IYATME.js} +4 -4
  50. package/dist/{chunk-WYZ5MYUA.js → chunk-BAHOV5I5.js} +44 -42
  51. package/dist/chunk-BAHOV5I5.js.map +1 -0
  52. package/dist/{chunk-G5APARUV.js → chunk-BEZDLIDG.js} +13 -15
  53. package/dist/chunk-BEZDLIDG.js.map +1 -0
  54. package/dist/{chunk-ERB6NDDW.js → chunk-CAGI4LLJ.js} +427 -72
  55. package/dist/chunk-CAGI4LLJ.js.map +1 -0
  56. package/dist/{chunk-4UVDI4XE.js → chunk-CLAHBPOI.js} +4 -4
  57. package/dist/{chunk-HNGSV2YC.js → chunk-CWM4GQD2.js} +39 -10
  58. package/dist/chunk-CWM4GQD2.js.map +1 -0
  59. package/dist/{chunk-HVQGCKY4.js → chunk-D3R7Q4QK.js} +2 -2
  60. package/dist/{chunk-I4F6PKUK.js → chunk-DIZ6HM7Q.js} +16 -17
  61. package/dist/chunk-DIZ6HM7Q.js.map +1 -0
  62. package/dist/{chunk-ZNACADFG.js → chunk-DVRZYAGT.js} +4 -4
  63. package/dist/chunk-DVRZYAGT.js.map +1 -0
  64. package/dist/{chunk-P7OG2ETF.js → chunk-DXKLLKME.js} +3 -3
  65. package/dist/{chunk-TDJPS3T2.js → chunk-E5SC6ENM.js} +24 -19
  66. package/dist/chunk-E5SC6ENM.js.map +1 -0
  67. package/dist/{chunk-26JMGSSC.js → chunk-EES37S2V.js} +4 -4
  68. package/dist/chunk-EES37S2V.js.map +1 -0
  69. package/dist/{chunk-JIUVJ4M7.js → chunk-EKEIEJL6.js} +2 -2
  70. package/dist/{chunk-GASWQ3XG.js → chunk-ESKIAXO2.js} +15 -16
  71. package/dist/chunk-ESKIAXO2.js.map +1 -0
  72. package/dist/{chunk-TOAIYQJR.js → chunk-FFSQFH6D.js} +7 -10
  73. package/dist/chunk-FFSQFH6D.js.map +1 -0
  74. package/dist/{chunk-DG27IUVI.js → chunk-FS7NTGCJ.js} +2 -2
  75. package/dist/{chunk-V5KYPBUR.js → chunk-FW7NGYLT.js} +11 -14
  76. package/dist/chunk-FW7NGYLT.js.map +1 -0
  77. package/dist/{chunk-52QYGZHH.js → chunk-GBBDFE6C.js} +2 -2
  78. package/dist/chunk-GBBDFE6C.js.map +1 -0
  79. package/dist/{chunk-HXGUIPQB.js → chunk-GQXFOAYZ.js} +3 -3
  80. package/dist/{chunk-BTVYJWSN.js → chunk-GTHVPVAR.js} +10 -10
  81. package/dist/{chunk-DMQCLZ4Z.js → chunk-GWO2IDAB.js} +2 -2
  82. package/dist/{chunk-6HFM7EIT.js → chunk-H3G4I3PN.js} +2 -2
  83. package/dist/chunk-HK67PX4J.js +27 -0
  84. package/dist/chunk-HK67PX4J.js.map +1 -0
  85. package/dist/{chunk-E7OBCBXS.js → chunk-HQSPF5IY.js} +22 -18
  86. package/dist/chunk-HQSPF5IY.js.map +1 -0
  87. package/dist/{chunk-VJFMXYKP.js → chunk-HR5R5JOM.js} +2 -2
  88. package/dist/{chunk-FDX7OWWI.js → chunk-HYYVT2KZ.js} +2 -2
  89. package/dist/{chunk-JRCYZEHU.js → chunk-I6QKB7MT.js} +2 -2
  90. package/dist/{chunk-MZ5ZFO2D.js → chunk-ICDHUUMQ.js} +84 -112
  91. package/dist/chunk-ICDHUUMQ.js.map +1 -0
  92. package/dist/{chunk-W5W6KHN2.js → chunk-IGNJOJEP.js} +1 -1
  93. package/dist/chunk-IGNJOJEP.js.map +1 -0
  94. package/dist/{chunk-KUDZVJKQ.js → chunk-IJ46VCWD.js} +2 -2
  95. package/dist/{chunk-4HDYQL3J.js → chunk-INMHEMXX.js} +2 -2
  96. package/dist/{chunk-66W5OOCX.js → chunk-JLYQQNY4.js} +52 -65
  97. package/dist/chunk-JLYQQNY4.js.map +1 -0
  98. package/dist/{chunk-UHXCLPGC.js → chunk-JNMTN5D5.js} +2 -2
  99. package/dist/chunk-JNMTN5D5.js.map +1 -0
  100. package/dist/{chunk-I4ZAO7F7.js → chunk-JWMBG5S3.js} +7 -11
  101. package/dist/chunk-JWMBG5S3.js.map +1 -0
  102. package/dist/chunk-KRVS7YWY.js +123 -0
  103. package/dist/chunk-KRVS7YWY.js.map +1 -0
  104. package/dist/{chunk-AR2JDFAE.js → chunk-KV6JM2IA.js} +2 -2
  105. package/dist/{chunk-PVU7LW5L.js → chunk-KX57HODD.js} +6 -6
  106. package/dist/{chunk-PY7CI6L5.js → chunk-LGFTOU27.js} +553 -275
  107. package/dist/chunk-LGFTOU27.js.map +1 -0
  108. package/dist/chunk-LN7P6MZB.js +190 -0
  109. package/dist/chunk-LN7P6MZB.js.map +1 -0
  110. package/dist/{chunk-UIBGXRDD.js → chunk-LX46B56Q.js} +25 -31
  111. package/dist/chunk-LX46B56Q.js.map +1 -0
  112. package/dist/{chunk-CEJWMBXO.js → chunk-LXECF2ZR.js} +2 -2
  113. package/dist/{chunk-7VHY5E3X.js → chunk-MSLPDFK2.js} +7 -7
  114. package/dist/{chunk-I6SDX7WX.js → chunk-MZTUTEHP.js} +16 -22
  115. package/dist/chunk-MZTUTEHP.js.map +1 -0
  116. package/dist/{chunk-VRA4Q7DA.js → chunk-NCCEDL2K.js} +55 -48
  117. package/dist/chunk-NCCEDL2K.js.map +1 -0
  118. package/dist/{chunk-HNHCQ556.js → chunk-NR2SUJ3H.js} +2 -2
  119. package/dist/{chunk-AHLJSVRL.js → chunk-NW4TY6VC.js} +5 -7
  120. package/dist/chunk-NW4TY6VC.js.map +1 -0
  121. package/dist/{chunk-RKKORO4M.js → chunk-O742QBZZ.js} +10 -10
  122. package/dist/chunk-O742QBZZ.js.map +1 -0
  123. package/dist/{chunk-VN45YLWM.js → chunk-OHOKBMTM.js} +343 -132
  124. package/dist/chunk-OHOKBMTM.js.map +1 -0
  125. package/dist/{chunk-W3TVWF6N.js → chunk-OIBEJN5H.js} +2 -2
  126. package/dist/{chunk-QD724WDJ.js → chunk-OMYCSTXL.js} +4 -4
  127. package/dist/{chunk-Z45YRGFO.js → chunk-ONVD6GBY.js} +2 -2
  128. package/dist/{chunk-TAGFGKHP.js → chunk-OTHHO3KI.js} +7 -10
  129. package/dist/chunk-OTHHO3KI.js.map +1 -0
  130. package/dist/{chunk-3737A6EA.js → chunk-P2MR5UNE.js} +75 -18
  131. package/dist/chunk-P2MR5UNE.js.map +1 -0
  132. package/dist/chunk-PENPHA45.js +66 -0
  133. package/dist/chunk-PENPHA45.js.map +1 -0
  134. package/dist/{chunk-3FSX6LDG.js → chunk-PPCOKVFA.js} +8 -3
  135. package/dist/{chunk-3FSX6LDG.js.map → chunk-PPCOKVFA.js.map} +1 -1
  136. package/dist/{chunk-VOQW5LAM.js → chunk-QSIEL6TL.js} +102 -71
  137. package/dist/chunk-QSIEL6TL.js.map +1 -0
  138. package/dist/chunk-RFO4UXKQ.js +201 -0
  139. package/dist/chunk-RFO4UXKQ.js.map +1 -0
  140. package/dist/{chunk-KCQX65FU.js → chunk-RKCRPPNB.js} +3 -3
  141. package/dist/{chunk-7TSYBD3E.js → chunk-RSXQNFGO.js} +2 -2
  142. package/dist/{chunk-SZ2K3MHL.js → chunk-S56VYR4Q.js} +8 -11
  143. package/dist/{chunk-SZ2K3MHL.js.map → chunk-S56VYR4Q.js.map} +1 -1
  144. package/dist/{chunk-7NXHMW6Y.js → chunk-SYS46BL7.js} +2 -2
  145. package/dist/{chunk-55LKVALY.js → chunk-T7IR4N2S.js} +1 -3
  146. package/dist/chunk-T7IR4N2S.js.map +1 -0
  147. package/dist/{chunk-A67356IR.js → chunk-T7JGWTES.js} +33 -8
  148. package/dist/chunk-T7JGWTES.js.map +1 -0
  149. package/dist/{chunk-WHJKIZS7.js → chunk-TDSN2O2V.js} +27 -149
  150. package/dist/chunk-TDSN2O2V.js.map +1 -0
  151. package/dist/{chunk-747LRSOO.js → chunk-TMBSPLUG.js} +2 -2
  152. package/dist/{chunk-LWSJG3LI.js → chunk-TQPASLY4.js} +7 -3
  153. package/dist/chunk-TQPASLY4.js.map +1 -0
  154. package/dist/{chunk-WKPJXWKR.js → chunk-TX5MKAHA.js} +3 -3
  155. package/dist/{chunk-HFQ6LGIO.js → chunk-U27Y4DJZ.js} +12 -10
  156. package/dist/{chunk-HFQ6LGIO.js.map → chunk-U27Y4DJZ.js.map} +1 -1
  157. package/dist/{chunk-E6427JU2.js → chunk-VVSOPRUE.js} +18 -2
  158. package/dist/chunk-VVSOPRUE.js.map +1 -0
  159. package/dist/{chunk-7G6VDWXB.js → chunk-WVE6YKMX.js} +3 -3
  160. package/dist/chunk-WVE6YKMX.js.map +1 -0
  161. package/dist/{chunk-GLKDWWNO.js → chunk-YALD3SST.js} +16 -14
  162. package/dist/chunk-YALD3SST.js.map +1 -0
  163. package/dist/{chunk-NJDQ4YSV.js → chunk-YKXZHUOW.js} +4 -4
  164. package/dist/{chunk-VW6ZZGCG.js → chunk-ZLHHE5XZ.js} +3 -3
  165. package/dist/{chunk-FUHKW252.js → chunk-ZZXLB6AS.js} +2 -2
  166. package/dist/classified/index.js +5 -5
  167. package/dist/{classified-marker-FTOX7Q5L.js → classified-marker-NA6HUV33.js} +3 -3
  168. package/dist/collection-facade-VBM35WAH.js +45 -0
  169. package/dist/{computed-6G5M3UPH.js → computed-GSTLWSY5.js} +3 -3
  170. package/dist/consent/index.js +10 -10
  171. package/dist/cover/index.js +10 -3
  172. package/dist/custody/index.js +11 -11
  173. package/dist/{dead-filter-ENRIOQIE.js → dead-filter-UALP5DJX.js} +2 -2
  174. package/dist/debug/index.js +1 -1
  175. package/dist/{delegation-SSEPLXXO.js → delegation-JLNXM7KH.js} +24 -23
  176. package/dist/delegation-JLNXM7KH.js.map +1 -0
  177. package/dist/derivations/index.js +12 -12
  178. package/dist/derive-YUO3TQYN.js +22 -0
  179. package/dist/directory/index.js +10 -10
  180. package/dist/{dispatch-RE74SH6L.js → dispatch-4ZHLSFZQ.js} +5 -5
  181. package/dist/{dispatch-BDVGYC6X.js → dispatch-77CB75KB.js} +18 -18
  182. package/dist/{enclave-52VUXNRL.js → enclave-O4NOROCJ.js} +27 -9
  183. package/dist/executor-CZDXBXKE.js +29 -0
  184. package/dist/executor-DVJAWN3B.js +9 -0
  185. package/dist/executor-VRLG4TQJ.js +9 -0
  186. package/dist/export-accessible-UXSMG7AB.js +23 -0
  187. package/dist/extract-partition-TVY7AMKH.js +38 -0
  188. package/dist/{fanout-sidecar-DTBIDOWF.js → fanout-sidecar-NLQ7QAYW.js} +18 -27
  189. package/dist/fanout-sidecar-NLQ7QAYW.js.map +1 -0
  190. package/dist/find-WSARMJBW.js +11 -0
  191. package/dist/forget/index.js +9 -9
  192. package/dist/guards/index.js +7 -7
  193. package/dist/history/index.js +23 -20
  194. package/dist/history/index.js.map +1 -1
  195. package/dist/i18n/index.js +14 -14
  196. package/dist/index.d.ts +33 -15
  197. package/dist/index.js +187 -191
  198. package/dist/index.js.map +1 -1
  199. package/dist/indexing/index.js +2 -2
  200. package/dist/introspection/index.js +11 -11
  201. package/dist/issue-3JNJNPT3.js +19 -0
  202. package/dist/kernel/constants.d.ts +18 -0
  203. package/dist/kernel/enclave/crypto.d.ts +24 -4
  204. package/dist/kernel/enclave/index.d.ts +9 -2
  205. package/dist/kernel/enclave/record-aad.d.ts +131 -0
  206. package/dist/kernel/enclave/record-envelope.d.ts +76 -0
  207. package/dist/kernel/enclave/record-keys/envelope-body.d.ts +34 -2
  208. package/dist/kernel/enclave/record-keys/lifecycle.d.ts +22 -5
  209. package/dist/kernel/enclave/record-keys/record-codec.d.ts +47 -14
  210. package/dist/kernel/enclave/record-keys/rekey-blob.d.ts +88 -0
  211. package/dist/kernel/enclave/record-keys/rekey.d.ts +68 -0
  212. package/dist/kernel/enclave/record-keys/tombstone.d.ts +3 -2
  213. package/dist/kernel/errors.d.ts +71 -12
  214. package/dist/kernel/merge-authority.d.ts +25 -0
  215. package/dist/kernel/noydb.d.ts +27 -4
  216. package/dist/kernel/query/builder.d.ts +15 -2
  217. package/dist/kernel/query/join.d.ts +27 -0
  218. package/dist/kernel/sync-policy.d.ts +0 -2
  219. package/dist/kernel/tier-visibility.d.ts +15 -0
  220. package/dist/kernel/types.d.ts +145 -12
  221. package/dist/kernel/vault.d.ts +22 -18
  222. package/dist/kernel/via/index.d.ts +11 -2
  223. package/dist/{ledger-4WJL66BW.js → ledger-MVPNG5OS.js} +11 -11
  224. package/dist/liberate-4LOJOLDT.js +24 -0
  225. package/dist/{link-set-N4ZPV6E6.js → link-set-3POMQR3I.js} +11 -11
  226. package/dist/{managed-secret-OTHS64IF.js → managed-secret-IARIJJ7Q.js} +11 -3
  227. package/dist/materialized-views/index.js +22 -21
  228. package/dist/migrate-cek-XM2ETTZW.js +19 -0
  229. package/dist/migrate-cek-XM2ETTZW.js.map +1 -0
  230. package/dist/money/index.js +12 -8
  231. package/dist/noydb-IRILUDED.js +84 -0
  232. package/dist/overlay-views/index.js +4 -4
  233. package/dist/periods/index.js +22 -12
  234. package/dist/pod/index.js +75 -86
  235. package/dist/pod-handle-MELERCKU.js +41 -0
  236. package/dist/pod-handle-MELERCKU.js.map +1 -0
  237. package/dist/policy/index.js +11 -4
  238. package/dist/port/to/index.d.ts +4 -4
  239. package/dist/port/to/locator.d.ts +54 -8
  240. package/dist/port/with/i18n-strategy.d.ts +4 -1
  241. package/dist/port/with/lookup-strategy.d.ts +4 -1
  242. package/dist/port/with/merge-authority.d.ts +52 -0
  243. package/dist/port/with/service-bus.d.ts +0 -4
  244. package/dist/port/with/strategies.d.ts +2 -0
  245. package/dist/port/with/team-strategy.d.ts +5 -1
  246. package/dist/portability/index.js +8 -8
  247. package/dist/{post-register-ZAG2CAIY.js → post-register-Z5T7FY45.js} +6 -6
  248. package/dist/query/index.js +3 -3
  249. package/dist/reduce/index.js +4 -4
  250. package/dist/register-UZ37QPDB.js +32 -0
  251. package/dist/registry-ETJNA7PO.js +9 -0
  252. package/dist/registry-F7U6KSLX.js +9 -0
  253. package/dist/registry-L4ELKX6C.js +18 -0
  254. package/dist/registry-SDT5LIGO.js +19 -0
  255. package/dist/request-withdrawal-PVFEYX57.js +31 -0
  256. package/dist/{reveal-CMOJY4VO.js → reveal-DQ2E3QAZ.js} +6 -6
  257. package/dist/revoke-YXY6SHUH.js +24 -0
  258. package/dist/satellites/index.js +1 -1
  259. package/dist/schema-update/index.js +2 -2
  260. package/dist/sealed-record/index.js +20 -13
  261. package/dist/sealed-record/index.js.map +1 -1
  262. package/dist/search/index.js +4 -4
  263. package/dist/{seed-UK4QRIUN.js → seed-DZ4ORU5N.js} +19 -22
  264. package/dist/seed-DZ4ORU5N.js.map +1 -0
  265. package/dist/sequence/index.js +9 -9
  266. package/dist/session/index.js +10 -10
  267. package/dist/shadow/index.js +2 -2
  268. package/dist/share-link/index.js +1 -1
  269. package/dist/signer-Q7XQBMPA.js +25 -0
  270. package/dist/snapshots/index.js +10 -10
  271. package/dist/snapshots/index.js.map +1 -1
  272. package/dist/{stale-ZWXSOWJI.js → stale-NI7SAXAZ.js} +10 -10
  273. package/dist/storage-3VNGSHXS.js +23 -0
  274. package/dist/{store-coordination-provider-PB6QZ57W.js → store-coordination-provider-TYKNR3OU.js} +18 -12
  275. package/dist/store-coordination-provider-TYKNR3OU.js.map +1 -0
  276. package/dist/sync/index.js +11 -11
  277. package/dist/team/index.js +15 -14
  278. package/dist/tiers/index.js +11 -10
  279. package/dist/to/index.js +17 -9
  280. package/dist/to/index.js.map +1 -1
  281. package/dist/transactions/index.js +4 -4
  282. package/dist/{ulid-PTAIMDG4.js → ulid-VQW6ERQN.js} +2 -2
  283. package/dist/util/index.js +1 -1
  284. package/dist/vault-head/index.js +115 -0
  285. package/dist/vault-head/index.js.map +1 -0
  286. package/dist/{verify-RO5RTZOJ.js → verify-6J2YLKSO.js} +5 -5
  287. package/dist/via/lookup/handle.d.ts +4 -1
  288. package/dist/via/money/exact.d.ts +44 -0
  289. package/dist/via/money/index.d.ts +2 -0
  290. package/dist/via/money/normalize.d.ts +20 -0
  291. package/dist/walk-WRA7RAPY.js +21 -0
  292. package/dist/with-audit/guards/immutable-guard.d.ts +14 -0
  293. package/dist/with-audit/periods/active.d.ts +28 -1
  294. package/dist/with-audit/periods/index.d.ts +4 -2
  295. package/dist/with-audit/periods/periods.d.ts +161 -6
  296. package/dist/with-audit/periods/strategy.d.ts +14 -5
  297. package/dist/with-audit/periods/vault-facade.d.ts +89 -10
  298. package/dist/with-audit/periods/window.d.ts +10 -0
  299. package/dist/with-audit/sealed-record/index.d.ts +13 -0
  300. package/dist/with-audit/tiers/index.d.ts +17 -2
  301. package/dist/with-cargo/adopt-partition.d.ts +1 -1
  302. package/dist/with-cargo/extract-partition.d.ts +1 -1
  303. package/dist/with-cargo/index.d.ts +2 -2
  304. package/dist/with-commit/history/history.d.ts +26 -0
  305. package/dist/with-commit/history/index.d.ts +2 -1
  306. package/dist/with-commit/history/ledger/store.d.ts +7 -1
  307. package/dist/with-commit/history/strategy.d.ts +11 -1
  308. package/dist/with-commit/numbering/index.d.ts +0 -5
  309. package/dist/with-commit/vault-head/active.d.ts +2 -0
  310. package/dist/with-commit/vault-head/head.d.ts +28 -0
  311. package/dist/with-commit/vault-head/index.d.ts +10 -0
  312. package/dist/with-commit/vault-head/strategy.d.ts +127 -0
  313. package/dist/with-commit/vault-head/verify.d.ts +90 -0
  314. package/dist/with-formula/materialized-views/types.d.ts +52 -0
  315. package/dist/with-party/directory/cover/storage.d.ts +0 -8
  316. package/dist/with-party/directory/storage.d.ts +0 -11
  317. package/dist/with-party/directory/visibility.d.ts +0 -21
  318. package/dist/with-party/policy/storage.d.ts +0 -10
  319. package/dist/with-party/team/index.d.ts +1 -1
  320. package/dist/with-party/team/keyring.d.ts +149 -3
  321. package/dist/with-party/team/noydb-facade.d.ts +5 -1
  322. package/dist/with-party/team/roster-tag.d.ts +101 -0
  323. package/dist/with-party/team/tiers.d.ts +2 -1
  324. package/dist/with-pod/format.d.ts +10 -12
  325. package/dist/with-pod/index.d.ts +10 -10
  326. package/dist/with-pod/open.d.ts +2 -2
  327. package/dist/with-pod/pod-handle.d.ts +19 -0
  328. package/dist/with-pod/pod-store.d.ts +0 -8
  329. package/dist/with-pod/{bundle.d.ts → pod.d.ts} +26 -19
  330. package/dist/with-pod/ulid.d.ts +1 -1
  331. package/dist/with-shape/blobs/blob-set.d.ts +2 -2
  332. package/dist/with-shape/introspection/index.d.ts +1 -0
  333. package/dist/with-sync/engine.d.ts +54 -5
  334. package/dist/with-sync/strategy.d.ts +3 -0
  335. package/dist/withdraw-accessible-4JTDFRFZ.js +28 -0
  336. package/package.json +13 -5
  337. package/dist/api-WVY3H3YH.js +0 -20
  338. package/dist/backup-YYBE5RPC.js.map +0 -1
  339. package/dist/bundle-handle-JEUWU2SJ.js +0 -36
  340. package/dist/bundle-handle-JEUWU2SJ.js.map +0 -1
  341. package/dist/chunk-26JMGSSC.js.map +0 -1
  342. package/dist/chunk-3737A6EA.js.map +0 -1
  343. package/dist/chunk-4MC5JRRX.js.map +0 -1
  344. package/dist/chunk-52QYGZHH.js.map +0 -1
  345. package/dist/chunk-55LKVALY.js.map +0 -1
  346. package/dist/chunk-5PR33AC4.js.map +0 -1
  347. package/dist/chunk-66W5OOCX.js.map +0 -1
  348. package/dist/chunk-7G6VDWXB.js.map +0 -1
  349. package/dist/chunk-A67356IR.js.map +0 -1
  350. package/dist/chunk-AFHQATY4.js +0 -47
  351. package/dist/chunk-AFHQATY4.js.map +0 -1
  352. package/dist/chunk-AHLJSVRL.js.map +0 -1
  353. package/dist/chunk-C2OOEM57.js.map +0 -1
  354. package/dist/chunk-DIMKRG2E.js +0 -131
  355. package/dist/chunk-DIMKRG2E.js.map +0 -1
  356. package/dist/chunk-E6427JU2.js.map +0 -1
  357. package/dist/chunk-E7OBCBXS.js.map +0 -1
  358. package/dist/chunk-EDXAQ6JI.js.map +0 -1
  359. package/dist/chunk-EP7VPR7Y.js.map +0 -1
  360. package/dist/chunk-ERB6NDDW.js.map +0 -1
  361. package/dist/chunk-G5APARUV.js.map +0 -1
  362. package/dist/chunk-GASWQ3XG.js.map +0 -1
  363. package/dist/chunk-GLKDWWNO.js.map +0 -1
  364. package/dist/chunk-HNGSV2YC.js.map +0 -1
  365. package/dist/chunk-I4F6PKUK.js.map +0 -1
  366. package/dist/chunk-I4ZAO7F7.js.map +0 -1
  367. package/dist/chunk-I6SDX7WX.js.map +0 -1
  368. package/dist/chunk-JXIDGFKS.js.map +0 -1
  369. package/dist/chunk-LWSJG3LI.js.map +0 -1
  370. package/dist/chunk-MWKDOHEF.js.map +0 -1
  371. package/dist/chunk-MZ5ZFO2D.js.map +0 -1
  372. package/dist/chunk-NIVEDYJZ.js.map +0 -1
  373. package/dist/chunk-NWCGDAV6.js +0 -45
  374. package/dist/chunk-NWCGDAV6.js.map +0 -1
  375. package/dist/chunk-PJNTR2NV.js.map +0 -1
  376. package/dist/chunk-PRDRGL73.js.map +0 -1
  377. package/dist/chunk-PY7CI6L5.js.map +0 -1
  378. package/dist/chunk-RKKORO4M.js.map +0 -1
  379. package/dist/chunk-TAGFGKHP.js.map +0 -1
  380. package/dist/chunk-TDJPS3T2.js.map +0 -1
  381. package/dist/chunk-TOAIYQJR.js.map +0 -1
  382. package/dist/chunk-UHXCLPGC.js.map +0 -1
  383. package/dist/chunk-UIBGXRDD.js.map +0 -1
  384. package/dist/chunk-V5KYPBUR.js.map +0 -1
  385. package/dist/chunk-VCETL77O.js.map +0 -1
  386. package/dist/chunk-VN45YLWM.js.map +0 -1
  387. package/dist/chunk-VOQW5LAM.js.map +0 -1
  388. package/dist/chunk-VRA4Q7DA.js.map +0 -1
  389. package/dist/chunk-VV4NSB7P.js.map +0 -1
  390. package/dist/chunk-W5W6KHN2.js.map +0 -1
  391. package/dist/chunk-WHJKIZS7.js.map +0 -1
  392. package/dist/chunk-WYZ5MYUA.js.map +0 -1
  393. package/dist/chunk-ZJADGNYF.js.map +0 -1
  394. package/dist/chunk-ZNACADFG.js.map +0 -1
  395. package/dist/collection-facade-QN5ULWYC.js +0 -45
  396. package/dist/delegation-SSEPLXXO.js.map +0 -1
  397. package/dist/derive-6V3PIZF7.js +0 -22
  398. package/dist/executor-CYJQLKKI.js +0 -9
  399. package/dist/executor-FHHLXO4Y.js +0 -28
  400. package/dist/executor-S4QIKEHW.js +0 -9
  401. package/dist/export-accessible-PE5AYKZR.js +0 -23
  402. package/dist/extract-partition-X2L26O6A.js +0 -38
  403. package/dist/fanout-sidecar-DTBIDOWF.js.map +0 -1
  404. package/dist/find-RBBYKXI7.js +0 -11
  405. package/dist/issue-RNU55YOF.js +0 -19
  406. package/dist/liberate-PX4CAT5V.js +0 -24
  407. package/dist/noydb-YPSEGK32.js +0 -83
  408. package/dist/register-TMD6YRCX.js +0 -32
  409. package/dist/registry-CZVINVQH.js +0 -9
  410. package/dist/registry-FVLDWQKT.js +0 -18
  411. package/dist/registry-IKUR2MXD.js +0 -9
  412. package/dist/registry-JET4HBLY.js +0 -19
  413. package/dist/request-withdrawal-RH55LNZL.js +0 -31
  414. package/dist/revoke-R5TBYVA6.js +0 -24
  415. package/dist/seed-UK4QRIUN.js.map +0 -1
  416. package/dist/signer-AGALOXOO.js +0 -25
  417. package/dist/storage-N7LB275C.js +0 -23
  418. package/dist/store-coordination-provider-PB6QZ57W.js.map +0 -1
  419. package/dist/walk-OCUHCYJ6.js +0 -21
  420. package/dist/with-pod/bundle-handle.d.ts +0 -9
  421. package/dist/withdraw-accessible-QQNWM5BO.js +0 -28
  422. /package/dist/{api-WVY3H3YH.js.map → api-EYNT6KGS.js.map} +0 -0
  423. /package/dist/{chunk-35EBKWQU.js.map → chunk-2LFOMUEA.js.map} +0 -0
  424. /package/dist/{chunk-OF3L2SD6.js.map → chunk-32B7VCKU.js.map} +0 -0
  425. /package/dist/{chunk-MSWYQLMQ.js.map → chunk-3B6S6RSI.js.map} +0 -0
  426. /package/dist/{chunk-7F4DBNSP.js.map → chunk-3O72ZD2E.js.map} +0 -0
  427. /package/dist/{chunk-FNSMZQS4.js.map → chunk-3PMFMUFX.js.map} +0 -0
  428. /package/dist/{chunk-FAXZQ5UF.js.map → chunk-4RAS6HN6.js.map} +0 -0
  429. /package/dist/{chunk-VMCCGUQB.js.map → chunk-6JPGVL7X.js.map} +0 -0
  430. /package/dist/{chunk-WLYIROCJ.js.map → chunk-6YD5SYQS.js.map} +0 -0
  431. /package/dist/{chunk-YAWK6AWF.js.map → chunk-7KAE7CQ2.js.map} +0 -0
  432. /package/dist/{chunk-NKH7GSIH.js.map → chunk-AUPSEJ7O.js.map} +0 -0
  433. /package/dist/{chunk-CCZJJ4I2.js.map → chunk-B6IYATME.js.map} +0 -0
  434. /package/dist/{chunk-4UVDI4XE.js.map → chunk-CLAHBPOI.js.map} +0 -0
  435. /package/dist/{chunk-HVQGCKY4.js.map → chunk-D3R7Q4QK.js.map} +0 -0
  436. /package/dist/{chunk-P7OG2ETF.js.map → chunk-DXKLLKME.js.map} +0 -0
  437. /package/dist/{chunk-JIUVJ4M7.js.map → chunk-EKEIEJL6.js.map} +0 -0
  438. /package/dist/{chunk-DG27IUVI.js.map → chunk-FS7NTGCJ.js.map} +0 -0
  439. /package/dist/{chunk-HXGUIPQB.js.map → chunk-GQXFOAYZ.js.map} +0 -0
  440. /package/dist/{chunk-BTVYJWSN.js.map → chunk-GTHVPVAR.js.map} +0 -0
  441. /package/dist/{chunk-DMQCLZ4Z.js.map → chunk-GWO2IDAB.js.map} +0 -0
  442. /package/dist/{chunk-6HFM7EIT.js.map → chunk-H3G4I3PN.js.map} +0 -0
  443. /package/dist/{chunk-VJFMXYKP.js.map → chunk-HR5R5JOM.js.map} +0 -0
  444. /package/dist/{chunk-FDX7OWWI.js.map → chunk-HYYVT2KZ.js.map} +0 -0
  445. /package/dist/{chunk-JRCYZEHU.js.map → chunk-I6QKB7MT.js.map} +0 -0
  446. /package/dist/{chunk-KUDZVJKQ.js.map → chunk-IJ46VCWD.js.map} +0 -0
  447. /package/dist/{chunk-4HDYQL3J.js.map → chunk-INMHEMXX.js.map} +0 -0
  448. /package/dist/{chunk-AR2JDFAE.js.map → chunk-KV6JM2IA.js.map} +0 -0
  449. /package/dist/{chunk-PVU7LW5L.js.map → chunk-KX57HODD.js.map} +0 -0
  450. /package/dist/{chunk-CEJWMBXO.js.map → chunk-LXECF2ZR.js.map} +0 -0
  451. /package/dist/{chunk-7VHY5E3X.js.map → chunk-MSLPDFK2.js.map} +0 -0
  452. /package/dist/{chunk-HNHCQ556.js.map → chunk-NR2SUJ3H.js.map} +0 -0
  453. /package/dist/{chunk-W3TVWF6N.js.map → chunk-OIBEJN5H.js.map} +0 -0
  454. /package/dist/{chunk-QD724WDJ.js.map → chunk-OMYCSTXL.js.map} +0 -0
  455. /package/dist/{chunk-Z45YRGFO.js.map → chunk-ONVD6GBY.js.map} +0 -0
  456. /package/dist/{chunk-KCQX65FU.js.map → chunk-RKCRPPNB.js.map} +0 -0
  457. /package/dist/{chunk-7TSYBD3E.js.map → chunk-RSXQNFGO.js.map} +0 -0
  458. /package/dist/{chunk-7NXHMW6Y.js.map → chunk-SYS46BL7.js.map} +0 -0
  459. /package/dist/{chunk-747LRSOO.js.map → chunk-TMBSPLUG.js.map} +0 -0
  460. /package/dist/{chunk-WKPJXWKR.js.map → chunk-TX5MKAHA.js.map} +0 -0
  461. /package/dist/{chunk-NJDQ4YSV.js.map → chunk-YKXZHUOW.js.map} +0 -0
  462. /package/dist/{chunk-VW6ZZGCG.js.map → chunk-ZLHHE5XZ.js.map} +0 -0
  463. /package/dist/{chunk-FUHKW252.js.map → chunk-ZZXLB6AS.js.map} +0 -0
  464. /package/dist/{classified-marker-FTOX7Q5L.js.map → classified-marker-NA6HUV33.js.map} +0 -0
  465. /package/dist/{collection-facade-QN5ULWYC.js.map → collection-facade-VBM35WAH.js.map} +0 -0
  466. /package/dist/{computed-6G5M3UPH.js.map → computed-GSTLWSY5.js.map} +0 -0
  467. /package/dist/{dead-filter-ENRIOQIE.js.map → dead-filter-UALP5DJX.js.map} +0 -0
  468. /package/dist/{derive-6V3PIZF7.js.map → derive-YUO3TQYN.js.map} +0 -0
  469. /package/dist/{dispatch-RE74SH6L.js.map → dispatch-4ZHLSFZQ.js.map} +0 -0
  470. /package/dist/{dispatch-BDVGYC6X.js.map → dispatch-77CB75KB.js.map} +0 -0
  471. /package/dist/{enclave-52VUXNRL.js.map → enclave-O4NOROCJ.js.map} +0 -0
  472. /package/dist/{executor-CYJQLKKI.js.map → executor-CZDXBXKE.js.map} +0 -0
  473. /package/dist/{executor-FHHLXO4Y.js.map → executor-DVJAWN3B.js.map} +0 -0
  474. /package/dist/{executor-S4QIKEHW.js.map → executor-VRLG4TQJ.js.map} +0 -0
  475. /package/dist/{export-accessible-PE5AYKZR.js.map → export-accessible-UXSMG7AB.js.map} +0 -0
  476. /package/dist/{extract-partition-X2L26O6A.js.map → extract-partition-TVY7AMKH.js.map} +0 -0
  477. /package/dist/{find-RBBYKXI7.js.map → find-WSARMJBW.js.map} +0 -0
  478. /package/dist/{issue-RNU55YOF.js.map → issue-3JNJNPT3.js.map} +0 -0
  479. /package/dist/{ledger-4WJL66BW.js.map → ledger-MVPNG5OS.js.map} +0 -0
  480. /package/dist/{liberate-PX4CAT5V.js.map → liberate-4LOJOLDT.js.map} +0 -0
  481. /package/dist/{link-set-N4ZPV6E6.js.map → link-set-3POMQR3I.js.map} +0 -0
  482. /package/dist/{managed-secret-OTHS64IF.js.map → managed-secret-IARIJJ7Q.js.map} +0 -0
  483. /package/dist/{noydb-YPSEGK32.js.map → noydb-IRILUDED.js.map} +0 -0
  484. /package/dist/{post-register-ZAG2CAIY.js.map → post-register-Z5T7FY45.js.map} +0 -0
  485. /package/dist/{register-TMD6YRCX.js.map → register-UZ37QPDB.js.map} +0 -0
  486. /package/dist/{registry-CZVINVQH.js.map → registry-ETJNA7PO.js.map} +0 -0
  487. /package/dist/{registry-FVLDWQKT.js.map → registry-F7U6KSLX.js.map} +0 -0
  488. /package/dist/{registry-IKUR2MXD.js.map → registry-L4ELKX6C.js.map} +0 -0
  489. /package/dist/{registry-JET4HBLY.js.map → registry-SDT5LIGO.js.map} +0 -0
  490. /package/dist/{request-withdrawal-RH55LNZL.js.map → request-withdrawal-PVFEYX57.js.map} +0 -0
  491. /package/dist/{reveal-CMOJY4VO.js.map → reveal-DQ2E3QAZ.js.map} +0 -0
  492. /package/dist/{revoke-R5TBYVA6.js.map → revoke-YXY6SHUH.js.map} +0 -0
  493. /package/dist/{signer-AGALOXOO.js.map → signer-Q7XQBMPA.js.map} +0 -0
  494. /package/dist/{stale-ZWXSOWJI.js.map → stale-NI7SAXAZ.js.map} +0 -0
  495. /package/dist/{storage-N7LB275C.js.map → storage-3VNGSHXS.js.map} +0 -0
  496. /package/dist/{ulid-PTAIMDG4.js.map → ulid-VQW6ERQN.js.map} +0 -0
  497. /package/dist/{verify-RO5RTZOJ.js.map → verify-6J2YLKSO.js.map} +0 -0
  498. /package/dist/{walk-OCUHCYJ6.js.map → walk-WRA7RAPY.js.map} +0 -0
  499. /package/dist/{withdraw-accessible-QQNWM5BO.js.map → withdraw-accessible-4JTDFRFZ.js.map} +0 -0
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The vault head's storage layer (#1044).
3
+ *
4
+ * A bucket is an ordinary encrypted record at `_head/<collection>::<n>`, so it
5
+ * inherits #1041's identity binding for free: the store cannot relocate a
6
+ * bucket, re-author it, or serve one bucket's bytes as another's. What it can
7
+ * still do is serve an OLD bucket, which is why {@link readBucket} enforces
8
+ * monotonicity against the caller's own record of what it last wrote.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+ import { type EnclaveKey } from '../../kernel/enclave/index.js';
13
+ import type { NoydbStore } from '../../kernel/types.js';
14
+ /** `{ recordId → version }` for one bucket. */
15
+ export type BucketBody = Record<string, number>;
16
+ /**
17
+ * FNV-1a over `collection/id`. A hash, not a cipher: the bucket a record lands
18
+ * in is not secret — the store already sees which bucket was written, and it
19
+ * already saw the record's own address. Choosing something stronger would buy
20
+ * nothing and cost every write.
21
+ */
22
+ export declare function bucketIndex(collection: string, id: string, buckets: number): number;
23
+ export declare function bucketId(collection: string, id: string, buckets: number): string;
24
+ export declare function readBucket(store: NoydbStore, vault: string, dek: EnclaveKey, bucket: string): Promise<{
25
+ body: BucketBody;
26
+ version: number;
27
+ }>;
28
+ export declare function writeBucket(store: NoydbStore, vault: string, dek: EnclaveKey, bucket: string, body: BucketBody, expectedVersion: number): Promise<void>;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `@noy-db/hub/vault-head` — detect a store that WITHHOLDS (#1044).
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ export { withVaultHead } from './active.js';
7
+ export { verifyVaultHead, type HeadDiscrepancy, type HeadVerifyResult, type HeadVerdict, type HeadUnverifiableReason } from './verify.js';
8
+ export { NO_VAULT_HEAD, VAULT_HEAD_COLLECTION, DEFAULT_HEAD_BUCKETS, type VaultHeadStrategy, type WithVaultHeadOptions, type HeadEntry, } from './strategy.js';
9
+ export type { NoydbStore, EncryptedEnvelope } from '../../kernel/types.js';
10
+ export type { EnclaveKey } from '../../kernel/enclave/index.js';
@@ -0,0 +1,127 @@
1
+ /**
2
+ * `withVaultHead()` — the opt-in detector for **omission** (#1044).
3
+ *
4
+ * ## What it is for, and what it deliberately is not
5
+ *
6
+ * #1041 made every envelope self-authenticating at its identity, and #1042
7
+ * made the merge reject one that is not. What neither can catch is **absence**:
8
+ * a store that serves a genuine, unmodified `v1` when `v7` exists, or serves
9
+ * nothing at all. An authentic old envelope is indistinguishable from an
10
+ * authentic current one without external knowledge of what *should* be there.
11
+ *
12
+ * The head is that external knowledge: an authenticated `{id → version}`
13
+ * manifest the client writes and the store cannot forge. It is **not** a Merkle
14
+ * chain over content — content integrity is already handled, so the head needs
15
+ * only versions.
16
+ *
17
+ * ## Why it is opt-in when AAD is not
18
+ *
19
+ * AAD costs nothing to coordinate and closes *alteration*, so it is kernel. The
20
+ * head costs a write per commit and needs anti-entropy; on a single-device
21
+ * offline vault it defends against nothing. Making it kernel would tax every
22
+ * user for a multi-writer property. ADR 0003, Decision 3.
23
+ *
24
+ * `SECURITY.md` states the split exactly: a store cannot alter, relocate,
25
+ * re-tier, re-author or rewind a record; **without `withVaultHead()` it can
26
+ * still withhold or omit.**
27
+ *
28
+ * ## Bucketed, and why that is not a compromise
29
+ *
30
+ * ADR 0003 left head granularity open and asked for it to be sized early.
31
+ * Measured, at the documented 50K-record vault ceiling:
32
+ *
33
+ * | shape | write cost per commit | detection |
34
+ * |---|---|---|
35
+ * | one per-vault manifest | **1.1 MiB** | per-record |
36
+ * | one per collection | the same problem, renamed | per-record |
37
+ * | **bucketed, 256 buckets** | **~4.4 KiB** | per-record |
38
+ *
39
+ * Bucketing changes *only* write amplification. Each bucket still lists every
40
+ * one of its records' versions, so detection stays per-record — which is why
41
+ * this is not a trade-off between cost and strength. Verifying one pulled
42
+ * record reads one bucket rather than a megabyte.
43
+ *
44
+ * ## Wired as a bus OBSERVER, not a call in `collection.ts`
45
+ *
46
+ * That is what `kernel-surface` means by "register on the ServiceBus instead of
47
+ * growing this file", and it keeps the hot write path untouched for anyone who
48
+ * has not opted in: nothing is registered at all, so `hasHandlers` stays false
49
+ * and the dispatch never happens.
50
+ *
51
+ * Both `afterPut` AND `afterDelete`, because a delete is a version bump like
52
+ * any other. A head that stopped tracking deleted records would let a store
53
+ * resurrect one by withholding the tombstone — precisely the omission this
54
+ * exists to catch.
55
+ *
56
+ * ⚠️ The registration must be UNCONDITIONAL on anything but `enabled`. Its first
57
+ * draft sat inside `#registerForgetHooks()`, which returns early when no forget
58
+ * subjects are declared, so the head silently recorded nothing unless the vault
59
+ * happened to use an unrelated feature. The tests caught it only because they
60
+ * asserted a COUNT rather than "no error" — a head that records nothing raises
61
+ * no errors and sweeps perfectly clean.
62
+ *
63
+ * @packageDocumentation
64
+ */
65
+ import type { NoydbStore, EncryptedEnvelope } from '../../kernel/types.js';
66
+ import type { EnclaveKey } from '../../kernel/enclave/index.js';
67
+ /** Reserved collection the head's buckets live in. */
68
+ export declare const VAULT_HEAD_COLLECTION: "_head";
69
+ /** Default bucket count — see the sizing table above. */
70
+ export declare const DEFAULT_HEAD_BUCKETS = 256;
71
+ export interface WithVaultHeadOptions {
72
+ /**
73
+ * How many buckets the manifest is split across. Higher means smaller writes
74
+ * and more reads to sweep the whole vault; lower means the opposite.
75
+ * Changing it on an existing vault re-homes every entry, so treat it as a
76
+ * layout decision rather than a tuning knob.
77
+ */
78
+ readonly buckets?: number;
79
+ }
80
+ /** One record's expected state, as the client last committed it. */
81
+ export interface HeadEntry {
82
+ readonly collection: string;
83
+ readonly id: string;
84
+ readonly version: number;
85
+ }
86
+ export interface VaultHeadStrategy {
87
+ /**
88
+ * Is the head actually keeping a manifest?
89
+ *
90
+ * An explicit flag rather than an identity check against the stub: the kernel
91
+ * decides whether to register the write-path observer at all, and
92
+ * `port-layering` forbids it importing `NO_VAULT_HEAD` to compare. Without
93
+ * this, every write in a vault that never opted in would still pay a cache
94
+ * lookup and a no-op call.
95
+ */
96
+ readonly enabled: boolean;
97
+ /** Bucket a record id lands in — pure, so callers can pre-group a batch. */
98
+ bucketFor(collection: string, id: string): string;
99
+ /**
100
+ * Record `entry` as the client's expectation for that record.
101
+ *
102
+ * Called on every committed write, INSIDE the same logical operation, so
103
+ * there is no window where the record exists and the head does not know it.
104
+ */
105
+ note(store: NoydbStore, vault: string, getDEK: (collection: string) => Promise<EnclaveKey>, entry: HeadEntry): Promise<void>;
106
+ /**
107
+ * What the client expects for `collection/id`, or `null` if the head has
108
+ * never seen it.
109
+ */
110
+ expected(store: NoydbStore, vault: string, getDEK: (collection: string) => Promise<EnclaveKey>, collection: string, id: string): Promise<number | null>;
111
+ /**
112
+ * Every record the head knows about in `collection` — the set a sweep
113
+ * compares against what the store actually serves, which is how DELETION
114
+ * SUPPRESSION is caught. A withheld record is absent from the store but
115
+ * present here.
116
+ */
117
+ knownIn(store: NoydbStore, vault: string, getDEK: (collection: string) => Promise<EnclaveKey>, collection: string): Promise<ReadonlyMap<string, number>>;
118
+ }
119
+ /**
120
+ * The un-opted-in stub. `note` is a NO-OP rather than a throw: the write path
121
+ * calls it unconditionally, and a vault without the head must simply not keep
122
+ * one. The READ side throws, because asking what the head expects when there is
123
+ * no head is a caller error, not a silent "nothing to report" — the latter
124
+ * would look exactly like a clean sweep.
125
+ */
126
+ export declare const NO_VAULT_HEAD: VaultHeadStrategy;
127
+ export type { EncryptedEnvelope };
@@ -0,0 +1,90 @@
1
+ /**
2
+ * The sweep — comparing what the head expects against what the store serves (#1044).
3
+ *
4
+ * This is the only place absence becomes visible. #1041 and #1042 can reject a
5
+ * record that lies about itself; neither can notice one that never arrived, or
6
+ * one served at an older version than the client wrote. Both are indistinguishable
7
+ * from the truth without an independent record of what should be there.
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ import type { NoydbStore } from '../../kernel/types.js';
12
+ import type { EnclaveKey } from '../../kernel/enclave/index.js';
13
+ import type { VaultHeadStrategy } from './strategy.js';
14
+ /** One record the store is not serving faithfully. */
15
+ export interface HeadDiscrepancy {
16
+ readonly collection: string;
17
+ readonly id: string;
18
+ /** What the client last committed. */
19
+ readonly expected: number;
20
+ /**
21
+ * What the store serves now — or `null` when it serves nothing.
22
+ *
23
+ * The two are different attacks wearing the same result. `null` is
24
+ * **suppression**: the record is gone. A lower number is **rollback**: an
25
+ * authentic older version served in place of the current one, which is the
26
+ * case no amount of per-envelope authentication can see.
27
+ */
28
+ readonly actual: number | null;
29
+ readonly kind: 'withheld' | 'rolled-back';
30
+ }
31
+ /**
32
+ * Why a sweep could not reach a conclusion.
33
+ *
34
+ * - `'no-expectations'` — the head holds nothing for this collection. A fresh
35
+ * vault, a head switched on after the fact, or a **restore from a snapshot**:
36
+ * `_head` is `_`-prefixed, so `loadAll` excludes it and a restored vault has
37
+ * no head to compare against.
38
+ * - `'store-cannot-cas'` — the store does not advertise `capabilities.casAtomic`,
39
+ * so two writers racing on one bucket can silently lose an entry. A lost entry
40
+ * is a record the sweep stops expecting, which is a false clean.
41
+ */
42
+ export type HeadUnverifiableReason = 'no-expectations' | 'store-cannot-cas';
43
+ /**
44
+ * ## Three-way, deliberately (#1101)
45
+ *
46
+ * - `'verified'` — the head held expectations, every one was met, and the store
47
+ * can serialize head writes.
48
+ * - `'unverifiable'` — the sweep could not conclude. See `because`.
49
+ * - `'tampered'` — at least one discrepancy. Positive evidence, so it wins over
50
+ * any `unverifiable` reason present at the same time.
51
+ *
52
+ * **The middle value is the point, and collapsing it is wrong in a different
53
+ * direction each way:** folded into "clean" it hides withholding, which is the
54
+ * one thing this service exists to catch; folded into "tampered" it cries wolf
55
+ * on a vault that is merely unexamined.
56
+ *
57
+ * That is not hypothetical. #1044's own first bug was a head that recorded
58
+ * nothing and swept **perfectly clean** — the degraded state rendered
59
+ * identically to a healthy one, which is why its test asserts `checked` before
60
+ * anything else. A two-way verdict makes that state a supported outcome.
61
+ */
62
+ export type HeadVerdict = 'verified' | 'unverifiable' | 'tampered';
63
+ export interface HeadVerifyResult {
64
+ readonly verdict: HeadVerdict;
65
+ readonly checked: number;
66
+ readonly discrepancies: readonly HeadDiscrepancy[];
67
+ /**
68
+ * Non-empty only when `verdict === 'unverifiable'`.
69
+ *
70
+ * There is deliberately no `clean: boolean`. It could not distinguish "no
71
+ * expectations" from "all expectations met" — both rendered `true` — and that
72
+ * indistinguishability *was* the defect. Replacing it rather than keeping it
73
+ * alongside forces every caller to face the three-way.
74
+ */
75
+ readonly because: readonly HeadUnverifiableReason[];
76
+ }
77
+ /**
78
+ * Sweep one collection.
79
+ *
80
+ * **A record the store serves that the head does NOT know is not reported.**
81
+ * That is not an oversight: the head can be enabled on an existing vault, and
82
+ * every pre-existing record would otherwise read as an anomaly. The head's
83
+ * claim is one-directional — *what I wrote must still be there* — and an
84
+ * unknown record simply falls outside it.
85
+ *
86
+ * **A HIGHER version than expected is also not reported**, for the same reason:
87
+ * another device legitimately advanced it. The head detects going backwards, not
88
+ * moving forwards.
89
+ */
90
+ export declare function verifyVaultHead(head: VaultHeadStrategy, store: NoydbStore, vault: string, getDEK: (collection: string) => Promise<EnclaveKey>, collection: string): Promise<HeadVerifyResult>;
@@ -4,6 +4,7 @@ import type { ReduceSpec, Reduction } from '../../with-lookup/reduce/reduction.j
4
4
  import type { GroupedReduction } from '../../with-lookup/reduce/groupby.js';
5
5
  import type { JoinStrategy } from '../../kernel/query/join.js';
6
6
  import type { MoneyDescriptor } from '../../via/money/descriptor.js';
7
+ import type { ExactMath } from '../../via/money/exact.js';
7
8
  import type { I18nTextDescriptor } from '../../via/i18n/core.js';
8
9
  /**
9
10
  * Minimal vault-shaped accessor passed to the MV `query()` callback.
@@ -269,6 +270,57 @@ export interface MaterializedViewSpec<TRow extends Record<string, unknown>> {
269
270
  * UNION-mode only. Ignored if {@link query} is set.
270
271
  */
271
272
  aggregate?: ReduceSpec;
273
+ /**
274
+ * Post-aggregate projection over ONE finished row (#1007).
275
+ *
276
+ * `aggregate` accepts reducers only, so a row can carry every input a
277
+ * derived value needs and still not express it — `max(0, netTotal - paid)`
278
+ * is not a reduction. `derive` closes that gap: it receives the row the
279
+ * grouping/aggregation pipeline just produced and returns a patch merged
280
+ * onto it, immediately before materialisation.
281
+ *
282
+ * ```ts
283
+ * aggregate: { paid: sum('paid'), netTotal: sum('netTotal') },
284
+ * derive: (row) => ({ toPay: Math.max(0, row.netTotal - row.paid) }),
285
+ * ```
286
+ *
287
+ * Deliberately narrow, and the narrowness is what keeps it safe under
288
+ * incremental recompute: **pure, single-row, no cross-row access, no second
289
+ * aggregation pass.** It only ever sees the row the reducer just produced,
290
+ * so a refresh triggered by one source write recomputes it correctly without
291
+ * the engine needing to know anything about the function.
292
+ *
293
+ * Returning `null` / `undefined` leaves the row unchanged. Returned keys
294
+ * that collide with a {@link groupBy} field throw
295
+ * `MaterializedViewConfigError` — a group key is the row's identity and
296
+ * feeds {@link rowKey}, so rewriting it would silently re-home the row.
297
+ *
298
+ * **Money:** money leaves a reducer as an exact decimal string, and
299
+ * `Number(a) - Number(b)` would put it straight back through binary floating
300
+ * point — `10.05 - 0.10` becomes `9.950000000000001`, which the money
301
+ * quantiser then refuses rather than storing drift. So `derive` receives
302
+ * {@link ExactMath} as its second argument; it works in scaled BigInt and
303
+ * cannot introduce a representation error:
304
+ *
305
+ * ```ts
306
+ * moneyFields: { netTotal: THB, paid: THB, toPay: THB },
307
+ * derive: (row, exact) => ({ toPay: exact.max(0, exact.sub(row.netTotal, row.paid)) }),
308
+ * ```
309
+ *
310
+ * Declare the derived field in {@link moneyFields} and the result is
311
+ * quantised through that descriptor before storage, exact at its scale.
312
+ *
313
+ * Note the one place `TRow` under-describes what arrives: a field declared
314
+ * in {@link moneyFields} reaches `derive` DECODED — the decimal string a
315
+ * reader would see, not the scaled integer the reducer left behind — even
316
+ * where `TRow` types it as `number` (which is what the arms' `map` emits).
317
+ * `ExactMath` accepts both, which is why its operations are the right tool
318
+ * here and why no cast is needed.
319
+ *
320
+ * Applies to every MV form (union, projection, and query), always as the
321
+ * last step before rows are materialised.
322
+ */
323
+ derive?: (row: TRow, exact: ExactMath) => Record<string, unknown> | null | undefined;
272
324
  /**
273
325
  * Money descriptors for the UNION-mode aggregate, keyed by the
274
326
  * OUTPUT/intermediate field name as it appears in the mapped row and
@@ -1,11 +1,3 @@
1
- /**
2
- * Persistence helpers for `_meta/public-envelope` — the cover's
3
- * frozen wire location. Mirrors the bypass-AES pattern used by
4
- * `_meta/handle` and `_meta/policy` — the document is plaintext
5
- * JSON, the envelope's `_iv` field is left empty.
6
- *
7
- * @module
8
- */
9
1
  import type { NoydbStore } from '../../../kernel/types.js';
10
2
  import type { Cover } from './types.js';
11
3
  /**
@@ -1,14 +1,3 @@
1
- /**
2
- * Persistence helpers for the vault-level user-directory toggle
3
- * (`_meta/directory`). Mirrors the bypass-AES pattern used by
4
- * `_meta/policy` — the directory document is plain JSON, the
5
- * envelope's `_iv` field is left empty.
6
- *
7
- * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/user-envelope.md → Directory visibility
8
- * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/plaintext-bypass.md — every `_iv: ''` write site
9
- *
10
- * @module
11
- */
12
1
  import type { NoydbStore } from '../../kernel/types.js';
13
2
  import type { DirectoryConfig } from './types.js';
14
3
  /** Reserved collection name for vault-level metadata documents. */
@@ -1,24 +1,3 @@
1
- /**
2
- * Persistence helpers for the per-user visibility flag
3
- * (`_meta/visibility/<keyringId>`). Mirrors the bypass-AES pattern used
4
- * by `_meta/policy` — the visibility document is plain JSON, the
5
- * envelope's `_iv` field is left empty.
6
- *
7
- * Stored alongside the keyring file rather than inside the encrypted
8
- * user envelope (`_users/<keyringId>`) because:
9
- *
10
- * - `UserEnvelope<T>.data` is opaque-to-hub by contract — hub does not
11
- * introspect or reserve any keys inside it. Adding `hidden` there
12
- * would violate that contract.
13
- * - `listUsersWithEnvelopes` filters by the flag, and the filter must
14
- * work even when decryption fails (legacy keyrings predating the
15
- * envelope feature, or a corrupted envelope).
16
- *
17
- * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/user-envelope.md → Directory visibility
18
- * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/plaintext-bypass.md — every `_iv: ''` write site
19
- *
20
- * @module
21
- */
22
1
  import type { NoydbStore } from '../../kernel/types.js';
23
2
  import type { UserVisibility } from './types.js';
24
3
  /** Prefix for per-user visibility records inside `_meta`. */
@@ -1,13 +1,3 @@
1
- /**
2
- * Persistence helpers for the vault-level policy document
3
- * (`_meta/policy`). Mirrors the bypass-AES pattern used by
4
- * `_meta/handle` — the policy document is plain JSON, the envelope's
5
- * `_iv` field is left empty.
6
- *
7
- * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/session-tiers.md → Storage location
8
- *
9
- * @module
10
- */
11
1
  import type { NoydbStore, VaultPolicy } from '../../kernel/types.js';
12
2
  /** Reserved collection name for vault-level metadata documents. */
13
3
  export declare const META_COLLECTION = "_meta";
@@ -17,7 +17,7 @@ export { NO_TEAM, type TeamStrategy } from './strategy.js';
17
17
  export { TeamNotEnabledError } from '../../kernel/errors.js';
18
18
  export type { UnlockedKeyring } from './keyring.js';
19
19
  export { loadKeyring, createOwnerKeyring, grant, revoke, changeSecret, listUsers, listUsersWithEnvelopes, ensureCollectionDEK, persistKeyring, updateKeyringIdentity, buildRecipientKeyringFile, } from './keyring.js';
20
- export type { BundleRecipient, ListUsersOptions } from './keyring.js';
20
+ export type { PodRecipient, ListUsersOptions } from './keyring.js';
21
21
  export type { LoadKeyringOptions, CreateOwnerKeyringOptions, RotateKeysOptions, ChangeSecretOptions, } from './keyring.js';
22
22
  export { enrollAuthenticator, removeAuthenticator, updateAuthenticator, findAuthenticator, } from './authenticators.js';
23
23
  export type { EnrollAuthenticatorOptions, EnrollAuthenticatorWrappingKEKOptions, EnrollAuthenticatorWrappingDEKsOptions, UpdateAuthenticatorOptions, } from './authenticators.js';
@@ -1,5 +1,6 @@
1
1
  import type { NoydbStore, KeyringFile, KeyringAuthenticator, Role, Permissions, GrantOptions, RevokeOptions, UpdateUserOptions, UserInfo, EncryptedEnvelope, ExportCapability, ExportFormat, ImportCapability, VaultPolicyOnDisk, UserEnvelope } from '../../kernel/types.js';
2
2
  import { type EnclaveKey, type EchoSecretParts } from '../../kernel/enclave/index.js';
3
+ import type { KeyringTamperedReason } from '../../kernel/errors.js';
3
4
  import { type SecretPolicy, type EchoSecretPolicy } from '../../kernel/validation.js';
4
5
  import type { DeviceSealProvider } from './device-seal.js';
5
6
  /** In-memory representation of an unlocked keyring. */
@@ -9,6 +10,11 @@ export interface UnlockedKeyring {
9
10
  readonly role: Role;
10
11
  readonly permissions: Permissions;
11
12
  readonly deks: Map<string, EnclaveKey>;
13
+ /**
14
+ * Unwrapped counterpart of {@link KeyringFile.pending_deks} — an
15
+ * uncommitted rotation (#1074). Empty in the normal state.
16
+ */
17
+ readonly pendingDeks?: Map<string, EnclaveKey> | undefined;
12
18
  /**
13
19
  * The KEK, when this keyring was unlocked via tier 1 (secret) or
14
20
  * a wrap-KEK tier-2 method (WebAuthn / OIDC). `null` when the
@@ -72,6 +78,23 @@ export interface UnlockedKeyring {
72
78
  }
73
79
  /** Mint a fresh wrapped-canary string. Deterministic for a given KEK. */
74
80
  export declare function mintKeyringCanary(kek: EnclaveKey): Promise<string>;
81
+ /**
82
+ * The vault roster key held by this keyring, or `null` when the keyring
83
+ * carries none.
84
+ *
85
+ * Null is expected on the resume-style paths (`kek: null` sessions, tier-3
86
+ * PIN resume, plaintext mode) — none of which may write a keyring file.
87
+ * Every stamping site null-guards this exactly as it guards `kek`: minting a
88
+ * file without a verifiable `roster_tag` would be worse than refusing, since
89
+ * it is indistinguishable on the next load from a store having stripped it.
90
+ */
91
+ export declare function rosterKeyOf(keyring: UnlockedKeyring): EnclaveKey | null;
92
+ /**
93
+ * Shared wording for the stamping-site guards — mirrors the `kek` guard's shape.
94
+ * Exported so every roster-stamping site in the hub raises ONE error with one
95
+ * wording, rather than each hand-copying it (`peer-recover`, `liberate`).
96
+ */
97
+ export declare function requireRosterKey(keyring: UnlockedKeyring, fn: string): EnclaveKey;
75
98
  /** Options for {@link loadKeyring} (#846b). */
76
99
  export interface LoadKeyringOptions {
77
100
  /** The user whose keyring to unlock. */
@@ -168,6 +191,100 @@ export declare function createOwnerKeyring(store: NoydbStore, vault: string, opt
168
191
  export declare function grant(store: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, options: GrantOptions): Promise<void>;
169
192
  /** Revoke a user's access. Optionally rotate keys for affected collections. */
170
193
  export declare function revoke(store: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, options: RevokeOptions): Promise<void>;
194
+ /** What {@link verifyRoster} found. */
195
+ export interface RosterVerifyResult {
196
+ /**
197
+ * How many `_keyring` files were examined.
198
+ *
199
+ * Reported first, and deliberately: "nothing unverified" is equally true of a
200
+ * sweep that examined nothing, and a roster check that silently covered zero
201
+ * members would look identical to a healthy vault. Same lesson as the vault
202
+ * head's `no-expectations` verdict (#1101).
203
+ */
204
+ readonly checked: number;
205
+ /** The files that failed authentication, and why. */
206
+ readonly unverified: ReadonlyArray<{
207
+ readonly userId: string;
208
+ readonly reason: KeyringTamperedReason;
209
+ }>;
210
+ }
211
+ export declare function verifyRoster(store: NoydbStore, vault: string, callerKeyring: UnlockedKeyring): Promise<RosterVerifyResult>;
212
+ /** What {@link quarantineKeyring} did. */
213
+ export interface QuarantineResult {
214
+ readonly userId: string;
215
+ /** Why the file could not be authenticated — the justification for removing it. */
216
+ readonly reason: KeyringTamperedReason;
217
+ /** Collections re-keyed as part of the removal. */
218
+ readonly rotated: readonly string[];
219
+ /**
220
+ * (member, collection) pairs whose access the rotation dropped — the OTHER
221
+ * members, who must be re-granted.
222
+ *
223
+ * Passed through from `rotateKeys` rather than discarded, because a
224
+ * quarantine rotates broadly (see the scope note on the function) and so
225
+ * de-provisions more people than the one being removed. An operator who is
226
+ * not told this discovers it as unrelated `NoAccessError`s later.
227
+ */
228
+ readonly needsRegrant: RotateResult['needsRegrant'];
229
+ /**
230
+ * OTHER members whose own files also failed authentication, found while
231
+ * rotating. One forged file is rarely the only one, and the operator is
232
+ * already holding the tool for them.
233
+ */
234
+ readonly alsoUnverified: RotateResult['unverified'];
235
+ }
236
+ /**
237
+ * Remove a `_keyring` file that cannot be authenticated, and re-key behind it
238
+ * (#1121).
239
+ *
240
+ * ## Why this is not a flag on `revoke`
241
+ *
242
+ * `revoke` reads the target's own `role` to decide whether the caller may
243
+ * revoke them, so it cannot act on a file it will not trust — which left a
244
+ * forged file removable only by editing the store by hand. Relaxing `revoke`
245
+ * conditionally would grow the safe path a parameter that turns it into the
246
+ * dangerous one; ADR 0003's standing rule is that if the implementation needs
247
+ * to weaken a guard, the design is wrong. This is a separate operation with its
248
+ * own contract, so `revoke`'s invariant stays absolute and the dangerous act is
249
+ * named at the call site rather than hidden in an option bag.
250
+ *
251
+ * ## The two properties that keep it from being a backdoor
252
+ *
253
+ * 1. **It refuses a file that verifies.** Otherwise it would delete any keyring
254
+ * while ignoring `canRevoke` — including an owner's, which `revoke` protects
255
+ * unconditionally.
256
+ * 2. **Because of (1) it can safely ignore the claimed `role` — and it must.**
257
+ * `canRevoke` refuses any target whose role reads `owner`, so a store that
258
+ * forged `"role":"owner"` onto its victim would otherwise make them
259
+ * permanently unremovable. Consulting the forged field is exactly the
260
+ * mistake this operation exists to avoid.
261
+ *
262
+ * Owner-only: the narrowest role that can always act, and quarantine
263
+ * deliberately consumes NO field of the file it is removing.
264
+ *
265
+ * ## Why it rotates, and why the scope comes from the CALLER
266
+ *
267
+ * Deleting the file is not a revocation — the store may decline the delete, and
268
+ * the member may already hold unwrapped DEKs. So this rotates, exactly as
269
+ * `revoke` does. The scope is every collection the CALLER holds, not the
270
+ * target's DEK map: that map is unauthenticated (#1115), so deriving the scope
271
+ * from it would let the store choose which collections survive a quarantine.
272
+ *
273
+ * ⚠️ **That is the security-correct scope, and it is NOT free.** An earlier
274
+ * draft of this comment called over-rotating "the safe direction"; a review
275
+ * probe disproved it. Rotation re-keys `store.list(vault, <name>)` plus the
276
+ * derived refs `rotateKeys` knows about, so a DEK slot whose ciphertext lives
277
+ * under a *different* collection name — `_blob`, whose data sits in
278
+ * `_blob_index`/`_blob_chunks`, and the `collection#tier` slots — is re-keyed
279
+ * without its data being re-encrypted, and that data then fails to open. That
280
+ * gap belongs to `rotateKeys` (it is reachable through an ordinary `revoke` of
281
+ * a whole-vault grantee, with no quarantine involved) and is filed as #1122,
282
+ * but a quarantine takes the maximal scope *unconditionally*, so it meets the
283
+ * gap every time rather than occasionally. Until that is fixed, treat a
284
+ * quarantine as an emergency operation with a real blast radius, and read
285
+ * `needsRegrant` afterwards.
286
+ */
287
+ export declare function quarantineKeyring(store: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, userId: string): Promise<QuarantineResult>;
171
288
  /**
172
289
  * Mutate `role`, `displayName`, and/or `permissions` on an existing
173
290
  * keyring. Pure plaintext-header rewrite — no DEK rewrap, no KEK
@@ -217,6 +334,26 @@ export interface RotateResult {
217
334
  readonly userId: string;
218
335
  readonly collection: string;
219
336
  }>;
337
+ /**
338
+ * Members skipped because their `_keyring` file failed roster verification
339
+ * (#1114).
340
+ *
341
+ * Rotation hands a member re-wrapped DEKs, so skipping one gives them
342
+ * **less**, never more: the file is left untouched and its wrappings for the
343
+ * rotated collections go stale. That is the same fail-closed end state as
344
+ * `needsRegrant`, but it needs a different remedy and so gets a different
345
+ * field — a `needsRegrant` entry is fixed by `grant()`, whereas one of these
346
+ * is a file that no longer authenticates and cannot be repaired by granting
347
+ * over it.
348
+ *
349
+ * Before this existed, one such file threw and took `revoke` and
350
+ * `rotateKeys` down vault-wide — the two operations most needed when a
351
+ * roster is suspect.
352
+ */
353
+ readonly unverified: ReadonlyArray<{
354
+ readonly userId: string;
355
+ readonly reason: KeyringTamperedReason;
356
+ }>;
220
357
  }
221
358
  /** Options for {@link rotateKeys} (#846b — was a bare `string[]`). */
222
359
  export interface RotateKeysOptions {
@@ -261,7 +398,7 @@ export interface EchoRecipientSecret extends EchoSecretParts {
261
398
  *
262
399
  * @public
263
400
  */
264
- export interface BundleRecipient {
401
+ export interface PodRecipient {
265
402
  /** User id stamped onto the keyring file in the bundle. */
266
403
  readonly id: string;
267
404
  /** Optional display name. Defaults to `id`. */
@@ -312,7 +449,7 @@ export interface BundleRecipient {
312
449
  *
313
450
  * @internal
314
451
  */
315
- export declare function buildRecipientKeyringFile(callerKeyring: UnlockedKeyring, recipient: BundleRecipient): Promise<KeyringFile>;
452
+ export declare function buildRecipientKeyringFile(callerKeyring: UnlockedKeyring, recipient: PodRecipient): Promise<KeyringFile>;
316
453
  /** List all users with access to a vault. */
317
454
  export declare function listUsers(store: NoydbStore, vault: string): Promise<UserInfo[]>;
318
455
  /**
@@ -368,8 +505,17 @@ export declare function listUsersWithEnvelopes<T = unknown>(store: NoydbStore, v
368
505
  user: UserInfo;
369
506
  envelope: UserEnvelope<T> | null;
370
507
  }>>;
371
- /** Ensure a DEK exists for a collection. Generates one if new. */
372
508
  export declare function ensureCollectionDEK(store: NoydbStore, vault: string, keyring: UnlockedKeyring): Promise<(collectionName: string) => Promise<EnclaveKey>>;
509
+ /**
510
+ * The `Permissions` catch-all key (#1010). `Permissions` has always documented
511
+ * `'*'` as "the wildcard collection matching all collections in the vault", but
512
+ * nothing expanded it — a grantee handed the documented catch-all got no keys
513
+ * at all. It is honoured in three places, and they must agree: the DEK wrapping
514
+ * in `grant()`, and both permission checks below.
515
+ */
516
+ export declare const PERMISSION_WILDCARD = "*";
517
+ /** Does this permission map hand over the whole vault? */
518
+ export declare function permissionsAreWildcard(permissions: Permissions | undefined): boolean;
373
519
  /** Check if a user has write permission for a collection. */
374
520
  export declare function hasWritePermission(keyring: UnlockedKeyring, collectionName: string): boolean;
375
521
  /** Check if a user has any access to a collection. */
@@ -19,7 +19,7 @@
19
19
  * Internal service — reached through `noydb.team.rotateSecret(...)` etc.
20
20
  */
21
21
  import type { NoydbOptions, NoydbStore, KeyringAuthenticator } from '../../kernel/types.js';
22
- import type { RotateResult, RotateKeysOptions } from './keyring.js';
22
+ import type { RotateResult, RotateKeysOptions, RosterVerifyResult, QuarantineResult } from './keyring.js';
23
23
  import { type RotateSecretInput, type RecoverSecretInput, type RecoverSecretResult, type RotateRecoveryOptions, type RotateRecoveryResult, type EnrollRecoveryResult, type RecoveryEnrollmentInput, type RecoveryProof } from './rotate-recover.js';
24
24
  import { type RecoverUserOptions } from './peer-recover.js';
25
25
  import { type PaperRecoveryEntry, type ShamirRecoveryEntry } from './recovery.js';
@@ -74,6 +74,10 @@ export declare class TeamFacade {
74
74
  runRevoke(engine: (adapter: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, options: RevokeOptions) => Promise<void>, vault: string, options: RevokeOptions, factors?: FactorProofBundle): Promise<void>;
75
75
  /** Gate + run a `rotateKeys` engine. See `Noydb.rotate` for the public contract. */
76
76
  runRotate(engine: (store: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, opts: RotateKeysOptions) => Promise<RotateResult>, vault: string, collections: string[]): Promise<RotateResult>;
77
+ /** Gate + run the `verifyRoster` engine (#1121). See `Noydb.verifyRoster`. */
78
+ runVerifyRoster(engine: (store: NoydbStore, vault: string, callerKeyring: UnlockedKeyring) => Promise<RosterVerifyResult>, vault: string): Promise<RosterVerifyResult>;
79
+ /** Gate + run the `quarantineKeyring` engine (#1121). See `Noydb.quarantineKeyring`. */
80
+ runQuarantine(engine: (store: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, userId: string) => Promise<QuarantineResult>, vault: string, userId: string, factors?: FactorProofBundle): Promise<QuarantineResult>;
77
81
  /**
78
82
  * Add a tier-2 authenticator slot to the calling user's keyring.
79
83
  * Each slot independently wraps the SAME KEK under a method-specific