@noy-db/hub 0.2.0-pre.16 → 0.2.0-pre.18
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.
- package/dist/aggregate/index.cjs.map +1 -1
- package/dist/aggregate/index.d.cts +3 -2
- package/dist/aggregate/index.d.ts +3 -2
- package/dist/aggregate/index.js +4 -4
- package/dist/attestation/index.cjs.map +1 -1
- package/dist/attestation/index.d.cts +5 -3
- package/dist/attestation/index.d.ts +5 -3
- package/dist/attestation/index.js +6 -6
- package/dist/blobs/index.cjs +226 -11
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +6 -4
- package/dist/blobs/index.d.ts +6 -4
- package/dist/blobs/index.js +6 -5
- package/dist/blobs/index.js.map +1 -1
- package/dist/bundle/index.cjs +2065 -352
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +7 -5
- package/dist/bundle/index.d.ts +7 -5
- package/dist/bundle/index.js +21 -10
- package/dist/bundle/index.js.map +1 -1
- package/dist/{chunk-6RR3MNMG.js → chunk-2U226RDC.js} +3 -3
- package/dist/{chunk-L2BNJ6HM.js → chunk-32XVU2LT.js} +3 -3
- package/dist/{chunk-X73VS74Y.js → chunk-33DAO2XG.js} +2 -2
- package/dist/chunk-45643PAU.js +151 -0
- package/dist/chunk-45643PAU.js.map +1 -0
- package/dist/{chunk-QSUK7YWK.js → chunk-4UI5T3K7.js} +4 -4
- package/dist/{chunk-G4SCICH5.js → chunk-5KKNBDCT.js} +2 -2
- package/dist/{chunk-DUREQF5W.js → chunk-647TFNYL.js} +34 -8
- package/dist/chunk-647TFNYL.js.map +1 -0
- package/dist/{chunk-E2CDVKMH.js → chunk-6FHCU3QO.js} +5 -5
- package/dist/{chunk-F4OJZIWQ.js → chunk-6Q5XRLKG.js} +4 -4
- package/dist/{chunk-HOR4R722.js → chunk-6XEGHIBA.js} +30 -4
- package/dist/chunk-6XEGHIBA.js.map +1 -0
- package/dist/{chunk-4TBBMHVC.js → chunk-6YEC7LLO.js} +2 -2
- package/dist/{chunk-ZNQYHJXX.js → chunk-AB7JF2KF.js} +2 -2
- package/dist/{chunk-UMLVJTYV.js → chunk-ADB7GPM3.js} +7 -4
- package/dist/chunk-ADB7GPM3.js.map +1 -0
- package/dist/{chunk-XL35NSEN.js → chunk-BUBJYIZ7.js} +3 -3
- package/dist/chunk-C2OYWD5S.js +125 -0
- package/dist/chunk-C2OYWD5S.js.map +1 -0
- package/dist/{chunk-KABJXG2F.js → chunk-CMISAJAE.js} +195 -17
- package/dist/chunk-CMISAJAE.js.map +1 -0
- package/dist/{chunk-3YWP3WBP.js → chunk-DKMPR76W.js} +5 -5
- package/dist/{chunk-BI6ETQPF.js → chunk-DR5I7Q6N.js} +4 -4
- package/dist/{chunk-667MB6AH.js → chunk-F2IJ2HGD.js} +1370 -232
- package/dist/chunk-F2IJ2HGD.js.map +1 -0
- package/dist/{chunk-6H2ZUNR7.js → chunk-FQRAYDS4.js} +4 -4
- package/dist/{chunk-535SSHBS.js → chunk-HMFC6M2G.js} +99 -2
- package/dist/chunk-HMFC6M2G.js.map +1 -0
- package/dist/{chunk-TS26M2SB.js → chunk-HOO5I3VG.js} +2 -2
- package/dist/{chunk-OMAMZKKD.js → chunk-HWK75CYX.js} +2 -2
- package/dist/{chunk-TKIY625R.js → chunk-HZOEBM67.js} +2 -2
- package/dist/{chunk-DLZ2ONOD.js → chunk-IQ4GMEYZ.js} +6 -6
- package/dist/{chunk-XWH4MXIU.js → chunk-K3NYRK7U.js} +2 -2
- package/dist/{chunk-7BQ4QWYX.js → chunk-KOURQXIU.js} +23 -6
- package/dist/chunk-KOURQXIU.js.map +1 -0
- package/dist/{chunk-7Z7KSVA5.js → chunk-KQ523X3A.js} +15 -2
- package/dist/chunk-KQ523X3A.js.map +1 -0
- package/dist/{chunk-JD3OZAI4.js → chunk-KTZ2MHQK.js} +2 -2
- package/dist/{chunk-F3BPIPLS.js → chunk-LGPSCKWZ.js} +1 -1
- package/dist/chunk-LGPSCKWZ.js.map +1 -0
- package/dist/{chunk-SCJPI4Z5.js → chunk-LQ3GD5LL.js} +5 -5
- package/dist/{chunk-AAVWKNZW.js → chunk-M3H7VSRV.js} +2 -2
- package/dist/{chunk-BR3AMFGS.js → chunk-MGB67HKX.js} +5 -5
- package/dist/{chunk-GNI5STXQ.js → chunk-P57D4KBG.js} +52 -38
- package/dist/chunk-P57D4KBG.js.map +1 -0
- package/dist/{chunk-Z6FNBOTC.js → chunk-PDVP3C2I.js} +1 -1
- package/dist/{chunk-Z6FNBOTC.js.map → chunk-PDVP3C2I.js.map} +1 -1
- package/dist/{chunk-OB2ZJQ2D.js → chunk-PGVEL5IZ.js} +3 -3
- package/dist/{chunk-YULZKK4F.js → chunk-QJKZ5WUP.js} +37 -2
- package/dist/chunk-QJKZ5WUP.js.map +1 -0
- package/dist/{chunk-BQ65SS5A.js → chunk-QPJ7Z4L3.js} +2 -2
- package/dist/{chunk-CZI2A4MQ.js → chunk-RQFG2YSV.js} +3 -3
- package/dist/{chunk-CJORTUJ2.js → chunk-RZWQNMMP.js} +2 -2
- package/dist/{chunk-FFXM3ZIF.js → chunk-T4T5I5L6.js} +3 -3
- package/dist/{chunk-QVIEAYTP.js → chunk-TFAN3NFD.js} +3 -3
- package/dist/{chunk-Z4DO7YSI.js → chunk-TPOHMOGX.js} +2 -2
- package/dist/{chunk-VLMPU56Q.js → chunk-TTS3RWL5.js} +2 -2
- package/dist/{chunk-IXBIFDEW.js → chunk-VVDSDOVV.js} +4 -4
- package/dist/{chunk-FWPKCXTN.js → chunk-WZCG3EZ6.js} +2 -2
- package/dist/{chunk-HBXJ37ZY.js → chunk-Y5XVB75E.js} +4 -4
- package/dist/chunk-YWYW2YNO.js +129 -0
- package/dist/chunk-YWYW2YNO.js.map +1 -0
- package/dist/{chunk-IQLVUT37.js → chunk-Z3BE5BRK.js} +2 -2
- package/dist/{chunk-42FEUPZQ.js → chunk-Z3I2WNGF.js} +58 -3
- package/dist/chunk-Z3I2WNGF.js.map +1 -0
- package/dist/{state-vault-TMXZRTY5.js → chunk-ZJ67TB4S.js} +24 -7
- package/dist/chunk-ZJ67TB4S.js.map +1 -0
- package/dist/consent/index.cjs.map +1 -1
- package/dist/consent/index.d.cts +6 -4
- package/dist/consent/index.d.ts +6 -4
- package/dist/consent/index.js +3 -3
- package/dist/{crypto-QXQOHMHF.js → crypto-FNK3XPCS.js} +7 -3
- package/dist/{delegation-NIQ43IPU.js → delegation-FMXNUWE6.js} +5 -5
- package/dist/derivations/index.cjs +82 -2
- package/dist/derivations/index.cjs.map +1 -1
- package/dist/derivations/index.d.cts +7 -5
- package/dist/derivations/index.d.ts +7 -5
- package/dist/derivations/index.js +8 -6
- package/dist/{dev-unlock-8XzcD2Z4.d.cts → dev-unlock-3_2b_vo6.d.cts} +1 -1
- package/dist/{dev-unlock-DR3upLd1.d.ts → dev-unlock-BMvwPr_E.d.ts} +1 -1
- package/dist/{strategy-BtW8fAjz.d.cts → errors-DUTlAt3Y.d.cts} +113 -727
- package/dist/{strategy-BtW8fAjz.d.ts → errors-DUTlAt3Y.d.ts} +113 -727
- package/dist/executor-IZ2NVXCY.js +11 -0
- package/dist/executor-THSEYEJG.js +8 -0
- package/dist/executor-WLFDUTOM.js +8 -0
- package/dist/{fanout-sidecar-67CMI3UT.js → fanout-sidecar-JGHXAJO5.js} +2 -2
- package/dist/forget/index.cjs +43 -0
- package/dist/forget/index.cjs.map +1 -0
- package/dist/forget/index.d.cts +1 -0
- package/dist/forget/index.d.ts +1 -0
- package/dist/forget/index.js +14 -0
- package/dist/guards/index.cjs +80 -3
- package/dist/guards/index.cjs.map +1 -1
- package/dist/guards/index.d.cts +7 -5
- package/dist/guards/index.d.ts +7 -5
- package/dist/guards/index.js +10 -6
- package/dist/{hash-CDjye9KV.d.ts → hash-BThBJFO1.d.ts} +1 -1
- package/dist/{hash-DuQ88_5W.d.cts → hash-BnWnL9bQ.d.cts} +1 -1
- package/dist/history/index.cjs +27 -4
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +7 -5
- package/dist/history/index.d.ts +7 -5
- package/dist/history/index.js +9 -7
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.cjs +53 -0
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +6 -4
- package/dist/i18n/index.d.ts +6 -4
- package/dist/i18n/index.js +16 -8
- package/dist/i18n/index.js.map +1 -1
- package/dist/index-C-SSRIxP.d.cts +348 -0
- package/dist/index-C-SSRIxP.d.ts +348 -0
- package/dist/{index-C8Bk3-VF.d.cts → index-C6lgoUhK.d.cts} +47 -2
- package/dist/{index-nP99bXLg.d.ts → index-DP1JTWHZ.d.ts} +47 -2
- package/dist/index.cjs +3280 -1208
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -12
- package/dist/index.d.ts +15 -12
- package/dist/index.js +149 -107
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.cjs.map +1 -1
- package/dist/indexing/index.js +4 -4
- package/dist/issue-R2MWQO6K.js +12 -0
- package/dist/{ledger-A3LL253R.js → ledger-GXC2YA3A.js} +6 -6
- package/dist/materialized-views/index.cjs.map +1 -1
- package/dist/materialized-views/index.d.cts +7 -5
- package/dist/materialized-views/index.d.ts +7 -5
- package/dist/materialized-views/index.js +12 -12
- package/dist/noydb-RJL6FQ4B.js +37 -0
- package/dist/overlay-views/index.cjs.map +1 -1
- package/dist/overlay-views/index.d.cts +7 -5
- package/dist/overlay-views/index.d.ts +7 -5
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +6 -4
- package/dist/periods/index.d.ts +6 -4
- package/dist/periods/index.js +6 -6
- package/dist/{public-envelope-YP2UWMLG.js → public-envelope-HXOFHY4N.js} +4 -4
- package/dist/query/index.cjs +30 -4
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +3 -2
- package/dist/query/index.d.ts +3 -2
- package/dist/query/index.js +6 -6
- package/dist/read-only-facade-EX6WZZBP.js +7 -0
- package/dist/registry-3T2RZC5A.js +8 -0
- package/dist/registry-DMS7OKBM.js +8 -0
- package/dist/{registry-UTA4CLQS.js → registry-WVXO6NH5.js} +3 -3
- package/dist/{revoke-HNMQZSCL.js → revoke-7LCWE2AH.js} +6 -6
- package/dist/sealed-record/index.cjs +139 -0
- package/dist/sealed-record/index.cjs.map +1 -0
- package/dist/sealed-record/index.d.cts +123 -0
- package/dist/sealed-record/index.d.ts +123 -0
- package/dist/sealed-record/index.js +42 -0
- package/dist/sealed-record/index.js.map +1 -0
- package/dist/session/index.cjs.map +1 -1
- package/dist/session/index.d.cts +7 -5
- package/dist/session/index.d.ts +7 -5
- package/dist/session/index.js +3 -3
- package/dist/shadow/index.cjs.map +1 -1
- package/dist/shadow/index.d.cts +6 -4
- package/dist/shadow/index.d.ts +6 -4
- package/dist/shadow/index.js +2 -2
- package/dist/{signer-DCMNKXSF.js → signer-HAVDLGOK.js} +5 -5
- package/dist/snapshots/index.cjs.map +1 -1
- package/dist/snapshots/index.d.cts +6 -4
- package/dist/snapshots/index.d.ts +6 -4
- package/dist/snapshots/index.js +4 -4
- package/dist/{stale-W5PQTRYH.js → stale-PGTEGJDI.js} +2 -2
- package/dist/stale-PGTEGJDI.js.map +1 -0
- package/dist/state-vault-QKQKN3H3.js +14 -0
- package/dist/state-vault-QKQKN3H3.js.map +1 -0
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +6 -4
- package/dist/store/index.d.ts +6 -4
- package/dist/store/index.js +2 -2
- package/dist/strategy-Diwh5lzS.d.ts +739 -0
- package/dist/strategy-nuyN8K5N.d.cts +739 -0
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +5 -3
- package/dist/sync/index.d.ts +5 -3
- package/dist/sync/index.js +4 -4
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +6 -4
- package/dist/team/index.d.ts +6 -4
- package/dist/team/index.js +8 -8
- package/dist/transition-guard--t3exQHF.d.cts +165 -0
- package/dist/transition-guard-BlI9Oy5K.d.ts +165 -0
- package/dist/tx/index.cjs.map +1 -1
- package/dist/tx/index.d.cts +6 -4
- package/dist/tx/index.d.ts +6 -4
- package/dist/tx/index.js +3 -3
- package/dist/{types-Bze6vkwm.d.cts → types-BpLPqyaO.d.cts} +1264 -513
- package/dist/{types-DrmBTscX.d.ts → types-Diqc2caK.d.ts} +1264 -513
- package/dist/{ulid-DbBVrNSt.d.ts → ulid-B1zNV8r9.d.ts} +1 -1
- package/dist/{ulid-DfZlAh0u.d.cts → ulid-DNiRB4Mx.d.cts} +1 -1
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.js +1 -1
- package/dist/{vault-group-DX2HFQMX.js → vault-group-DPZVFRI5.js} +182 -6
- package/dist/vault-group-DPZVFRI5.js.map +1 -0
- package/dist/{with-materialized-view--4PsvMDu.d.cts → with-materialized-view-BdH_A_r6.d.cts} +1 -1
- package/dist/{with-materialized-view-QT1Tp7NO.d.ts → with-materialized-view-CzAgp_HJ.d.ts} +1 -1
- package/dist/{with-overlayed-view-BEXfpzSb.d.ts → with-overlayed-view-BJbqQnsR.d.ts} +1 -1
- package/dist/{with-overlayed-view-DlH5qmeB.d.cts → with-overlayed-view-C40rDPlu.d.cts} +1 -1
- package/dist/with-rollup-Bopu5UDZ.d.cts +47 -0
- package/dist/with-rollup-DrlGkxiE.d.ts +47 -0
- package/package.json +23 -3
- package/dist/chunk-42FEUPZQ.js.map +0 -1
- package/dist/chunk-535SSHBS.js.map +0 -1
- package/dist/chunk-667MB6AH.js.map +0 -1
- package/dist/chunk-7BQ4QWYX.js.map +0 -1
- package/dist/chunk-7Z7KSVA5.js.map +0 -1
- package/dist/chunk-DUREQF5W.js.map +0 -1
- package/dist/chunk-F3BPIPLS.js.map +0 -1
- package/dist/chunk-GNI5STXQ.js.map +0 -1
- package/dist/chunk-HOR4R722.js.map +0 -1
- package/dist/chunk-KABJXG2F.js.map +0 -1
- package/dist/chunk-OQSRJG6A.js +0 -63
- package/dist/chunk-OQSRJG6A.js.map +0 -1
- package/dist/chunk-UMLVJTYV.js.map +0 -1
- package/dist/chunk-YULZKK4F.js.map +0 -1
- package/dist/executor-6ZDSDZ6V.js +0 -8
- package/dist/executor-AZLS3KBK.js +0 -11
- package/dist/executor-IDZDAFNH.js +0 -8
- package/dist/immutable-guard-CRPvu24K.d.cts +0 -82
- package/dist/immutable-guard-Dov3WvwF.d.ts +0 -82
- package/dist/issue-RZP3VI6O.js +0 -12
- package/dist/noydb-WCMY2ZOW.js +0 -35
- package/dist/read-only-facade-ITU6L7BL.js +0 -7
- package/dist/registry-EB6SISTA.js +0 -8
- package/dist/registry-IUZQVVBB.js +0 -8
- package/dist/state-vault-TMXZRTY5.js.map +0 -1
- package/dist/vault-group-DX2HFQMX.js.map +0 -1
- package/dist/with-derivation-CCqAchD5.d.cts +0 -13
- package/dist/with-derivation-_lySGdlm.d.ts +0 -13
- /package/dist/{chunk-6RR3MNMG.js.map → chunk-2U226RDC.js.map} +0 -0
- /package/dist/{chunk-L2BNJ6HM.js.map → chunk-32XVU2LT.js.map} +0 -0
- /package/dist/{chunk-X73VS74Y.js.map → chunk-33DAO2XG.js.map} +0 -0
- /package/dist/{chunk-QSUK7YWK.js.map → chunk-4UI5T3K7.js.map} +0 -0
- /package/dist/{chunk-G4SCICH5.js.map → chunk-5KKNBDCT.js.map} +0 -0
- /package/dist/{chunk-E2CDVKMH.js.map → chunk-6FHCU3QO.js.map} +0 -0
- /package/dist/{chunk-F4OJZIWQ.js.map → chunk-6Q5XRLKG.js.map} +0 -0
- /package/dist/{chunk-4TBBMHVC.js.map → chunk-6YEC7LLO.js.map} +0 -0
- /package/dist/{chunk-ZNQYHJXX.js.map → chunk-AB7JF2KF.js.map} +0 -0
- /package/dist/{chunk-XL35NSEN.js.map → chunk-BUBJYIZ7.js.map} +0 -0
- /package/dist/{chunk-3YWP3WBP.js.map → chunk-DKMPR76W.js.map} +0 -0
- /package/dist/{chunk-BI6ETQPF.js.map → chunk-DR5I7Q6N.js.map} +0 -0
- /package/dist/{chunk-6H2ZUNR7.js.map → chunk-FQRAYDS4.js.map} +0 -0
- /package/dist/{chunk-TS26M2SB.js.map → chunk-HOO5I3VG.js.map} +0 -0
- /package/dist/{chunk-OMAMZKKD.js.map → chunk-HWK75CYX.js.map} +0 -0
- /package/dist/{chunk-TKIY625R.js.map → chunk-HZOEBM67.js.map} +0 -0
- /package/dist/{chunk-DLZ2ONOD.js.map → chunk-IQ4GMEYZ.js.map} +0 -0
- /package/dist/{chunk-XWH4MXIU.js.map → chunk-K3NYRK7U.js.map} +0 -0
- /package/dist/{chunk-JD3OZAI4.js.map → chunk-KTZ2MHQK.js.map} +0 -0
- /package/dist/{chunk-SCJPI4Z5.js.map → chunk-LQ3GD5LL.js.map} +0 -0
- /package/dist/{chunk-AAVWKNZW.js.map → chunk-M3H7VSRV.js.map} +0 -0
- /package/dist/{chunk-BR3AMFGS.js.map → chunk-MGB67HKX.js.map} +0 -0
- /package/dist/{chunk-OB2ZJQ2D.js.map → chunk-PGVEL5IZ.js.map} +0 -0
- /package/dist/{chunk-BQ65SS5A.js.map → chunk-QPJ7Z4L3.js.map} +0 -0
- /package/dist/{chunk-CZI2A4MQ.js.map → chunk-RQFG2YSV.js.map} +0 -0
- /package/dist/{chunk-CJORTUJ2.js.map → chunk-RZWQNMMP.js.map} +0 -0
- /package/dist/{chunk-FFXM3ZIF.js.map → chunk-T4T5I5L6.js.map} +0 -0
- /package/dist/{chunk-QVIEAYTP.js.map → chunk-TFAN3NFD.js.map} +0 -0
- /package/dist/{chunk-Z4DO7YSI.js.map → chunk-TPOHMOGX.js.map} +0 -0
- /package/dist/{chunk-VLMPU56Q.js.map → chunk-TTS3RWL5.js.map} +0 -0
- /package/dist/{chunk-IXBIFDEW.js.map → chunk-VVDSDOVV.js.map} +0 -0
- /package/dist/{chunk-FWPKCXTN.js.map → chunk-WZCG3EZ6.js.map} +0 -0
- /package/dist/{chunk-HBXJ37ZY.js.map → chunk-Y5XVB75E.js.map} +0 -0
- /package/dist/{chunk-IQLVUT37.js.map → chunk-Z3BE5BRK.js.map} +0 -0
- /package/dist/{crypto-QXQOHMHF.js.map → crypto-FNK3XPCS.js.map} +0 -0
- /package/dist/{delegation-NIQ43IPU.js.map → delegation-FMXNUWE6.js.map} +0 -0
- /package/dist/{executor-6ZDSDZ6V.js.map → executor-IZ2NVXCY.js.map} +0 -0
- /package/dist/{executor-AZLS3KBK.js.map → executor-THSEYEJG.js.map} +0 -0
- /package/dist/{executor-IDZDAFNH.js.map → executor-WLFDUTOM.js.map} +0 -0
- /package/dist/{fanout-sidecar-67CMI3UT.js.map → fanout-sidecar-JGHXAJO5.js.map} +0 -0
- /package/dist/{issue-RZP3VI6O.js.map → forget/index.js.map} +0 -0
- /package/dist/{ledger-A3LL253R.js.map → issue-R2MWQO6K.js.map} +0 -0
- /package/dist/{noydb-WCMY2ZOW.js.map → ledger-GXC2YA3A.js.map} +0 -0
- /package/dist/{public-envelope-YP2UWMLG.js.map → noydb-RJL6FQ4B.js.map} +0 -0
- /package/dist/{read-only-facade-ITU6L7BL.js.map → public-envelope-HXOFHY4N.js.map} +0 -0
- /package/dist/{registry-EB6SISTA.js.map → read-only-facade-EX6WZZBP.js.map} +0 -0
- /package/dist/{registry-IUZQVVBB.js.map → registry-3T2RZC5A.js.map} +0 -0
- /package/dist/{registry-UTA4CLQS.js.map → registry-DMS7OKBM.js.map} +0 -0
- /package/dist/{revoke-HNMQZSCL.js.map → registry-WVXO6NH5.js.map} +0 -0
- /package/dist/{signer-DCMNKXSF.js.map → revoke-7LCWE2AH.js.map} +0 -0
- /package/dist/{stale-W5PQTRYH.js.map → signer-HAVDLGOK.js.map} +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { I as IndexStrategy, d as LazyQuery } from './lazy-builder-ChSqcF5t.js';
|
|
2
|
-
import {
|
|
2
|
+
import { L as LiveAggregation, b as AggregateSpec, a as AggregateResult, v as MoneyDescriptor, A as AggregateStrategy } from './strategy-Diwh5lzS.js';
|
|
3
3
|
import { C as CrdtStrategy, a as CrdtMode, b as CrdtState } from './strategy-BSxFXGzb.js';
|
|
4
|
-
import { L as
|
|
4
|
+
import { L as LedgerEntry, F as ForgetStrategy, S as SubjectRef, b as ForgetResult } from './index-C-SSRIxP.js';
|
|
5
|
+
import { N as NoydbError } from './errors-DUTlAt3Y.js';
|
|
6
|
+
import { L as LiveQuery, Q as Query, c as JoinStrategy, j as RefRegistry, R as RefDescriptor, d as JoinableSource, l as RefViolation, S as ScanBuilder } from './index-DP1JTWHZ.js';
|
|
5
7
|
import { I as IndexDef, O as Operator, F as FieldClause, C as CollectionIndexes } from './predicate-BmhBSPCH.js';
|
|
6
8
|
import { AttestationFieldSchema, RevocationList } from '@noy-db/attestation';
|
|
7
9
|
|
|
@@ -415,6 +417,7 @@ declare class BlobSet {
|
|
|
415
417
|
private readonly encrypted;
|
|
416
418
|
private readonly userId;
|
|
417
419
|
private readonly maxBlobBytes;
|
|
420
|
+
private readonly erasableBlobs;
|
|
418
421
|
constructor(opts: {
|
|
419
422
|
store: NoydbStore;
|
|
420
423
|
vault: string;
|
|
@@ -424,7 +427,18 @@ declare class BlobSet {
|
|
|
424
427
|
encrypted: boolean;
|
|
425
428
|
userId?: string;
|
|
426
429
|
maxBlobBytes?: number;
|
|
430
|
+
erasableBlobs?: boolean;
|
|
427
431
|
});
|
|
432
|
+
/**
|
|
433
|
+
* Resolve the key the blob's CHUNKS are encrypted under.
|
|
434
|
+
*
|
|
435
|
+
* - `_cek` present (erasable blob) → unwrap the per-blob content CEK under
|
|
436
|
+
* the `_blob` DEK. Deleting the BlobObject (at `refCount → 0`) makes this
|
|
437
|
+
* key unrecoverable → the chunks are crypto-shredded.
|
|
438
|
+
* - `_cek` absent (legacy) → the `_blob` DEK encrypts chunks directly.
|
|
439
|
+
* - unencrypted vault → `null` (chunks stored as plaintext base64).
|
|
440
|
+
*/
|
|
441
|
+
private resolveChunkKey;
|
|
428
442
|
/** The internal collection that holds slot metadata for this collection's blobs. */
|
|
429
443
|
private get slotsCollection();
|
|
430
444
|
/** The internal collection that holds published versions for this collection's blobs. */
|
|
@@ -442,6 +456,73 @@ declare class BlobSet {
|
|
|
442
456
|
* CAS retry loop for refCount changes on a BlobObject.
|
|
443
457
|
*/
|
|
444
458
|
private casUpdateRefCount;
|
|
459
|
+
/**
|
|
460
|
+
* Release `n` references to a blob and reclaim it at refCount 0 (#365 slice 4).
|
|
461
|
+
*
|
|
462
|
+
* The single reclaim choke point for every reference-drop path — slot
|
|
463
|
+
* delete/overwrite, published-version delete, and `forget()` shred — so the
|
|
464
|
+
* refCount-0 policy is uniform:
|
|
465
|
+
* - **erasable blob** (`_cek` present) → delete the `BlobObject` (the SOLE
|
|
466
|
+
* copy of the wrapped content CEK → chunks permanently undecryptable) and
|
|
467
|
+
* reclaim the chunks. The crypto-shred is EAGER on every path: GDPR erasure
|
|
468
|
+
* must not wait on orphan retention.
|
|
469
|
+
* - **legacy blob** (no `_cek`) → reclaimed only when `reclaimLegacy` (the
|
|
470
|
+
* `forget()` erasure path); otherwise left for deferred GC so the existing
|
|
471
|
+
* `BlobLifecyclePolicy.orphanRetentionDays` semantics are preserved.
|
|
472
|
+
*
|
|
473
|
+
* @returns `'shredded'` (erasable, refCount 0, chunks dead) · `'retainedShared'`
|
|
474
|
+
* (erasable, still referenced) · `'residue'` (legacy — not a crypto-shred).
|
|
475
|
+
*/
|
|
476
|
+
private releaseRef;
|
|
477
|
+
/**
|
|
478
|
+
* Crypto-shred this record's blob attachments (#365 slice 2) — called by
|
|
479
|
+
* `vault.forget()`.
|
|
480
|
+
*
|
|
481
|
+
* For each distinct eTag the record references (a record may attach the same
|
|
482
|
+
* content under several slot names → several refCount holds): decrement the
|
|
483
|
+
* blob's refCount by that many. When it reaches 0:
|
|
484
|
+
* - **erasable blob** (`_cek` present) → delete the `BlobObject` (the SOLE
|
|
485
|
+
* recoverable copy of the wrapped content CEK → chunks permanently
|
|
486
|
+
* undecryptable) and reclaim the chunk bytes. This is the crypto-shred.
|
|
487
|
+
* - **legacy blob** (no `_cek`) → chunks are under the shared `_blob` DEK and
|
|
488
|
+
* stay decryptable until byte-deleted; we delete the orphaned chunks +
|
|
489
|
+
* index but report it as residue, not a cryptographic erasure.
|
|
490
|
+
* When refCount stays > 0 the content legitimately persists for its other
|
|
491
|
+
* owner — reported as `retainedShared` (or `residue` if legacy).
|
|
492
|
+
*
|
|
493
|
+
* Finally drops the record's slot map, severing the subject's link.
|
|
494
|
+
*/
|
|
495
|
+
shredAllForRecord(): Promise<{
|
|
496
|
+
shredded: string[];
|
|
497
|
+
retainedShared: string[];
|
|
498
|
+
residue: string[];
|
|
499
|
+
}>;
|
|
500
|
+
/** CAS retry loop for an arbitrary BlobObject mutation. */
|
|
501
|
+
private casUpdateBlobObject;
|
|
502
|
+
/**
|
|
503
|
+
* Migrate this record's LEGACY blobs (no `_cek`, chunks under the shared
|
|
504
|
+
* `_blob` DEK) to per-blob content CEKs so they become crypto-shreddable
|
|
505
|
+
* (#365 slice 3). Returns the eTags migrated vs. already-erasable.
|
|
506
|
+
*
|
|
507
|
+
* **Explicit maintenance pass** (mirrors the record-CEK migration posture):
|
|
508
|
+
* re-encrypts the existing compressed chunks IN PLACE under a fresh content
|
|
509
|
+
* CEK — preserving the eTag, chunkCount, chunkSize, and compression — then
|
|
510
|
+
* flips the `_cek` discriminant. Crash-safe + idempotent via `_cekPending`:
|
|
511
|
+
* 1. persist the wrapped content CEK in `_cekPending` (readers ignore it →
|
|
512
|
+
* the blob stays readable under the `_blob` DEK; the key survives a crash);
|
|
513
|
+
* 2. re-encrypt each chunk under the content CEK (a resume reads an
|
|
514
|
+
* already-migrated chunk under the content CEK, else under the `_blob` DEK);
|
|
515
|
+
* 3. promote `_cekPending` → `_cek` (atomic flip). Reads now use the CEK.
|
|
516
|
+
* A re-run after a crash resumes from whichever phase was reached.
|
|
517
|
+
*
|
|
518
|
+
* Dedup-safe: migrating a shared blob (refCount > 1) re-keys it for every
|
|
519
|
+
* referencer at once; a non-erasable collection still reads it (it unwraps
|
|
520
|
+
* `_cek` under the `_blob` DEK it holds).
|
|
521
|
+
*/
|
|
522
|
+
migrate(): Promise<{
|
|
523
|
+
migrated: string[];
|
|
524
|
+
alreadyErasable: string[];
|
|
525
|
+
}>;
|
|
445
526
|
private writeChunk;
|
|
446
527
|
private readChunk;
|
|
447
528
|
private versionKey;
|
|
@@ -598,6 +679,13 @@ interface BlobStrategyOpenArgs {
|
|
|
598
679
|
readonly getDEK: (collectionName: string) => Promise<CryptoKey>;
|
|
599
680
|
readonly encrypted: boolean;
|
|
600
681
|
readonly userId: string;
|
|
682
|
+
/**
|
|
683
|
+
* Collection opts into per-record keys (`perRecordKeys`), so its blobs are
|
|
684
|
+
* erasable: new uploads mint a per-blob content CEK (crypto-shreddable at
|
|
685
|
+
* `refCount → 0`). Off → legacy shared-`_blob`-DEK chunks. See the per-blob
|
|
686
|
+
* CEK design spec.
|
|
687
|
+
*/
|
|
688
|
+
readonly erasableBlobs?: boolean;
|
|
601
689
|
}
|
|
602
690
|
/**
|
|
603
691
|
* The seam interface. `@internal` — do not build public APIs on this
|
|
@@ -807,224 +895,6 @@ interface ConsentStrategy {
|
|
|
807
895
|
read(adapter: NoydbStore, vault: string, encrypted: boolean, getDEK: (collectionName: string) => Promise<CryptoKey>, filter?: ConsentAuditFilter): Promise<ConsentAuditEntry[]>;
|
|
808
896
|
}
|
|
809
897
|
|
|
810
|
-
/**
|
|
811
|
-
* Ledger entry shape + canonical JSON + sha256 helpers.
|
|
812
|
-
*
|
|
813
|
-
* This file holds the PURE primitives used by the hash-chained ledger:
|
|
814
|
-
* the entry type, the deterministic (sort-stable) JSON encoder, and
|
|
815
|
-
* the sha256 hasher that produces `prevHash` and `ledger.head()`.
|
|
816
|
-
*
|
|
817
|
-
* Everything here is validator-free and side-effect free — the only
|
|
818
|
-
* runtime dep is Web Crypto's `subtle.digest` for the sha256 call,
|
|
819
|
-
* which we already use for every other hashing operation in the core.
|
|
820
|
-
*
|
|
821
|
-
* The hash chain property works like this:
|
|
822
|
-
*
|
|
823
|
-
* hash(entry[i]) = sha256(canonicalJSON(entry[i]))
|
|
824
|
-
* entry[i+1].prevHash = hash(entry[i])
|
|
825
|
-
*
|
|
826
|
-
* Any modification to `entry[i]` (field values, field order, whitespace)
|
|
827
|
-
* produces a different `hash(entry[i])`, which means `entry[i+1]`'s
|
|
828
|
-
* stored `prevHash` no longer matches the recomputed hash, which means
|
|
829
|
-
* `verify()` returns `{ ok: false, divergedAt: i + 1 }`. The chain is
|
|
830
|
-
* append-only and tamper-evident without external anchoring.
|
|
831
|
-
*/
|
|
832
|
-
/**
|
|
833
|
-
* A single ledger entry in its plaintext form — what gets serialized,
|
|
834
|
-
* hashed, and then encrypted with the ledger DEK before being written
|
|
835
|
-
* to the `_ledger/` adapter collection.
|
|
836
|
-
*
|
|
837
|
-
* ## Why hash the ciphertext, not the plaintext?
|
|
838
|
-
*
|
|
839
|
-
* `payloadHash` is the sha256 of the record's ENCRYPTED envelope bytes,
|
|
840
|
-
* not its plaintext. This matters:
|
|
841
|
-
*
|
|
842
|
-
* 1. **Zero-knowledge preserved.** A user (or a third party) can
|
|
843
|
-
* verify the ledger against the stored envelopes without any
|
|
844
|
-
* decryption keys. The adapter layer already holds only
|
|
845
|
-
* ciphertext, so hashing the ciphertext keeps the ledger at the
|
|
846
|
-
* same privacy level as the adapter.
|
|
847
|
-
*
|
|
848
|
-
* 2. **Determinism.** Plaintext → ciphertext is randomized by the
|
|
849
|
-
* fresh per-write IV, so `hash(plaintext)` would need extra
|
|
850
|
-
* normalization. `hash(ciphertext)` is already deterministic and
|
|
851
|
-
* unique per write.
|
|
852
|
-
*
|
|
853
|
-
* 3. **Detection property.** If an attacker modifies even one byte of
|
|
854
|
-
* the stored ciphertext (trying to flip a record), the hash
|
|
855
|
-
* changes, the ledger's recorded `payloadHash` no longer matches,
|
|
856
|
-
* and a data-integrity check fails. We don't do that check in
|
|
857
|
-
* `verify()` today, but the
|
|
858
|
-
* hook is there for a future `verifyIntegrity()` follow-up.
|
|
859
|
-
*
|
|
860
|
-
* Fields marked `op`, `collection`, `id`, `version`, `ts`, `actor` are
|
|
861
|
-
* plaintext METADATA about the operation — NOT the record itself. The
|
|
862
|
-
* entry is still encrypted at rest via the ledger DEK, but adapters
|
|
863
|
-
* could theoretically infer operation patterns from the sizes and
|
|
864
|
-
* timestamps. This is an accepted trade-off for the tamper-evidence
|
|
865
|
-
* property; full ORAM-level privacy is out of scope for noy-db.
|
|
866
|
-
*/
|
|
867
|
-
interface LedgerEntry {
|
|
868
|
-
/**
|
|
869
|
-
* Zero-based sequential position of this entry in the chain. The
|
|
870
|
-
* canonical adapter key is this number zero-padded to 10 digits
|
|
871
|
-
* (`"0000000001"`) so lexicographic ordering matches numeric order.
|
|
872
|
-
*/
|
|
873
|
-
readonly index: number;
|
|
874
|
-
/**
|
|
875
|
-
* Hex-encoded sha256 of the canonical JSON of the PREVIOUS entry.
|
|
876
|
-
* The genesis entry (index 0) has `prevHash === ''` — the first
|
|
877
|
-
* entry in a fresh vault has nothing to point back to.
|
|
878
|
-
*/
|
|
879
|
-
readonly prevHash: string;
|
|
880
|
-
/**
|
|
881
|
-
* Which kind of mutation this entry records. only supports
|
|
882
|
-
* data operations (`put`, `delete`, `amendment`). Access-control
|
|
883
|
-
* operations (`grant`, `revoke`, `rotate`) will be added in a
|
|
884
|
-
* follow-up once the keyring write path is instrumented — that's
|
|
885
|
-
* tracked in the epic issue.
|
|
886
|
-
*
|
|
887
|
-
* `'amendment'` is the multi-record audit entry written by the
|
|
888
|
-
* guards subsystem when an admin/owner uses `withTransactions(...)`
|
|
889
|
-
* to repair a constraint-violating state. See `amendment` field
|
|
890
|
-
* below for the structured payload.
|
|
891
|
-
*
|
|
892
|
-
* `'lifecycle'` records a non-data audit event (e.g. partition
|
|
893
|
-
* handover) — `collection`/`id` are empty and the event detail
|
|
894
|
-
* lives in `reason` (e.g. `'partition-handed-over:<sealId>'`). Like
|
|
895
|
-
* `amendment`, it carries no data envelope, so `verifyBackupIntegrity`
|
|
896
|
-
* skips it in the data cross-check (it still participates in the
|
|
897
|
-
* tamper-evident chain).
|
|
898
|
-
*/
|
|
899
|
-
readonly op: 'put' | 'delete' | 'amendment' | 'lifecycle' | 'migration';
|
|
900
|
-
/** The collection the mutation targeted. */
|
|
901
|
-
readonly collection: string;
|
|
902
|
-
/** The record id the mutation targeted. */
|
|
903
|
-
readonly id: string;
|
|
904
|
-
/**
|
|
905
|
-
* The record version AFTER this mutation. For `put` this is the
|
|
906
|
-
* newly assigned version; for `delete` this is the version that
|
|
907
|
-
* was deleted (the last version visible to reads).
|
|
908
|
-
*/
|
|
909
|
-
readonly version: number;
|
|
910
|
-
/** ISO timestamp of the mutation. */
|
|
911
|
-
readonly ts: string;
|
|
912
|
-
/** User id of the actor who performed the mutation. */
|
|
913
|
-
readonly actor: string;
|
|
914
|
-
/**
|
|
915
|
-
* Hex-encoded sha256 of the encrypted envelope's `_data` field.
|
|
916
|
-
* For `put`, this is the hash of the new ciphertext. For `delete`,
|
|
917
|
-
* it's the hash of the last visible ciphertext at deletion time,
|
|
918
|
-
* or the empty string if nothing was there to delete. Hashing the
|
|
919
|
-
* ciphertext (not the plaintext) preserves zero-knowledge — see
|
|
920
|
-
* the file docstring.
|
|
921
|
-
*/
|
|
922
|
-
readonly payloadHash: string;
|
|
923
|
-
/**
|
|
924
|
-
* Optional human-readable tag describing why this mutation happened.
|
|
925
|
-
* Threaded through `collection.put(_, _, { reason })`. Common
|
|
926
|
-
* values include `'import:csv'`, `'import:json'`, `'import:xlsx'` from
|
|
927
|
-
* `as-*` ImportPlan.apply(), but consumers can use any string for
|
|
928
|
-
* domain-specific audit filtering. Auto-strip via `canonicalJson` —
|
|
929
|
-
* absent on the wire, never serialized as `null`.
|
|
930
|
-
*
|
|
931
|
-
* Audit consumers filter: `entries.filter(e => e.reason?.startsWith('import:'))`.
|
|
932
|
-
*/
|
|
933
|
-
readonly reason?: string;
|
|
934
|
-
/**
|
|
935
|
-
* Optional hex-encoded sha256 of the encrypted JSON Patch delta
|
|
936
|
-
* blob stored alongside this entry in `_ledger_deltas/`. Present
|
|
937
|
-
* only for `put` operations that had a previous version — the
|
|
938
|
-
* genesis put of a new record, and every `delete`, leave this
|
|
939
|
-
* field undefined.
|
|
940
|
-
*
|
|
941
|
-
* The delta payload itself lives in a sibling internal collection
|
|
942
|
-
* (`_ledger_deltas/<paddedIndex>`) and is encrypted with the
|
|
943
|
-
* ledger DEK. Callers use `ledger.loadDelta(index)` to decrypt and
|
|
944
|
-
* deserialize it when reconstructing a historical version.
|
|
945
|
-
*
|
|
946
|
-
* Why optional instead of always-present: the first put of a
|
|
947
|
-
* record has no previous version to diff against, so storing an
|
|
948
|
-
* empty patch would be noise. For deletes there's no "next" state
|
|
949
|
-
* to describe with a delta. Both cases set this field to undefined.
|
|
950
|
-
*
|
|
951
|
-
* Note: the canonical-JSON hasher treats `undefined` as invalid
|
|
952
|
-
* (it's one of the guard rails), so on the wire this field is
|
|
953
|
-
* either `{ deltaHash: '<hex>' }` or absent from the JSON
|
|
954
|
-
* entirely — never `{ deltaHash: undefined }`.
|
|
955
|
-
*/
|
|
956
|
-
readonly deltaHash?: string;
|
|
957
|
-
/**
|
|
958
|
-
* Present only when `op === 'amendment'`. Records the human reason,
|
|
959
|
-
* the role of the actor, the (collection, id, vBefore, vAfter) tuple
|
|
960
|
-
* for every record touched, and which guard invariants passed.
|
|
961
|
-
*
|
|
962
|
-
* See docs/superpowers/specs/2026-05-18-guards-design.md.
|
|
963
|
-
*/
|
|
964
|
-
readonly amendment?: {
|
|
965
|
-
readonly reason: string;
|
|
966
|
-
readonly role: 'admin' | 'owner';
|
|
967
|
-
readonly changes: ReadonlyArray<{
|
|
968
|
-
readonly collection: string;
|
|
969
|
-
readonly id: string;
|
|
970
|
-
readonly vBefore: number;
|
|
971
|
-
readonly vAfter: number;
|
|
972
|
-
}>;
|
|
973
|
-
readonly invariantsPassed: ReadonlyArray<string>;
|
|
974
|
-
};
|
|
975
|
-
}
|
|
976
|
-
/**
|
|
977
|
-
* Canonical (sort-stable) JSON encoder.
|
|
978
|
-
*
|
|
979
|
-
* This function is the load-bearing primitive of the hash chain:
|
|
980
|
-
* `sha256(canonicalJSON(entry))` must produce the same hex string
|
|
981
|
-
* every time, on every machine, for the same logical entry — otherwise
|
|
982
|
-
* `verify()` would return `{ ok: false }` on cross-platform reads.
|
|
983
|
-
*
|
|
984
|
-
* JavaScript's `JSON.stringify` is almost canonical, but NOT quite:
|
|
985
|
-
* it preserves the insertion order of object keys, which means
|
|
986
|
-
* `{a:1,b:2}` and `{b:2,a:1}` serialize differently. We fix this by
|
|
987
|
-
* recursively walking objects and sorting their keys before
|
|
988
|
-
* concatenation.
|
|
989
|
-
*
|
|
990
|
-
* Arrays keep their original order (reordering them would change
|
|
991
|
-
* semantics). Numbers, strings, booleans, and `null` use the default
|
|
992
|
-
* JSON encoding. `undefined` and functions are rejected — ledger
|
|
993
|
-
* entries are plain data, and silently dropping `undefined` would
|
|
994
|
-
* break the "same input → same hash" property if a caller forgot to
|
|
995
|
-
* omit a field.
|
|
996
|
-
*
|
|
997
|
-
* Performance: one pass per nesting level; O(n log n) for key sorting
|
|
998
|
-
* at each object. Entries are small (< 1 KB) so this is negligible
|
|
999
|
-
* compared to the sha256 call.
|
|
1000
|
-
*/
|
|
1001
|
-
declare function canonicalJson(value: unknown): string;
|
|
1002
|
-
/**
|
|
1003
|
-
* Compute a hex-encoded sha256 of a string via Web Crypto's subtle API.
|
|
1004
|
-
*
|
|
1005
|
-
* We use hex (not base64) for hashes because hex is case-insensitive,
|
|
1006
|
-
* fixed-length (64 chars), and easier to compare visually in debug
|
|
1007
|
-
* output. Base64 would save a few bytes in storage but every encrypted
|
|
1008
|
-
* ledger entry is already much larger than the hash itself.
|
|
1009
|
-
*/
|
|
1010
|
-
declare function sha256Hex(input: string): Promise<string>;
|
|
1011
|
-
/**
|
|
1012
|
-
* Compute the canonical hash of a ledger entry. Short wrapper around
|
|
1013
|
-
* `canonicalJson` + `sha256Hex`; callers use this instead of composing
|
|
1014
|
-
* the two functions every time, so any future change to the hashing
|
|
1015
|
-
* pipeline (e.g., adding a domain-separation prefix) lives in one place.
|
|
1016
|
-
*/
|
|
1017
|
-
declare function hashEntry(entry: LedgerEntry): Promise<string>;
|
|
1018
|
-
/**
|
|
1019
|
-
* Pad an index to the canonical 10-digit form used as the adapter key.
|
|
1020
|
-
* Ten digits is enough for ~10 billion ledger entries per vault
|
|
1021
|
-
* — far beyond any realistic use case, but cheap enough that the extra
|
|
1022
|
-
* digits don't hurt storage.
|
|
1023
|
-
*/
|
|
1024
|
-
declare function paddedIndex(index: number): string;
|
|
1025
|
-
/** Parse a padded adapter key back into a number. Returns NaN on malformed input. */
|
|
1026
|
-
declare function parseIndex(key: string): number;
|
|
1027
|
-
|
|
1028
898
|
/**
|
|
1029
899
|
* RFC 6902 JSON Patch — compute + apply.
|
|
1030
900
|
*
|
|
@@ -1888,12 +1758,14 @@ interface I18nTextOptions {
|
|
|
1888
1758
|
* export). Default `'throw'` — today's behavior, zero breaking change.
|
|
1889
1759
|
* See {@link OnMissingPolicy}.
|
|
1890
1760
|
*
|
|
1891
|
-
* NOTE (current wiring): the `read`
|
|
1892
|
-
*
|
|
1893
|
-
*
|
|
1894
|
-
*
|
|
1895
|
-
*
|
|
1896
|
-
*
|
|
1761
|
+
* NOTE (current wiring): the `read` (`get`/`list`), `guard` and
|
|
1762
|
+
* `derivation` layers are enforced — guard / derivation `ctx.vault`
|
|
1763
|
+
* reads resolve under their own layer policy (`guard` defaults to the
|
|
1764
|
+
* lenient `'substitute'`). The `mv`, `join` and `export` layers are NOT
|
|
1765
|
+
* yet wired: mv/join read raw `{locale}` maps in the query/aggregate
|
|
1766
|
+
* pipeline (no resolution call site), so injecting resolution there is a
|
|
1767
|
+
* tracked follow-up (#285 D2/D3). Until then those reads observe the raw
|
|
1768
|
+
* map, not this policy.
|
|
1897
1769
|
*/
|
|
1898
1770
|
readonly onMissing?: OnMissingPolicy;
|
|
1899
1771
|
/**
|
|
@@ -2572,6 +2444,88 @@ declare function dictKey<Keys extends string>(name: string, keys?: readonly Keys
|
|
|
2572
2444
|
}): DictKeyDescriptor<Keys>;
|
|
2573
2445
|
/** Runtime predicate for detecting a DictKeyDescriptor. */
|
|
2574
2446
|
declare function isDictKeyDescriptor(x: unknown): x is DictKeyDescriptor;
|
|
2447
|
+
/**
|
|
2448
|
+
* Descriptor returned by `staticDict()`. A sibling to {@link DictKeyDescriptor}
|
|
2449
|
+
* for **closed, defined-in-code, identical-across-vaults** enums (honorific,
|
|
2450
|
+
* civil-status, gender, religion, ContactTitle, status…).
|
|
2451
|
+
*
|
|
2452
|
+
* Unlike `dictKey`, the labels are supplied **at registration in code** and
|
|
2453
|
+
* resolved through the *same* label machinery, but with **no `_dict_*`
|
|
2454
|
+
* per-vault encrypted copy** and **no `rename()`**. The record stores only
|
|
2455
|
+
* the **code**; a static dict has no mutation surface.
|
|
2456
|
+
*
|
|
2457
|
+
* **Hybrid resolution.** Because a static dict is pure code with no
|
|
2458
|
+
* vault-locale dependency, it can — via a configured `displayLocale` — emit a
|
|
2459
|
+
* `<field>Label` even under a **locale-less read** (the property a locale-less
|
|
2460
|
+
* consumer needs and `dictKey` cannot provide). When a locale *is* active it
|
|
2461
|
+
* behaves exactly like `dictKey` (honoring `onMissing`/`substitute`).
|
|
2462
|
+
*
|
|
2463
|
+
* ```ts
|
|
2464
|
+
* const workers = vault.collection<Worker>('workers', {
|
|
2465
|
+
* dictKeyFields: {
|
|
2466
|
+
* civilStatus: staticDict('civilStatus', {
|
|
2467
|
+
* adultMale: { th: 'นาย', en: 'Mr' },
|
|
2468
|
+
* adultFemale: { th: 'นาง', en: 'Mrs' },
|
|
2469
|
+
* }, { displayLocale: 'th' }),
|
|
2470
|
+
* },
|
|
2471
|
+
* })
|
|
2472
|
+
* ```
|
|
2473
|
+
*/
|
|
2474
|
+
interface StaticDictDescriptor<Keys extends string = string> {
|
|
2475
|
+
readonly _noydbStaticDict: true;
|
|
2476
|
+
/** Which dictionary this field references (the registry name). */
|
|
2477
|
+
readonly name: string;
|
|
2478
|
+
/** The in-code label table: key → { locale → label }. */
|
|
2479
|
+
readonly table: Readonly<Record<Keys, Readonly<Record<string, string>>>>;
|
|
2480
|
+
/** Declared valid keys — derived from `Object.keys(table)`. */
|
|
2481
|
+
readonly keys: readonly Keys[];
|
|
2482
|
+
/**
|
|
2483
|
+
* Locale used to emit `<field>Label` under a **locale-less** read — the
|
|
2484
|
+
* hybrid hinge. When unset, a static dict behaves like `dictKey` under a
|
|
2485
|
+
* locale-less read (no label); a locale-less consumer almost always wants
|
|
2486
|
+
* it set.
|
|
2487
|
+
*/
|
|
2488
|
+
readonly displayLocale?: string;
|
|
2489
|
+
/** Same `onMissing` policy engine as `dictKey`. Default `'null'`. */
|
|
2490
|
+
readonly onMissing?: OnMissingPolicy;
|
|
2491
|
+
/** Ordered preferred-substitute locales for label resolution. */
|
|
2492
|
+
readonly substitute?: readonly string[];
|
|
2493
|
+
/**
|
|
2494
|
+
* Validate the stored code against `keys` on every `put()`. Default `true`
|
|
2495
|
+
* — codes are closed by construction, so an unknown code is a bug. Set
|
|
2496
|
+
* `false` to allow open codes (skips the `UnknownDictCodeError` guard).
|
|
2497
|
+
*/
|
|
2498
|
+
readonly validateCodes?: boolean;
|
|
2499
|
+
}
|
|
2500
|
+
/**
|
|
2501
|
+
* Create a `StaticDictDescriptor` for a code-provided enum field — a sibling
|
|
2502
|
+
* to {@link dictKey} for closed, code-defined, identical-across-vaults enums.
|
|
2503
|
+
*
|
|
2504
|
+
* The labels live in `table` (no `_dict_*` collection, no `rename()`); the
|
|
2505
|
+
* record stores only the stable code. Pass `displayLocale` so `<field>Label`
|
|
2506
|
+
* resolves even under a locale-less read.
|
|
2507
|
+
*
|
|
2508
|
+
* @param name The dictionary name (used for the readonly-guard registry and
|
|
2509
|
+
* the query label seam — never creates a `_dict_<name>` key).
|
|
2510
|
+
* @param table `{ key: { locale: label } }` map.
|
|
2511
|
+
* @param opts `displayLocale` (locale-less label), `onMissing`, `substitute`.
|
|
2512
|
+
*
|
|
2513
|
+
* @example
|
|
2514
|
+
* ```ts
|
|
2515
|
+
* staticDict('civilStatus', {
|
|
2516
|
+
* adultMale: { th: 'นาย', en: 'Mr' },
|
|
2517
|
+
* adultFemale: { th: 'นาง', en: 'Mrs' },
|
|
2518
|
+
* }, { displayLocale: 'th' })
|
|
2519
|
+
* ```
|
|
2520
|
+
*/
|
|
2521
|
+
declare function staticDict<const T extends Record<string, Record<string, string>>>(name: string, table: T, opts?: {
|
|
2522
|
+
displayLocale?: string;
|
|
2523
|
+
onMissing?: OnMissingPolicy;
|
|
2524
|
+
substitute?: readonly string[];
|
|
2525
|
+
validateCodes?: boolean;
|
|
2526
|
+
}): StaticDictDescriptor<Extract<keyof T, string>>;
|
|
2527
|
+
/** Runtime predicate for detecting a StaticDictDescriptor. */
|
|
2528
|
+
declare function isStaticDictDescriptor(x: unknown): x is StaticDictDescriptor;
|
|
2575
2529
|
/**
|
|
2576
2530
|
* One entry in a `_dict_*` collection. The record `id` (adapter-side
|
|
2577
2531
|
* key) IS the stable dictionary key (e.g. `'paid'`). The `labels`
|
|
@@ -3475,6 +3429,12 @@ interface HistoryStrategy {
|
|
|
3475
3429
|
* `NO_HISTORY`.
|
|
3476
3430
|
*/
|
|
3477
3431
|
clearHistory(adapter: NoydbStore, vault: string, collection?: string, recordId?: string): Promise<number>;
|
|
3432
|
+
/**
|
|
3433
|
+
* Crypto-shred (overwrite-to-tombstone) every `_history` version of a
|
|
3434
|
+
* record for GDPR erasure (#304). Returns the number of versions newly
|
|
3435
|
+
* tombstoned, or `0` under `NO_HISTORY` (no history = nothing to shred).
|
|
3436
|
+
*/
|
|
3437
|
+
tombstoneHistory(adapter: NoydbStore, vault: string, collection: string, recordId: string, actor: string): Promise<number>;
|
|
3478
3438
|
/**
|
|
3479
3439
|
* Compute the SHA-256 hash of an envelope's encrypted payload, used
|
|
3480
3440
|
* by `LedgerStore.append` to track tamper-evidence. Returns the
|
|
@@ -3792,6 +3752,25 @@ interface VaultGroupOptions<T> {
|
|
|
3792
3752
|
*/
|
|
3793
3753
|
readonly registry?: Collection<VaultRegistryRow>;
|
|
3794
3754
|
readonly sharding: ShardingConfig<T>;
|
|
3755
|
+
/**
|
|
3756
|
+
* Lazy migrate-on-open (#271 fleet migration). When `true`, opening a shard
|
|
3757
|
+
* whose registry `schemaVersion` is behind the template's version runs that
|
|
3758
|
+
* shard's cutover inline (via `migrateShard`) before surfacing the handle.
|
|
3759
|
+
* Zero cost for shards never opened. Default `false` (use `migrateFleet`).
|
|
3760
|
+
*/
|
|
3761
|
+
readonly migrateOnOpen?: boolean;
|
|
3762
|
+
}
|
|
3763
|
+
/** Result of `VaultGroup.migrateFleet` (#271 active batch runner). */
|
|
3764
|
+
interface FleetMigrationResult {
|
|
3765
|
+
/** The version migrated toward (the template's current version). */
|
|
3766
|
+
readonly target: number;
|
|
3767
|
+
/** vaultIds successfully migrated (or already current). */
|
|
3768
|
+
readonly migrated: string[];
|
|
3769
|
+
/** vaultIds whose cutover failed, with the error message. */
|
|
3770
|
+
readonly failed: {
|
|
3771
|
+
readonly vaultId: string;
|
|
3772
|
+
readonly error: string;
|
|
3773
|
+
}[];
|
|
3795
3774
|
}
|
|
3796
3775
|
/** Options for a cross-shard fan-out read. */
|
|
3797
3776
|
interface FanoutQueryOptions {
|
|
@@ -3836,6 +3815,48 @@ interface CrossVaultLiveAggregation<R> extends LiveAggregation<R> {
|
|
|
3836
3815
|
readonly skippedVaults: readonly SkippedVault[];
|
|
3837
3816
|
readonly ready: Promise<void>;
|
|
3838
3817
|
}
|
|
3818
|
+
/**
|
|
3819
|
+
* Context passed to a cross-vault `derive` callback (#271 Insight Vault).
|
|
3820
|
+
* One call per shard; identifies which shard the records came from.
|
|
3821
|
+
*/
|
|
3822
|
+
interface CrossVaultDerivationContext {
|
|
3823
|
+
/** The shard's vault id (e.g. `firm-clients--acme`). */
|
|
3824
|
+
readonly vaultId: string;
|
|
3825
|
+
/** The shard's partition key (e.g. `acme`). */
|
|
3826
|
+
readonly partitionKey: string;
|
|
3827
|
+
/** The shard's schema/template version, from its registry row. */
|
|
3828
|
+
readonly schemaVersion: number;
|
|
3829
|
+
}
|
|
3830
|
+
/**
|
|
3831
|
+
* A push-model cross-vault derivation (#271, Insight Vault — Layer 4).
|
|
3832
|
+
*
|
|
3833
|
+
* For each eligible shard, `refreshInsights()` reads the shard's `source`
|
|
3834
|
+
* collection, runs `derive` on that shard's records, and writes the returned
|
|
3835
|
+
* summary row into a separate analytics ("Insight") vault — keyed by partition
|
|
3836
|
+
* key, one row per shard. The summary is re-encrypted under the Insight Vault's
|
|
3837
|
+
* own DEK; the shard's ciphertext never leaves its DEK boundary (the push model
|
|
3838
|
+
* that resolves the cross-vault DEK conflict). See the ZK note in the spec —
|
|
3839
|
+
* the Insight Vault backend sees aggregated structure across shards, a weaker
|
|
3840
|
+
* profile than per-shard vaults; opt-in.
|
|
3841
|
+
*/
|
|
3842
|
+
interface CrossVaultDerivationSpec<R = Record<string, unknown>, S = Record<string, unknown>> {
|
|
3843
|
+
/** Collection read from each shard. */
|
|
3844
|
+
readonly source: string;
|
|
3845
|
+
/** Destination Insight Vault + collection for the per-shard summary rows. */
|
|
3846
|
+
readonly target: {
|
|
3847
|
+
readonly vault: string;
|
|
3848
|
+
readonly collection: string;
|
|
3849
|
+
};
|
|
3850
|
+
/** Per-shard reducer: that shard's source records + context → one summary row. */
|
|
3851
|
+
readonly derive: (records: R[], ctx: CrossVaultDerivationContext) => S;
|
|
3852
|
+
}
|
|
3853
|
+
/** The result of `refreshInsights()`. */
|
|
3854
|
+
interface RefreshInsightsResult {
|
|
3855
|
+
/** Number of summary rows written (one per eligible shard × registered derivation). */
|
|
3856
|
+
readonly written: number;
|
|
3857
|
+
/** Shards excluded (schema-drift, unprovisioned, or read error). */
|
|
3858
|
+
readonly skippedVaults: SkippedVault[];
|
|
3859
|
+
}
|
|
3839
3860
|
/** A serializable blueprint captured from a VaultTemplate.configure run. */
|
|
3840
3861
|
interface CapturedBlueprint {
|
|
3841
3862
|
/** Sorted collection names declared by the template. */
|
|
@@ -3860,12 +3881,34 @@ interface SchemaManifestRow {
|
|
|
3860
3881
|
interface DeploymentEvent {
|
|
3861
3882
|
readonly id: string;
|
|
3862
3883
|
readonly ts: number;
|
|
3863
|
-
readonly type: 'shard-created' | 'manifest-recorded' | 'group-opened';
|
|
3884
|
+
readonly type: 'shard-created' | 'manifest-recorded' | 'group-opened' | 'migration-started' | 'migration-completed' | 'migration-failed';
|
|
3864
3885
|
readonly group: string;
|
|
3865
3886
|
readonly vaultId?: string;
|
|
3866
3887
|
readonly templateName?: string;
|
|
3867
3888
|
readonly version?: number;
|
|
3868
3889
|
readonly actor?: string;
|
|
3890
|
+
/** Free-form detail (e.g. migration error message). */
|
|
3891
|
+
readonly detail?: string;
|
|
3892
|
+
}
|
|
3893
|
+
/**
|
|
3894
|
+
* One row in the StateManagement `migration-status` collection (#271 fleet
|
|
3895
|
+
* schema-migration runner), keyed by `vaultId`. Tracks each shard's progress
|
|
3896
|
+
* toward the template's current version so the active batch runner is
|
|
3897
|
+
* resumable and the staged rollout can verify a cohort before proceeding.
|
|
3898
|
+
*/
|
|
3899
|
+
interface MigrationStatusRow {
|
|
3900
|
+
readonly vaultId: string;
|
|
3901
|
+
readonly group: string;
|
|
3902
|
+
/** The shard's registry schemaVersion at the time of this status. */
|
|
3903
|
+
readonly currentVersion: number;
|
|
3904
|
+
/** The version the runner is moving this shard to (the template's version). */
|
|
3905
|
+
readonly targetVersion: number;
|
|
3906
|
+
readonly status: 'pending' | 'running' | 'done' | 'failed';
|
|
3907
|
+
readonly startedAt?: number;
|
|
3908
|
+
readonly finishedAt?: number;
|
|
3909
|
+
/** Records migrated by the per-shard cutover (when status `done`). */
|
|
3910
|
+
readonly migrated?: number;
|
|
3911
|
+
readonly error?: string;
|
|
3869
3912
|
}
|
|
3870
3913
|
|
|
3871
3914
|
/**
|
|
@@ -3880,8 +3923,14 @@ declare class StateManagementVault {
|
|
|
3880
3923
|
readonly registry: Collection<VaultRegistryRow>;
|
|
3881
3924
|
readonly schemaManifest: Collection<SchemaManifestRow>;
|
|
3882
3925
|
private constructor();
|
|
3883
|
-
/** Idempotently open the reserved state vault and bind the
|
|
3926
|
+
/** Idempotently open the reserved state vault and bind the control-plane collections. */
|
|
3884
3927
|
static open(db: Noydb): Promise<StateManagementVault>;
|
|
3928
|
+
/** Read one shard's migration status (or null). */
|
|
3929
|
+
getMigrationStatus(vaultId: string): Promise<MigrationStatusRow | null>;
|
|
3930
|
+
/** All migration-status rows (hydrates first). */
|
|
3931
|
+
listMigrationStatus(): Promise<MigrationStatusRow[]>;
|
|
3932
|
+
/** Upsert one shard's migration status (keyed by vaultId). */
|
|
3933
|
+
upsertMigrationStatus(row: MigrationStatusRow): Promise<void>;
|
|
3885
3934
|
/** Read-only query over the append-only deployment-events log. */
|
|
3886
3935
|
queryEvents(): Query<DeploymentEvent>;
|
|
3887
3936
|
/**
|
|
@@ -5586,12 +5635,14 @@ declare class VaultGroup<T> {
|
|
|
5586
5635
|
/** @internal */ readonly registry: Collection<VaultRegistryRow>;
|
|
5587
5636
|
/** @internal */ readonly sharding: ShardingConfig<T>;
|
|
5588
5637
|
/** @internal */ readonly template: VaultTemplate;
|
|
5638
|
+
/** @internal — lazy migrate-on-open (#271). */ readonly migrateOnOpen: boolean;
|
|
5589
5639
|
constructor(
|
|
5590
5640
|
/** @internal */ db: Noydb,
|
|
5591
5641
|
/** @internal */ name: string,
|
|
5592
5642
|
/** @internal */ registry: Collection<VaultRegistryRow>,
|
|
5593
5643
|
/** @internal */ sharding: ShardingConfig<T>,
|
|
5594
|
-
/** @internal */ template: VaultTemplate
|
|
5644
|
+
/** @internal */ template: VaultTemplate,
|
|
5645
|
+
/** @internal — lazy migrate-on-open (#271). */ migrateOnOpen?: boolean);
|
|
5595
5646
|
/** @internal — set when the group is managed (no explicit registry). */
|
|
5596
5647
|
private stateVault;
|
|
5597
5648
|
/** @internal */
|
|
@@ -5614,8 +5665,14 @@ declare class VaultGroup<T> {
|
|
|
5614
5665
|
* `liveBinding().isRelevant` already applies to the reactive path.
|
|
5615
5666
|
*/
|
|
5616
5667
|
allRows(): Promise<VaultRegistryRow[]>;
|
|
5617
|
-
/**
|
|
5668
|
+
/**
|
|
5669
|
+
* Open an existing shard and apply the template. When `migrateOnOpen` is set
|
|
5670
|
+
* (#271) and the shard's registry version is behind the template, its cutover
|
|
5671
|
+
* runs inline first — so a behind shard never surfaces a stale handle.
|
|
5672
|
+
*/
|
|
5618
5673
|
openShard(partitionKey: string): Promise<Vault>;
|
|
5674
|
+
/** @internal — open + configure with no migrate-on-open hook (used by the migration path itself to avoid recursion). */
|
|
5675
|
+
private _openShardRaw;
|
|
5619
5676
|
/**
|
|
5620
5677
|
* Idempotently provision a shard for `partitionKey`. Returns the
|
|
5621
5678
|
* configured vault handle.
|
|
@@ -5640,6 +5697,69 @@ declare class VaultGroup<T> {
|
|
|
5640
5697
|
eligible: VaultRegistryRow[];
|
|
5641
5698
|
skipped: SkippedVault[];
|
|
5642
5699
|
}>;
|
|
5700
|
+
/** @internal — registered push-model cross-vault derivations (#271 Insight Vault). */
|
|
5701
|
+
private readonly crossVaultDerivations;
|
|
5702
|
+
/**
|
|
5703
|
+
* Register a push-model cross-vault derivation — the Insight Vault pattern
|
|
5704
|
+
* (#271, Layer 4). Drive it with {@link refreshInsights}.
|
|
5705
|
+
*
|
|
5706
|
+
* For each shard, `derive(records, ctx)` runs on that shard's `source`
|
|
5707
|
+
* records and its return value is written into the analytics
|
|
5708
|
+
* (`target.vault` / `target.collection`) vault, keyed by partition key —
|
|
5709
|
+
* one summary row per shard. The derivation runs in-process under THIS
|
|
5710
|
+
* group's `Noydb` (which already holds both the shard and Insight Vault
|
|
5711
|
+
* keyrings); the shard's decrypted records are reduced to a summary that is
|
|
5712
|
+
* re-encrypted under the Insight Vault's own DEK, so no shard ciphertext
|
|
5713
|
+
* crosses a DEK boundary.
|
|
5714
|
+
*
|
|
5715
|
+
* **Zero-knowledge note:** the Insight Vault backend sees aggregated
|
|
5716
|
+
* structure (totals, counts, timestamps) drawn from many shards — a weaker
|
|
5717
|
+
* ZK profile than the per-shard vaults. Opt-in; keep summaries to aggregate
|
|
5718
|
+
* scalars (no embeddings / no raw records).
|
|
5719
|
+
*
|
|
5720
|
+
* v1 is explicit-refresh (no write-path push); call `refreshInsights()`
|
|
5721
|
+
* after a batch of writes, or on a schedule.
|
|
5722
|
+
*/
|
|
5723
|
+
withCrossVaultDerivation<R = Record<string, unknown>, S = Record<string, unknown>>(spec: CrossVaultDerivationSpec<R, S>): void;
|
|
5724
|
+
/**
|
|
5725
|
+
* Run every registered {@link withCrossVaultDerivation}: read each eligible
|
|
5726
|
+
* shard's source records, derive a per-shard summary, and write it into the
|
|
5727
|
+
* Insight Vault keyed by partition key. Shards behind `minVersion`,
|
|
5728
|
+
* unprovisioned, or whose read errors are reported in `skippedVaults` and
|
|
5729
|
+
* are not written (a stale summary is never left behind for a failed shard).
|
|
5730
|
+
*/
|
|
5731
|
+
refreshInsights(options?: {
|
|
5732
|
+
minVersion?: number;
|
|
5733
|
+
concurrency?: number;
|
|
5734
|
+
}): Promise<RefreshInsightsResult>;
|
|
5735
|
+
/** @internal — the control-plane vault for migration status; lazily opened. */
|
|
5736
|
+
private ensureStateVault;
|
|
5737
|
+
/**
|
|
5738
|
+
* Migrate ONE shard to the template's current version (#271 fleet runner,
|
|
5739
|
+
* per-shard step). Opens the shard (applying the template, which arms the
|
|
5740
|
+
* M12 cutover), drains schema-write detection, runs `vault.runSchemaCutover()`
|
|
5741
|
+
* (the per-vault drain-barrier-transform protocol), then advances the
|
|
5742
|
+
* registry row's `schemaVersion` and records `migration-status`. A shard
|
|
5743
|
+
* already at the template version is a no-op (`status: 'done'`, migrated 0).
|
|
5744
|
+
* Never throws on a cutover failure — it records `status: 'failed'` and
|
|
5745
|
+
* returns the row, so a fleet run continues past a bad shard.
|
|
5746
|
+
*/
|
|
5747
|
+
migrateShard(partitionKey: string): Promise<MigrationStatusRow>;
|
|
5748
|
+
/**
|
|
5749
|
+
* Active batch runner (#271): migrate every shard behind the template version
|
|
5750
|
+
* to it, in controlled batches. **Resumable + crash-safe** — shards already at
|
|
5751
|
+
* the target are skipped (the registry version is the source of truth), so a
|
|
5752
|
+
* re-run after a crash only picks up the unfinished + previously-failed shards.
|
|
5753
|
+
*
|
|
5754
|
+
* - `cohort` — restrict to these partition keys (the staged / canary rollout:
|
|
5755
|
+
* migrate a small cohort, verify the Insight Vault, then run the rest).
|
|
5756
|
+
* - `batchSize` — max shards migrated concurrently per batch (back-pressure).
|
|
5757
|
+
* Default 4. Batches run sequentially; shards within a batch run in parallel.
|
|
5758
|
+
*/
|
|
5759
|
+
migrateFleet(options?: {
|
|
5760
|
+
cohort?: readonly string[];
|
|
5761
|
+
batchSize?: number;
|
|
5762
|
+
}): Promise<FleetMigrationResult>;
|
|
5643
5763
|
}
|
|
5644
5764
|
declare class ShardedCollection<T, R = T> {
|
|
5645
5765
|
private readonly group;
|
|
@@ -5737,6 +5857,7 @@ declare class Noydb {
|
|
|
5737
5857
|
private readonly policyEnforcers;
|
|
5738
5858
|
private readonly vaultTemplates;
|
|
5739
5859
|
private readonly txStrategy;
|
|
5860
|
+
private readonly forgetStrategy;
|
|
5740
5861
|
private readonly sessionStrategy;
|
|
5741
5862
|
private readonly syncStrategy;
|
|
5742
5863
|
private readonly snapshotStrategy;
|
|
@@ -5761,6 +5882,8 @@ declare class Noydb {
|
|
|
5761
5882
|
/** Audit log for all translator invocations in this session. Cleared on `close()`. */
|
|
5762
5883
|
private readonly _translatorAuditLog;
|
|
5763
5884
|
constructor(options: NoydbOptions);
|
|
5885
|
+
/** @internal — resolved forget strategy (NO_FORGET when not configured). */
|
|
5886
|
+
get _forgetStrategy(): ForgetStrategy;
|
|
5764
5887
|
private resetSessionTimer;
|
|
5765
5888
|
/**
|
|
5766
5889
|
* Attach a policy enforcer for a vault.
|
|
@@ -6901,6 +7024,27 @@ interface RecordOutputSpec {
|
|
|
6901
7024
|
* `DerivationOutputShapeError` — same as v1.
|
|
6902
7025
|
*/
|
|
6903
7026
|
optional?: boolean;
|
|
7027
|
+
/**
|
|
7028
|
+
* Field-level provenance for a **self-write** output (#376) — an output
|
|
7029
|
+
* whose `collection` equals the strategy's `source`, used by
|
|
7030
|
+
* reverse-denormalization (`triggerBy`) to patch a denormalized field
|
|
7031
|
+
* back onto the source record.
|
|
7032
|
+
*
|
|
7033
|
+
* `denorm` names the ONLY top-level fields the derivation owns on that
|
|
7034
|
+
* record. The engine merges just those fields from the `derive` return
|
|
7035
|
+
* value onto the current stored record (`{ ...current, ...pick(out, denorm) }`)
|
|
7036
|
+
* — the rest of the user's record is never clobbered by a stale snapshot.
|
|
7037
|
+
* The whole-record `_derivedFrom` provenance tag is NOT applied (the
|
|
7038
|
+
* record stays user-owned); the derivation only claims `denorm`.
|
|
7039
|
+
*
|
|
7040
|
+
* Cycle break is value-level: if the patch changes nothing, no write is
|
|
7041
|
+
* issued — so the self-write that re-fires the source-path derivation
|
|
7042
|
+
* terminates after one idempotent pass.
|
|
7043
|
+
*
|
|
7044
|
+
* REQUIRED when `collection === source` (validated at construction);
|
|
7045
|
+
* ignored for outputs to a different collection.
|
|
7046
|
+
*/
|
|
7047
|
+
denorm?: readonly string[];
|
|
6904
7048
|
}
|
|
6905
7049
|
/**
|
|
6906
7050
|
* Array-shape output — one source row produces a variable-length
|
|
@@ -6981,6 +7125,52 @@ interface DerivationStrategy<TSource extends Record<string, unknown>, TOutputs e
|
|
|
6981
7125
|
* (validated at `withDerivation()` construction time).
|
|
6982
7126
|
*/
|
|
6983
7127
|
sources?: ReadonlyArray<string>;
|
|
7128
|
+
/**
|
|
7129
|
+
* Foreign-key-keyed triggers for reverse-denormalization (#376). Unlike
|
|
7130
|
+
* `sources[]` (which re-fires at the SAME id), a `triggerBy` entry fans a
|
|
7131
|
+
* write to a PARENT collection OUT to every source record whose FK matches
|
|
7132
|
+
* the written parent's id.
|
|
7133
|
+
*
|
|
7134
|
+
* `{ collection, on }`: a write to `collection` (the parent, e.g.
|
|
7135
|
+
* `'buyers'`) re-fires this derivation once per source record where
|
|
7136
|
+
* `source[on] === writtenParentId` (`on` is the FK field ON the source,
|
|
7137
|
+
* e.g. `'buyerId'`). The matched source record — not the parent — is
|
|
7138
|
+
* passed to `derive`.
|
|
7139
|
+
*
|
|
7140
|
+
* Typical use: keep a denormalized field on the source in sync with a
|
|
7141
|
+
* parent change (a buyer rename → refresh `buyerName` on all their sales),
|
|
7142
|
+
* via a self-write output (`collection === source`) declaring `denorm`.
|
|
7143
|
+
*
|
|
7144
|
+
* Fan-out runs through `ctx.vault.collection(source).query().where(on,'==',id)`,
|
|
7145
|
+
* which uses the FK index when the source declares `withIndexing()` on
|
|
7146
|
+
* `on` (O(children)) and otherwise scans (O(N) — fine for small child
|
|
7147
|
+
* sets). Set `maxFanout` as a safety rail; exceeding it throws
|
|
7148
|
+
* `DerivationCapExceededError` before any write. `triggerBy` collections
|
|
7149
|
+
* participate in cycle detection like `source`/`sources`.
|
|
7150
|
+
*
|
|
7151
|
+
* Each `collection` must be non-empty and not equal `source`; `on` must
|
|
7152
|
+
* be a non-empty field name (validated at construction).
|
|
7153
|
+
*/
|
|
7154
|
+
triggerBy?: ReadonlyArray<{
|
|
7155
|
+
collection: string;
|
|
7156
|
+
on: string;
|
|
7157
|
+
maxFanout?: number;
|
|
7158
|
+
}>;
|
|
7159
|
+
/**
|
|
7160
|
+
* @internal — set by `withRollup()` (#376 slice 2). Marks this strategy as
|
|
7161
|
+
* an aggregate-onto-parent rollup: a write OR delete of a `from` (child)
|
|
7162
|
+
* record recomputes `compute(children where child[key] === parentId)` and
|
|
7163
|
+
* patches it onto `source[field]` of the parent at `parentId` (= child[key]).
|
|
7164
|
+
* `source` is the parent (`into`) collection; the synthetic self-write
|
|
7165
|
+
* output carries `denorm: [field]`. Dispatch handles rollup specially (it
|
|
7166
|
+
* does not run the executor). Eager-only in this slice.
|
|
7167
|
+
*/
|
|
7168
|
+
rollup?: {
|
|
7169
|
+
readonly from: string;
|
|
7170
|
+
readonly key: string;
|
|
7171
|
+
readonly field: string;
|
|
7172
|
+
readonly compute: (children: any[]) => unknown;
|
|
7173
|
+
};
|
|
6984
7174
|
/** v1: only deterministic derivations supported. */
|
|
6985
7175
|
deterministic: true;
|
|
6986
7176
|
/**
|
|
@@ -7602,7 +7792,43 @@ interface NextOptions {
|
|
|
7602
7792
|
interface SequenceOptions {
|
|
7603
7793
|
/** Partition tuple. Each component is URI-encoded and `'/'`-joined. */
|
|
7604
7794
|
readonly partition?: readonly (string | number)[];
|
|
7795
|
+
/**
|
|
7796
|
+
* Render template for the serial string (#375). When set, `vault.sequence`
|
|
7797
|
+
* returns a {@link FormattedSequenceHandle} whose `next()` resolves to
|
|
7798
|
+
* `{ serial, formatted }`. Tokens:
|
|
7799
|
+
* - `{seq}` — the allocated integer
|
|
7800
|
+
* - `{seq:0N}` — zero-padded to width N (e.g. `{seq:04}` → `0001`)
|
|
7801
|
+
* - `{partition.i}` — the i-th `partition` component (original value)
|
|
7802
|
+
*
|
|
7803
|
+
* Any other token, or a `{partition.i}` index beyond the supplied
|
|
7804
|
+
* `partition`, throws `ValidationError` at `vault.sequence()` construction.
|
|
7805
|
+
* Per-partition reset is inherent: a new partition tuple starts at 1.
|
|
7806
|
+
*/
|
|
7807
|
+
readonly format?: string;
|
|
7808
|
+
}
|
|
7809
|
+
/**
|
|
7810
|
+
* A formatted sequence handle (#375). Identical to {@link SequenceHandle}
|
|
7811
|
+
* except `next()` also returns the rendered `formatted` string. `peek()` /
|
|
7812
|
+
* `seedTo()` operate on the underlying integer counter, unchanged.
|
|
7813
|
+
*/
|
|
7814
|
+
interface FormattedSequenceHandle {
|
|
7815
|
+
/** Allocate the next value and return it with its rendered serial string. */
|
|
7816
|
+
next(opts?: NextOptions): Promise<{
|
|
7817
|
+
serial: number;
|
|
7818
|
+
formatted: string;
|
|
7819
|
+
}>;
|
|
7820
|
+
/** Read the current integer value without allocating. Returns 0 if never used. */
|
|
7821
|
+
peek(): Promise<number>;
|
|
7822
|
+
/** Set-if-greater on the underlying integer counter. See {@link SequenceHandle.seedTo}. */
|
|
7823
|
+
seedTo(n: number): Promise<void>;
|
|
7605
7824
|
}
|
|
7825
|
+
/**
|
|
7826
|
+
* Validate a sequence `format` against the supplied partition and return a
|
|
7827
|
+
* pure `(serial) => string` renderer. Eager validation: every token is
|
|
7828
|
+
* checked now, so a bad pattern throws `ValidationError` at construction —
|
|
7829
|
+
* never at `next()` time.
|
|
7830
|
+
*/
|
|
7831
|
+
declare function compileSequenceFormat(format: string, series: string, partition: readonly (string | number)[] | undefined): (serial: number) => string;
|
|
7606
7832
|
/**
|
|
7607
7833
|
* Resolve the CAS storage key for a (series, partition) pair.
|
|
7608
7834
|
*
|
|
@@ -7678,6 +7904,78 @@ interface Assignment {
|
|
|
7678
7904
|
serial: number;
|
|
7679
7905
|
}
|
|
7680
7906
|
|
|
7907
|
+
/**
|
|
7908
|
+
* `_links_*` reserved collections — managed bidirectional many-to-many
|
|
7909
|
+
* junctions (#377 design B).
|
|
7910
|
+
*
|
|
7911
|
+
* Where `refArray` (design A) stores an id-array on one owning record,
|
|
7912
|
+
* `vault.link()` creates a first-class junction: a dedicated encrypted
|
|
7913
|
+
* `_links_<name>` collection whose rows are `{ a, b, meta? }` link tuples.
|
|
7914
|
+
* It is queryable from BOTH sides (`of(id)`), carries optional per-link
|
|
7915
|
+
* metadata, and cascades on endpoint delete.
|
|
7916
|
+
*
|
|
7917
|
+
* Each link is slot-typed: `a` is an id in the `a` endpoint collection,
|
|
7918
|
+
* `b` an id in the `b` endpoint collection (they may be the same
|
|
7919
|
+
* collection for self-links). A link's identity is the ordered pair
|
|
7920
|
+
* `(a, b)`; `of(id)` matches either slot.
|
|
7921
|
+
*
|
|
7922
|
+
* Rows are encrypted under a dedicated `_links_<name>` DEK — same
|
|
7923
|
+
* zero-knowledge stack as every other collection (the store sees only
|
|
7924
|
+
* ciphertext). Backup/restore rides the normal `loadAll` path.
|
|
7925
|
+
*/
|
|
7926
|
+
|
|
7927
|
+
/** True for any reserved link-collection name. */
|
|
7928
|
+
declare function isLinkCollectionName(name: string): boolean;
|
|
7929
|
+
/** What happens to a link's rows when one of its endpoint records is deleted. */
|
|
7930
|
+
type LinkOnDelete = 'cascade' | 'strict' | 'warn';
|
|
7931
|
+
/**
|
|
7932
|
+
* Declaration for a link set, passed to `vault.link(name, spec)`. `a` and
|
|
7933
|
+
* `b` are the endpoint collection names (slot-typed). `onDelete` governs
|
|
7934
|
+
* what happens to link rows when an endpoint record is deleted:
|
|
7935
|
+
* `'cascade'` (default) removes the touching link rows, `'strict'` blocks
|
|
7936
|
+
* the endpoint delete while links exist, `'warn'` leaves orphan rows
|
|
7937
|
+
* (surfaced by `vault.checkIntegrity()`).
|
|
7938
|
+
*/
|
|
7939
|
+
interface LinkSpec {
|
|
7940
|
+
readonly a: string;
|
|
7941
|
+
readonly b: string;
|
|
7942
|
+
readonly onDelete?: LinkOnDelete;
|
|
7943
|
+
}
|
|
7944
|
+
/** One link tuple as returned by `of()` / `list()`. */
|
|
7945
|
+
interface LinkRow {
|
|
7946
|
+
readonly a: string;
|
|
7947
|
+
readonly b: string;
|
|
7948
|
+
readonly meta?: Record<string, unknown>;
|
|
7949
|
+
}
|
|
7950
|
+
/** Public handle returned by `vault.links(name)`. */
|
|
7951
|
+
interface LinkSetHandle {
|
|
7952
|
+
/** Create (or overwrite the metadata of) the link `(aId, bId)`. Validates both endpoints exist. */
|
|
7953
|
+
connect(aId: string, bId: string, meta?: Record<string, unknown>): Promise<void>;
|
|
7954
|
+
/** Remove the link `(aId, bId)`. Idempotent — a no-op if it doesn't exist. */
|
|
7955
|
+
disconnect(aId: string, bId: string): Promise<void>;
|
|
7956
|
+
/** Whether the link `(aId, bId)` exists. */
|
|
7957
|
+
has(aId: string, bId: string): Promise<boolean>;
|
|
7958
|
+
/** All links touching `id` on EITHER endpoint. */
|
|
7959
|
+
of(id: string): Promise<LinkRow[]>;
|
|
7960
|
+
/** All links in the set. */
|
|
7961
|
+
list(): Promise<LinkRow[]>;
|
|
7962
|
+
}
|
|
7963
|
+
/** Thrown by `connect()` when an endpoint record does not exist. */
|
|
7964
|
+
declare class LinkEndpointError extends NoydbError {
|
|
7965
|
+
readonly link: string;
|
|
7966
|
+
readonly endpoint: string;
|
|
7967
|
+
readonly missingId: string;
|
|
7968
|
+
constructor(link: string, endpoint: string, missingId: string);
|
|
7969
|
+
}
|
|
7970
|
+
/** Thrown when a `strict` link blocks deletion of an endpoint that still has links. */
|
|
7971
|
+
declare class LinkIntegrityError extends NoydbError {
|
|
7972
|
+
readonly link: string;
|
|
7973
|
+
readonly endpoint: string;
|
|
7974
|
+
readonly id: string;
|
|
7975
|
+
readonly count: number;
|
|
7976
|
+
constructor(link: string, endpoint: string, id: string, count: number);
|
|
7977
|
+
}
|
|
7978
|
+
|
|
7681
7979
|
/**
|
|
7682
7980
|
* Vault-internal singleton that holds the guard graph and dispatches
|
|
7683
7981
|
* per-collection guard execution. Owned by `Vault`; not exported.
|
|
@@ -7747,12 +8045,25 @@ declare class GuardRegistry {
|
|
|
7747
8045
|
|
|
7748
8046
|
/**
|
|
7749
8047
|
* Minimal read-only wrapper over a `Vault`. Used as `ctx.vault` inside
|
|
7750
|
-
* guard callbacks so they can fetch related records without
|
|
7751
|
-
* any write capability.
|
|
8048
|
+
* guard / derivation callbacks so they can fetch related records without
|
|
8049
|
+
* acquiring any write capability.
|
|
8050
|
+
*
|
|
8051
|
+
* The `layer` tags every `get`/`list` read with the resolution layer it
|
|
8052
|
+
* belongs to (#285). A guard-seeded facade reads at `'guard'`, a
|
|
8053
|
+
* derivation-seeded one at `'derivation'`, so i18nText / dictKey fields
|
|
8054
|
+
* resolve under that layer's `onMissing` policy instead of the `'read'`
|
|
8055
|
+
* policy — e.g. a guard read can `substitute` a missing locale (lenient
|
|
8056
|
+
* default) while the same field `throw`s on an ordinary app read.
|
|
8057
|
+
*
|
|
8058
|
+
* `query()` is left untagged: the query/aggregate pipeline reads raw
|
|
8059
|
+
* `{locale}` maps (no resolution call site), so a layer tag there would be
|
|
8060
|
+
* inert. Routing `mv`/`join` resolution through the pipeline is tracked
|
|
8061
|
+
* separately (#285 D2/D3).
|
|
7752
8062
|
*/
|
|
7753
8063
|
declare class ReadOnlyVaultFacade implements ReadOnlyVaultFacade$1 {
|
|
7754
8064
|
private readonly _vault;
|
|
7755
|
-
|
|
8065
|
+
private readonly _layer;
|
|
8066
|
+
constructor(vault: Vault, layer?: Layer);
|
|
7756
8067
|
collection<T = unknown>(name: string): {
|
|
7757
8068
|
get(id: string): Promise<T | null>;
|
|
7758
8069
|
list(): Promise<T[]>;
|
|
@@ -7761,45 +8072,326 @@ declare class ReadOnlyVaultFacade implements ReadOnlyVaultFacade$1 {
|
|
|
7761
8072
|
}
|
|
7762
8073
|
|
|
7763
8074
|
/**
|
|
7764
|
-
*
|
|
8075
|
+
* Managed-passphrase mode — rubber-hose-resistant vaults.
|
|
7765
8076
|
*
|
|
7766
|
-
*
|
|
7767
|
-
*
|
|
7768
|
-
*
|
|
7769
|
-
*
|
|
7770
|
-
*
|
|
7771
|
-
* memory.
|
|
8077
|
+
* A vault mode where the passphrase is machine-generated and never
|
|
8078
|
+
* exposed to the user, sealed under a developer-provided
|
|
8079
|
+
* {@link SealingKeyProvider} (macOS Keychain, Windows Credential
|
|
8080
|
+
* Manager, libsecret, AWS KMS, …). The user has no secret to give
|
|
8081
|
+
* up to coercion — they can't reveal what they don't know.
|
|
7772
8082
|
*
|
|
7773
|
-
* ##
|
|
8083
|
+
* ## Components in this file
|
|
7774
8084
|
*
|
|
7775
|
-
*
|
|
7776
|
-
*
|
|
7777
|
-
*
|
|
7778
|
-
*
|
|
7779
|
-
* -
|
|
7780
|
-
*
|
|
7781
|
-
*
|
|
7782
|
-
*
|
|
8085
|
+
* - {@link SealingKeyProvider} — the interface concrete providers
|
|
8086
|
+
* implement. Provider implementations live OUTSIDE hub (per-
|
|
8087
|
+
* platform packages).
|
|
8088
|
+
* - {@link MemorySealingKeyProvider} — in-memory test provider; uses
|
|
8089
|
+
* a deterministic per-instance "key" so two providers with
|
|
8090
|
+
* different ids cannot unseal each other's outputs.
|
|
8091
|
+
* - {@link RecipientHint} — public material a sender uses to seal
|
|
8092
|
+
* plaintext for a specific recipient; published by
|
|
8093
|
+
* {@link RecipientSealer.publishRecipientHint} and transported
|
|
8094
|
+
* out-of-band to the sender before bundle writes.
|
|
8095
|
+
* - {@link RecipientSealer} — interface for asymmetric/granted
|
|
8096
|
+
* providers that support recipient-target sealing (RSA-OAEP,
|
|
8097
|
+
* cloud-KMS asymmetric, etc.); distinct from self-only
|
|
8098
|
+
* {@link SealingKeyProvider} (macOS Keychain, WebAuthn-PRF).
|
|
8099
|
+
* - {@link MemoryRecipientSealer} — in-process reference
|
|
8100
|
+
* implementation of both `RecipientSealer` and
|
|
8101
|
+
* `SealingKeyProvider` using real WebCrypto RSA-OAEP + AES-GCM;
|
|
8102
|
+
* safe for tests and same-process sender/recipient scenarios.
|
|
8103
|
+
* - {@link loadSealedPassphrase} / {@link saveSealedPassphrase} —
|
|
8104
|
+
* plaintext envelope storage at `_meta/sealed-passphrase`.
|
|
8105
|
+
* Mirrors the `_meta/handle` and `_meta/public-envelope` AES-
|
|
8106
|
+
* GCM-bypassed patterns. The sealing layer (provider's job)
|
|
8107
|
+
* is the security boundary; hub doesn't have a key to encrypt
|
|
8108
|
+
* with at this layer — that's the whole point of the design.
|
|
8109
|
+
* - {@link resolveManagedSecret} — orchestrates the "generate +
|
|
8110
|
+
* seal + persist on first open; unseal on reopen" flow.
|
|
8111
|
+
* Returns the plaintext passphrase string that the rest of the
|
|
8112
|
+
* `createNoydb` keyring path consumes.
|
|
7783
8113
|
*
|
|
7784
|
-
*
|
|
8114
|
+
* Deferred to follow-ups:
|
|
8115
|
+
* - Block `rotate-passphrase` policy gate under managed mode.
|
|
8116
|
+
* - Mandatory strong-recovery enforcement.
|
|
8117
|
+
* - Recovery flow under managed mode (generates fresh sealed phrase).
|
|
7785
8118
|
*
|
|
7786
|
-
* -
|
|
7787
|
-
* boundary throws `AbortError`. Consumers already in `for await`
|
|
7788
|
-
* can catch and exit cleanly.
|
|
7789
|
-
* - Restart after a partial failure with `{ afterBlobId }` — the
|
|
7790
|
-
* iterator skips tuples up to (and including) that blob id before
|
|
7791
|
-
* yielding again. Combined with a blob-count ceiling it supports
|
|
7792
|
-
* idempotent batch re-runs.
|
|
8119
|
+
* @see docs/subsystems/session-tiers.md → Managed-passphrase mode
|
|
7793
8120
|
*
|
|
7794
8121
|
* @module
|
|
7795
8122
|
*/
|
|
7796
8123
|
|
|
7797
|
-
|
|
8124
|
+
/**
|
|
8125
|
+
* The contract concrete providers (per-platform key stores) implement
|
|
8126
|
+
* to seal and unseal a hub-generated random passphrase. The plaintext
|
|
8127
|
+
* passphrase NEVER leaves hub-controlled memory in unsealed form —
|
|
8128
|
+
* the provider receives the bytes, returns opaque sealed bytes, and
|
|
8129
|
+
* later reverses the operation. Hub treats the sealed bytes as
|
|
8130
|
+
* fully opaque.
|
|
8131
|
+
*
|
|
8132
|
+
* Implementations live OUTSIDE `@noy-db/hub` (separate packages
|
|
8133
|
+
* per the issue's "Concrete providers (live outside hub)" note):
|
|
8134
|
+
*
|
|
8135
|
+
* | Platform | Package (TBD) | Backing |
|
|
8136
|
+
* |---|---|---|
|
|
8137
|
+
* | macOS | `@noy-db/seal-macos-keychain` | Security.framework |
|
|
8138
|
+
* | Windows | `@noy-db/seal-wincred` | Credential Manager |
|
|
8139
|
+
* | Linux | `@noy-db/seal-libsecret` | libsecret / secret-service |
|
|
8140
|
+
* | Cloud / server | `@noy-db/seal-aws-kms` | AWS KMS Decrypt |
|
|
8141
|
+
*/
|
|
8142
|
+
interface SealingKeyProvider {
|
|
7798
8143
|
/**
|
|
7799
|
-
*
|
|
7800
|
-
*
|
|
8144
|
+
* Non-sensitive identifier disclosed in the persisted envelope.
|
|
8145
|
+
* Surfaced to consumers via `loadSealedPassphrase().providerId` so
|
|
8146
|
+
* a vault opened with the wrong provider class can detect the
|
|
8147
|
+
* mismatch and surface a clear error. NOT secret — fine to log.
|
|
8148
|
+
*
|
|
8149
|
+
* Suggested format: `<family>:<scope>` — e.g. `macos-keychain:com.acme.app`,
|
|
8150
|
+
* `aws-kms:arn:aws:kms:us-east-1:123:key/abc`. The hub never
|
|
8151
|
+
* parses this; it's purely audit metadata.
|
|
7801
8152
|
*/
|
|
7802
|
-
readonly
|
|
8153
|
+
readonly id: string;
|
|
8154
|
+
/** Seal raw passphrase bytes. Output bytes are opaque to hub. */
|
|
8155
|
+
seal(passphrase: Uint8Array): Promise<Uint8Array>;
|
|
8156
|
+
/**
|
|
8157
|
+
* Reverse {@link seal}. MUST throw on tamper, wrong-provider, or
|
|
8158
|
+
* any other failure — hub treats a thrown error as "this provider
|
|
8159
|
+
* cannot unlock this vault" and surfaces it to the caller.
|
|
8160
|
+
*/
|
|
8161
|
+
unseal(sealed: Uint8Array): Promise<Uint8Array>;
|
|
8162
|
+
}
|
|
8163
|
+
/**
|
|
8164
|
+
* In-memory test provider. NOT secure — uses a deterministic
|
|
8165
|
+
* per-instance "key" (16-byte SHA-256 of `id`) XOR'd over the
|
|
8166
|
+
* passphrase plus a 4-byte provider-id fingerprint prefix. The XOR is
|
|
8167
|
+
* sufficient to make different `id` values produce mutually-unsealable
|
|
8168
|
+
* outputs (the contract tests for that), but offers ZERO real
|
|
8169
|
+
* confidentiality — never use outside tests.
|
|
8170
|
+
*
|
|
8171
|
+
* Replace with a real platform provider in production.
|
|
8172
|
+
*/
|
|
8173
|
+
declare class MemorySealingKeyProvider implements SealingKeyProvider {
|
|
8174
|
+
readonly id: string;
|
|
8175
|
+
private readonly fingerprint;
|
|
8176
|
+
private readonly keyBytes;
|
|
8177
|
+
constructor(opts: {
|
|
8178
|
+
id: string;
|
|
8179
|
+
});
|
|
8180
|
+
seal(passphrase: Uint8Array): Promise<Uint8Array>;
|
|
8181
|
+
unseal(sealed: Uint8Array): Promise<Uint8Array>;
|
|
8182
|
+
}
|
|
8183
|
+
/**
|
|
8184
|
+
* Public material a sender uses to seal-for-this-recipient. Published by
|
|
8185
|
+
* a recipient's RecipientSealer; transported to the sender out-of-band
|
|
8186
|
+
* (email, S3, in-app message). The sender obtains the hint, supplies it
|
|
8187
|
+
* to writeNoydbBundle's sealedCredentials.perUser[userId].hint, and the
|
|
8188
|
+
* hub seals each user's credential against it. Per foundation §11.4.
|
|
8189
|
+
*/
|
|
8190
|
+
type RecipientHint = {
|
|
8191
|
+
readonly v: 1;
|
|
8192
|
+
/** Recipient's provider id; matches the SealedAutoUnlockEntry.pid they'll unseal under. */
|
|
8193
|
+
readonly pid: string;
|
|
8194
|
+
/** Algorithm the sender uses to produce the seal. Slice 1 ships RSA-OAEP-SHA256 only. */
|
|
8195
|
+
readonly alg: 'rsa-oaep-sha256';
|
|
8196
|
+
/** Public material — alg-specific. For 'rsa-oaep-sha256': { publicKeyPem: string }. */
|
|
8197
|
+
readonly material: Readonly<Record<string, unknown>>;
|
|
8198
|
+
};
|
|
8199
|
+
/**
|
|
8200
|
+
* Handover-capable provider. Implemented additionally by asymmetric/granted
|
|
8201
|
+
* providers (cloud-KMS asymmetric, Azure RSA Key Vault, AWS KMS with grant).
|
|
8202
|
+
* Self-only providers (macOS Keychain, env-var, WebAuthn-PRF) do NOT
|
|
8203
|
+
* implement this — the §11.2 capability matrix lives in the type system.
|
|
8204
|
+
*
|
|
8205
|
+
* Per foundation §11.4. A function that requires recipient-target sealing
|
|
8206
|
+
* takes `RecipientSealer`, not `SealingKeyProvider` — the compiler rejects
|
|
8207
|
+
* passing a self-only provider at the spec site.
|
|
8208
|
+
*/
|
|
8209
|
+
interface RecipientSealer {
|
|
8210
|
+
readonly id: string;
|
|
8211
|
+
/** Produce hint material a sender uses to seal-for-this-recipient. */
|
|
8212
|
+
publishRecipientHint(): Promise<RecipientHint>;
|
|
8213
|
+
/**
|
|
8214
|
+
* Seal plaintext for the recipient described by `hint`. Returns opaque
|
|
8215
|
+
* bytes — same contract as `SealingKeyProvider.seal()`. The bundle
|
|
8216
|
+
* layer base64-encodes the bytes into `SealedAutoUnlockEntry.sealed`
|
|
8217
|
+
* without inspecting them.
|
|
8218
|
+
*/
|
|
8219
|
+
sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array>;
|
|
8220
|
+
}
|
|
8221
|
+
/**
|
|
8222
|
+
* Shared RSA-OAEP-SHA256 + AES-GCM seal in the canonical recipient-target
|
|
8223
|
+
* TLV wire format. Mints a fresh 32-byte CEK, AES-GCM-encrypts `plaintext`
|
|
8224
|
+
* under it, RSA-OAEP-SHA256-wraps the CEK to `publicKeyPem`, and packs:
|
|
8225
|
+
*
|
|
8226
|
+
* byte 0 : version (0x01)
|
|
8227
|
+
* bytes 1..256 : RSA-OAEP-wrapped CEK (fixed 256 bytes at RSA-2048)
|
|
8228
|
+
* bytes 257..268: AES-GCM IV (12 bytes)
|
|
8229
|
+
* bytes 269.. : AES-GCM ciphertext ‖ 16-byte tag
|
|
8230
|
+
*
|
|
8231
|
+
* This is the single source of truth for the wire format — both
|
|
8232
|
+
* {@link MemoryRecipientSealer} and external sealers (e.g. `@noy-db/at-aws-kms`'s
|
|
8233
|
+
* asymmetric-KMS recipient sealer) call it so a blob sealed by one unseals
|
|
8234
|
+
* by the other. WebCrypto RSA-OAEP/SHA-256 here is wire-compatible with
|
|
8235
|
+
* AWS KMS `RSAES_OAEP_SHA_256` (both RSAES-OAEP, SHA-256 hash, MGF1-SHA256,
|
|
8236
|
+
* empty label).
|
|
8237
|
+
*
|
|
8238
|
+
* @public — re-exported from the hub barrel for external sealer packages.
|
|
8239
|
+
*/
|
|
8240
|
+
declare function sealRsaOaepTlv(plaintext: Uint8Array, publicKeyPem: string): Promise<Uint8Array>;
|
|
8241
|
+
/**
|
|
8242
|
+
* Parse a {@link sealRsaOaepTlv} blob into its three segments without
|
|
8243
|
+
* decrypting. The `wrapped` CEK is RSA-OAEP-SHA256 ciphertext over a
|
|
8244
|
+
* 32-byte CEK — the unwrap step is pluggable: {@link MemoryRecipientSealer}
|
|
8245
|
+
* decrypts it with a local RSA private key; `@noy-db/at-aws-kms` hands it to
|
|
8246
|
+
* KMS `Decrypt`. After unwrapping, pass the CEK + `iv` + `ct` to
|
|
8247
|
+
* {@link aesGcmOpen}.
|
|
8248
|
+
*
|
|
8249
|
+
* @public — re-exported from the hub barrel for external sealer packages.
|
|
8250
|
+
*/
|
|
8251
|
+
declare function parseRsaOaepTlv(bytes: Uint8Array): {
|
|
8252
|
+
wrapped: Uint8Array;
|
|
8253
|
+
iv: Uint8Array;
|
|
8254
|
+
ct: Uint8Array;
|
|
8255
|
+
};
|
|
8256
|
+
/**
|
|
8257
|
+
* AES-GCM-decrypt the `ct` segment of a {@link parseRsaOaepTlv} result under
|
|
8258
|
+
* the unwrapped 32-byte CEK and its `iv`. Throws on a bad tag (tamper) — the
|
|
8259
|
+
* same authenticated-decryption guarantee the TLV relies on.
|
|
8260
|
+
*
|
|
8261
|
+
* @public — re-exported from the hub barrel for external sealer packages.
|
|
8262
|
+
*/
|
|
8263
|
+
declare function aesGcmOpen(cekBytes: Uint8Array, iv: Uint8Array, ct: Uint8Array): Promise<Uint8Array>;
|
|
8264
|
+
/**
|
|
8265
|
+
* Reference implementation of `RecipientSealer` + `SealingKeyProvider`.
|
|
8266
|
+
* Uses WebCrypto RSA-OAEP-SHA256 (2048-bit) to wrap a fresh 32-byte
|
|
8267
|
+
* AES-GCM CEK, AES-GCM-encrypts plaintext under it, and packs the
|
|
8268
|
+
* result into a self-describing TLV:
|
|
8269
|
+
*
|
|
8270
|
+
* byte 0 : version (0x01)
|
|
8271
|
+
* bytes 1..256 : RSA-OAEP-wrapped CEK (fixed 256 bytes at RSA-2048)
|
|
8272
|
+
* bytes 257..268: AES-GCM IV (12 bytes)
|
|
8273
|
+
* bytes 269.. : AES-GCM ciphertext ‖ 16-byte tag
|
|
8274
|
+
*
|
|
8275
|
+
* Implements BOTH interfaces. `seal(plaintext)` (self-target) is just
|
|
8276
|
+
* `sealForRecipient(plaintext, this own hint)` — same TLV. Convenient
|
|
8277
|
+
* for tests where one provider plays both ends. Real cloud providers
|
|
8278
|
+
* (`at-aws-kms`, etc.) will pick their own internal layouts; the only
|
|
8279
|
+
* contract is round-trip identity.
|
|
8280
|
+
*
|
|
8281
|
+
* SAFE for production within its scope — the cryptography is real
|
|
8282
|
+
* (RSA-OAEP + AES-GCM via WebCrypto), but the keypair lives in-process
|
|
8283
|
+
* and is regenerated on every construction. Not suitable as a managed
|
|
8284
|
+
* keychain; use it for tests and for shipping bundles where the
|
|
8285
|
+
* recipient instance lives in the same process as the sender (rare).
|
|
8286
|
+
*/
|
|
8287
|
+
declare class MemoryRecipientSealer implements SealingKeyProvider, RecipientSealer {
|
|
8288
|
+
readonly id: string;
|
|
8289
|
+
private readonly keypair;
|
|
8290
|
+
constructor(opts: {
|
|
8291
|
+
id: string;
|
|
8292
|
+
});
|
|
8293
|
+
publishRecipientHint(): Promise<RecipientHint>;
|
|
8294
|
+
sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array>;
|
|
8295
|
+
seal(plaintext: Uint8Array): Promise<Uint8Array>;
|
|
8296
|
+
unseal(bytes: Uint8Array): Promise<Uint8Array>;
|
|
8297
|
+
}
|
|
8298
|
+
/** Reserved id for the managed-passphrase envelope under `_meta`. */
|
|
8299
|
+
declare const SEALED_PASSPHRASE_RECORD_ID: "sealed-passphrase";
|
|
8300
|
+
/** Plaintext payload stored inside the `_meta/sealed-passphrase` envelope. */
|
|
8301
|
+
interface SealedPassphrase {
|
|
8302
|
+
readonly _noydb_sealed: 1;
|
|
8303
|
+
readonly providerId: string;
|
|
8304
|
+
/** Sealed bytes. Base64-encoded on the wire; decoded on load. */
|
|
8305
|
+
readonly sealed: Uint8Array;
|
|
8306
|
+
}
|
|
8307
|
+
/**
|
|
8308
|
+
* Wire-format envelope persisted at `_meta/sealed-passphrase` for
|
|
8309
|
+
* managed-mode vaults. The provider produces raw sealed bytes via
|
|
8310
|
+
* {@link SealingKeyProvider.seal}; this wrapper carries the dispatch
|
|
8311
|
+
* metadata hub needs to pick the right provider on the unseal path.
|
|
8312
|
+
*
|
|
8313
|
+
* Stability boundary: once shipped, the wire format only grows by
|
|
8314
|
+
* adding optional fields. See the at-* sealing dimension foundation
|
|
8315
|
+
* doc, §11.9.1.
|
|
8316
|
+
*
|
|
8317
|
+
* v1 shape (this release): `{ v: 1, _noydb_sealed: 1, pid, payload }`.
|
|
8318
|
+
*
|
|
8319
|
+
* Legacy shape (earlier releases): `{ _noydb_sealed: 1, providerId, sealed }`
|
|
8320
|
+
* — accepted on read for backwards compatibility; never produced on
|
|
8321
|
+
* write going forward.
|
|
8322
|
+
*/
|
|
8323
|
+
interface SealedEnvelope {
|
|
8324
|
+
/** Envelope schema version. v1 is the current shape. */
|
|
8325
|
+
readonly v: 1;
|
|
8326
|
+
/** Magic marker for forensics + legacy-shape detection. */
|
|
8327
|
+
readonly _noydb_sealed: 1;
|
|
8328
|
+
/** Matches the producing provider's `.id`. Dispatch key on unseal. */
|
|
8329
|
+
readonly pid: string;
|
|
8330
|
+
/** Sealed bytes from the provider, base64-encoded on the wire. */
|
|
8331
|
+
readonly payload: string;
|
|
8332
|
+
}
|
|
8333
|
+
/**
|
|
8334
|
+
* Parse a `_meta/sealed-passphrase` `_data` JSON string into the
|
|
8335
|
+
* in-memory {@link SealedPassphrase} representation. Accepts both:
|
|
8336
|
+
*
|
|
8337
|
+
* 1. v1 wire format `{ v: 1, _noydb_sealed: 1, pid, payload }` —
|
|
8338
|
+
* the current shape.
|
|
8339
|
+
* 2. Legacy wire format `{ _noydb_sealed: 1, providerId, sealed }` —
|
|
8340
|
+
* read-only; never written
|
|
8341
|
+
* going forward.
|
|
8342
|
+
*
|
|
8343
|
+
* Returns `undefined` for any input that doesn't match either shape,
|
|
8344
|
+
* so callers can fall back to "no managed-mode envelope present."
|
|
8345
|
+
*
|
|
8346
|
+
* @internal — exported only for the migration safety-net test suite.
|
|
8347
|
+
*/
|
|
8348
|
+
declare function parseSealedEnvelope(raw: unknown): SealedPassphrase | undefined;
|
|
8349
|
+
declare function saveSealedPassphrase(store: NoydbStore, vault: string, payload: {
|
|
8350
|
+
readonly providerId: string;
|
|
8351
|
+
readonly sealed: Uint8Array;
|
|
8352
|
+
}): Promise<void>;
|
|
8353
|
+
declare function loadSealedPassphrase(store: NoydbStore, vault: string): Promise<SealedPassphrase | undefined>;
|
|
8354
|
+
|
|
8355
|
+
/**
|
|
8356
|
+
* `vault.exportBlobs()` — bulk blob extraction primitive.
|
|
8357
|
+
*
|
|
8358
|
+
* Async-iterable handle over every blob attached to records in a
|
|
8359
|
+
* vault, optionally filtered by collection allowlist and per-record
|
|
8360
|
+
* predicate. Emits tuples of `{ blobId, recordRef, bytes, meta }` so
|
|
8361
|
+
* the consumer can pipe into any sink (zip stream, S3 multipart, USB
|
|
8362
|
+
* copy, cold-storage tape) without pulling the whole export into
|
|
8363
|
+
* memory.
|
|
8364
|
+
*
|
|
8365
|
+
* ## Auth + audit
|
|
8366
|
+
*
|
|
8367
|
+
* - Capability check runs **once** at handle creation via
|
|
8368
|
+
* `Vault.assertCanExport('plaintext', 'blob')`. An operator whose
|
|
8369
|
+
* keyring lacks that bit fails before a single byte of ciphertext
|
|
8370
|
+
* is decrypted.
|
|
8371
|
+
* - Audit entry lands in `_export_audit` at handle creation: the
|
|
8372
|
+
* actor, start timestamp, target collections, predicate presence,
|
|
8373
|
+
* and batch mechanism. **No content hashes** — per the spec
|
|
8374
|
+
* non-correlation invariant.
|
|
8375
|
+
*
|
|
8376
|
+
* ## Abort + resume
|
|
8377
|
+
*
|
|
8378
|
+
* - `handle.abort()` flips the internal signal; the next iteration
|
|
8379
|
+
* boundary throws `AbortError`. Consumers already in `for await`
|
|
8380
|
+
* can catch and exit cleanly.
|
|
8381
|
+
* - Restart after a partial failure with `{ afterBlobId }` — the
|
|
8382
|
+
* iterator skips tuples up to (and including) that blob id before
|
|
8383
|
+
* yielding again. Combined with a blob-count ceiling it supports
|
|
8384
|
+
* idempotent batch re-runs.
|
|
8385
|
+
*
|
|
8386
|
+
* @module
|
|
8387
|
+
*/
|
|
8388
|
+
|
|
8389
|
+
interface ExportBlobsOptions {
|
|
8390
|
+
/**
|
|
8391
|
+
* Collection allowlist. Omit to export blobs from every collection
|
|
8392
|
+
* the caller has read access to.
|
|
8393
|
+
*/
|
|
8394
|
+
readonly collections?: readonly string[];
|
|
7803
8395
|
/**
|
|
7804
8396
|
* Per-record predicate. Called on the decrypted record BEFORE any
|
|
7805
8397
|
* blob bytes are read for that record — returning false skips the
|
|
@@ -8638,6 +9230,7 @@ declare class Vault {
|
|
|
8638
9230
|
private readonly periodsStrategy;
|
|
8639
9231
|
private readonly shadowStrategy;
|
|
8640
9232
|
private readonly historyStrategy;
|
|
9233
|
+
private readonly forgetStrategy;
|
|
8641
9234
|
private readonly i18nStrategy;
|
|
8642
9235
|
private readonly syncStrategy;
|
|
8643
9236
|
/**
|
|
@@ -8667,13 +9260,17 @@ declare class Vault {
|
|
|
8667
9260
|
*/
|
|
8668
9261
|
private overlayedViewRegistry;
|
|
8669
9262
|
/**
|
|
8670
|
-
* Cached read-only
|
|
8671
|
-
* and to derivation callbacks via `derive(source, ctx)`.
|
|
8672
|
-
*
|
|
9263
|
+
* Cached read-only facades handed to guard callbacks via `ctx.vault`
|
|
9264
|
+
* and to derivation callbacks via `derive(source, ctx)`. Split by
|
|
9265
|
+
* resolution layer (#285): the guard facade reads at `layer:'guard'`,
|
|
9266
|
+
* the derivation facade at `layer:'derivation'`, so i18nText / dictKey
|
|
9267
|
+
* fields resolve under that layer's `onMissing` policy. Allocated
|
|
9268
|
+
* eagerly inside `_initGuards()` / `_initDerivations()` so read
|
|
8673
9269
|
* accessors stay synchronous (callers in `tx/transaction.ts` rely on
|
|
8674
|
-
* that).
|
|
9270
|
+
* that). Each stays `null` for vaults without that subsystem.
|
|
8675
9271
|
*/
|
|
8676
|
-
private
|
|
9272
|
+
private guardFacade;
|
|
9273
|
+
private derivationFacade;
|
|
8677
9274
|
private getDEK;
|
|
8678
9275
|
/**
|
|
8679
9276
|
* Per-principal user envelope API.
|
|
@@ -8799,6 +9396,27 @@ declare class Vault {
|
|
|
8799
9396
|
* Populated by `collection()` when the `dictKeyFields` option is passed.
|
|
8800
9397
|
*/
|
|
8801
9398
|
private readonly dictKeyFieldRegistry;
|
|
9399
|
+
/**
|
|
9400
|
+
* Names of dictionaries backed by a `staticDict()` descriptor (#291).
|
|
9401
|
+
* A static dict skips the `dictKeyFieldRegistry` rename machinery, but the
|
|
9402
|
+
* vault must still *know* a name is static so `vault.dictionary(name)` can
|
|
9403
|
+
* refuse mutation (`StaticDictReadonlyError`). Populated at `collection()`
|
|
9404
|
+
* config time whenever a `StaticDictDescriptor` is seen.
|
|
9405
|
+
*/
|
|
9406
|
+
private readonly staticDictNames;
|
|
9407
|
+
/**
|
|
9408
|
+
* Static-dict descriptors keyed by dictionary name (#291). Backs the
|
|
9409
|
+
* read-path label resolver (resolve from the in-memory table) and the
|
|
9410
|
+
* query-seam `resolveDictSource` snapshot. Last writer wins when the same
|
|
9411
|
+
* name is registered by multiple collections (identical-across-vaults by
|
|
9412
|
+
* construction, so the tables match).
|
|
9413
|
+
*/
|
|
9414
|
+
private readonly staticByName;
|
|
9415
|
+
/**
|
|
9416
|
+
* Per-collection map of field name → StaticDictDescriptor (#291). Used by
|
|
9417
|
+
* `enforceStaticDictOnPut` to validate stored codes against `desc.keys`.
|
|
9418
|
+
*/
|
|
9419
|
+
private readonly staticDescriptorByField;
|
|
8802
9420
|
/**
|
|
8803
9421
|
* Registry of i18nText fields declared across all collections. Keyed
|
|
8804
9422
|
* by collection name → field name → I18nTextDescriptor. Used by
|
|
@@ -8809,6 +9427,10 @@ declare class Vault {
|
|
|
8809
9427
|
private readonly i18nFieldRegistry;
|
|
8810
9428
|
/** Cache of DictionaryHandle instances, one per dictionary name. */
|
|
8811
9429
|
private readonly dictionaryCache;
|
|
9430
|
+
/** Registered link specs (#377-B), keyed by link name; set by `vault.link()`. */
|
|
9431
|
+
private readonly linkRegistry;
|
|
9432
|
+
/** Cache of LinkSet handles, one per link name. */
|
|
9433
|
+
private readonly linkSetCache;
|
|
8812
9434
|
/** — subscribers for cross-tier access events. */
|
|
8813
9435
|
private readonly crossTierSubs;
|
|
8814
9436
|
/** — currently-active elevation, or null. One per vault. */
|
|
@@ -8858,6 +9480,7 @@ declare class Vault {
|
|
|
8858
9480
|
syncStrategy?: SyncStrategy | undefined;
|
|
8859
9481
|
guardStrategies?: ReadonlyArray<GuardStrategyHandleAny> | undefined;
|
|
8860
9482
|
numberingConfigs?: ReadonlyArray<DeferredNumberingConfig> | undefined;
|
|
9483
|
+
forgetStrategy?: ForgetStrategy | undefined;
|
|
8861
9484
|
});
|
|
8862
9485
|
/**
|
|
8863
9486
|
* Construct (or reconstruct) the lazy DEK resolver. Captures the
|
|
@@ -8907,8 +9530,8 @@ declare class Vault {
|
|
|
8907
9530
|
refs?: Record<string, RefDescriptor>;
|
|
8908
9531
|
/** — declare i18nText fields for locale-aware reads. */
|
|
8909
9532
|
i18nFields?: Record<string, I18nTextDescriptor>;
|
|
8910
|
-
/** — declare dictKey fields for label resolution on reads. */
|
|
8911
|
-
dictKeyFields?: Record<string, DictKeyDescriptor>;
|
|
9533
|
+
/** — declare dictKey / staticDict fields for label resolution on reads. */
|
|
9534
|
+
dictKeyFields?: Record<string, DictKeyDescriptor | StaticDictDescriptor>;
|
|
8912
9535
|
/** — declare money() fields for currency-safe decimal storage/formatting. */
|
|
8913
9536
|
moneyFields?: Record<string, MoneyDescriptor>;
|
|
8914
9537
|
/** — declare computed scalar fields, evaluated on write (schema-owned). */
|
|
@@ -8925,6 +9548,14 @@ declare class Vault {
|
|
|
8925
9548
|
deterministicFields?: readonly string[];
|
|
8926
9549
|
/** — explicit ack that deterministic encryption leaks equality. */
|
|
8927
9550
|
acknowledgeDeterministicRisk?: boolean;
|
|
9551
|
+
/**
|
|
9552
|
+
* — per-record content-encryption keys. When `true`, every record
|
|
9553
|
+
* body is encrypted under a fresh per-record CEK wrapped under the
|
|
9554
|
+
* collection DEK (`_cek`), stable across versions. Foundation for
|
|
9555
|
+
* per-record erasure (#304) / record-scoped sealing (#306). Off by
|
|
9556
|
+
* default; non-adopting collections take the legacy path unchanged.
|
|
9557
|
+
*/
|
|
9558
|
+
perRecordKeys?: boolean;
|
|
8928
9559
|
/**
|
|
8929
9560
|
* declarative blob retention / TTL policy per slot
|
|
8930
9561
|
* name. Values are `{ retainDays?, evictWhen? }`. Evaluated only
|
|
@@ -8959,6 +9590,17 @@ declare class Vault {
|
|
|
8959
9590
|
schemaUpdate?: readonly SchemaUpdateStrategy[];
|
|
8960
9591
|
/** — declare the per-field schema for document attestation (issue side). */
|
|
8961
9592
|
attestation?: AttestationFieldSchema;
|
|
9593
|
+
/**
|
|
9594
|
+
* Per-collection history & tamper-ledger scoping. Overrides the
|
|
9595
|
+
* vault-wide `history` config for THIS collection only (wholesale, not
|
|
9596
|
+
* merged). `enabled: false` suppresses per-record snapshots for this
|
|
9597
|
+
* collection; `ledger: false` excludes its writes from the vault-wide
|
|
9598
|
+
* hash-chained tamper ledger. Lets you confine version snapshots +
|
|
9599
|
+
* tamper-evidence to the few collections where they carry legal weight,
|
|
9600
|
+
* without paying snapshot + ledger-entry-per-write across operational /
|
|
9601
|
+
* derived collections. Defaults to the vault-wide `history` config. See #361.
|
|
9602
|
+
*/
|
|
9603
|
+
historyConfig?: HistoryConfig;
|
|
8962
9604
|
}): Collection<T>;
|
|
8963
9605
|
/**
|
|
8964
9606
|
* Await all background persisted-schema writes triggered by
|
|
@@ -9011,6 +9653,14 @@ declare class Vault {
|
|
|
9011
9653
|
* `MissingTranslationError` when a required translation is absent.
|
|
9012
9654
|
*/
|
|
9013
9655
|
enforceI18nOnPut(collectionName: string, record: unknown): void;
|
|
9656
|
+
/**
|
|
9657
|
+
* Validate staticDict codes on a `put()` (#291). For each `staticDict()`
|
|
9658
|
+
* field, every stored code must be a declared key of the descriptor's
|
|
9659
|
+
* table, else `UnknownDictCodeError`. Opt out per descriptor with
|
|
9660
|
+
* `{ validateCodes: false }`. Supports scalar, dotted, and `[].`-wildcard
|
|
9661
|
+
* field paths via `getAtPath` (same path support as i18n validation).
|
|
9662
|
+
*/
|
|
9663
|
+
enforceStaticDictOnPut(collectionName: string, record: unknown): void;
|
|
9014
9664
|
/**
|
|
9015
9665
|
* Apply locale resolution to a record for the given collection.
|
|
9016
9666
|
*
|
|
@@ -9037,6 +9687,32 @@ declare class Vault {
|
|
|
9037
9687
|
* ```
|
|
9038
9688
|
*/
|
|
9039
9689
|
dictionary<Keys extends string = string>(name: string, options?: DictionaryOptions): DictionaryHandle<Keys>;
|
|
9690
|
+
/**
|
|
9691
|
+
* Declare a managed many-to-many link set (#377-B). Registers a
|
|
9692
|
+
* `_links_<name>` junction between two endpoint collections; access its
|
|
9693
|
+
* rows via `vault.links(name)`. Idempotent for an identical re-declaration;
|
|
9694
|
+
* a conflicting one throws. See {@link links}.
|
|
9695
|
+
*
|
|
9696
|
+
* ```ts
|
|
9697
|
+
* vault.link('saleLineLinks', { a: ref('saleLines'), b: ref('purchaseLines'), onDelete: 'cascade' })
|
|
9698
|
+
* ```
|
|
9699
|
+
*
|
|
9700
|
+
* `a` / `b` accept either a collection name or a `ref(target)` descriptor
|
|
9701
|
+
* (only its `target` is used — links manage their own integrity). `onDelete`
|
|
9702
|
+
* governs what happens to link rows when an endpoint record is deleted
|
|
9703
|
+
* (`'cascade'` default, `'strict'`, `'warn'`).
|
|
9704
|
+
*/
|
|
9705
|
+
link(name: string, spec: {
|
|
9706
|
+
a: string | RefDescriptor;
|
|
9707
|
+
b: string | RefDescriptor;
|
|
9708
|
+
onDelete?: LinkSpec['onDelete'];
|
|
9709
|
+
}): void;
|
|
9710
|
+
/**
|
|
9711
|
+
* Access a declared link set (#377-B). Throws if `name` was not first
|
|
9712
|
+
* declared via {@link link}. Returns a cached {@link LinkSetHandle}:
|
|
9713
|
+
* `connect(a, b, meta?)`, `disconnect(a, b)`, `has(a, b)`, `of(id)`, `list()`.
|
|
9714
|
+
*/
|
|
9715
|
+
links(name: string): LinkSetHandle;
|
|
9040
9716
|
/**
|
|
9041
9717
|
* Build a `JoinableSource` for a dictKey field, for use in dict joins
|
|
9042
9718
|
*. Returns a source whose snapshot contains `{ key, ...labels }`
|
|
@@ -9192,7 +9868,19 @@ declare class Vault {
|
|
|
9192
9868
|
* const n = await vault.sequence('invoice-2026').next() // 1, then 2, …
|
|
9193
9869
|
* const cur = await vault.sequence('invoice-2026').peek() // current value, no allocation
|
|
9194
9870
|
* ```
|
|
9871
|
+
*
|
|
9872
|
+
* Pass a `format` (#375) to emit a serial string instead of a bare
|
|
9873
|
+
* integer — `next()` then returns `{ serial, formatted }`. Per-partition
|
|
9874
|
+
* reset is inherent (a new partition tuple starts at 1):
|
|
9875
|
+
*
|
|
9876
|
+
* ```ts
|
|
9877
|
+
* const seq = vault.sequence('fatture', { partition: [2026], format: '{partition.0}/{seq:04}' })
|
|
9878
|
+
* await seq.next() // { serial: 1, formatted: '2026/0001' }
|
|
9879
|
+
* ```
|
|
9195
9880
|
*/
|
|
9881
|
+
sequence(series: string, opts: SequenceOptions & {
|
|
9882
|
+
format: string;
|
|
9883
|
+
}): FormattedSequenceHandle;
|
|
9196
9884
|
sequence(series: string, opts?: SequenceOptions): SequenceHandle;
|
|
9197
9885
|
/** @internal — lazily build the deferred-numbering engine with a cache-coherent stamp. */
|
|
9198
9886
|
private deferred;
|
|
@@ -9285,6 +9973,13 @@ declare class Vault {
|
|
|
9285
9973
|
* mutually-cascading collections don't recurse forever.
|
|
9286
9974
|
*/
|
|
9287
9975
|
enforceRefsOnDelete(collectionName: string, id: string): Promise<void>;
|
|
9976
|
+
/**
|
|
9977
|
+
* @internal — apply link `onDelete` policy when an endpoint record is
|
|
9978
|
+
* deleted (#377-B). `'strict'` throws (blocks the delete), `'cascade'`
|
|
9979
|
+
* removes the touching link rows (tx-atomic when a transaction is active),
|
|
9980
|
+
* `'warn'` leaves orphans for `checkIntegrity()`.
|
|
9981
|
+
*/
|
|
9982
|
+
private enforceLinksOnDelete;
|
|
9288
9983
|
/**
|
|
9289
9984
|
* Look up the `RefDescriptor` the left collection declared for a
|
|
9290
9985
|
* given field name. Returns `null` when the field has no ref
|
|
@@ -9351,6 +10046,102 @@ declare class Vault {
|
|
|
9351
10046
|
* throws on null; this one stays silent so the off-path no-ops.
|
|
9352
10047
|
*/
|
|
9353
10048
|
private getLedgerOrNull;
|
|
10049
|
+
/** @internal — add a subject→record ref to the encrypted subject index. */
|
|
10050
|
+
_addSubjectRef(subjectId: string, ref: SubjectRef): Promise<void>;
|
|
10051
|
+
/** @internal — drop a subject→record ref from the encrypted subject index. */
|
|
10052
|
+
_removeSubjectRef(subjectId: string, ref: SubjectRef): Promise<void>;
|
|
10053
|
+
/**
|
|
10054
|
+
* Rebuild the encrypted subject index from canonical records. The recovery
|
|
10055
|
+
* path for the documented read-modify-write race (RISK #3). Returns the
|
|
10056
|
+
* number of distinct subjects re-indexed.
|
|
10057
|
+
*/
|
|
10058
|
+
rebuildSubjectIndex(): Promise<number>;
|
|
10059
|
+
/**
|
|
10060
|
+
* GDPR crypto-shred of a data subject (#304). Consults the encrypted subject
|
|
10061
|
+
* index and, per matching record:
|
|
10062
|
+
* - rewrites the LIVE envelope to a tombstone (drops `_iv`/`_data`/`_cek`/`_det`),
|
|
10063
|
+
* - tombstones every `_history` version of the record,
|
|
10064
|
+
* so the body and all prior versions become permanently undecryptable while
|
|
10065
|
+
* the collection DEK and every OTHER record stay intact. Then appends ONE
|
|
10066
|
+
* `op:'forget'` ledger entry whose `payloadHash` is `sha256Hex(subjectId)` —
|
|
10067
|
+
* the chain still `verify()`s, PROVING the subject existed and was erased
|
|
10068
|
+
* without retaining any plaintext.
|
|
10069
|
+
*
|
|
10070
|
+
* Reports — but does not silently swallow — two completeness gaps:
|
|
10071
|
+
* - `unmigratedRecords`: a record whose body was NOT yet migrated to a
|
|
10072
|
+
* per-record CEK (legacy body still under the shared collection DEK). It
|
|
10073
|
+
* is still tombstoned, but its pre-shred ciphertext (if leaked to a
|
|
10074
|
+
* backup before migration) stays decryptable. Migrate, then re-forget.
|
|
10075
|
+
* - `blobResidueCollections`: a shredded record still has blob attachments,
|
|
10076
|
+
* which are keyed off a separate `_blob` DEK and are out of scope here.
|
|
10077
|
+
*
|
|
10078
|
+
* @throws ForgetStrategyNotConfiguredError when no `withForgetCascade` was set.
|
|
10079
|
+
*/
|
|
10080
|
+
forget(subjectId: string): Promise<ForgetResult>;
|
|
10081
|
+
/**
|
|
10082
|
+
* Seal ONE record's content-encryption key (CEK) to an `at-*` host so that
|
|
10083
|
+
* host — and only that host — can decrypt exactly that record, with no
|
|
10084
|
+
* access to the vault DEK and no ability to read any other record.
|
|
10085
|
+
*
|
|
10086
|
+
* The grantor (this caller, who holds the collection DEK) reads the record's
|
|
10087
|
+
* live `_cek`, unwraps it under the collection DEK, exports the raw CEK
|
|
10088
|
+
* bytes, builds a {@link SealedCekBinding} `{collection, id, cek, expiresAt}`,
|
|
10089
|
+
* seals that binding for the recipient host via the host's published hint,
|
|
10090
|
+
* and persists a thin {@link SealedCekDeliveryEnvelope} at
|
|
10091
|
+
* `_sealed_cek/<collection>/<id>/<pid>`. The binding (not the delivery
|
|
10092
|
+
* envelope) is the security boundary: the host re-verifies `{collection, id}`
|
|
10093
|
+
* and `expiresAt` from inside the sealed payload.
|
|
10094
|
+
*
|
|
10095
|
+
* Only works on a `perRecordKeys` record — a legacy record has no `_cek` to
|
|
10096
|
+
* seal (its body is under the shared collection DEK, which is never exposed
|
|
10097
|
+
* by sealing) → {@link RecordCekNotFoundError}.
|
|
10098
|
+
*
|
|
10099
|
+
* @param collection Collection holding the record.
|
|
10100
|
+
* @param id Record id.
|
|
10101
|
+
* @param hostSealer The recipient host's {@link RecipientSealer}.
|
|
10102
|
+
* @param opts.expiresAt REQUIRED authoritative expiry (ISO 8601), sealed into
|
|
10103
|
+
* the binding the host verifies.
|
|
10104
|
+
* @returns `{ pid, envelopeKey }` — the host provider id and the
|
|
10105
|
+
* `<collection>/<id>/<pid>` key the delivery envelope was written under.
|
|
10106
|
+
*/
|
|
10107
|
+
sealRecordToHost(collection: string, id: string, hostSealer: RecipientSealer, opts: {
|
|
10108
|
+
expiresAt: string;
|
|
10109
|
+
}): Promise<{
|
|
10110
|
+
pid: string;
|
|
10111
|
+
envelopeKey: string;
|
|
10112
|
+
}>;
|
|
10113
|
+
/**
|
|
10114
|
+
* Revoke a single sealed-CEK delivery envelope by deleting it from the store.
|
|
10115
|
+
* A soft revocation: it removes the host's copy of the sealed CEK, but a host
|
|
10116
|
+
* that already fetched the envelope keeps whatever it cached. For a hard
|
|
10117
|
+
* revocation that makes the live record undecryptable to every prior grant,
|
|
10118
|
+
* use {@link rotateRecordCek}.
|
|
10119
|
+
*/
|
|
10120
|
+
revokeSealedRecord(collection: string, id: string, pid: string): Promise<void>;
|
|
10121
|
+
/**
|
|
10122
|
+
* HARD-rotate a record's CEK: decrypt the live body under the old CEK,
|
|
10123
|
+
* re-encrypt it under a freshly-minted CEK, write the new live envelope, evict
|
|
10124
|
+
* the in-memory caches, and delete EVERY sealed-CEK delivery envelope for the
|
|
10125
|
+
* record. After this, any host holding a previously-sealed CEK can still
|
|
10126
|
+
* decrypt PRE-rotation history versions (they keep their old `_cek`) but NOT
|
|
10127
|
+
* the rotated live record (its body is under the new CEK → the old CEK fails
|
|
10128
|
+
* the AES-GCM auth tag → `TamperedError`). That asymmetry IS the revocation:
|
|
10129
|
+
* old grants lose the live record.
|
|
10130
|
+
*
|
|
10131
|
+
* Administrative path — bypasses `Collection.put` deliberately (no guards, no
|
|
10132
|
+
* history snapshot, no materialized-view refresh): rotation is a key-rotation
|
|
10133
|
+
* operation, not a business write, and must not version-bump history (which
|
|
10134
|
+
* would re-encrypt the prior version under the NEW CEK and defeat the point).
|
|
10135
|
+
*
|
|
10136
|
+
* @throws {@link RecordCekNotFoundError} if the record is missing or has no `_cek`.
|
|
10137
|
+
*/
|
|
10138
|
+
rotateRecordCek(collection: string, id: string): Promise<void>;
|
|
10139
|
+
/**
|
|
10140
|
+
* Build the {@link SealingContext} the record-keys grantor functions need:
|
|
10141
|
+
* the vault-bound adapter, DEK resolver, actor, and the dual-cache eviction
|
|
10142
|
+
* `rotateRecordCek` performs (per-record CEK cache + decrypted-record cache).
|
|
10143
|
+
*/
|
|
10144
|
+
private sealingContext;
|
|
9354
10145
|
/**
|
|
9355
10146
|
* @internal — called by `Noydb.openVault` after construction.
|
|
9356
10147
|
* Dynamic-imports `GuardRegistry` + `ReadOnlyVaultFacade` and seeds
|
|
@@ -9449,9 +10240,10 @@ declare class Vault {
|
|
|
9449
10240
|
*/
|
|
9450
10241
|
_getReadOnlyFacade(): ReadOnlyVaultFacade | null;
|
|
9451
10242
|
/**
|
|
9452
|
-
* Internal lazy-allocator for the read-only facade
|
|
9453
|
-
* defensive fallback; in practice
|
|
9454
|
-
* instantiates this, so the lazy path is
|
|
10243
|
+
* Internal lazy-allocator for the derivation read-only facade
|
|
10244
|
+
* (`layer:'derivation'`). Used as a defensive fallback; in practice
|
|
10245
|
+
* `_initDerivations()` eagerly instantiates this, so the lazy path is
|
|
10246
|
+
* a no-op.
|
|
9455
10247
|
*/
|
|
9456
10248
|
private _ensureReadOnlyFacade;
|
|
9457
10249
|
/**
|
|
@@ -10343,6 +11135,25 @@ declare class Collection<T> {
|
|
|
10343
11135
|
* is inactive for this collection; a frozen `Set` otherwise.
|
|
10344
11136
|
*/
|
|
10345
11137
|
private readonly deterministicFields;
|
|
11138
|
+
/**
|
|
11139
|
+
* Per-record CEK opt-in (`perRecordKeys: true`). When set, writes mint /
|
|
11140
|
+
* reuse a per-record content-encryption key and stamp `_cek` on the
|
|
11141
|
+
* envelope (see {@link EncryptedEnvelope._cek}). OFF by default — a
|
|
11142
|
+
* non-adopting collection takes the byte-identical legacy path. The READ
|
|
11143
|
+
* path does not consult this flag: `_cek` presence on the envelope is the
|
|
11144
|
+
* format discriminant, so a mixed vault (and a recipient that never set the
|
|
11145
|
+
* flag) still decrypts CEK records.
|
|
11146
|
+
*/
|
|
11147
|
+
private readonly perRecordCek;
|
|
11148
|
+
/**
|
|
11149
|
+
* Session-scoped `(id) → CEK` cache for this collection. Lets updates
|
|
11150
|
+
* reuse a record's stable CEK and lets repeated reads skip the AES-KW
|
|
11151
|
+
* unwrap. Bounded by LRU; never persisted. Dropped when the owning
|
|
11152
|
+
* collection instance is discarded — `vault.load()` clears the
|
|
11153
|
+
* collectionCache, so a keyring refresh drops every CEK alongside the
|
|
11154
|
+
* DEK cache. `null` unless `perRecordCek` is set.
|
|
11155
|
+
*/
|
|
11156
|
+
private readonly cekCache;
|
|
10346
11157
|
/**
|
|
10347
11158
|
* declared tiers for this collection. `null` when
|
|
10348
11159
|
* tier-aware methods are disabled. Tier 0 is implicit and never
|
|
@@ -10563,7 +11374,7 @@ declare class Collection<T> {
|
|
|
10563
11374
|
/** — i18nText field descriptors for locale-aware reads. */
|
|
10564
11375
|
i18nFields?: Record<string, I18nTextDescriptor> | undefined;
|
|
10565
11376
|
/** — dictKey field descriptors for label resolution on reads. */
|
|
10566
|
-
dictKeyFields?: Record<string, DictKeyDescriptor> | undefined;
|
|
11377
|
+
dictKeyFields?: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined;
|
|
10567
11378
|
moneyFields?: Record<string, MoneyDescriptor> | undefined;
|
|
10568
11379
|
computed?: ComputedFields | undefined;
|
|
10569
11380
|
/**
|
|
@@ -10646,6 +11457,15 @@ declare class Collection<T> {
|
|
|
10646
11457
|
* any deterministic field is declared. Any other value throws.
|
|
10647
11458
|
*/
|
|
10648
11459
|
acknowledgeDeterministicRisk?: boolean | undefined;
|
|
11460
|
+
/**
|
|
11461
|
+
* Per-record content-encryption keys. When `true`, every record body
|
|
11462
|
+
* (and every history version of it) is encrypted under a fresh
|
|
11463
|
+
* per-record CEK, AES-KW-wrapped under the collection DEK and stored
|
|
11464
|
+
* on the envelope's `_cek`. Off by default. Foundation for per-record
|
|
11465
|
+
* erasure (#304) and record-scoped sealing (#306). `_det` slots stay
|
|
11466
|
+
* keyed to the collection DEK regardless.
|
|
11467
|
+
*/
|
|
11468
|
+
perRecordKeys?: boolean | undefined;
|
|
10649
11469
|
/**
|
|
10650
11470
|
* declared tiers this collection supports. An
|
|
10651
11471
|
* undefined or empty list disables the hierarchical-tier surface
|
|
@@ -10811,7 +11631,35 @@ declare class Collection<T> {
|
|
|
10811
11631
|
* output (carries `_derivedFrom`) — defensive guard against missed
|
|
10812
11632
|
* cycle detection.
|
|
10813
11633
|
*/
|
|
10814
|
-
|
|
11634
|
+
/**
|
|
11635
|
+
* @internal #376 — the RAW stored record (canonical-money form, i18n maps
|
|
11636
|
+
* intact), WITHOUT the locale resolution `get()` applies. Used as the
|
|
11637
|
+
* patch base for self-write reverse-denorm so writing back never clobbers
|
|
11638
|
+
* an i18n map or re-quantizes money incorrectly. Returns null for
|
|
11639
|
+
* missing / tombstoned records.
|
|
11640
|
+
*/
|
|
11641
|
+
_getStoredRecord(id: string): Promise<T | null>;
|
|
11642
|
+
/**
|
|
11643
|
+
* @internal #376 — ids of records whose top-level `field` equals `value`.
|
|
11644
|
+
* Uses the FK index when the field is indexed (O(matches)); otherwise a
|
|
11645
|
+
* linear scan (O(N) — fine for small child sets; index the FK to scale).
|
|
11646
|
+
*/
|
|
11647
|
+
_findMatchingIds(field: string, value: unknown): Promise<string[]>;
|
|
11648
|
+
/**
|
|
11649
|
+
* @internal #376 slice 2 — recompute a rollup aggregate onto the parent.
|
|
11650
|
+
* Gathers every child of `parentId`, runs `compute`, and patches only the
|
|
11651
|
+
* rollup `field` onto the parent's raw stored record (value-equality
|
|
11652
|
+
* guarded). No-op when the parent record does not exist.
|
|
11653
|
+
*/
|
|
11654
|
+
private recomputeRollup;
|
|
11655
|
+
/**
|
|
11656
|
+
* @internal #376 slice 2 — fire any rollups for which THIS collection is the
|
|
11657
|
+
* child `from`, recomputing the affected parent after a child delete. Called
|
|
11658
|
+
* from the delete path with the just-removed record's key value. Other
|
|
11659
|
+
* derivation kinds do not react to deletes (unchanged).
|
|
11660
|
+
*/
|
|
11661
|
+
private dispatchRollupsOnDelete;
|
|
11662
|
+
private dispatchDerivations;
|
|
10815
11663
|
/**
|
|
10816
11664
|
* Delete a record by ID. Runs inside the hub's write-queue tracker
|
|
10817
11665
|
* so `hub.writeQueue.pending` reflects this write.
|
|
@@ -10865,6 +11713,37 @@ declare class Collection<T> {
|
|
|
10865
11713
|
*/
|
|
10866
11714
|
_internalDelete(id: string, txCtx?: TxContext | null): Promise<void>;
|
|
10867
11715
|
private _doDelete;
|
|
11716
|
+
/**
|
|
11717
|
+
* @internal — GDPR crypto-shred a LIVE record to a tombstone (#304).
|
|
11718
|
+
*
|
|
11719
|
+
* Rewrites the on-disk envelope to `{ _noydb, _v, _ts, _by, _iv:'', _data:'' }`,
|
|
11720
|
+
* dropping `_iv`/`_data`/`_cek`/`_det`. The wrapped per-record CEK is gone, so
|
|
11721
|
+
* the body — and (via {@link tombstoneHistory}) every history version under
|
|
11722
|
+
* the same CEK — is permanently undecryptable; the collection DEK and every
|
|
11723
|
+
* other record are untouched. `_det` is stripped too, so `findByDet` no
|
|
11724
|
+
* longer matches the shredded record (avoiding a post-shred TamperedError).
|
|
11725
|
+
*
|
|
11726
|
+
* Unlike `delete()`/`_internalDelete`, this:
|
|
11727
|
+
* - does NOT fire onDelete guards / MV / derivation dispatch (a shred is an
|
|
11728
|
+
* erasure, not a domain delete — re-running those would be wrong),
|
|
11729
|
+
* - does NOT append a per-record ledger entry (`vault.forget()` appends a
|
|
11730
|
+
* single `op:'forget'` summary for the whole subject),
|
|
11731
|
+
* - keeps the record KEY present (it's an overwrite, not an adapter delete)
|
|
11732
|
+
* so the version counter + "record existed" survive for audit.
|
|
11733
|
+
*
|
|
11734
|
+
* Idempotent: returns `null` when the record is absent or already a tombstone.
|
|
11735
|
+
* Otherwise returns `{ previousVersion }`. Invalidates the eager cache, the
|
|
11736
|
+
* lazy LRU, and the per-record CEK cache for this id.
|
|
11737
|
+
*/
|
|
11738
|
+
/**
|
|
11739
|
+
* @internal — decrypt an envelope to a plain record for subject-index
|
|
11740
|
+
* rebuild (#304). Returns `null` for a tombstone or unreadable envelope.
|
|
11741
|
+
* Skips schema validation — the rebuild only reads the subject field.
|
|
11742
|
+
*/
|
|
11743
|
+
_decodeEnvelope(envelope: EncryptedEnvelope, id: string): Promise<Record<string, unknown> | null>;
|
|
11744
|
+
_writeTombstone(id: string, actor: string): Promise<{
|
|
11745
|
+
previousVersion: number;
|
|
11746
|
+
} | null>;
|
|
10868
11747
|
/**
|
|
10869
11748
|
* Cascade deletes of array-shape derived rows when a source row is
|
|
10870
11749
|
* deleted. Reads each registered strategy's fanout sidecar
|
|
@@ -11166,6 +12045,16 @@ declare class Collection<T> {
|
|
|
11166
12045
|
* the cache entry (record still present) or deletes it (record was
|
|
11167
12046
|
* gone before the tx and the revert deleted it again).
|
|
11168
12047
|
*/
|
|
12048
|
+
/**
|
|
12049
|
+
* @internal — evict ONLY the per-record CEK cache entry for `id`. Used by
|
|
12050
|
+
* `vault.rotateRecordCek()`: after a hard CEK rotation the cached unwrapped
|
|
12051
|
+
* CEK is stale (it would decrypt the pre-rotation body and fail GCM auth on
|
|
12052
|
+
* the post-rotation body). Eviction must be synchronous with the live-envelope
|
|
12053
|
+
* rewrite so no concurrent read observes the old CEK. Paired with
|
|
12054
|
+
* {@link _invalidateCacheEntry} (which refreshes the decrypted-record cache).
|
|
12055
|
+
* No-op when the collection is not `perRecordKeys`.
|
|
12056
|
+
*/
|
|
12057
|
+
_invalidateCekCacheEntry(id: string): void;
|
|
11169
12058
|
_invalidateCacheEntry(id: string): Promise<void>;
|
|
11170
12059
|
/**
|
|
11171
12060
|
* Apply a peer tab's committed write to THIS tab's in-memory view:
|
|
@@ -11378,6 +12267,21 @@ declare class Collection<T> {
|
|
|
11378
12267
|
* query with no index would need to enumerate the whole collection.
|
|
11379
12268
|
*/
|
|
11380
12269
|
lazyQuery(): LazyQuery<T>;
|
|
12270
|
+
/**
|
|
12271
|
+
* Resolve the stable CEK for a record on the WRITE path — see
|
|
12272
|
+
* {@link resolveStableCek}. Thin delegate that supplies the collection's
|
|
12273
|
+
* CEK cache, live-envelope reader, and DEK resolver.
|
|
12274
|
+
*/
|
|
12275
|
+
private resolveRecordCek;
|
|
12276
|
+
/**
|
|
12277
|
+
* Encrypt a JSON body into an envelope.
|
|
12278
|
+
*
|
|
12279
|
+
* When `cek` is supplied (per-record CEK collections), the body is
|
|
12280
|
+
* encrypted under the CEK and the CEK is AES-KW-wrapped under the
|
|
12281
|
+
* collection DEK and stamped on `_cek`. When `cek` is omitted, the legacy
|
|
12282
|
+
* path encrypts the body directly under the collection DEK — byte-identical
|
|
12283
|
+
* to pre-CEK behaviour, so non-adopting collections pay nothing.
|
|
12284
|
+
*/
|
|
11381
12285
|
private encryptJsonString;
|
|
11382
12286
|
private encryptRecord;
|
|
11383
12287
|
/**
|
|
@@ -11459,7 +12363,20 @@ declare class Collection<T> {
|
|
|
11459
12363
|
demote(id: string, toTier: number): Promise<void>;
|
|
11460
12364
|
private isElevatorOrOwner;
|
|
11461
12365
|
private emitCrossTierEvent;
|
|
11462
|
-
/**
|
|
12366
|
+
/**
|
|
12367
|
+
* Low-level: decrypt an envelope and return the raw JSON string.
|
|
12368
|
+
*
|
|
12369
|
+
* `_cek` presence is the format discriminant (NOT `this.perRecordCek`),
|
|
12370
|
+
* so a mixed vault — and a recipient that never opted into
|
|
12371
|
+
* `perRecordKeys` — decrypts both legacy and CEK records:
|
|
12372
|
+
* - `_cek` present → unwrap the CEK under the collection DEK, decrypt the
|
|
12373
|
+
* body under the CEK (cache the unwrapped CEK so repeated reads skip it).
|
|
12374
|
+
* - `_cek` absent → legacy path, body decrypts directly under the
|
|
12375
|
+
* collection DEK.
|
|
12376
|
+
*
|
|
12377
|
+
* The optional `id` lets reads populate the CEK cache; it is omitted by
|
|
12378
|
+
* callers (history, conflict merge) that have only the envelope.
|
|
12379
|
+
*/
|
|
11463
12380
|
private decryptJsonString;
|
|
11464
12381
|
/**
|
|
11465
12382
|
* Decrypt an envelope into a record of type `T`.
|
|
@@ -11736,244 +12653,6 @@ interface SessionStrategy {
|
|
|
11736
12653
|
revokeAllSessions(): void;
|
|
11737
12654
|
}
|
|
11738
12655
|
|
|
11739
|
-
/**
|
|
11740
|
-
* Managed-passphrase mode — rubber-hose-resistant vaults.
|
|
11741
|
-
*
|
|
11742
|
-
* A vault mode where the passphrase is machine-generated and never
|
|
11743
|
-
* exposed to the user, sealed under a developer-provided
|
|
11744
|
-
* {@link SealingKeyProvider} (macOS Keychain, Windows Credential
|
|
11745
|
-
* Manager, libsecret, AWS KMS, …). The user has no secret to give
|
|
11746
|
-
* up to coercion — they can't reveal what they don't know.
|
|
11747
|
-
*
|
|
11748
|
-
* ## Components in this file
|
|
11749
|
-
*
|
|
11750
|
-
* - {@link SealingKeyProvider} — the interface concrete providers
|
|
11751
|
-
* implement. Provider implementations live OUTSIDE hub (per-
|
|
11752
|
-
* platform packages).
|
|
11753
|
-
* - {@link MemorySealingKeyProvider} — in-memory test provider; uses
|
|
11754
|
-
* a deterministic per-instance "key" so two providers with
|
|
11755
|
-
* different ids cannot unseal each other's outputs.
|
|
11756
|
-
* - {@link RecipientHint} — public material a sender uses to seal
|
|
11757
|
-
* plaintext for a specific recipient; published by
|
|
11758
|
-
* {@link RecipientSealer.publishRecipientHint} and transported
|
|
11759
|
-
* out-of-band to the sender before bundle writes.
|
|
11760
|
-
* - {@link RecipientSealer} — interface for asymmetric/granted
|
|
11761
|
-
* providers that support recipient-target sealing (RSA-OAEP,
|
|
11762
|
-
* cloud-KMS asymmetric, etc.); distinct from self-only
|
|
11763
|
-
* {@link SealingKeyProvider} (macOS Keychain, WebAuthn-PRF).
|
|
11764
|
-
* - {@link MemoryRecipientSealer} — in-process reference
|
|
11765
|
-
* implementation of both `RecipientSealer` and
|
|
11766
|
-
* `SealingKeyProvider` using real WebCrypto RSA-OAEP + AES-GCM;
|
|
11767
|
-
* safe for tests and same-process sender/recipient scenarios.
|
|
11768
|
-
* - {@link loadSealedPassphrase} / {@link saveSealedPassphrase} —
|
|
11769
|
-
* plaintext envelope storage at `_meta/sealed-passphrase`.
|
|
11770
|
-
* Mirrors the `_meta/handle` and `_meta/public-envelope` AES-
|
|
11771
|
-
* GCM-bypassed patterns. The sealing layer (provider's job)
|
|
11772
|
-
* is the security boundary; hub doesn't have a key to encrypt
|
|
11773
|
-
* with at this layer — that's the whole point of the design.
|
|
11774
|
-
* - {@link resolveManagedSecret} — orchestrates the "generate +
|
|
11775
|
-
* seal + persist on first open; unseal on reopen" flow.
|
|
11776
|
-
* Returns the plaintext passphrase string that the rest of the
|
|
11777
|
-
* `createNoydb` keyring path consumes.
|
|
11778
|
-
*
|
|
11779
|
-
* Deferred to follow-ups:
|
|
11780
|
-
* - Block `rotate-passphrase` policy gate under managed mode.
|
|
11781
|
-
* - Mandatory strong-recovery enforcement.
|
|
11782
|
-
* - Recovery flow under managed mode (generates fresh sealed phrase).
|
|
11783
|
-
*
|
|
11784
|
-
* @see docs/subsystems/session-tiers.md → Managed-passphrase mode
|
|
11785
|
-
*
|
|
11786
|
-
* @module
|
|
11787
|
-
*/
|
|
11788
|
-
|
|
11789
|
-
/**
|
|
11790
|
-
* The contract concrete providers (per-platform key stores) implement
|
|
11791
|
-
* to seal and unseal a hub-generated random passphrase. The plaintext
|
|
11792
|
-
* passphrase NEVER leaves hub-controlled memory in unsealed form —
|
|
11793
|
-
* the provider receives the bytes, returns opaque sealed bytes, and
|
|
11794
|
-
* later reverses the operation. Hub treats the sealed bytes as
|
|
11795
|
-
* fully opaque.
|
|
11796
|
-
*
|
|
11797
|
-
* Implementations live OUTSIDE `@noy-db/hub` (separate packages
|
|
11798
|
-
* per the issue's "Concrete providers (live outside hub)" note):
|
|
11799
|
-
*
|
|
11800
|
-
* | Platform | Package (TBD) | Backing |
|
|
11801
|
-
* |---|---|---|
|
|
11802
|
-
* | macOS | `@noy-db/seal-macos-keychain` | Security.framework |
|
|
11803
|
-
* | Windows | `@noy-db/seal-wincred` | Credential Manager |
|
|
11804
|
-
* | Linux | `@noy-db/seal-libsecret` | libsecret / secret-service |
|
|
11805
|
-
* | Cloud / server | `@noy-db/seal-aws-kms` | AWS KMS Decrypt |
|
|
11806
|
-
*/
|
|
11807
|
-
interface SealingKeyProvider {
|
|
11808
|
-
/**
|
|
11809
|
-
* Non-sensitive identifier disclosed in the persisted envelope.
|
|
11810
|
-
* Surfaced to consumers via `loadSealedPassphrase().providerId` so
|
|
11811
|
-
* a vault opened with the wrong provider class can detect the
|
|
11812
|
-
* mismatch and surface a clear error. NOT secret — fine to log.
|
|
11813
|
-
*
|
|
11814
|
-
* Suggested format: `<family>:<scope>` — e.g. `macos-keychain:com.acme.app`,
|
|
11815
|
-
* `aws-kms:arn:aws:kms:us-east-1:123:key/abc`. The hub never
|
|
11816
|
-
* parses this; it's purely audit metadata.
|
|
11817
|
-
*/
|
|
11818
|
-
readonly id: string;
|
|
11819
|
-
/** Seal raw passphrase bytes. Output bytes are opaque to hub. */
|
|
11820
|
-
seal(passphrase: Uint8Array): Promise<Uint8Array>;
|
|
11821
|
-
/**
|
|
11822
|
-
* Reverse {@link seal}. MUST throw on tamper, wrong-provider, or
|
|
11823
|
-
* any other failure — hub treats a thrown error as "this provider
|
|
11824
|
-
* cannot unlock this vault" and surfaces it to the caller.
|
|
11825
|
-
*/
|
|
11826
|
-
unseal(sealed: Uint8Array): Promise<Uint8Array>;
|
|
11827
|
-
}
|
|
11828
|
-
/**
|
|
11829
|
-
* In-memory test provider. NOT secure — uses a deterministic
|
|
11830
|
-
* per-instance "key" (16-byte SHA-256 of `id`) XOR'd over the
|
|
11831
|
-
* passphrase plus a 4-byte provider-id fingerprint prefix. The XOR is
|
|
11832
|
-
* sufficient to make different `id` values produce mutually-unsealable
|
|
11833
|
-
* outputs (the contract tests for that), but offers ZERO real
|
|
11834
|
-
* confidentiality — never use outside tests.
|
|
11835
|
-
*
|
|
11836
|
-
* Replace with a real platform provider in production.
|
|
11837
|
-
*/
|
|
11838
|
-
declare class MemorySealingKeyProvider implements SealingKeyProvider {
|
|
11839
|
-
readonly id: string;
|
|
11840
|
-
private readonly fingerprint;
|
|
11841
|
-
private readonly keyBytes;
|
|
11842
|
-
constructor(opts: {
|
|
11843
|
-
id: string;
|
|
11844
|
-
});
|
|
11845
|
-
seal(passphrase: Uint8Array): Promise<Uint8Array>;
|
|
11846
|
-
unseal(sealed: Uint8Array): Promise<Uint8Array>;
|
|
11847
|
-
}
|
|
11848
|
-
/**
|
|
11849
|
-
* Public material a sender uses to seal-for-this-recipient. Published by
|
|
11850
|
-
* a recipient's RecipientSealer; transported to the sender out-of-band
|
|
11851
|
-
* (email, S3, in-app message). The sender obtains the hint, supplies it
|
|
11852
|
-
* to writeNoydbBundle's sealedCredentials.perUser[userId].hint, and the
|
|
11853
|
-
* hub seals each user's credential against it. Per foundation §11.4.
|
|
11854
|
-
*/
|
|
11855
|
-
type RecipientHint = {
|
|
11856
|
-
readonly v: 1;
|
|
11857
|
-
/** Recipient's provider id; matches the SealedAutoUnlockEntry.pid they'll unseal under. */
|
|
11858
|
-
readonly pid: string;
|
|
11859
|
-
/** Algorithm the sender uses to produce the seal. Slice 1 ships RSA-OAEP-SHA256 only. */
|
|
11860
|
-
readonly alg: 'rsa-oaep-sha256';
|
|
11861
|
-
/** Public material — alg-specific. For 'rsa-oaep-sha256': { publicKeyPem: string }. */
|
|
11862
|
-
readonly material: Readonly<Record<string, unknown>>;
|
|
11863
|
-
};
|
|
11864
|
-
/**
|
|
11865
|
-
* Handover-capable provider. Implemented additionally by asymmetric/granted
|
|
11866
|
-
* providers (cloud-KMS asymmetric, Azure RSA Key Vault, AWS KMS with grant).
|
|
11867
|
-
* Self-only providers (macOS Keychain, env-var, WebAuthn-PRF) do NOT
|
|
11868
|
-
* implement this — the §11.2 capability matrix lives in the type system.
|
|
11869
|
-
*
|
|
11870
|
-
* Per foundation §11.4. A function that requires recipient-target sealing
|
|
11871
|
-
* takes `RecipientSealer`, not `SealingKeyProvider` — the compiler rejects
|
|
11872
|
-
* passing a self-only provider at the spec site.
|
|
11873
|
-
*/
|
|
11874
|
-
interface RecipientSealer {
|
|
11875
|
-
readonly id: string;
|
|
11876
|
-
/** Produce hint material a sender uses to seal-for-this-recipient. */
|
|
11877
|
-
publishRecipientHint(): Promise<RecipientHint>;
|
|
11878
|
-
/**
|
|
11879
|
-
* Seal plaintext for the recipient described by `hint`. Returns opaque
|
|
11880
|
-
* bytes — same contract as `SealingKeyProvider.seal()`. The bundle
|
|
11881
|
-
* layer base64-encodes the bytes into `SealedAutoUnlockEntry.sealed`
|
|
11882
|
-
* without inspecting them.
|
|
11883
|
-
*/
|
|
11884
|
-
sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array>;
|
|
11885
|
-
}
|
|
11886
|
-
/**
|
|
11887
|
-
* Reference implementation of `RecipientSealer` + `SealingKeyProvider`.
|
|
11888
|
-
* Uses WebCrypto RSA-OAEP-SHA256 (2048-bit) to wrap a fresh 32-byte
|
|
11889
|
-
* AES-GCM CEK, AES-GCM-encrypts plaintext under it, and packs the
|
|
11890
|
-
* result into a self-describing TLV:
|
|
11891
|
-
*
|
|
11892
|
-
* byte 0 : version (0x01)
|
|
11893
|
-
* bytes 1..256 : RSA-OAEP-wrapped CEK (fixed 256 bytes at RSA-2048)
|
|
11894
|
-
* bytes 257..268: AES-GCM IV (12 bytes)
|
|
11895
|
-
* bytes 269.. : AES-GCM ciphertext ‖ 16-byte tag
|
|
11896
|
-
*
|
|
11897
|
-
* Implements BOTH interfaces. `seal(plaintext)` (self-target) is just
|
|
11898
|
-
* `sealForRecipient(plaintext, this own hint)` — same TLV. Convenient
|
|
11899
|
-
* for tests where one provider plays both ends. Real cloud providers
|
|
11900
|
-
* (`at-aws-kms`, etc.) will pick their own internal layouts; the only
|
|
11901
|
-
* contract is round-trip identity.
|
|
11902
|
-
*
|
|
11903
|
-
* SAFE for production within its scope — the cryptography is real
|
|
11904
|
-
* (RSA-OAEP + AES-GCM via WebCrypto), but the keypair lives in-process
|
|
11905
|
-
* and is regenerated on every construction. Not suitable as a managed
|
|
11906
|
-
* keychain; use it for tests and for shipping bundles where the
|
|
11907
|
-
* recipient instance lives in the same process as the sender (rare).
|
|
11908
|
-
*/
|
|
11909
|
-
declare class MemoryRecipientSealer implements SealingKeyProvider, RecipientSealer {
|
|
11910
|
-
readonly id: string;
|
|
11911
|
-
private readonly keypair;
|
|
11912
|
-
constructor(opts: {
|
|
11913
|
-
id: string;
|
|
11914
|
-
});
|
|
11915
|
-
publishRecipientHint(): Promise<RecipientHint>;
|
|
11916
|
-
sealForRecipient(plaintext: Uint8Array, hint: RecipientHint): Promise<Uint8Array>;
|
|
11917
|
-
seal(plaintext: Uint8Array): Promise<Uint8Array>;
|
|
11918
|
-
unseal(bytes: Uint8Array): Promise<Uint8Array>;
|
|
11919
|
-
}
|
|
11920
|
-
/** Reserved id for the managed-passphrase envelope under `_meta`. */
|
|
11921
|
-
declare const SEALED_PASSPHRASE_RECORD_ID: "sealed-passphrase";
|
|
11922
|
-
/** Plaintext payload stored inside the `_meta/sealed-passphrase` envelope. */
|
|
11923
|
-
interface SealedPassphrase {
|
|
11924
|
-
readonly _noydb_sealed: 1;
|
|
11925
|
-
readonly providerId: string;
|
|
11926
|
-
/** Sealed bytes. Base64-encoded on the wire; decoded on load. */
|
|
11927
|
-
readonly sealed: Uint8Array;
|
|
11928
|
-
}
|
|
11929
|
-
/**
|
|
11930
|
-
* Wire-format envelope persisted at `_meta/sealed-passphrase` for
|
|
11931
|
-
* managed-mode vaults. The provider produces raw sealed bytes via
|
|
11932
|
-
* {@link SealingKeyProvider.seal}; this wrapper carries the dispatch
|
|
11933
|
-
* metadata hub needs to pick the right provider on the unseal path.
|
|
11934
|
-
*
|
|
11935
|
-
* Stability boundary: once shipped, the wire format only grows by
|
|
11936
|
-
* adding optional fields. See the at-* sealing dimension foundation
|
|
11937
|
-
* doc, §11.9.1.
|
|
11938
|
-
*
|
|
11939
|
-
* v1 shape (this release): `{ v: 1, _noydb_sealed: 1, pid, payload }`.
|
|
11940
|
-
*
|
|
11941
|
-
* Legacy shape (earlier releases): `{ _noydb_sealed: 1, providerId, sealed }`
|
|
11942
|
-
* — accepted on read for backwards compatibility; never produced on
|
|
11943
|
-
* write going forward.
|
|
11944
|
-
*/
|
|
11945
|
-
interface SealedEnvelope {
|
|
11946
|
-
/** Envelope schema version. v1 is the current shape. */
|
|
11947
|
-
readonly v: 1;
|
|
11948
|
-
/** Magic marker for forensics + legacy-shape detection. */
|
|
11949
|
-
readonly _noydb_sealed: 1;
|
|
11950
|
-
/** Matches the producing provider's `.id`. Dispatch key on unseal. */
|
|
11951
|
-
readonly pid: string;
|
|
11952
|
-
/** Sealed bytes from the provider, base64-encoded on the wire. */
|
|
11953
|
-
readonly payload: string;
|
|
11954
|
-
}
|
|
11955
|
-
/**
|
|
11956
|
-
* Parse a `_meta/sealed-passphrase` `_data` JSON string into the
|
|
11957
|
-
* in-memory {@link SealedPassphrase} representation. Accepts both:
|
|
11958
|
-
*
|
|
11959
|
-
* 1. v1 wire format `{ v: 1, _noydb_sealed: 1, pid, payload }` —
|
|
11960
|
-
* the current shape.
|
|
11961
|
-
* 2. Legacy wire format `{ _noydb_sealed: 1, providerId, sealed }` —
|
|
11962
|
-
* read-only; never written
|
|
11963
|
-
* going forward.
|
|
11964
|
-
*
|
|
11965
|
-
* Returns `undefined` for any input that doesn't match either shape,
|
|
11966
|
-
* so callers can fall back to "no managed-mode envelope present."
|
|
11967
|
-
*
|
|
11968
|
-
* @internal — exported only for the migration safety-net test suite.
|
|
11969
|
-
*/
|
|
11970
|
-
declare function parseSealedEnvelope(raw: unknown): SealedPassphrase | undefined;
|
|
11971
|
-
declare function saveSealedPassphrase(store: NoydbStore, vault: string, payload: {
|
|
11972
|
-
readonly providerId: string;
|
|
11973
|
-
readonly sealed: Uint8Array;
|
|
11974
|
-
}): Promise<void>;
|
|
11975
|
-
declare function loadSealedPassphrase(store: NoydbStore, vault: string): Promise<SealedPassphrase | undefined>;
|
|
11976
|
-
|
|
11977
12656
|
/**
|
|
11978
12657
|
* Core types — the {@link NoydbStore} interface, envelope format, roles, and
|
|
11979
12658
|
* all configuration shapes consumed by {@link createNoydb}.
|
|
@@ -12070,6 +12749,27 @@ interface EncryptedEnvelope {
|
|
|
12070
12749
|
* side channel.
|
|
12071
12750
|
*/
|
|
12072
12751
|
readonly _det?: Record<string, string>;
|
|
12752
|
+
/**
|
|
12753
|
+
* Per-record content-encryption key (CEK), base64 AES-KW-wrapped under
|
|
12754
|
+
* the collection (or tier) DEK. Present only on records written by a
|
|
12755
|
+
* collection opened with `perRecordKeys: true`. When present, the body
|
|
12756
|
+
* (`_iv`/`_data`) is encrypted under the unwrapped CEK rather than the
|
|
12757
|
+
* collection DEK directly.
|
|
12758
|
+
*
|
|
12759
|
+
* Presence is the format discriminant: `_cek` absent → legacy body
|
|
12760
|
+
* keyed off the collection DEK (read unchanged); `_cek` present →
|
|
12761
|
+
* unwrap under the collection DEK, then decrypt the body under the CEK.
|
|
12762
|
+
*
|
|
12763
|
+
* The CEK is stable across every version of a record (insert mints it;
|
|
12764
|
+
* updates and history snapshots reuse it), so all `_history` envelopes
|
|
12765
|
+
* for a record carry the same `_cek`. This is the foundation for
|
|
12766
|
+
* per-record erasure (#304) and record-scoped sealing (#306).
|
|
12767
|
+
*
|
|
12768
|
+
* `_det` slots are deliberately NOT keyed off the CEK — they remain
|
|
12769
|
+
* keyed to the collection DEK so blind-equality search keeps working
|
|
12770
|
+
* across records.
|
|
12771
|
+
*/
|
|
12772
|
+
readonly _cek?: string;
|
|
12073
12773
|
}
|
|
12074
12774
|
/**
|
|
12075
12775
|
* Placeholder returned by `getAtTier()` in `'ghost'` mode when a
|
|
@@ -13146,6 +13846,15 @@ interface LocaleReadOptions {
|
|
|
13146
13846
|
* element to fall back to any present translation.
|
|
13147
13847
|
*/
|
|
13148
13848
|
readonly fallback?: string | readonly string[];
|
|
13849
|
+
/**
|
|
13850
|
+
* @internal — the resolution layer this read belongs to (`'read'` by
|
|
13851
|
+
* default). Threaded by layer-tagged read facades (guard / derivation)
|
|
13852
|
+
* so `applyI18nLocale` and dictKey `resolvePolicy` select that layer's
|
|
13853
|
+
* `onMissing` policy instead of the `'read'` policy. Not part of the
|
|
13854
|
+
* public read API — callers select policy via the field's `onMissing`
|
|
13855
|
+
* map, not by setting this. See #285.
|
|
13856
|
+
*/
|
|
13857
|
+
readonly _layer?: Layer;
|
|
13149
13858
|
}
|
|
13150
13859
|
/**
|
|
13151
13860
|
* Context passed to the consumer-supplied `plaintextTranslator` function.
|
|
@@ -13288,6 +13997,25 @@ interface BlobObject {
|
|
|
13288
13997
|
readonly createdAt: string;
|
|
13289
13998
|
/** Live reference count — slots + published versions pointing to this blob. */
|
|
13290
13999
|
readonly refCount: number;
|
|
14000
|
+
/**
|
|
14001
|
+
* Base64 AES-KW-wrapped per-blob **content CEK** (wrapped under the `_blob`
|
|
14002
|
+
* DEK). Present on erasable-collection blobs (`perRecordKeys`): the chunks
|
|
14003
|
+
* are encrypted under this content CEK rather than directly under the `_blob`
|
|
14004
|
+
* DEK, so deleting this BlobObject at `refCount → 0` crypto-shreds the chunks
|
|
14005
|
+
* (they become permanently undecryptable). Absent → legacy blob, chunks
|
|
14006
|
+
* decrypt directly under the `_blob` DEK (read unchanged). See
|
|
14007
|
+
* docs/superpowers/specs/2026-06-13-per-blob-cek-design.md.
|
|
14008
|
+
*/
|
|
14009
|
+
readonly _cek?: string;
|
|
14010
|
+
/**
|
|
14011
|
+
* Transient migration marker (#365 slice 3). Present only while a legacy
|
|
14012
|
+
* blob is being migrated to a content CEK: it holds the wrapped content CEK
|
|
14013
|
+
* BEFORE the chunks have been re-encrypted under it. Readers **ignore**
|
|
14014
|
+
* `_cekPending` (they key off `_cek`), so the blob stays readable under the
|
|
14015
|
+
* `_blob` DEK during migration AND the content CEK survives a crash → a
|
|
14016
|
+
* re-run resumes and promotes `_cekPending` → `_cek`. Never set on a settled blob.
|
|
14017
|
+
*/
|
|
14018
|
+
readonly _cekPending?: string;
|
|
13291
14019
|
/**
|
|
13292
14020
|
* Hint indicating which store holds the chunk data.
|
|
13293
14021
|
* Used by `routeStore` size-tiered routing: `'default'` for small blobs
|
|
@@ -13519,6 +14247,19 @@ interface NoydbOptions {
|
|
|
13519
14247
|
* @internal
|
|
13520
14248
|
*/
|
|
13521
14249
|
readonly historyStrategy?: HistoryStrategy;
|
|
14250
|
+
/**
|
|
14251
|
+
* GDPR right-to-erasure (#304). Pass `withForgetCascade({ subjects })`
|
|
14252
|
+
* from `@noy-db/hub/forget` to declare which collections carry erasable
|
|
14253
|
+
* subject data and the record field naming the data subject. Enables
|
|
14254
|
+
* `vault.forget(subjectId)` crypto-shred (rewrite-to-tombstone of the live
|
|
14255
|
+
* record + every history version → body permanently undecryptable, single
|
|
14256
|
+
* `op:'forget'` ledger entry, chain still verifies). Each declared
|
|
14257
|
+
* collection is forced to `perRecordKeys: true`. When omitted (the
|
|
14258
|
+
* `NO_FORGET` default), `vault.forget()` throws
|
|
14259
|
+
* `ForgetStrategyNotConfiguredError` and no subject-index write hooks run.
|
|
14260
|
+
* Requires `historyStrategy` (the ledger) for the erasure-proof entry.
|
|
14261
|
+
*/
|
|
14262
|
+
readonly forgetStrategy?: ForgetStrategy;
|
|
13522
14263
|
/**
|
|
13523
14264
|
* tree-shake seam — optional i18n strategy. Pass `withI18n()`
|
|
13524
14265
|
* from `@noy-db/hub/i18n` to enable `i18nText`/`dictKey` field
|
|
@@ -13806,6 +14547,16 @@ interface HistoryConfig {
|
|
|
13806
14547
|
readonly enabled?: boolean;
|
|
13807
14548
|
/** Maximum history entries per record. Oldest pruned on overflow. Default: unlimited. */
|
|
13808
14549
|
readonly maxVersions?: number;
|
|
14550
|
+
/**
|
|
14551
|
+
* Participate in the vault-wide hash-chained tamper ledger. Default:
|
|
14552
|
+
* `true` (every write of this collection appends a ledger entry when
|
|
14553
|
+
* `withHistory()` is active). Set `false` to exclude this collection's
|
|
14554
|
+
* writes from the chain — its puts/deletes leave no ledger entry,
|
|
14555
|
+
* confining tamper-evidence to the collections where it carries weight.
|
|
14556
|
+
* Independent of `enabled`, which gates per-record snapshots. Has no
|
|
14557
|
+
* effect when `withHistory()` is not active (there is no ledger). See #361.
|
|
14558
|
+
*/
|
|
14559
|
+
readonly ledger?: boolean;
|
|
13809
14560
|
}
|
|
13810
14561
|
/** Options for querying history. */
|
|
13811
14562
|
interface HistoryOptions {
|
|
@@ -13874,4 +14625,4 @@ interface DeleteManyResult {
|
|
|
13874
14625
|
}>;
|
|
13875
14626
|
}
|
|
13876
14627
|
|
|
13877
|
-
export { type ExportBlobsAuditEntry as $, BLOB_COLLECTION as A, type BlobStrategy as B, BLOB_EVICTION_AUDIT_COLLECTION as C, DICT_COLLECTION_PREFIX as D, BLOB_INDEX_COLLECTION as E, BLOB_SLOTS_PREFIX as F, BLOB_VERSIONS_PREFIX as G, type BlobEvictionEntry as H, type I18nStrategy as I, type BlobFieldPolicy as J, type BlobFieldsConfig as K, type Layer as L, type BlobObject as M, type BlobPutOptions as N, type OnMissing as O, PolicyEnforcer as P, type BlobResponseOptions as Q, type ResolveI18nOptions as R, type ScriptWarning as S, BlobSet as T, type BlobStrategyOpenArgs as U, type CompactRunOptions as V, type CompactionContext as W, type CompactionResult as X, DEFAULT_CHUNK_SIZE as Y, EXPORT_AUDIT_COLLECTION as Z, ExportBlobsAbortedError as _, type DictEntry as a, type NoydbStore as a$, type ExportBlobsHandle as a0, type ExportBlobsOptions as a1, type ExportedBlob as a2, type SlotInfo as a3, type SlotRecord as a4, type VersionRecord as a5, createExportBlobsHandle as a6, runCompaction as a7, type ConsentStrategy as a8, CONSENT_AUDIT_COLLECTION as a9, VaultFrame as aA, type NoydbBundleStore as aB, type RetentionPolicy as aC, type SnapshotPolicy as aD, type SnapshotStrategy as aE, type SnapshotMeta as aF, type SnapshotMode as aG, type DerivationStrategy as aH, type DerivationContext as aI, type ArrayOutputSpec as aJ, DerivationRegistry as aK, type DerivationStrategyHandle as aL, type DerivedFromMeta as aM, type OutputSpec as aN, type RecordOutputSpec as aO, type MaterializedViewStrategy as aP, type MaterializedViewStrategyHandle as aQ, type OverlayedViewStrategy as aR, Collection as aS, type OverlayFieldMergeMode as aT, type OverlayFieldMergeRule as aU, OverlayedViewRegistry as aV, type OverlayedViewStrategyHandle as aW, type SyncStrategy as aX, type Role as aY, type UnlockedKeyring as aZ, type HistoryStrategy as a_, type ConsentAuditEntry as aa, type ConsentAuditFilter as ab, type ConsentContext as ac, type ConsentOp as ad, loadConsentEntries as ae, writeConsentEntry as af, type PeriodsStrategy as ag, type CarryForwardContext as ah, type ClosePeriodOptions as ai, type OpenPeriodOptions as aj, PERIODS_COLLECTION as ak, type PeriodRecord as al, type ReadOnlyCollection as am, appendPeriodLedgerEntry as an, assertTsWritable as ao, chainAnchor as ap, loadPeriods as aq, validatePeriodName as ar, type GuardStrategy as as, type GuardChange as at, type GuardContext as au, GuardRegistry as av, type GuardStrategyHandle as aw, ReadOnlyVaultFacade as ax, type ShadowStrategy as ay, CollectionFrame as az, type DictKeyDescriptor as b, type CollectionChangeEvent as b$, type HistoryOptions as b0, type EncryptedEnvelope as b1, type PruneOptions as b2, type AppendInput as b3, type ChangeType as b4, CollectionInstant as b5, type DiffEntry as b6, type JsonPatch as b7, type JsonPatchOp as b8, type LedgerEntry as b9, type MaterializedViewOutput as bA, type UnionArmJoin as bB, type UnionSource as bC, type UserEnvelope as bD, type GateName as bE, type GatePolicy as bF, type VaultPolicy as bG, type ActiveTier as bH, type FactorProof as bI, type SchemaUpdateStrategy as bJ, type TransformFn as bK, type PersistedSchemaEnvelope as bL, type UpdateDecision as bM, type DirectoryConfig as bN, type UserVisibility as bO, type AccessibleVault as bP, type AffectedDocument as bQ, type ArchivePolicy as bR, type ArchiveResult as bS, type ArchiveRunOptions as bT, type ArchiveStrategy as bU, BUNDLE_STORE_POLICY as bV, type BuiltInGateName as bW, type CacheOptions as bX, type CacheStats as bY, type CapturedBlueprint as bZ, type ChangeEvent as b_, LedgerStore as ba, type VaultEngine as bb, VaultInstant as bc, type VerifyResult as bd, applyPatch as be, canonicalJson as bf, computePatch as bg, diff as bh, formatDiff as bi, hashEntry as bj, paddedIndex as bk, parseIndex as bl, sha256Hex as bm, type PublicEnvelope as bn, type SealingKeyProvider as bo, type BundleRecipient as bp, type RecipientSealer as bq, type RecipientHint as br, Vault as bs, type RecoveryEnrollmentInput as bt, type ShamirRecoveryProvider as bu, TxContext as bv, type MVQueryContext as bw, type RegisteredMV as bx, MaterializedViewRegistry as by, type MaterializedFromMeta as bz, DictionaryHandle as c, type ListPageResult as c$, type CollectionConflictResolver as c0, type CollectionDescriptor as c1, type CollectionStats as c2, ComputedFieldError as c3, type ComputedFields as c4, type ComputedFn as c5, type Conflict as c6, type ConflictPolicy as c7, type ConflictStrategy as c8, type CrossTierAccessEvent as c9, type ExportStreamOptions as cA, type FactorKind as cB, type FactorProofBundle as cC, type FactorRequirement as cD, type FanoutQueryOptions as cE, type FanoutResult as cF, type FenceDoc as cG, type FenceState as cH, type FieldChange as cI, type FieldDescriptor as cJ, type FieldSource as cK, type GhostRecord as cL, type GrantOptions as cM, type GuardViolation as cN, type HistoryConfig as cO, type HistoryEntry as cP, INDEXED_STORE_POLICY as cQ, type ImportCapability as cR, type InferOutput as cS, type InternalCollectionStats as cT, type IssueDelegationOptions as cU, type IssueMagicLinkGrantOptions as cV, type KeyringAuthenticator as cW, type KeyringAuthenticatorWrappingDEKs as cX, type KeyringAuthenticatorWrappingKEK as cY, type KeyringFile as cZ, type ListAccessibleVaultsOptions as c_, CrossVaultAggregation as ca, CrossVaultGroupedAggregation as cb, type GroupedRow as cc, type CrossVaultLiveAggregation as cd, type CrossVaultLiveQuery as ce, DEFAULT_PUBLIC_ENVELOPE_SCHEMA as cf, DELEGATIONS_COLLECTION as cg, type DeepPartial as ch, type DeepPartialOrNull as ci, type DeferredNumberingConfig as cj, type DelegationToken as ck, type DeleteManyResult as cl, type DeploymentEvent as cm, type DerivationDescriptor as cn, type DirtyEntry as co, type DryRunResult as cp, type DumpSchemaOptions as cq, ELEVATION_AUDIT_COLLECTION as cr, ElevatedHandle as cs, type EnrollAuthenticatorOptions as ct, type EnrollAuthenticatorWrappingDEKsOptions as cu, type EnrollAuthenticatorWrappingKEKOptions as cv, type EnrollRecoveryResult as cw, type ExportCapability as cx, type ExportChunk as cy, type ExportFormat as cz, type DictionaryOptions as d, type RotatePassphraseInput as d$, type ListUsersOptions as d0, type LiveQueryOptions as d1, type LiveUserEnvelope as d2, type LocaleReadOptions as d3, Lru as d4, type LruOptions as d5, type LruStats as d6, MAGIC_LINK_CONTENT_INFO_PREFIX as d7, MAGIC_LINK_GRANTS_COLLECTION as d8, MAGIC_LINK_KEK_INFO_PREFIX as d9, PresenceHandle as dA, type PresencePeer as dB, type PublicEnvelopeField as dC, type PublicEnvelopeSchema as dD, type PublicEnvelopeText as dE, type PullMode as dF, type PullOptions as dG, type PullPolicy as dH, type PullResult as dI, type PushMode as dJ, type PushOptions as dK, type PushPolicy as dL, type PushResult as dM, type PutManyItemOptions as dN, type PutManyOptions as dO, type PutManyResult as dP, type QueryAcrossOptions as dQ, type QueryAcrossResult as dR, type QuickUnlockState as dS, QuickUnlockStore as dT, type ReAuthOperation as dU, type RecoverPassphraseInput as dV, type RecoverPassphraseResult as dW, type RecoverUserOptions as dX, type RecoveryProof as dY, type ResolvedPublicEnvelopeSchema as dZ, type RevokeOptions as d_, type MagicLinkGrantPayload as da, type MagicLinkGrantRecord as db, type MaterializedViewDescriptor as dc, MemoryRecipientSealer as dd, MemorySealingKeyProvider as de, NOYDB_BACKUP_VERSION as df, NOYDB_FORMAT_VERSION as dg, NOYDB_KEYRING_VERSION as dh, NOYDB_SYNC_VERSION as di, type NextOptions as dj, Noydb as dk, type NoydbEventMap as dl, type NoydbOptions as dm, type Assignment as dn, type OverlayViewDescriptor as dp, PUBLIC_ENVELOPE_FIELDS as dq, type PaperRecoveryDoc as dr, type PaperRecoveryEntry as ds, type PassphrasePolicy as dt, type PassphraseValidationResult as du, type Permission as dv, type Permissions as dw, type PersistedSchemaKind as dx, type PlaintextTranslatorContext as dy, type PlaintextTranslatorFn as dz, type I18nMap as e, VaultGroup as e$, type RotateRecoveryOptions as e0, type RotateRecoveryResult as e1, SEALED_PASSPHRASE_RECORD_ID as e2, type SchemaDelta as e3, type SchemaIntrospection as e4, type SchemaManifestRow as e5, type SealedEnvelope as e6, type SealedPassphrase as e7, type SequenceHandle as e8, type SequenceOptions as e9, type SyncTarget as eA, type SyncTargetRole as eB, SyncTransaction as eC, type SyncTransactionResult as eD, type TabChannel as eE, type TabCoordinationOptions as eF, type TabLockManager as eG, type TabPresence as eH, type TabRole as eI, type TierMode as eJ, type TransactionInvariant as eK, type TranslatorAuditEntry as eL, TxCollection as eM, type TxOp as eN, TxVault as eO, USER_ENVELOPE_COLLECTION as eP, USER_ENVELOPE_MAX_BYTES as eQ, type Unsubscribe as eR, type UpdateAuthenticatorOptions as eS, type UpdateContext as eT, type UpdateUserOptions as eU, UserApi as eV, type UserEnvelopeCheckGate as eW, UserEnvelopeOversizedError as eX, type UserEnvelopePresented as eY, type UserInfo as eZ, type VaultBackup as e_, SequenceStore as ea, type SessionPolicy as eb, type SetPublicEnvelopeInput as ec, type ShamirRecoveryDoc as ed, type ShamirRecoveryEntry as ee, ShardedCollection as ef, ShardedGroupedQuery as eg, ShardedQuery as eh, type ShardingConfig as ei, type SkippedVault as ej, type SlotRewrapCeremony as ek, type SlotRewrapContext as el, type StandardSchemaV1 as em, type StandardSchemaV1Issue as en, type StandardSchemaV1SyncResult as eo, StateManagementVault as ep, type StoreAuth as eq, type StoreAuthKind as er, type StoreCapabilities as es, type StoreTime as et, SyncEngine as eu, type SyncMetadata as ev, type SyncPolicy as ew, SyncScheduler as ex, type SyncSchedulerStatus as ey, type SyncStatus as ez, type I18nTextDescriptor as f, validatePublicEnvelopeInput as f$, type VaultGroupOptions as f0, type VaultPolicyOnDisk as f1, type VaultRegistryRow as f2, type VaultSchemaSnapshot as f3, type VaultSnapshot as f4, type VaultTemplate as f5, type WarningRules as f6, WeakPassphraseError as f7, type WeakPassphraseReason as f8, type WithArchiveOptions as f9, listUsers as fA, listUsersWithEnvelopes as fB, loadActiveDelegations as fC, loadPaperRecoveryEntries as fD, loadSealedPassphrase as fE, loadShamirRecoveryEntries as fF, magicLinkGrantRecordId as fG, mintPaperRecoveryEntry as fH, mintShamirRecoveryEntry as fI, mintWrappedDeksBlob as fJ, parseSealedEnvelope as fK, readMagicLinkGrantRecord as fL, recoverUser as fM, removeAuthenticator as fN, resolveSchema as fO, resolveSequenceKey as fP, revokeDelegation as fQ, revokeMagicLinkGrant as fR, runTransaction as fS, savePaperRecoveryEntries as fT, saveSealedPassphrase as fU, saveShamirRecoveryEntries as fV, unwrapDeksFromBlob as fW, unwrapDeksFromPaperEntry as fX, unwrapDeksFromShamirEntry as fY, unwrapMagicLinkGrant as fZ, validatePassphrase as f_, type WrappedDeksBlob as fa, type WriteConflict as fb, type WriteEvent as fc, type WriteHook as fd, type WriteQueue as fe, assertStrongPassphrase as ff, buildRecipientKeyringFile as fg, burnPaperRecoveryEntry as fh, createNoydb as fi, createStore as fj, deriveMagicLinkContentKey as fk, enrollAuthenticator as fl, estimateEntropy as fm, evalComputedFields as fn, evaluateExportCapability as fo, evaluateImportCapability as fp, findAuthenticator as fq, hasExportCapability as fr, hasImportCapability as fs, hasRecoveryEnrolled as ft, isMagicLinkGrantExpired as fu, isPublicEnvelope as fv, issueDelegation as fw, recoverPassphrase as fx, rotatePassphrase as fy, listMagicLinkGrants as fz, type I18nTextOptions as g, validateSchemaInput as g0, validateSchemaOutput as g1, withArchive as g2, withDeferredNumbering as g3, writeMagicLinkGrant as g4, changeSecret as g5, createOwnerKeyring as g6, ensureCollectionDEK as g7, grant as g8, loadKeyring as g9, persistKeyring as ga, revoke as gb, updateAuthenticator as gc, updateKeyringIdentity as gd, type TxStrategy as ge, type AmendmentTxOptions as gf, type OnMissingPolicy as h, applyI18nLocale as i, dictCollectionName as j, dictKey as k, enforceScript as l, getAtPath as m, i18nText as n, inferScripts as o, isDictCollectionName as p, isDictKeyDescriptor as q, isI18nTextDescriptor as r, resolveI18nText as s, resolvePolicy as t, setAtPathInPlace as u, validateI18nTextValue as v, type SessionStrategy as w, createEnforcer as x, validateSessionPolicy as y, BLOB_CHUNKS_COLLECTION as z };
|
|
14628
|
+
export { DEFAULT_CHUNK_SIZE as $, createEnforcer as A, validateSessionPolicy as B, type BlobStrategy as C, DICT_COLLECTION_PREFIX as D, BLOB_CHUNKS_COLLECTION as E, BLOB_COLLECTION as F, BLOB_EVICTION_AUDIT_COLLECTION as G, BLOB_INDEX_COLLECTION as H, type I18nStrategy as I, BLOB_SLOTS_PREFIX as J, BLOB_VERSIONS_PREFIX as K, type Layer as L, type BlobEvictionEntry as M, type BlobFieldPolicy as N, type OnMissing as O, PolicyEnforcer as P, type BlobFieldsConfig as Q, type ResolveI18nOptions as R, type ScriptWarning as S, type BlobObject as T, type BlobPutOptions as U, type BlobResponseOptions as V, BlobSet as W, type BlobStrategyOpenArgs as X, type CompactRunOptions as Y, type CompactionContext as Z, type CompactionResult as _, type DictEntry as a, type Role as a$, EXPORT_AUDIT_COLLECTION as a0, ExportBlobsAbortedError as a1, type ExportBlobsAuditEntry as a2, type ExportBlobsHandle as a3, type ExportBlobsOptions as a4, type ExportedBlob as a5, type SlotInfo as a6, type SlotRecord as a7, type VersionRecord as a8, createExportBlobsHandle as a9, ReadOnlyVaultFacade as aA, type ShadowStrategy as aB, CollectionFrame as aC, VaultFrame as aD, type NoydbBundleStore as aE, type RetentionPolicy as aF, type SnapshotPolicy as aG, type SnapshotStrategy as aH, type SnapshotMeta as aI, type SnapshotMode as aJ, type DerivationStrategy as aK, type DerivationContext as aL, type ArrayOutputSpec as aM, DerivationRegistry as aN, type DerivationStrategyHandle as aO, type DerivedFromMeta as aP, type OutputSpec as aQ, type RecordOutputSpec as aR, type MaterializedViewStrategy as aS, type MaterializedViewStrategyHandle as aT, type OverlayedViewStrategy as aU, Collection as aV, type OverlayFieldMergeMode as aW, type OverlayFieldMergeRule as aX, OverlayedViewRegistry as aY, type OverlayedViewStrategyHandle as aZ, type SyncStrategy as a_, runCompaction as aa, type ConsentStrategy as ab, CONSENT_AUDIT_COLLECTION as ac, type ConsentAuditEntry as ad, type ConsentAuditFilter as ae, type ConsentContext as af, type ConsentOp as ag, loadConsentEntries as ah, writeConsentEntry as ai, type PeriodsStrategy as aj, type CarryForwardContext as ak, type ClosePeriodOptions as al, type OpenPeriodOptions as am, PERIODS_COLLECTION as an, type PeriodRecord as ao, type ReadOnlyCollection as ap, appendPeriodLedgerEntry as aq, assertTsWritable as ar, chainAnchor as as, loadPeriods as at, validatePeriodName as au, type GuardStrategy as av, type GuardChange as aw, type GuardContext as ax, GuardRegistry as ay, type GuardStrategyHandle as az, type DictKeyDescriptor as b, type CollectionStats as b$, type UnlockedKeyring as b0, type HistoryStrategy as b1, type NoydbStore as b2, type HistoryOptions as b3, type EncryptedEnvelope as b4, type PruneOptions as b5, type AppendInput as b6, type ChangeType as b7, CollectionInstant as b8, type DiffEntry as b9, type UserEnvelope as bA, type GateName as bB, type GatePolicy as bC, type VaultPolicy as bD, type ActiveTier as bE, type FactorProof as bF, type SchemaUpdateStrategy as bG, type TransformFn as bH, type PersistedSchemaEnvelope as bI, type UpdateDecision as bJ, type DirectoryConfig as bK, type UserVisibility as bL, type AccessibleVault as bM, type AffectedDocument as bN, type ArchivePolicy as bO, type ArchiveResult as bP, type ArchiveRunOptions as bQ, type ArchiveStrategy as bR, BUNDLE_STORE_POLICY as bS, type BuiltInGateName as bT, type CacheOptions as bU, type CacheStats as bV, type CapturedBlueprint as bW, type ChangeEvent as bX, type CollectionChangeEvent as bY, type CollectionConflictResolver as bZ, type CollectionDescriptor as b_, type JsonPatch as ba, type JsonPatchOp as bb, LedgerStore as bc, type VaultEngine as bd, VaultInstant as be, type VerifyResult as bf, applyPatch as bg, computePatch as bh, diff as bi, formatDiff as bj, type PublicEnvelope as bk, type SealingKeyProvider as bl, type BundleRecipient as bm, type RecipientSealer as bn, type RecipientHint as bo, Vault as bp, type RecoveryEnrollmentInput as bq, type ShamirRecoveryProvider as br, TxContext as bs, type MVQueryContext as bt, type RegisteredMV as bu, MaterializedViewRegistry as bv, type MaterializedFromMeta as bw, type MaterializedViewOutput as bx, type UnionArmJoin as by, type UnionSource as bz, DictionaryHandle as c, LinkEndpointError as c$, ComputedFieldError as c0, type ComputedFields as c1, type ComputedFn as c2, type Conflict as c3, type ConflictPolicy as c4, type ConflictStrategy as c5, type CrossTierAccessEvent as c6, CrossVaultAggregation as c7, type CrossVaultDerivationContext as c8, type CrossVaultDerivationSpec as c9, type FactorKind as cA, type FactorProofBundle as cB, type FactorRequirement as cC, type FanoutQueryOptions as cD, type FanoutResult as cE, type FenceDoc as cF, type FenceState as cG, type FieldChange as cH, type FieldDescriptor as cI, type FieldSource as cJ, type FleetMigrationResult as cK, type FormattedSequenceHandle as cL, type GhostRecord as cM, type GrantOptions as cN, type GuardViolation as cO, type HistoryConfig as cP, type HistoryEntry as cQ, INDEXED_STORE_POLICY as cR, type ImportCapability as cS, type InferOutput as cT, type InternalCollectionStats as cU, type IssueDelegationOptions as cV, type IssueMagicLinkGrantOptions as cW, type KeyringAuthenticator as cX, type KeyringAuthenticatorWrappingDEKs as cY, type KeyringAuthenticatorWrappingKEK as cZ, type KeyringFile as c_, CrossVaultGroupedAggregation as ca, type GroupedRow as cb, type CrossVaultLiveAggregation as cc, type CrossVaultLiveQuery as cd, DEFAULT_PUBLIC_ENVELOPE_SCHEMA as ce, DELEGATIONS_COLLECTION as cf, type DeepPartial as cg, type DeepPartialOrNull as ch, type DeferredNumberingConfig as ci, type DelegationToken as cj, type DeleteManyResult as ck, type DeploymentEvent as cl, type DerivationDescriptor as cm, type DirtyEntry as cn, type DryRunResult as co, type DumpSchemaOptions as cp, ELEVATION_AUDIT_COLLECTION as cq, ElevatedHandle as cr, type EnrollAuthenticatorOptions as cs, type EnrollAuthenticatorWrappingDEKsOptions as ct, type EnrollAuthenticatorWrappingKEKOptions as cu, type EnrollRecoveryResult as cv, type ExportCapability as cw, type ExportChunk as cx, type ExportFormat as cy, type ExportStreamOptions as cz, type DictionaryOptions as d, QuickUnlockStore as d$, LinkIntegrityError as d0, type LinkOnDelete as d1, type LinkRow as d2, type LinkSetHandle as d3, type LinkSpec as d4, type ListAccessibleVaultsOptions as d5, type ListPageResult as d6, type ListUsersOptions as d7, type LiveQueryOptions as d8, type LiveUserEnvelope as d9, type PaperRecoveryEntry as dA, type PassphrasePolicy as dB, type PassphraseValidationResult as dC, type Permission as dD, type Permissions as dE, type PersistedSchemaKind as dF, type PlaintextTranslatorContext as dG, type PlaintextTranslatorFn as dH, PresenceHandle as dI, type PresencePeer as dJ, type PublicEnvelopeField as dK, type PublicEnvelopeSchema as dL, type PublicEnvelopeText as dM, type PullMode as dN, type PullOptions as dO, type PullPolicy as dP, type PullResult as dQ, type PushMode as dR, type PushOptions as dS, type PushPolicy as dT, type PushResult as dU, type PutManyItemOptions as dV, type PutManyOptions as dW, type PutManyResult as dX, type QueryAcrossOptions as dY, type QueryAcrossResult as dZ, type QuickUnlockState as d_, type LocaleReadOptions as da, Lru as db, type LruOptions as dc, type LruStats as dd, MAGIC_LINK_CONTENT_INFO_PREFIX as de, MAGIC_LINK_GRANTS_COLLECTION as df, MAGIC_LINK_KEK_INFO_PREFIX as dg, type MagicLinkGrantPayload as dh, type MagicLinkGrantRecord as di, type MaterializedViewDescriptor as dj, MemoryRecipientSealer as dk, MemorySealingKeyProvider as dl, type MigrationStatusRow as dm, NOYDB_BACKUP_VERSION as dn, NOYDB_FORMAT_VERSION as dp, NOYDB_KEYRING_VERSION as dq, NOYDB_SYNC_VERSION as dr, type NextOptions as ds, Noydb as dt, type NoydbEventMap as du, type NoydbOptions as dv, type Assignment as dw, type OverlayViewDescriptor as dx, PUBLIC_ENVELOPE_FIELDS as dy, type PaperRecoveryDoc as dz, type I18nMap as e, type UpdateAuthenticatorOptions as e$, type ReAuthOperation as e0, type RecoverPassphraseInput as e1, type RecoverPassphraseResult as e2, type RecoverUserOptions as e3, type RecoveryProof as e4, type RefreshInsightsResult as e5, type ResolvedPublicEnvelopeSchema as e6, type RevokeOptions as e7, type RotatePassphraseInput as e8, type RotateRecoveryOptions as e9, type StoreAuthKind as eA, type StoreCapabilities as eB, type StoreTime as eC, SyncEngine as eD, type SyncMetadata as eE, type SyncPolicy as eF, SyncScheduler as eG, type SyncSchedulerStatus as eH, type SyncStatus as eI, type SyncTarget as eJ, type SyncTargetRole as eK, SyncTransaction as eL, type SyncTransactionResult as eM, type TabChannel as eN, type TabCoordinationOptions as eO, type TabLockManager as eP, type TabPresence as eQ, type TabRole as eR, type TierMode as eS, type TransactionInvariant as eT, type TranslatorAuditEntry as eU, TxCollection as eV, type TxOp as eW, TxVault as eX, USER_ENVELOPE_COLLECTION as eY, USER_ENVELOPE_MAX_BYTES as eZ, type Unsubscribe as e_, type RotateRecoveryResult as ea, SEALED_PASSPHRASE_RECORD_ID as eb, type SchemaDelta as ec, type SchemaIntrospection as ed, type SchemaManifestRow as ee, type SealedEnvelope as ef, type SealedPassphrase as eg, type SequenceHandle as eh, type SequenceOptions as ei, SequenceStore as ej, type SessionPolicy as ek, type SetPublicEnvelopeInput as el, type ShamirRecoveryDoc as em, type ShamirRecoveryEntry as en, ShardedCollection as eo, ShardedGroupedQuery as ep, ShardedQuery as eq, type ShardingConfig as er, type SkippedVault as es, type SlotRewrapCeremony as et, type SlotRewrapContext as eu, type StandardSchemaV1 as ev, type StandardSchemaV1Issue as ew, type StandardSchemaV1SyncResult as ex, StateManagementVault as ey, type StoreAuth as ez, type I18nTextDescriptor as f, resolveSchema as f$, type UpdateContext as f0, type UpdateUserOptions as f1, UserApi as f2, type UserEnvelopeCheckGate as f3, UserEnvelopeOversizedError as f4, type UserEnvelopePresented as f5, type UserInfo as f6, type VaultBackup as f7, VaultGroup as f8, type VaultGroupOptions as f9, evaluateImportCapability as fA, findAuthenticator as fB, hasExportCapability as fC, hasImportCapability as fD, hasRecoveryEnrolled as fE, isLinkCollectionName as fF, isMagicLinkGrantExpired as fG, isPublicEnvelope as fH, issueDelegation as fI, recoverPassphrase as fJ, rotatePassphrase as fK, listMagicLinkGrants as fL, listUsers as fM, listUsersWithEnvelopes as fN, loadActiveDelegations as fO, loadPaperRecoveryEntries as fP, loadSealedPassphrase as fQ, loadShamirRecoveryEntries as fR, magicLinkGrantRecordId as fS, mintPaperRecoveryEntry as fT, mintShamirRecoveryEntry as fU, mintWrappedDeksBlob as fV, parseRsaOaepTlv as fW, parseSealedEnvelope as fX, readMagicLinkGrantRecord as fY, recoverUser as fZ, removeAuthenticator as f_, type VaultPolicyOnDisk as fa, type VaultRegistryRow as fb, type VaultSchemaSnapshot as fc, type VaultSnapshot as fd, type VaultTemplate as fe, type WarningRules as ff, WeakPassphraseError as fg, type WeakPassphraseReason as fh, type WithArchiveOptions as fi, type WrappedDeksBlob as fj, type WriteConflict as fk, type WriteEvent as fl, type WriteHook as fm, type WriteQueue as fn, aesGcmOpen as fo, assertStrongPassphrase as fp, buildRecipientKeyringFile as fq, burnPaperRecoveryEntry as fr, compileSequenceFormat as fs, createNoydb as ft, createStore as fu, deriveMagicLinkContentKey as fv, enrollAuthenticator as fw, estimateEntropy as fx, evalComputedFields as fy, evaluateExportCapability as fz, type I18nTextOptions as g, resolveSequenceKey as g0, revokeDelegation as g1, revokeMagicLinkGrant as g2, runTransaction as g3, savePaperRecoveryEntries as g4, saveSealedPassphrase as g5, saveShamirRecoveryEntries as g6, sealRsaOaepTlv as g7, unwrapDeksFromBlob as g8, unwrapDeksFromPaperEntry as g9, unwrapDeksFromShamirEntry as ga, unwrapMagicLinkGrant as gb, validatePassphrase as gc, validatePublicEnvelopeInput as gd, validateSchemaInput as ge, validateSchemaOutput as gf, withArchive as gg, withDeferredNumbering as gh, writeMagicLinkGrant as gi, changeSecret as gj, createOwnerKeyring as gk, ensureCollectionDEK as gl, grant as gm, loadKeyring as gn, persistKeyring as go, revoke as gp, updateAuthenticator as gq, updateKeyringIdentity as gr, type TxStrategy as gs, type AmendmentTxOptions as gt, type OnMissingPolicy as h, type StaticDictDescriptor as i, applyI18nLocale as j, dictCollectionName as k, dictKey as l, enforceScript as m, getAtPath as n, i18nText as o, inferScripts as p, isDictCollectionName as q, isDictKeyDescriptor as r, isI18nTextDescriptor as s, isStaticDictDescriptor as t, resolveI18nText as u, resolvePolicy as v, setAtPathInPlace as w, staticDict as x, validateI18nTextValue as y, type SessionStrategy as z };
|