@noy-db/hub 0.2.0-pre.4 → 0.2.0-pre.6
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.js +4 -4
- package/dist/attestation/index.cjs.map +1 -1
- package/dist/attestation/index.d.cts +4 -4
- package/dist/attestation/index.d.ts +4 -4
- package/dist/attestation/index.js +6 -6
- package/dist/blobs/index.cjs.map +1 -1
- package/dist/blobs/index.d.cts +5 -5
- package/dist/blobs/index.d.ts +5 -5
- package/dist/blobs/index.js +5 -5
- package/dist/bundle/index.cjs +496 -344
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +17 -17
- package/dist/bundle/index.d.ts +17 -17
- package/dist/bundle/index.js +10 -10
- package/dist/bundle/index.js.map +1 -1
- package/dist/{chunk-YL2DR3HY.js → chunk-25WFLKOH.js} +2 -2
- package/dist/chunk-25WFLKOH.js.map +1 -0
- package/dist/{chunk-EMEX37ZN.js → chunk-2GMRNNI3.js} +3 -3
- package/dist/chunk-2GMRNNI3.js.map +1 -0
- package/dist/{chunk-NGSPBLLE.js → chunk-34XGYMQT.js} +3 -3
- package/dist/chunk-34XGYMQT.js.map +1 -0
- package/dist/{chunk-FXQYZNOW.js → chunk-5OVIFUQE.js} +1 -1
- package/dist/chunk-5OVIFUQE.js.map +1 -0
- package/dist/{chunk-P6256WTJ.js → chunk-5QPF2MJ5.js} +3 -3
- package/dist/chunk-5QPF2MJ5.js.map +1 -0
- package/dist/{chunk-5ZGZ6HIZ.js → chunk-5VMTAX4Y.js} +2 -2
- package/dist/{chunk-74JEQFMT.js → chunk-6A4AMQ2H.js} +5 -5
- package/dist/chunk-6A4AMQ2H.js.map +1 -0
- package/dist/{chunk-YDLAFP36.js → chunk-6HJ2ZALB.js} +1 -1
- package/dist/chunk-6HJ2ZALB.js.map +1 -0
- package/dist/{chunk-GDTCGIPX.js → chunk-7TX7HN42.js} +2 -2
- package/dist/chunk-7TX7HN42.js.map +1 -0
- package/dist/{chunk-EPK6A3WJ.js → chunk-A3JMGXPG.js} +2 -2
- package/dist/chunk-A3JMGXPG.js.map +1 -0
- package/dist/{chunk-75QDHSE4.js → chunk-A4JNVBPF.js} +5 -5
- package/dist/{chunk-IS5HWQO7.js → chunk-ARZAHCCF.js} +3 -3
- package/dist/{chunk-4OQWR46B.js → chunk-CCC25PA7.js} +5 -5
- package/dist/{chunk-NSLTPGEN.js → chunk-CGJFCT3X.js} +2 -2
- package/dist/{chunk-YK72A4IT.js → chunk-CKH247ZR.js} +4 -4
- package/dist/{chunk-HGZ7DC5H.js → chunk-DFCINPB5.js} +2 -2
- package/dist/chunk-DFCINPB5.js.map +1 -0
- package/dist/{chunk-4X2S7PBF.js → chunk-E225X5CQ.js} +3 -3
- package/dist/chunk-E225X5CQ.js.map +1 -0
- package/dist/{chunk-5YHWBPOT.js → chunk-ED3E3OLO.js} +2 -2
- package/dist/{chunk-UOF74WQY.js → chunk-EKTOYEZ3.js} +2 -2
- package/dist/{chunk-SAVQ6E2O.js → chunk-G26QAQNI.js} +2 -2
- package/dist/{chunk-YMYK7US4.js → chunk-HIELMTUK.js} +2 -2
- package/dist/{chunk-MRIBLZL3.js → chunk-ICH4AIGL.js} +1 -1
- package/dist/chunk-ICH4AIGL.js.map +1 -0
- package/dist/{chunk-KMI2NBBF.js → chunk-JICBEFBT.js} +181 -6
- package/dist/chunk-JICBEFBT.js.map +1 -0
- package/dist/{chunk-LOL725S4.js → chunk-JSYTGEX4.js} +3 -3
- package/dist/{chunk-FBMXWVGP.js → chunk-KGFV72WK.js} +5 -5
- package/dist/{chunk-GVXBHCZ2.js → chunk-LJO6Q3X6.js} +5 -5
- package/dist/chunk-LJO6Q3X6.js.map +1 -0
- package/dist/{chunk-ZC2AAE6J.js → chunk-LWFQYT4N.js} +2 -2
- package/dist/chunk-LWFQYT4N.js.map +1 -0
- package/dist/{chunk-K5PVGKE4.js → chunk-MDIC4FAU.js} +2 -2
- package/dist/{chunk-ZUMGGHRB.js → chunk-OPD3PZOG.js} +4 -4
- package/dist/{chunk-LS3JLEIB.js → chunk-PS5G6A3Y.js} +4 -4
- package/dist/{chunk-KYKMKLJ6.js → chunk-PX3MJ6RB.js} +3 -3
- package/dist/{chunk-FCDO7UAO.js → chunk-R4LTCI6O.js} +2 -2
- package/dist/{chunk-BFI3RS42.js → chunk-R7JTYCRX.js} +2 -2
- package/dist/chunk-R7JTYCRX.js.map +1 -0
- package/dist/{chunk-WRLHNG6H.js → chunk-RIHZBSWJ.js} +4 -4
- package/dist/chunk-RIHZBSWJ.js.map +1 -0
- package/dist/{chunk-UVPGJXVO.js → chunk-SGSHQ4PH.js} +5 -5
- package/dist/{chunk-TLFUDXVV.js → chunk-T6MTNGBM.js} +5 -5
- package/dist/chunk-T6MTNGBM.js.map +1 -0
- package/dist/{chunk-6S3LLAQ5.js → chunk-TNBIWSQ7.js} +2 -2
- package/dist/{chunk-GD3BGKAR.js → chunk-UGVDIOY7.js} +2 -2
- package/dist/{chunk-T6HQMVML.js → chunk-W277AG6N.js} +411 -308
- package/dist/chunk-W277AG6N.js.map +1 -0
- package/dist/{chunk-FS7A4XNF.js → chunk-WEA4TDTJ.js} +3 -3
- package/dist/{chunk-4UBOTYP5.js → chunk-XDW37COG.js} +5 -5
- package/dist/chunk-XDW37COG.js.map +1 -0
- package/dist/{chunk-QAU5HM6Q.js → chunk-XVJFFGTG.js} +3 -3
- package/dist/{chunk-2EYC3WDT.js → chunk-Y3P5DEMZ.js} +6 -6
- package/dist/chunk-Y3P5DEMZ.js.map +1 -0
- package/dist/{chunk-G7PAZ3TD.js → chunk-YEHUEUNP.js} +4 -4
- package/dist/chunk-YEHUEUNP.js.map +1 -0
- package/dist/{chunk-2XLVPKXG.js → chunk-YJ46RFCD.js} +2 -2
- package/dist/{chunk-NCO2JGKK.js → chunk-Z6FNBOTC.js} +1 -1
- package/dist/chunk-Z6FNBOTC.js.map +1 -0
- package/dist/{chunk-GAUBWHAF.js → chunk-ZQMYB56Z.js} +4 -4
- package/dist/consent/index.cjs.map +1 -1
- package/dist/consent/index.d.cts +5 -5
- package/dist/consent/index.d.ts +5 -5
- package/dist/consent/index.js +3 -3
- package/dist/{crypto-H2Y3DDFW.js → crypto-5UDZZL26.js} +3 -3
- package/dist/{delegation-QSC7G5QC.js → delegation-42LO4WFO.js} +5 -5
- package/dist/derivations/index.cjs +1 -1
- package/dist/derivations/index.cjs.map +1 -1
- package/dist/derivations/index.d.cts +8 -8
- package/dist/derivations/index.d.ts +8 -8
- package/dist/derivations/index.js +4 -4
- package/dist/{dev-unlock-Cf2B7Kih.d.ts → dev-unlock-Cvo-xCQC.d.ts} +1 -1
- package/dist/{dev-unlock-De3mjQWv.d.cts → dev-unlock-Dy1qVpkL.d.cts} +1 -1
- package/dist/executor-AWCHQ2KN.js +8 -0
- package/dist/executor-RWICJI7J.js +11 -0
- package/dist/executor-SOLEQVUB.js +8 -0
- package/dist/{fanout-sidecar-NRBWSLRK.js → fanout-sidecar-EVICRM46.js} +2 -2
- package/dist/fanout-sidecar-EVICRM46.js.map +1 -0
- package/dist/guards/index.cjs +1 -1
- package/dist/guards/index.cjs.map +1 -1
- package/dist/guards/index.d.cts +6 -6
- package/dist/guards/index.d.ts +6 -6
- package/dist/guards/index.js +4 -4
- package/dist/{hash-gVn_uKhp.d.ts → hash-BAlWR4WD.d.ts} +1 -1
- package/dist/{hash-vBCB0-Ps.d.cts → hash-BgEQklQc.d.cts} +1 -1
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +6 -6
- package/dist/history/index.d.ts +6 -6
- package/dist/history/index.js +6 -6
- package/dist/i18n/index.cjs +75 -10
- package/dist/i18n/index.cjs.map +1 -1
- package/dist/i18n/index.d.cts +5 -5
- package/dist/i18n/index.d.ts +5 -5
- package/dist/i18n/index.js +16 -14
- package/dist/{index-DVkvrgpm.d.cts → index-5I0MZ0jQ.d.cts} +12 -12
- package/dist/{index-BF1B2HB9.d.ts → index-fIPPh5dg.d.ts} +12 -12
- package/dist/index.cjs +538 -378
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -22
- package/dist/index.d.ts +20 -22
- package/dist/index.js +50 -52
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.cjs +1 -1
- package/dist/indexing/index.cjs.map +1 -1
- package/dist/indexing/index.d.cts +3 -3
- package/dist/indexing/index.d.ts +3 -3
- package/dist/indexing/index.js +4 -4
- package/dist/issue-IODMTPME.js +12 -0
- package/dist/{lazy-builder-Rpd-V3jP.d.ts → lazy-builder-D1MyR1qH.d.ts} +2 -2
- package/dist/{lazy-builder-C-rPfWG0.d.cts → lazy-builder-DXlSCNCJ.d.cts} +2 -2
- package/dist/{ledger-WOEJUYTP.js → ledger-UX4QIHWI.js} +6 -6
- package/dist/materialized-views/index.cjs.map +1 -1
- package/dist/materialized-views/index.d.cts +18 -18
- package/dist/materialized-views/index.d.ts +18 -18
- package/dist/materialized-views/index.js +7 -7
- package/dist/noydb-FY2666NY.js +34 -0
- package/dist/overlay-views/index.cjs +1 -1
- package/dist/overlay-views/index.cjs.map +1 -1
- package/dist/overlay-views/index.d.cts +8 -8
- package/dist/overlay-views/index.d.ts +8 -8
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.cjs.map +1 -1
- package/dist/periods/index.d.cts +5 -5
- package/dist/periods/index.d.ts +5 -5
- package/dist/periods/index.js +6 -6
- package/dist/{predicate-Dnu81tsS.d.cts → predicate-B0IKeBXx.d.cts} +1 -1
- package/dist/{predicate-Dnu81tsS.d.ts → predicate-B0IKeBXx.d.ts} +1 -1
- package/dist/{public-envelope-OHQ5UZFM.js → public-envelope-YKHKP74C.js} +4 -4
- package/dist/query/index.cjs +2 -2
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +2 -2
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +6 -6
- package/dist/registry-446I2NMN.js +8 -0
- package/dist/{registry-CDHASH73.js → registry-4NEW7LQY.js} +3 -3
- package/dist/registry-524KJZG4.js +8 -0
- package/dist/registry-DKEXOJVO.js +7 -0
- package/dist/{revoke-7JOVLZFD.js → revoke-R5NIQ74J.js} +6 -6
- package/dist/session/index.cjs.map +1 -1
- package/dist/session/index.d.cts +6 -6
- package/dist/session/index.d.ts +6 -6
- package/dist/session/index.js +3 -3
- package/dist/shadow/index.cjs.map +1 -1
- package/dist/shadow/index.d.cts +5 -5
- package/dist/shadow/index.d.ts +5 -5
- package/dist/shadow/index.js +2 -2
- package/dist/{signer-M4K5HBLD.js → signer-WGDJNWSU.js} +5 -5
- package/dist/{stale-PAGCS4K5.js → stale-74WGLVZ2.js} +2 -2
- package/dist/store/index.cjs.map +1 -1
- package/dist/store/index.d.cts +5 -5
- package/dist/store/index.d.ts +5 -5
- package/dist/store/index.js +2 -2
- package/dist/sync/index.cjs.map +1 -1
- package/dist/sync/index.d.cts +4 -4
- package/dist/sync/index.d.ts +4 -4
- package/dist/sync/index.js +4 -4
- package/dist/team/index.cjs +1 -1
- package/dist/team/index.cjs.map +1 -1
- package/dist/team/index.d.cts +5 -5
- package/dist/team/index.d.ts +5 -5
- package/dist/team/index.js +8 -8
- package/dist/tx/index.cjs +2 -2
- package/dist/tx/index.cjs.map +1 -1
- package/dist/tx/index.d.cts +5 -5
- package/dist/tx/index.d.ts +5 -5
- package/dist/tx/index.js +3 -3
- package/dist/tx/index.js.map +1 -1
- package/dist/{types-CSLcfytP.d.cts → types-DVlvNn2c.d.cts} +362 -307
- package/dist/{types-D9eB0Rvh.d.ts → types-DlnZh1_i.d.ts} +362 -307
- package/dist/{ulid-CiM2OAeM.d.ts → ulid-CzPONlhG.d.ts} +19 -19
- package/dist/{ulid-CG2YvAbg.d.cts → ulid-r98nkjVd.d.cts} +19 -19
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.js +1 -1
- package/dist/{with-derivation-Bzpj6UTv.d.ts → with-derivation-B98shCV8.d.ts} +1 -1
- package/dist/{with-derivation-DWajFh4K.d.cts → with-derivation-BMQ9pIHe.d.cts} +1 -1
- package/dist/{with-guard-DF_Ul3DT.d.cts → with-guard-DUnC3JDN.d.cts} +1 -1
- package/dist/{with-guard-DR7U-l4v.d.ts → with-guard-DmT50nVG.d.ts} +1 -1
- package/dist/{with-materialized-view-qtoJ3xKJ.d.ts → with-materialized-view-Bp_M3sNG.d.ts} +2 -2
- package/dist/{with-materialized-view-_piodoIz.d.cts → with-materialized-view-eMTZ65_J.d.cts} +2 -2
- package/dist/{with-overlayed-view-DFaRfgMr.d.ts → with-overlayed-view-BoY6PB3n.d.cts} +2 -2
- package/dist/{with-overlayed-view-DwzCKxn2.d.cts → with-overlayed-view-zzSnRQmS.d.ts} +2 -2
- package/package.json +3 -3
- package/dist/chunk-2EYC3WDT.js.map +0 -1
- package/dist/chunk-4UBOTYP5.js.map +0 -1
- package/dist/chunk-4X2S7PBF.js.map +0 -1
- package/dist/chunk-74JEQFMT.js.map +0 -1
- package/dist/chunk-A6SWRXUQ.js +0 -118
- package/dist/chunk-A6SWRXUQ.js.map +0 -1
- package/dist/chunk-BFI3RS42.js.map +0 -1
- package/dist/chunk-EMEX37ZN.js.map +0 -1
- package/dist/chunk-EPK6A3WJ.js.map +0 -1
- package/dist/chunk-FXQYZNOW.js.map +0 -1
- package/dist/chunk-G7PAZ3TD.js.map +0 -1
- package/dist/chunk-GDTCGIPX.js.map +0 -1
- package/dist/chunk-GVXBHCZ2.js.map +0 -1
- package/dist/chunk-HGZ7DC5H.js.map +0 -1
- package/dist/chunk-KMI2NBBF.js.map +0 -1
- package/dist/chunk-MRIBLZL3.js.map +0 -1
- package/dist/chunk-NCO2JGKK.js.map +0 -1
- package/dist/chunk-NGSPBLLE.js.map +0 -1
- package/dist/chunk-P6256WTJ.js.map +0 -1
- package/dist/chunk-T6HQMVML.js.map +0 -1
- package/dist/chunk-TLFUDXVV.js.map +0 -1
- package/dist/chunk-WRLHNG6H.js.map +0 -1
- package/dist/chunk-YDLAFP36.js.map +0 -1
- package/dist/chunk-YL2DR3HY.js.map +0 -1
- package/dist/chunk-ZC2AAE6J.js.map +0 -1
- package/dist/executor-BZKFZVRC.js +0 -8
- package/dist/executor-GFZFDQXV.js +0 -8
- package/dist/executor-KT2IOZVP.js +0 -11
- package/dist/fanout-sidecar-NRBWSLRK.js.map +0 -1
- package/dist/issue-BAJ7ZB4S.js +0 -12
- package/dist/noydb-XNQSKXGO.js +0 -34
- package/dist/registry-2IEARCGT.js +0 -7
- package/dist/registry-EMGLZGR6.js +0 -8
- package/dist/registry-NQALYR77.js +0 -8
- /package/dist/{chunk-5ZGZ6HIZ.js.map → chunk-5VMTAX4Y.js.map} +0 -0
- /package/dist/{chunk-75QDHSE4.js.map → chunk-A4JNVBPF.js.map} +0 -0
- /package/dist/{chunk-IS5HWQO7.js.map → chunk-ARZAHCCF.js.map} +0 -0
- /package/dist/{chunk-4OQWR46B.js.map → chunk-CCC25PA7.js.map} +0 -0
- /package/dist/{chunk-NSLTPGEN.js.map → chunk-CGJFCT3X.js.map} +0 -0
- /package/dist/{chunk-YK72A4IT.js.map → chunk-CKH247ZR.js.map} +0 -0
- /package/dist/{chunk-5YHWBPOT.js.map → chunk-ED3E3OLO.js.map} +0 -0
- /package/dist/{chunk-UOF74WQY.js.map → chunk-EKTOYEZ3.js.map} +0 -0
- /package/dist/{chunk-SAVQ6E2O.js.map → chunk-G26QAQNI.js.map} +0 -0
- /package/dist/{chunk-YMYK7US4.js.map → chunk-HIELMTUK.js.map} +0 -0
- /package/dist/{chunk-LOL725S4.js.map → chunk-JSYTGEX4.js.map} +0 -0
- /package/dist/{chunk-FBMXWVGP.js.map → chunk-KGFV72WK.js.map} +0 -0
- /package/dist/{chunk-K5PVGKE4.js.map → chunk-MDIC4FAU.js.map} +0 -0
- /package/dist/{chunk-ZUMGGHRB.js.map → chunk-OPD3PZOG.js.map} +0 -0
- /package/dist/{chunk-LS3JLEIB.js.map → chunk-PS5G6A3Y.js.map} +0 -0
- /package/dist/{chunk-KYKMKLJ6.js.map → chunk-PX3MJ6RB.js.map} +0 -0
- /package/dist/{chunk-FCDO7UAO.js.map → chunk-R4LTCI6O.js.map} +0 -0
- /package/dist/{chunk-UVPGJXVO.js.map → chunk-SGSHQ4PH.js.map} +0 -0
- /package/dist/{chunk-6S3LLAQ5.js.map → chunk-TNBIWSQ7.js.map} +0 -0
- /package/dist/{chunk-GD3BGKAR.js.map → chunk-UGVDIOY7.js.map} +0 -0
- /package/dist/{chunk-FS7A4XNF.js.map → chunk-WEA4TDTJ.js.map} +0 -0
- /package/dist/{chunk-QAU5HM6Q.js.map → chunk-XVJFFGTG.js.map} +0 -0
- /package/dist/{chunk-2XLVPKXG.js.map → chunk-YJ46RFCD.js.map} +0 -0
- /package/dist/{chunk-GAUBWHAF.js.map → chunk-ZQMYB56Z.js.map} +0 -0
- /package/dist/{crypto-H2Y3DDFW.js.map → crypto-5UDZZL26.js.map} +0 -0
- /package/dist/{delegation-QSC7G5QC.js.map → delegation-42LO4WFO.js.map} +0 -0
- /package/dist/{executor-BZKFZVRC.js.map → executor-AWCHQ2KN.js.map} +0 -0
- /package/dist/{executor-GFZFDQXV.js.map → executor-RWICJI7J.js.map} +0 -0
- /package/dist/{executor-KT2IOZVP.js.map → executor-SOLEQVUB.js.map} +0 -0
- /package/dist/{issue-BAJ7ZB4S.js.map → issue-IODMTPME.js.map} +0 -0
- /package/dist/{ledger-WOEJUYTP.js.map → ledger-UX4QIHWI.js.map} +0 -0
- /package/dist/{noydb-XNQSKXGO.js.map → noydb-FY2666NY.js.map} +0 -0
- /package/dist/{public-envelope-OHQ5UZFM.js.map → public-envelope-YKHKP74C.js.map} +0 -0
- /package/dist/{registry-2IEARCGT.js.map → registry-446I2NMN.js.map} +0 -0
- /package/dist/{registry-CDHASH73.js.map → registry-4NEW7LQY.js.map} +0 -0
- /package/dist/{registry-EMGLZGR6.js.map → registry-524KJZG4.js.map} +0 -0
- /package/dist/{registry-NQALYR77.js.map → registry-DKEXOJVO.js.map} +0 -0
- /package/dist/{revoke-7JOVLZFD.js.map → revoke-R5NIQ74J.js.map} +0 -0
- /package/dist/{signer-M4K5HBLD.js.map → signer-WGDJNWSU.js.map} +0 -0
- /package/dist/{stale-PAGCS4K5.js.map → stale-74WGLVZ2.js.map} +0 -0
|
@@ -4,34 +4,36 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
TxContext,
|
|
6
6
|
revertExecuted
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LJO6Q3X6.js";
|
|
8
8
|
import {
|
|
9
9
|
OverlayedCollection
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-34XGYMQT.js";
|
|
11
11
|
import {
|
|
12
12
|
LazyQuery,
|
|
13
13
|
decodeIdxId,
|
|
14
14
|
encodeIdxId
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-RIHZBSWJ.js";
|
|
16
16
|
import {
|
|
17
17
|
SCHEMAS_COLLECTION,
|
|
18
18
|
loadPersistedSchema,
|
|
19
19
|
resolveManagedSecret,
|
|
20
20
|
savePersistedSchema,
|
|
21
21
|
saveSealedPassphrase
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-E225X5CQ.js";
|
|
23
23
|
import {
|
|
24
24
|
loadPublicEnvelope,
|
|
25
25
|
readPublicEnvelope,
|
|
26
26
|
savePublicEnvelope,
|
|
27
27
|
validatePublicEnvelopeInput
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-WEA4TDTJ.js";
|
|
29
29
|
import {
|
|
30
30
|
PERIODS_COLLECTION
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-ZQMYB56Z.js";
|
|
32
32
|
import {
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
getAtPath,
|
|
34
|
+
isDictCollectionName,
|
|
35
|
+
setAtPathInPlace
|
|
36
|
+
} from "./chunk-JICBEFBT.js";
|
|
35
37
|
import {
|
|
36
38
|
ManagedRecoveryNotEnrolledError,
|
|
37
39
|
PolicyDeniedError,
|
|
@@ -53,11 +55,11 @@ import {
|
|
|
53
55
|
saveShamirRecoveryEntries,
|
|
54
56
|
updateAuthenticator,
|
|
55
57
|
writeMagicLinkGrant
|
|
56
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-Y3P5DEMZ.js";
|
|
57
59
|
import {
|
|
58
60
|
assertTierAccess,
|
|
59
61
|
dekKey
|
|
60
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-TNBIWSQ7.js";
|
|
61
63
|
import {
|
|
62
64
|
USER_ENVELOPE_COLLECTION,
|
|
63
65
|
buildRecipientKeyringFile,
|
|
@@ -81,7 +83,7 @@ import {
|
|
|
81
83
|
rotateKeys,
|
|
82
84
|
saveUserEnvelope,
|
|
83
85
|
updateKeyringIdentity
|
|
84
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-T6MTNGBM.js";
|
|
85
87
|
import {
|
|
86
88
|
INDEXED_STORE_POLICY
|
|
87
89
|
} from "./chunk-2QR2PQTT.js";
|
|
@@ -91,30 +93,30 @@ import {
|
|
|
91
93
|
import {
|
|
92
94
|
LEDGER_COLLECTION,
|
|
93
95
|
LEDGER_DELTAS_COLLECTION
|
|
94
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-6A4AMQ2H.js";
|
|
95
97
|
import {
|
|
96
98
|
sha256Hex as sha256Hex2
|
|
97
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-Z6FNBOTC.js";
|
|
98
100
|
import {
|
|
99
101
|
NO_AGGREGATE,
|
|
100
102
|
Query,
|
|
101
103
|
ScanBuilder
|
|
102
|
-
} from "./chunk-
|
|
104
|
+
} from "./chunk-XDW37COG.js";
|
|
103
105
|
import {
|
|
104
106
|
EXPORT_AUDIT_COLLECTION,
|
|
105
107
|
createExportBlobsHandle,
|
|
106
108
|
runCompaction
|
|
107
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-JSYTGEX4.js";
|
|
108
110
|
import {
|
|
109
111
|
NOYDB_BACKUP_VERSION,
|
|
110
112
|
NOYDB_FORMAT_VERSION
|
|
111
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-5OVIFUQE.js";
|
|
112
114
|
import {
|
|
113
115
|
decrypt,
|
|
114
116
|
encrypt,
|
|
115
117
|
encryptDeterministic,
|
|
116
118
|
sha256Hex
|
|
117
|
-
} from "./chunk-
|
|
119
|
+
} from "./chunk-EKTOYEZ3.js";
|
|
118
120
|
import {
|
|
119
121
|
AlreadyElevatedError,
|
|
120
122
|
AttestationError,
|
|
@@ -141,7 +143,7 @@ import {
|
|
|
141
143
|
TierNotGrantedError,
|
|
142
144
|
TranslatorNotConfiguredError,
|
|
143
145
|
ValidationError
|
|
144
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-6HJ2ZALB.js";
|
|
145
147
|
|
|
146
148
|
// src/policy/storage.ts
|
|
147
149
|
var META_COLLECTION = "_meta";
|
|
@@ -644,7 +646,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
|
|
|
644
646
|
}
|
|
645
647
|
const sourceWithId = { ...source, id };
|
|
646
648
|
if (DerivationExecutor === null) {
|
|
647
|
-
({ DerivationExecutor } = await import("./executor-
|
|
649
|
+
({ DerivationExecutor } = await import("./executor-SOLEQVUB.js"));
|
|
648
650
|
}
|
|
649
651
|
const ctx = { vault: accessor.getReadOnlyFacade() };
|
|
650
652
|
const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx);
|
|
@@ -664,7 +666,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
|
|
|
664
666
|
}
|
|
665
667
|
if (out.kind === "array") {
|
|
666
668
|
console.warn(
|
|
667
|
-
`[derivation] unexpected array-shape output "${key}" in lazy resolve path; array-shape derivations require lifecycle: "eager"
|
|
669
|
+
`[derivation] unexpected array-shape output "${key}" in lazy resolve path; array-shape derivations require lifecycle: "eager".`
|
|
668
670
|
);
|
|
669
671
|
continue;
|
|
670
672
|
}
|
|
@@ -702,6 +704,7 @@ var Collection = class {
|
|
|
702
704
|
schemaUpdateGate;
|
|
703
705
|
schemaFence;
|
|
704
706
|
writeHooks;
|
|
707
|
+
subsystemBus;
|
|
705
708
|
activeTxId;
|
|
706
709
|
getDEK;
|
|
707
710
|
onDirty;
|
|
@@ -890,42 +893,14 @@ var Collection = class {
|
|
|
890
893
|
syncAdapter;
|
|
891
894
|
/** — consent-audit hook, no-op when no scope is active. */
|
|
892
895
|
onAccess;
|
|
893
|
-
/**
|
|
894
|
-
* accounting-period write guard. Called BEFORE any
|
|
895
|
-
* adapter write with:
|
|
896
|
-
* - `existing` — the prior envelope's `_ts` and decrypted record
|
|
897
|
-
* (or `null` if no prior envelope exists)
|
|
898
|
-
* - `incoming` — the record being written (or `null` for delete)
|
|
899
|
-
*
|
|
900
|
-
* Throws `PeriodClosedError` if either side falls inside a closed
|
|
901
|
-
* period. Installed by Vault; no-op when no period has been closed.
|
|
902
|
-
* Async so the Vault can lazy-load the period list from the
|
|
903
|
-
* adapter on first use.
|
|
904
|
-
*/
|
|
905
|
-
periodGuard;
|
|
906
|
-
/**
|
|
907
|
-
* Optional back-reference to the owning vault's guard registry + a
|
|
908
|
-
* read-only vault facade. When present, `Collection.put` and
|
|
909
|
-
* `Collection.delete` consult the registry for guards declared
|
|
910
|
-
* against this collection and run their `check` + `frozenFields`
|
|
911
|
-
* before the adapter write. Absent in unit tests that construct
|
|
912
|
-
* a Collection directly; production code always sets it via
|
|
913
|
-
* `Vault.collection()`.
|
|
914
|
-
*
|
|
915
|
-
* Typed structurally rather than as `Vault` to avoid a circular
|
|
916
|
-
* import (mirrors the `refEnforcer` / `joinResolver` pattern).
|
|
917
|
-
*/
|
|
918
|
-
guardSource;
|
|
919
896
|
/**
|
|
920
897
|
* Vault-internal hook for derivation dispatch. When set,
|
|
921
898
|
* `Collection.put` consults the registry after the source-write
|
|
922
899
|
* commits and writes derived outputs through `getCollection(name).put`.
|
|
923
|
-
* Same structural-interface pattern as `guardSource` to avoid a
|
|
924
|
-
* circular Vault import.
|
|
925
900
|
*/
|
|
926
901
|
derivationSource;
|
|
927
902
|
/**
|
|
928
|
-
* Vault-internal hook for materialized-view dispatch
|
|
903
|
+
* Vault-internal hook for materialized-view dispatch.
|
|
929
904
|
* Parallel to `derivationSource` — when set, `Collection.put` fires
|
|
930
905
|
* `MaterializedViewRegistry.onSourceWrite` after the source-write
|
|
931
906
|
* commits + after `dispatchDerivations` has run.
|
|
@@ -981,6 +956,7 @@ var Collection = class {
|
|
|
981
956
|
this.schemaUpdateGate = opts.schemaUpdateGate;
|
|
982
957
|
this.schemaFence = opts.schemaFence;
|
|
983
958
|
this.writeHooks = opts.writeHooks;
|
|
959
|
+
this.subsystemBus = opts.subsystemBus;
|
|
984
960
|
this.activeTxId = opts.activeTxId;
|
|
985
961
|
this.blobStrategy = opts.blobStrategy ?? NO_BLOBS;
|
|
986
962
|
this.aggregateStrategy = opts.aggregateStrategy ?? NO_AGGREGATE;
|
|
@@ -1005,8 +981,6 @@ var Collection = class {
|
|
|
1005
981
|
this.crdtMode = opts.crdt;
|
|
1006
982
|
this.syncAdapter = opts.syncAdapter;
|
|
1007
983
|
this.onAccess = opts.onAccess;
|
|
1008
|
-
this.periodGuard = opts.periodGuard;
|
|
1009
|
-
this.guardSource = opts.guardSource;
|
|
1010
984
|
this.derivationSource = opts.derivationSource;
|
|
1011
985
|
this.materializedViewSource = opts.materializedViewSource;
|
|
1012
986
|
this.tiers = opts.tiers && opts.tiers.length > 0 ? new Set(opts.tiers) : null;
|
|
@@ -1140,7 +1114,7 @@ var Collection = class {
|
|
|
1140
1114
|
}
|
|
1141
1115
|
}
|
|
1142
1116
|
if (this.materializedViewSource !== void 0) {
|
|
1143
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
1117
|
+
const { resolveStaleMVOnRead } = await import("./stale-74WGLVZ2.js");
|
|
1144
1118
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name);
|
|
1145
1119
|
}
|
|
1146
1120
|
let record;
|
|
@@ -1208,21 +1182,23 @@ var Collection = class {
|
|
|
1208
1182
|
}
|
|
1209
1183
|
/**
|
|
1210
1184
|
* Create or update a record. Runs inside the hub's write-queue tracker
|
|
1211
|
-
*
|
|
1185
|
+
* so `hub.writeQueue.pending` reflects this write.
|
|
1212
1186
|
*
|
|
1213
1187
|
* @param id Record identifier.
|
|
1214
1188
|
* @param record The record body (validated by the collection's schema
|
|
1215
1189
|
* if one was attached at `vault.collection(...)` time).
|
|
1216
1190
|
* @param options Optional metadata for audit + import workflows.
|
|
1217
1191
|
* `reason` is stamped onto the resulting ledger entry
|
|
1218
|
-
*
|
|
1192
|
+
* so audit consumers can filter via
|
|
1219
1193
|
* `entries.filter(e => e.reason?.startsWith('import:'))`.
|
|
1220
1194
|
*/
|
|
1221
1195
|
async put(id, record, options) {
|
|
1222
1196
|
await this.schemaUpdateGate?.assertWritable();
|
|
1223
1197
|
await this.schemaFence?.assertWritable(this.name);
|
|
1198
|
+
const hooksActive = this.#hooksActive();
|
|
1199
|
+
const busAfterPut = (this.subsystemBus?.hasHandlers("afterPut") ?? false) && !(this.subsystemBus?.dispatching ?? false);
|
|
1224
1200
|
let event;
|
|
1225
|
-
if (
|
|
1201
|
+
if (hooksActive || busAfterPut) {
|
|
1226
1202
|
const prior = await this.#priorForHook(id);
|
|
1227
1203
|
event = {
|
|
1228
1204
|
op: prior.record === null ? "create" : "update",
|
|
@@ -1237,23 +1213,26 @@ var Collection = class {
|
|
|
1237
1213
|
baseVersion: prior.version,
|
|
1238
1214
|
version: prior.version + 1
|
|
1239
1215
|
};
|
|
1240
|
-
await this.writeHooks.runBefore(event);
|
|
1216
|
+
if (hooksActive) await this.writeHooks.runBefore(event);
|
|
1241
1217
|
}
|
|
1242
1218
|
if (this.writeQueue) await this.writeQueue.track(() => this.putInternal(id, record, options));
|
|
1243
1219
|
else await this.putInternal(id, record, options);
|
|
1244
|
-
if (event)
|
|
1220
|
+
if (event) {
|
|
1221
|
+
if (hooksActive) await this.writeHooks.runAfter(event);
|
|
1222
|
+
if (busAfterPut) await this.subsystemBus.dispatch("afterPut", event);
|
|
1223
|
+
}
|
|
1245
1224
|
}
|
|
1246
|
-
/** @internal
|
|
1225
|
+
/** @internal — true when hooks should fire for this write (handlers exist, not re-entrant). */
|
|
1247
1226
|
#hooksActive() {
|
|
1248
1227
|
return this.writeHooks !== void 0 && this.writeHooks.hasHandlers && !this.writeHooks.suppressed;
|
|
1249
1228
|
}
|
|
1250
1229
|
/**
|
|
1251
|
-
* @internal
|
|
1230
|
+
* @internal — resolve the prior record for a hook's `before` and
|
|
1252
1231
|
* its version. Critically, this uses the SAME basis `putInternal` writes from
|
|
1253
1232
|
* (the in-memory cache in eager mode; lru-then-adapter in lazy) — NOT a fresh
|
|
1254
1233
|
* store read — so `baseVersion`/`version` match the version actually written.
|
|
1255
1234
|
* A separate store read would diverge once another tab has advanced the shared
|
|
1256
|
-
* store past this tab's cache, breaking
|
|
1235
|
+
* store past this tab's cache, breaking cross-tab conflict detection.
|
|
1257
1236
|
*/
|
|
1258
1237
|
async #priorForHook(id) {
|
|
1259
1238
|
if (this.lazy && this.lru) {
|
|
@@ -1275,52 +1254,28 @@ var Collection = class {
|
|
|
1275
1254
|
if (!hasWritePermission(this.keyring, this.name)) {
|
|
1276
1255
|
throw new ReadOnlyError();
|
|
1277
1256
|
}
|
|
1278
|
-
if (this.
|
|
1279
|
-
const registry = this.guardSource.registry();
|
|
1280
|
-
const guards = registry.guardsFor(this.name);
|
|
1281
|
-
if (guards.length > 0) {
|
|
1282
|
-
const existingEnv = await this.adapter.get(this.vault, this.name, id);
|
|
1283
|
-
let existingRecord = null;
|
|
1284
|
-
if (existingEnv) {
|
|
1285
|
-
try {
|
|
1286
|
-
existingRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
|
|
1287
|
-
} catch {
|
|
1288
|
-
existingRecord = null;
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
const incomingRecord = record;
|
|
1292
|
-
const ctx = {
|
|
1293
|
-
existing: existingRecord,
|
|
1294
|
-
vault: this.guardSource.readOnlyVault(),
|
|
1295
|
-
userId: this.keyring.userId,
|
|
1296
|
-
role: this.keyring.role
|
|
1297
|
-
};
|
|
1298
|
-
if (registry.isAmendmentActive()) {
|
|
1299
|
-
const vBefore = existingEnv?._v ?? 0;
|
|
1300
|
-
registry.collectChange(this.name, id, existingRecord, incomingRecord, vBefore, vBefore + 1);
|
|
1301
|
-
} else {
|
|
1302
|
-
await registry.runChecks(this.name, incomingRecord, ctx);
|
|
1303
|
-
const { GuardExecutor } = await import("./executor-BZKFZVRC.js");
|
|
1304
|
-
for (const g of guards) {
|
|
1305
|
-
await GuardExecutor.checkFrozenFields(g, id, existingRecord, incomingRecord);
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
}
|
|
1310
|
-
if (this.periodGuard !== void 0) {
|
|
1257
|
+
if (this.subsystemBus?.hasGateHandlers("beforePut")) {
|
|
1311
1258
|
const existingEnv = await this.adapter.get(this.vault, this.name, id);
|
|
1312
|
-
let
|
|
1259
|
+
let existingRecord = null;
|
|
1313
1260
|
if (existingEnv) {
|
|
1314
1261
|
try {
|
|
1315
|
-
|
|
1262
|
+
existingRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
|
|
1316
1263
|
} catch {
|
|
1317
|
-
|
|
1264
|
+
existingRecord = null;
|
|
1318
1265
|
}
|
|
1319
1266
|
}
|
|
1320
|
-
await this.
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1267
|
+
await this.subsystemBus.dispatchGate("beforePut", {
|
|
1268
|
+
op: existingEnv ? "update" : "create",
|
|
1269
|
+
vault: this.vault,
|
|
1270
|
+
collection: this.name,
|
|
1271
|
+
docId: id,
|
|
1272
|
+
incoming: record,
|
|
1273
|
+
existing: existingRecord,
|
|
1274
|
+
existingVersion: existingEnv?._v ?? 0,
|
|
1275
|
+
existingTs: existingEnv?._ts,
|
|
1276
|
+
userId: this.keyring.userId,
|
|
1277
|
+
role: this.keyring.role
|
|
1278
|
+
});
|
|
1324
1279
|
}
|
|
1325
1280
|
if (this.schema !== void 0) {
|
|
1326
1281
|
record = await validateSchemaInput(this.schema, record, `put(${id})`);
|
|
@@ -1329,7 +1284,9 @@ var Collection = class {
|
|
|
1329
1284
|
const obj = record;
|
|
1330
1285
|
for (const [field, descriptor] of Object.entries(this.i18nFields)) {
|
|
1331
1286
|
if (!descriptor.options.autoTranslate) continue;
|
|
1332
|
-
const
|
|
1287
|
+
const leafValues = getAtPath(obj, field);
|
|
1288
|
+
if (leafValues.length !== 1) continue;
|
|
1289
|
+
const value = leafValues[0];
|
|
1333
1290
|
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
1334
1291
|
const map = value;
|
|
1335
1292
|
const { languages, required } = descriptor.options;
|
|
@@ -1353,8 +1310,7 @@ var Collection = class {
|
|
|
1353
1310
|
this.name
|
|
1354
1311
|
);
|
|
1355
1312
|
}
|
|
1356
|
-
;
|
|
1357
|
-
record[field] = translated;
|
|
1313
|
+
setAtPathInPlace(obj, field, translated);
|
|
1358
1314
|
}
|
|
1359
1315
|
}
|
|
1360
1316
|
if (this.i18nPutValidator !== void 0) {
|
|
@@ -1506,7 +1462,7 @@ var Collection = class {
|
|
|
1506
1462
|
* Fire registered MV strategies whose dependency set includes this
|
|
1507
1463
|
* collection. Eager-mode MVs re-materialize inline via
|
|
1508
1464
|
* `MaterializedViewExecutor.refresh`; lazy / manual modes are
|
|
1509
|
-
* no-ops in the foundation
|
|
1465
|
+
* no-ops in the foundation; wired in the lazy-mode implementation.
|
|
1510
1466
|
*
|
|
1511
1467
|
* Skips entirely when the record being written is itself an
|
|
1512
1468
|
* MV-emitted row (carries `_materializedFrom`) — defensive guard
|
|
@@ -1529,7 +1485,7 @@ var Collection = class {
|
|
|
1529
1485
|
if (mode === "eager") {
|
|
1530
1486
|
if (executor === null) {
|
|
1531
1487
|
;
|
|
1532
|
-
({ MaterializedViewExecutor: executor } = await import("./executor-
|
|
1488
|
+
({ MaterializedViewExecutor: executor } = await import("./executor-RWICJI7J.js"));
|
|
1533
1489
|
}
|
|
1534
1490
|
await executor.refresh(reg, {
|
|
1535
1491
|
getCollection: (name) => this.materializedViewSource.getCollection(name),
|
|
@@ -1538,7 +1494,7 @@ var Collection = class {
|
|
|
1538
1494
|
});
|
|
1539
1495
|
} else if (mode === "lazy") {
|
|
1540
1496
|
if (staleHelpers === null) {
|
|
1541
|
-
staleHelpers = await import("./stale-
|
|
1497
|
+
staleHelpers = await import("./stale-74WGLVZ2.js");
|
|
1542
1498
|
}
|
|
1543
1499
|
staleHelpers.markMVStale(registry, reg.spec.name);
|
|
1544
1500
|
}
|
|
@@ -1567,7 +1523,7 @@ var Collection = class {
|
|
|
1567
1523
|
const mode = typeof spec.lifecycle === "string" ? spec.lifecycle : spec.lifecycle.mode;
|
|
1568
1524
|
if (mode === "eager") {
|
|
1569
1525
|
if (DerivationExecutor === null) {
|
|
1570
|
-
({ DerivationExecutor } = await import("./executor-
|
|
1526
|
+
({ DerivationExecutor } = await import("./executor-SOLEQVUB.js"));
|
|
1571
1527
|
}
|
|
1572
1528
|
const sourceWithId = { ...incoming, id };
|
|
1573
1529
|
const ctx = { vault: this.derivationSource.getReadOnlyFacade() };
|
|
@@ -1586,7 +1542,7 @@ var Collection = class {
|
|
|
1586
1542
|
const outputCollection = this.derivationSource.getCollection(outSpec.collection);
|
|
1587
1543
|
const txCtx = this.derivationSource.getActiveTxContext();
|
|
1588
1544
|
if (out.kind === "array") {
|
|
1589
|
-
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-
|
|
1545
|
+
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-EVICRM46.js");
|
|
1590
1546
|
const prior = await loadFanoutSidecar(
|
|
1591
1547
|
this.adapter,
|
|
1592
1548
|
this.vault,
|
|
@@ -1650,13 +1606,15 @@ var Collection = class {
|
|
|
1650
1606
|
}
|
|
1651
1607
|
/**
|
|
1652
1608
|
* Delete a record by ID. Runs inside the hub's write-queue tracker
|
|
1653
|
-
*
|
|
1609
|
+
* so `hub.writeQueue.pending` reflects this write.
|
|
1654
1610
|
*/
|
|
1655
1611
|
async delete(id) {
|
|
1656
1612
|
await this.schemaUpdateGate?.assertWritable();
|
|
1657
1613
|
await this.schemaFence?.assertWritable(this.name);
|
|
1614
|
+
const hooksActive = this.#hooksActive();
|
|
1615
|
+
const busAfterDelete = (this.subsystemBus?.hasHandlers("afterDelete") ?? false) && !(this.subsystemBus?.dispatching ?? false);
|
|
1658
1616
|
let event;
|
|
1659
|
-
if (
|
|
1617
|
+
if (hooksActive || busAfterDelete) {
|
|
1660
1618
|
const prior = await this.#priorForHook(id);
|
|
1661
1619
|
event = {
|
|
1662
1620
|
op: "delete",
|
|
@@ -1671,14 +1629,17 @@ var Collection = class {
|
|
|
1671
1629
|
baseVersion: prior.version,
|
|
1672
1630
|
version: prior.version + 1
|
|
1673
1631
|
};
|
|
1674
|
-
await this.writeHooks.runBefore(event);
|
|
1632
|
+
if (hooksActive) await this.writeHooks.runBefore(event);
|
|
1675
1633
|
}
|
|
1676
1634
|
if (this.writeQueue) await this.writeQueue.track(() => this.deleteInternal(id));
|
|
1677
1635
|
else await this.deleteInternal(id);
|
|
1678
|
-
if (event)
|
|
1636
|
+
if (event) {
|
|
1637
|
+
if (hooksActive) await this.writeHooks.runAfter(event);
|
|
1638
|
+
if (busAfterDelete) await this.subsystemBus.dispatch("afterDelete", event);
|
|
1639
|
+
}
|
|
1679
1640
|
}
|
|
1680
1641
|
/**
|
|
1681
|
-
* @internal
|
|
1642
|
+
* @internal — bulk-rewrite every record through a cutover transform.
|
|
1682
1643
|
* Raw adapter path (bypasses the write gate + guards — the transform is
|
|
1683
1644
|
* trusted and runs only during the `migrating` phase). Bumps each
|
|
1684
1645
|
* record's `_v` and appends a ledger `op:'migration'` entry.
|
|
@@ -1717,8 +1678,7 @@ var Collection = class {
|
|
|
1717
1678
|
}
|
|
1718
1679
|
/**
|
|
1719
1680
|
* @internal — system-internal delete that bypasses user-facing
|
|
1720
|
-
* delete hooks (`onDelete`,
|
|
1721
|
-
* enforcer). Used by derivation tombstones (#144) and MV refresh
|
|
1681
|
+
* delete hooks (`onDelete`, FK ref enforcer). Used by derivation tombstones and MV refresh
|
|
1722
1682
|
* (Dim 14 v2) — system housekeeping shouldn't trip user invariants
|
|
1723
1683
|
* registered against the output collection. The ledger entry and
|
|
1724
1684
|
* history snapshot still fire so backup integrity and time-travel
|
|
@@ -1730,7 +1690,7 @@ var Collection = class {
|
|
|
1730
1690
|
*
|
|
1731
1691
|
* When a `txCtx` is supplied, the prior envelope is captured and
|
|
1732
1692
|
* pushed onto `txCtx._executed` BEFORE the delete fires — mirrors
|
|
1733
|
-
* the
|
|
1693
|
+
* the rollback hardening for puts. Callers outside a
|
|
1734
1694
|
* multi-record transaction pass `null` and skip the tracking.
|
|
1735
1695
|
*
|
|
1736
1696
|
* Amendment composition: if `_internalDelete` runs while a vault's
|
|
@@ -1773,58 +1733,27 @@ var Collection = class {
|
|
|
1773
1733
|
if (!hasWritePermission(this.keyring, this.name)) {
|
|
1774
1734
|
throw new ReadOnlyError();
|
|
1775
1735
|
}
|
|
1776
|
-
if (this.
|
|
1777
|
-
const registry = this.guardSource.registry();
|
|
1778
|
-
const guards = registry.guardsFor(this.name);
|
|
1779
|
-
if (guards.length > 0) {
|
|
1780
|
-
const existingEnv = await this.adapter.get(this.vault, this.name, id);
|
|
1781
|
-
if (existingEnv) {
|
|
1782
|
-
let existingRecord = null;
|
|
1783
|
-
try {
|
|
1784
|
-
existingRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
|
|
1785
|
-
} catch {
|
|
1786
|
-
existingRecord = null;
|
|
1787
|
-
}
|
|
1788
|
-
if (registry.isAmendmentActive()) {
|
|
1789
|
-
const vBefore = existingEnv._v;
|
|
1790
|
-
registry.collectChange(
|
|
1791
|
-
this.name,
|
|
1792
|
-
id,
|
|
1793
|
-
existingRecord,
|
|
1794
|
-
null,
|
|
1795
|
-
vBefore,
|
|
1796
|
-
vBefore
|
|
1797
|
-
);
|
|
1798
|
-
} else if (!internal) {
|
|
1799
|
-
const ctx = {
|
|
1800
|
-
existing: existingRecord,
|
|
1801
|
-
vault: this.guardSource.readOnlyVault(),
|
|
1802
|
-
userId: this.keyring.userId,
|
|
1803
|
-
role: this.keyring.role
|
|
1804
|
-
};
|
|
1805
|
-
await registry.runOnDelete(
|
|
1806
|
-
this.name,
|
|
1807
|
-
existingRecord ?? {},
|
|
1808
|
-
ctx
|
|
1809
|
-
);
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
if (!internal && this.periodGuard !== void 0) {
|
|
1736
|
+
if (this.subsystemBus?.hasGateHandlers("beforeDelete")) {
|
|
1815
1737
|
const existingEnv = await this.adapter.get(this.vault, this.name, id);
|
|
1816
|
-
let priorRecord = null;
|
|
1817
1738
|
if (existingEnv) {
|
|
1739
|
+
let existingRecord = null;
|
|
1818
1740
|
try {
|
|
1819
|
-
|
|
1741
|
+
existingRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
|
|
1820
1742
|
} catch {
|
|
1821
|
-
|
|
1743
|
+
existingRecord = null;
|
|
1822
1744
|
}
|
|
1745
|
+
await this.subsystemBus.dispatchGate("beforeDelete", {
|
|
1746
|
+
vault: this.vault,
|
|
1747
|
+
collection: this.name,
|
|
1748
|
+
docId: id,
|
|
1749
|
+
existing: existingRecord,
|
|
1750
|
+
existingVersion: existingEnv._v,
|
|
1751
|
+
existingTs: existingEnv._ts,
|
|
1752
|
+
internal,
|
|
1753
|
+
userId: this.keyring.userId,
|
|
1754
|
+
role: this.keyring.role
|
|
1755
|
+
});
|
|
1823
1756
|
}
|
|
1824
|
-
await this.periodGuard(
|
|
1825
|
-
existingEnv ? { ts: existingEnv._ts, record: priorRecord } : null,
|
|
1826
|
-
null
|
|
1827
|
-
);
|
|
1828
1757
|
}
|
|
1829
1758
|
if (!internal && this.refEnforcer !== void 0) {
|
|
1830
1759
|
await this.refEnforcer.enforceRefsOnDelete(this.name, id);
|
|
@@ -1885,7 +1814,7 @@ var Collection = class {
|
|
|
1885
1814
|
}
|
|
1886
1815
|
/**
|
|
1887
1816
|
* Cascade deletes of array-shape derived rows when a source row is
|
|
1888
|
-
* deleted
|
|
1817
|
+
* deleted. Reads each registered strategy's fanout sidecar
|
|
1889
1818
|
* for this source id, deletes every listed derived row, then
|
|
1890
1819
|
* deletes the sidecar itself.
|
|
1891
1820
|
*
|
|
@@ -1905,7 +1834,7 @@ var Collection = class {
|
|
|
1905
1834
|
for (const [outputKey, outSpec] of Object.entries(spec.outputs)) {
|
|
1906
1835
|
if (outSpec.shape !== "array") continue;
|
|
1907
1836
|
if (helpers === null) {
|
|
1908
|
-
helpers = await import("./fanout-sidecar-
|
|
1837
|
+
helpers = await import("./fanout-sidecar-EVICRM46.js");
|
|
1909
1838
|
}
|
|
1910
1839
|
const sidecar = await helpers.loadFanoutSidecar(
|
|
1911
1840
|
this.adapter,
|
|
@@ -1924,8 +1853,8 @@ var Collection = class {
|
|
|
1924
1853
|
}
|
|
1925
1854
|
}
|
|
1926
1855
|
/**
|
|
1927
|
-
* Mirror of {@link dispatchMaterializedViews} for the delete path
|
|
1928
|
-
*
|
|
1856
|
+
* Mirror of {@link dispatchMaterializedViews} for the delete path.
|
|
1857
|
+
* No record content is available (it's gone), so the
|
|
1929
1858
|
* `_materializedFrom` skip used by the put-side dispatch doesn't
|
|
1930
1859
|
* apply here — instead, the recursion guard is the `internal` gate
|
|
1931
1860
|
* at the `_doDelete` call site above.
|
|
@@ -1945,7 +1874,7 @@ var Collection = class {
|
|
|
1945
1874
|
if (mode === "eager") {
|
|
1946
1875
|
if (executor === null) {
|
|
1947
1876
|
;
|
|
1948
|
-
({ MaterializedViewExecutor: executor } = await import("./executor-
|
|
1877
|
+
({ MaterializedViewExecutor: executor } = await import("./executor-RWICJI7J.js"));
|
|
1949
1878
|
}
|
|
1950
1879
|
await executor.refresh(reg, {
|
|
1951
1880
|
getCollection: (name) => this.materializedViewSource.getCollection(name),
|
|
@@ -1954,7 +1883,7 @@ var Collection = class {
|
|
|
1954
1883
|
});
|
|
1955
1884
|
} else if (mode === "lazy") {
|
|
1956
1885
|
if (staleHelpers === null) {
|
|
1957
|
-
staleHelpers = await import("./stale-
|
|
1886
|
+
staleHelpers = await import("./stale-74WGLVZ2.js");
|
|
1958
1887
|
}
|
|
1959
1888
|
staleHelpers.markMVStale(registry, reg.spec.name);
|
|
1960
1889
|
}
|
|
@@ -1977,7 +1906,7 @@ var Collection = class {
|
|
|
1977
1906
|
);
|
|
1978
1907
|
}
|
|
1979
1908
|
if (this.materializedViewSource !== void 0) {
|
|
1980
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
1909
|
+
const { resolveStaleMVOnRead } = await import("./stale-74WGLVZ2.js");
|
|
1981
1910
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name);
|
|
1982
1911
|
}
|
|
1983
1912
|
await this.ensureHydrated();
|
|
@@ -2455,7 +2384,7 @@ var Collection = class {
|
|
|
2455
2384
|
* .aggregate({ total: sum('amount'), n: count() })
|
|
2456
2385
|
* ```
|
|
2457
2386
|
*
|
|
2458
|
-
* **Lazy-MV gap
|
|
2387
|
+
* **Lazy-MV gap:** `scan()` is synchronous-build and does
|
|
2459
2388
|
* NOT trigger lazy materialized-view resolve-on-read. For lazy
|
|
2460
2389
|
* MVs, call `list()` (which DOES resolve) or `vault.refreshView(name)`
|
|
2461
2390
|
* before scanning. Same shape as the `query()` limitation.
|
|
@@ -2536,7 +2465,7 @@ var Collection = class {
|
|
|
2536
2465
|
this.indexes?.upsert(id, record, previous ? previous.record : null);
|
|
2537
2466
|
}
|
|
2538
2467
|
/**
|
|
2539
|
-
*
|
|
2468
|
+
* Apply a peer tab's committed write to THIS tab's in-memory view:
|
|
2540
2469
|
* re-read the (already-persisted) envelope from the shared store + refresh
|
|
2541
2470
|
* cache/indexes, then emit a `change` event so reactive consumers re-render.
|
|
2542
2471
|
* Never writes to the store and never fires write hooks, so it cannot loop.
|
|
@@ -2545,7 +2474,7 @@ var Collection = class {
|
|
|
2545
2474
|
await this._invalidateCacheEntry(id);
|
|
2546
2475
|
this.emitter.emit("change", { vault: this.vault, collection: this.name, id, action });
|
|
2547
2476
|
}
|
|
2548
|
-
/** @internal
|
|
2477
|
+
/** @internal — the current in-memory record without a store read (for conflict capture). */
|
|
2549
2478
|
_peekCached(id) {
|
|
2550
2479
|
const entry = this.lazy && this.lru ? this.lru.get(id) : this.cache.get(id);
|
|
2551
2480
|
return entry ? entry.record : null;
|
|
@@ -3648,7 +3577,7 @@ var UserApi = class {
|
|
|
3648
3577
|
* the envelope on first call. Optimistic-concurrency safe — a stale
|
|
3649
3578
|
* `_v` (parallel writer on another device) throws `ConflictError`.
|
|
3650
3579
|
*
|
|
3651
|
-
* Patch semantics
|
|
3580
|
+
* Patch semantics:
|
|
3652
3581
|
* - `undefined` (or omitted key) — skip; existing value preserved
|
|
3653
3582
|
* - `null` — delete the field from the merged result
|
|
3654
3583
|
* - any other value — overwrite (deep-merge for plain objects,
|
|
@@ -3704,7 +3633,7 @@ var UserApi = class {
|
|
|
3704
3633
|
this.fireChange(this.writerKeyringId, written);
|
|
3705
3634
|
return written;
|
|
3706
3635
|
}
|
|
3707
|
-
// ─── Visibility
|
|
3636
|
+
// ─── Visibility ──────────────────────────────────────────────────────
|
|
3708
3637
|
/**
|
|
3709
3638
|
* Read the current user's visibility flag from
|
|
3710
3639
|
* `_meta/visibility/<keyringId>`. Returns `{ hidden: false }` when no
|
|
@@ -4554,23 +4483,23 @@ var Vault = class {
|
|
|
4554
4483
|
* `null` for vaults that never register any guard strategy. The
|
|
4555
4484
|
* runtime class is dynamic-imported on demand so consumers that
|
|
4556
4485
|
* never use guards don't pull `GuardRegistry`/`GuardExecutor` into
|
|
4557
|
-
* their bundle
|
|
4486
|
+
* their bundle.
|
|
4558
4487
|
*/
|
|
4559
4488
|
guardRegistry = null;
|
|
4560
4489
|
/**
|
|
4561
4490
|
* Per-vault derivation registry. Same lazy-load contract as
|
|
4562
4491
|
* `guardRegistry` — `null` until `_initDerivations()` runs with at
|
|
4563
|
-
* least one strategy handle.
|
|
4492
|
+
* least one strategy handle.
|
|
4564
4493
|
*/
|
|
4565
4494
|
derivationRegistry = null;
|
|
4566
4495
|
/**
|
|
4567
|
-
* Per-vault materialized-view registry
|
|
4496
|
+
* Per-vault materialized-view registry. Same lazy-load
|
|
4568
4497
|
* contract as `derivationRegistry` — `null` until
|
|
4569
4498
|
* `_initMaterializedViews()` runs with at least one MV handle.
|
|
4570
4499
|
*/
|
|
4571
4500
|
materializedViewRegistry = null;
|
|
4572
4501
|
/**
|
|
4573
|
-
* Per-vault overlay registry
|
|
4502
|
+
* Per-vault overlay registry. Same lazy-load contract as
|
|
4574
4503
|
* `materializedViewRegistry` — `null` until `_initOverlayedViews()`
|
|
4575
4504
|
* runs with at least one handle.
|
|
4576
4505
|
*/
|
|
@@ -4591,7 +4520,7 @@ var Vault = class {
|
|
|
4591
4520
|
* target this vault session's keyringId. There is no method to write
|
|
4592
4521
|
* another principal's envelope (own-only write rule, structural).
|
|
4593
4522
|
* - Read-anyone: `get(keyringId)`, `list()` — read other principals'
|
|
4594
|
-
* envelopes, subject to the `view-team-profiles` policy gate
|
|
4523
|
+
* envelopes, subject to the `view-team-profiles` policy gate.
|
|
4595
4524
|
* - Reactive: `subscribe(id, cb)`, `live(id)` — fire on local writes.
|
|
4596
4525
|
*
|
|
4597
4526
|
* @see docs/superpowers/specs/2026-05-05-user-envelope-design.md
|
|
@@ -4611,12 +4540,12 @@ var Vault = class {
|
|
|
4611
4540
|
*/
|
|
4612
4541
|
reloadKeyring;
|
|
4613
4542
|
collectionCache = /* @__PURE__ */ new Map();
|
|
4614
|
-
/**
|
|
4543
|
+
/** Vault-level schema cutover fence/controller. */
|
|
4615
4544
|
schemaFence;
|
|
4616
|
-
/**
|
|
4545
|
+
/** Per-client heartbeat/watcher; started lazily on cutover registration. */
|
|
4617
4546
|
#fenceWatcher;
|
|
4618
4547
|
#fenceCoordinationStarted = false;
|
|
4619
|
-
/**
|
|
4548
|
+
/** Per-collection registered schema-update strategy names. */
|
|
4620
4549
|
#schemaUpdateNames = /* @__PURE__ */ new Map();
|
|
4621
4550
|
/**
|
|
4622
4551
|
* per-collection `blobFields` retention/TTL config.
|
|
@@ -4690,8 +4619,7 @@ var Vault = class {
|
|
|
4690
4619
|
* Cache of closed/opened accounting periods.
|
|
4691
4620
|
* Populated on first `closePeriod` / `openPeriod` / `listPeriods` /
|
|
4692
4621
|
* per-collection write call. Kept in memory as an ordered list (by
|
|
4693
|
-
* `closedAt`) so
|
|
4694
|
-
* each collection's put/delete path.
|
|
4622
|
+
* `closedAt`) so period checks run fast when the gate bus fires.
|
|
4695
4623
|
*
|
|
4696
4624
|
* Sentinel `null` means "not yet loaded" — the first consumer
|
|
4697
4625
|
* triggers a one-time `loadPeriods()` pass. Every subsequent
|
|
@@ -4886,6 +4814,7 @@ var Vault = class {
|
|
|
4886
4814
|
emitter: this.emitter,
|
|
4887
4815
|
writeQueue: this.noydb._writeQueueTracker,
|
|
4888
4816
|
writeHooks: this.noydb._writeHooks,
|
|
4817
|
+
subsystemBus: this.noydb._subsystemBus,
|
|
4889
4818
|
activeTxId: () => this.noydb._activeTxContextOrNull?.txId ?? null,
|
|
4890
4819
|
schemaUpdateGate,
|
|
4891
4820
|
schemaFence: this.schemaFence,
|
|
@@ -4908,18 +4837,12 @@ var Vault = class {
|
|
|
4908
4837
|
defaultLocale: this.locale,
|
|
4909
4838
|
onRegisterConflictResolver: this.onRegisterConflictResolver,
|
|
4910
4839
|
onAccess: (op, id) => this._logConsent(op, collectionName, id),
|
|
4911
|
-
|
|
4912
|
-
// Guard
|
|
4913
|
-
//
|
|
4914
|
-
//
|
|
4915
|
-
// `if (this.
|
|
4916
|
-
//
|
|
4917
|
-
...this.guardRegistry !== null ? {
|
|
4918
|
-
guardSource: {
|
|
4919
|
-
registry: () => this.guardRegistry,
|
|
4920
|
-
readOnlyVault: () => this._ensureReadOnlyFacade()
|
|
4921
|
-
}
|
|
4922
|
-
} : {},
|
|
4840
|
+
// Derivation source is only wired when the corresponding registry
|
|
4841
|
+
// has been initialised. Guard source was removed in Track A slice 3b
|
|
4842
|
+
// — guards now run via the gate bus in Noydb.#registerGuardGate.
|
|
4843
|
+
// Vaults without derivations skip this so `Collection.put`'s
|
|
4844
|
+
// `if (this.derivationSource)` branch no-ops without touching the
|
|
4845
|
+
// derivation subsystem code.
|
|
4923
4846
|
...this.derivationRegistry !== null ? {
|
|
4924
4847
|
derivationSource: {
|
|
4925
4848
|
registry: () => this.derivationRegistry,
|
|
@@ -5009,7 +4932,7 @@ var Vault = class {
|
|
|
5009
4932
|
await Promise.allSettled(pending);
|
|
5010
4933
|
}
|
|
5011
4934
|
/**
|
|
5012
|
-
* Run a coordinated schema cutover
|
|
4935
|
+
* Run a coordinated schema cutover. Drains pending writes, waits
|
|
5013
4936
|
* for the active client set to quiesce (the ack-barrier), applies every
|
|
5014
4937
|
* pending collection transform in bulk, bumps the vault schema generation,
|
|
5015
4938
|
* and clears the fence. Returns the count of collections migrated.
|
|
@@ -5027,9 +4950,9 @@ var Vault = class {
|
|
|
5027
4950
|
await coll._applyCutoverTransform(transform);
|
|
5028
4951
|
}
|
|
5029
4952
|
/**
|
|
5030
|
-
*
|
|
4953
|
+
* Refresh a loaded collection's view of one document from a peer
|
|
5031
4954
|
* tab's broadcast. No-op when the collection isn't loaded in this tab
|
|
5032
|
-
* (it will read fresh on next open). Mirrors
|
|
4955
|
+
* (it will read fresh on next open). Mirrors `#runCutoverTransform`'s guard.
|
|
5033
4956
|
*/
|
|
5034
4957
|
async _applyRemoteWrite(collectionName, docId, action) {
|
|
5035
4958
|
const coll = this.collectionCache.get(collectionName);
|
|
@@ -5037,9 +4960,9 @@ var Vault = class {
|
|
|
5037
4960
|
await coll._applyRemoteChange(docId, action);
|
|
5038
4961
|
}
|
|
5039
4962
|
/**
|
|
5040
|
-
*
|
|
4963
|
+
* For a detected conflict: capture this tab's clobbered record,
|
|
5041
4964
|
* read the common ancestor from history, converge the cache to the store's
|
|
5042
|
-
* authoritative value (the
|
|
4965
|
+
* authoritative value (the re-read), and return all three for the
|
|
5043
4966
|
* WriteConflict payload. Returns null when the collection isn't loaded.
|
|
5044
4967
|
*/
|
|
5045
4968
|
async _captureAndConverge(collectionName, docId, action, baseV) {
|
|
@@ -5056,15 +4979,15 @@ var Vault = class {
|
|
|
5056
4979
|
const remote = await coll.get(docId);
|
|
5057
4980
|
return { local, remote, base };
|
|
5058
4981
|
}
|
|
5059
|
-
/** Recover a stuck cutover fence
|
|
4982
|
+
/** Recover a stuck cutover fence — reset to normal without bumping. */
|
|
5060
4983
|
async abortSchemaCutover() {
|
|
5061
4984
|
await this.schemaFence.abort();
|
|
5062
4985
|
}
|
|
5063
|
-
/** Current schema-cutover fence state for this vault
|
|
4986
|
+
/** Current schema-cutover fence state for this vault. Thin live read. */
|
|
5064
4987
|
async schemaFenceState() {
|
|
5065
4988
|
return loadFence(this.adapter, this.name);
|
|
5066
4989
|
}
|
|
5067
|
-
/** @internal Start the per-client heartbeat + fence watcher once a cutover is registered
|
|
4990
|
+
/** @internal Start the per-client heartbeat + fence watcher once a cutover is registered. */
|
|
5068
4991
|
_ensureFenceCoordination() {
|
|
5069
4992
|
if (this.#fenceCoordinationStarted) return;
|
|
5070
4993
|
this.#fenceCoordinationStarted = true;
|
|
@@ -5100,9 +5023,11 @@ var Vault = class {
|
|
|
5100
5023
|
if (!record || typeof record !== "object") return;
|
|
5101
5024
|
const obj = record;
|
|
5102
5025
|
for (const [field, descriptor] of Object.entries(i18nFields)) {
|
|
5103
|
-
const
|
|
5104
|
-
|
|
5105
|
-
|
|
5026
|
+
const values = getAtPath(obj, field);
|
|
5027
|
+
for (const value of values) {
|
|
5028
|
+
if (value === void 0 || value === null) continue;
|
|
5029
|
+
this.i18nStrategy.validateI18nTextValue(value, field, descriptor);
|
|
5030
|
+
}
|
|
5106
5031
|
}
|
|
5107
5032
|
}
|
|
5108
5033
|
/**
|
|
@@ -5414,12 +5339,12 @@ var Vault = class {
|
|
|
5414
5339
|
if (!fieldSchema) {
|
|
5415
5340
|
throw new AttestationError(`issueAttestation: collection '${collectionName}' has no attestation field-schema. Declare it via vault.collection('${collectionName}', { attestation: { fields: [...] } }).`);
|
|
5416
5341
|
}
|
|
5417
|
-
const { issueAttestationCore } = await import("./issue-
|
|
5342
|
+
const { issueAttestationCore } = await import("./issue-IODMTPME.js");
|
|
5418
5343
|
const out = await issueAttestationCore(this.makeIssueContext(), { collection: collectionName, id, fieldSchema });
|
|
5419
5344
|
return { docId: out.docId, qr: out.qr, keyId: out.keyId, publicKeyB64: out.publicKeyB64 };
|
|
5420
5345
|
}
|
|
5421
5346
|
async getDocumentSigningPublicKey() {
|
|
5422
|
-
const { loadSigner, loadOrCreateSigner } = await import("./signer-
|
|
5347
|
+
const { loadSigner, loadOrCreateSigner } = await import("./signer-WGDJNWSU.js");
|
|
5423
5348
|
const existing = await loadSigner(this.adapter, this.name, this.getDEK);
|
|
5424
5349
|
if (existing) return { keyId: existing.keyId, publicKeyB64: existing.publicKeyB64 };
|
|
5425
5350
|
if (this.keyring.role !== "owner") {
|
|
@@ -5445,19 +5370,19 @@ var Vault = class {
|
|
|
5445
5370
|
};
|
|
5446
5371
|
}
|
|
5447
5372
|
async revokeAttestation(docId) {
|
|
5448
|
-
const { revokeDocCore } = await import("./revoke-
|
|
5373
|
+
const { revokeDocCore } = await import("./revoke-R5NIQ74J.js");
|
|
5449
5374
|
await revokeDocCore(this.makeRevokeContext(), docId);
|
|
5450
5375
|
}
|
|
5451
5376
|
async unrevokeAttestation(docId) {
|
|
5452
|
-
const { unrevokeDocCore } = await import("./revoke-
|
|
5377
|
+
const { unrevokeDocCore } = await import("./revoke-R5NIQ74J.js");
|
|
5453
5378
|
await unrevokeDocCore(this.makeRevokeContext(), docId);
|
|
5454
5379
|
}
|
|
5455
5380
|
async getRevokedDocIds() {
|
|
5456
|
-
const { getRevokedDocIdsCore } = await import("./revoke-
|
|
5381
|
+
const { getRevokedDocIdsCore } = await import("./revoke-R5NIQ74J.js");
|
|
5457
5382
|
return getRevokedDocIdsCore(this.makeRevokeContext());
|
|
5458
5383
|
}
|
|
5459
5384
|
async publishRevocationList() {
|
|
5460
|
-
const { publishRevocationListCore } = await import("./revoke-
|
|
5385
|
+
const { publishRevocationListCore } = await import("./revoke-R5NIQ74J.js");
|
|
5461
5386
|
return publishRevocationListCore(this.makeRevokeContext());
|
|
5462
5387
|
}
|
|
5463
5388
|
makeRevokeContext() {
|
|
@@ -5737,7 +5662,7 @@ var Vault = class {
|
|
|
5737
5662
|
* Dynamic-imports `GuardRegistry` + `ReadOnlyVaultFacade` and seeds
|
|
5738
5663
|
* the registry with the supplied strategy handles. No-op when the
|
|
5739
5664
|
* handles array is empty — keeps the guard subsystem out of the
|
|
5740
|
-
* floor bundle for consumers that don't use guards
|
|
5665
|
+
* floor bundle for consumers that don't use guards.
|
|
5741
5666
|
*
|
|
5742
5667
|
* The read-only facade is eagerly instantiated here so the sync
|
|
5743
5668
|
* accessor `_getReadOnlyFacade()` (called from the tx amendment
|
|
@@ -5746,7 +5671,7 @@ var Vault = class {
|
|
|
5746
5671
|
async _initGuards(handles) {
|
|
5747
5672
|
if (handles.length === 0) return;
|
|
5748
5673
|
const [{ GuardRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
|
|
5749
|
-
import("./registry-
|
|
5674
|
+
import("./registry-DKEXOJVO.js"),
|
|
5750
5675
|
import("./read-only-facade-ITU6L7BL.js")
|
|
5751
5676
|
]);
|
|
5752
5677
|
const registry = new GuardRegistry();
|
|
@@ -5755,10 +5680,9 @@ var Vault = class {
|
|
|
5755
5680
|
this.readOnlyFacade = new ReadOnlyVaultFacade(this);
|
|
5756
5681
|
}
|
|
5757
5682
|
/**
|
|
5758
|
-
* @internal —
|
|
5759
|
-
* vaults that never registered any guard
|
|
5760
|
-
* gate on null
|
|
5761
|
-
* `Collection` already do this transitively).
|
|
5683
|
+
* @internal — The gate handler in Noydb.#registerGuardGate calls into
|
|
5684
|
+
* this. Returns `null` for vaults that never registered any guard
|
|
5685
|
+
* strategy. Callers MUST gate on null.
|
|
5762
5686
|
*/
|
|
5763
5687
|
_getGuardRegistry() {
|
|
5764
5688
|
return this.guardRegistry;
|
|
@@ -5769,13 +5693,13 @@ var Vault = class {
|
|
|
5769
5693
|
* derivation strategies (async because `strategyHash` computation
|
|
5770
5694
|
* goes through `crypto.subtle.digest`). No-op when the handles
|
|
5771
5695
|
* array is empty — keeps the derivation subsystem out of the floor
|
|
5772
|
-
* bundle for consumers that don't use derivations
|
|
5696
|
+
* bundle for consumers that don't use derivations. Throws
|
|
5773
5697
|
* `DerivationCycleError` if a cycle is detected after registration.
|
|
5774
5698
|
*/
|
|
5775
5699
|
async _initDerivations(handles) {
|
|
5776
5700
|
if (handles.length === 0) return;
|
|
5777
5701
|
const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
|
|
5778
|
-
import("./registry-
|
|
5702
|
+
import("./registry-446I2NMN.js"),
|
|
5779
5703
|
import("./read-only-facade-ITU6L7BL.js")
|
|
5780
5704
|
]);
|
|
5781
5705
|
const registry = new DerivationRegistry();
|
|
@@ -5801,12 +5725,12 @@ var Vault = class {
|
|
|
5801
5725
|
* MV spec (which invokes its `query()` once for dependency
|
|
5802
5726
|
* analysis), then runs the unified cycle detection across the MV +
|
|
5803
5727
|
* derivation graphs. No-op when the handles array is empty — keeps
|
|
5804
|
-
* the MV subsystem out of the floor bundle (mirrors
|
|
5728
|
+
* the MV subsystem out of the floor bundle (mirrors the derivation lazy-import pattern).
|
|
5805
5729
|
* Throws `MaterializedViewCycleError` if a cycle is detected.
|
|
5806
5730
|
*/
|
|
5807
5731
|
async _initMaterializedViews(handles) {
|
|
5808
5732
|
if (handles.length === 0) return;
|
|
5809
|
-
const { MaterializedViewRegistry } = await import("./registry-
|
|
5733
|
+
const { MaterializedViewRegistry } = await import("./registry-4NEW7LQY.js");
|
|
5810
5734
|
const registry = new MaterializedViewRegistry();
|
|
5811
5735
|
this.materializedViewRegistry = registry;
|
|
5812
5736
|
const db = this;
|
|
@@ -5830,7 +5754,7 @@ var Vault = class {
|
|
|
5830
5754
|
*/
|
|
5831
5755
|
async _initOverlayedViews(handles) {
|
|
5832
5756
|
if (handles.length === 0) return;
|
|
5833
|
-
const { OverlayedViewRegistry } = await import("./registry-
|
|
5757
|
+
const { OverlayedViewRegistry } = await import("./registry-524KJZG4.js");
|
|
5834
5758
|
const registry = new OverlayedViewRegistry();
|
|
5835
5759
|
const mvRegistry = this.materializedViewRegistry;
|
|
5836
5760
|
const overlayNames = /* @__PURE__ */ new Set();
|
|
@@ -5858,13 +5782,13 @@ var Vault = class {
|
|
|
5858
5782
|
return this.overlayedViewRegistry;
|
|
5859
5783
|
}
|
|
5860
5784
|
/**
|
|
5861
|
-
* Manual re-materialize for a single registered MV
|
|
5785
|
+
* Manual re-materialize for a single registered MV. Useful
|
|
5862
5786
|
* for `refresh: 'manual'` MVs (whose consumer drives refreshes
|
|
5863
5787
|
* externally), for stale-bit recovery on vault re-open, and as the
|
|
5864
5788
|
* explicit bulk-recompute escape hatch after a strategy change.
|
|
5865
5789
|
*
|
|
5866
|
-
* Returns `{ written, deleted, failed }`. `deleted` is always 0
|
|
5867
|
-
*
|
|
5790
|
+
* Returns `{ written, deleted, failed }`. `deleted` is always 0
|
|
5791
|
+
* when tombstoning is not enabled.
|
|
5868
5792
|
*
|
|
5869
5793
|
* Throws if `name` is not a registered MV.
|
|
5870
5794
|
*/
|
|
@@ -5877,13 +5801,13 @@ var Vault = class {
|
|
|
5877
5801
|
if (!reg) {
|
|
5878
5802
|
throw new Error(`refreshView: no MV registered with name "${name}"`);
|
|
5879
5803
|
}
|
|
5880
|
-
const { MaterializedViewExecutor } = await import("./executor-
|
|
5804
|
+
const { MaterializedViewExecutor } = await import("./executor-RWICJI7J.js");
|
|
5881
5805
|
const result = await MaterializedViewExecutor.refresh(reg, {
|
|
5882
5806
|
getCollection: (n) => this.collection(n),
|
|
5883
5807
|
getActiveTxContext: () => this.noydb._activeTxContextOrNull,
|
|
5884
5808
|
getQueryContext: () => this
|
|
5885
5809
|
});
|
|
5886
|
-
const { clearMVStale } = await import("./stale-
|
|
5810
|
+
const { clearMVStale } = await import("./stale-74WGLVZ2.js");
|
|
5887
5811
|
clearMVStale(registry, name);
|
|
5888
5812
|
return result;
|
|
5889
5813
|
}
|
|
@@ -5899,7 +5823,7 @@ var Vault = class {
|
|
|
5899
5823
|
if (registry === null) return { derived: 0, failed: 0 };
|
|
5900
5824
|
const strategies = registry.strategiesForSource(sourceCollection);
|
|
5901
5825
|
if (strategies.length === 0) return { derived: 0, failed: 0 };
|
|
5902
|
-
const { DerivationExecutor } = await import("./executor-
|
|
5826
|
+
const { DerivationExecutor } = await import("./executor-SOLEQVUB.js");
|
|
5903
5827
|
const sourceColl = this.collection(sourceCollection);
|
|
5904
5828
|
const records = await sourceColl.list();
|
|
5905
5829
|
const ctx = { vault: this.readOnlyFacade ?? new (await import("./read-only-facade-ITU6L7BL.js")).ReadOnlyVaultFacade(this) };
|
|
@@ -5924,7 +5848,7 @@ var Vault = class {
|
|
|
5924
5848
|
if (!outSpec) continue;
|
|
5925
5849
|
const outputColl = this.collection(outSpec.collection);
|
|
5926
5850
|
if (out.kind === "array") {
|
|
5927
|
-
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-
|
|
5851
|
+
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-EVICRM46.js");
|
|
5928
5852
|
const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key);
|
|
5929
5853
|
const prevKeys = new Set(prior?.keys ?? []);
|
|
5930
5854
|
const newKeysList = out.entries.map((e) => e.key);
|
|
@@ -5960,22 +5884,19 @@ var Vault = class {
|
|
|
5960
5884
|
/**
|
|
5961
5885
|
* @internal — exposed for `runTransaction({ amendment: true })` so
|
|
5962
5886
|
* the amendment invariant runner can pass the SAME read-only vault
|
|
5963
|
-
* facade that the
|
|
5964
|
-
*
|
|
5965
|
-
* `
|
|
5966
|
-
*
|
|
5967
|
-
*
|
|
5887
|
+
* facade that the gate handler in Noydb.#registerGuardGate uses.
|
|
5888
|
+
* Eagerly instantiated by `_initGuards()` so this accessor stays
|
|
5889
|
+
* synchronous; returns `null` for vaults that never registered any
|
|
5890
|
+
* guard (amendments require at least one guard, so the caller should
|
|
5891
|
+
* never see null).
|
|
5968
5892
|
*/
|
|
5969
5893
|
_getReadOnlyFacade() {
|
|
5970
5894
|
return this.readOnlyFacade;
|
|
5971
5895
|
}
|
|
5972
5896
|
/**
|
|
5973
|
-
* Internal lazy-allocator for the read-only facade. Used
|
|
5974
|
-
*
|
|
5975
|
-
*
|
|
5976
|
-
* invocation (theoretically impossible — `Noydb.openVault` awaits
|
|
5977
|
-
* `_initGuards` before returning — but we keep the defensive lazy
|
|
5978
|
-
* path so the closure's contract stays "always returns a facade").
|
|
5897
|
+
* Internal lazy-allocator for the read-only facade. Used as a
|
|
5898
|
+
* defensive fallback; in practice `_initGuards()` eagerly
|
|
5899
|
+
* instantiates this, so the lazy path is a no-op.
|
|
5979
5900
|
*/
|
|
5980
5901
|
_ensureReadOnlyFacade() {
|
|
5981
5902
|
if (this.readOnlyFacade !== null) return this.readOnlyFacade;
|
|
@@ -6148,7 +6069,7 @@ var Vault = class {
|
|
|
6148
6069
|
* collection.
|
|
6149
6070
|
*/
|
|
6150
6071
|
async delegate(opts) {
|
|
6151
|
-
const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-
|
|
6072
|
+
const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-42LO4WFO.js");
|
|
6152
6073
|
if (!this.keyring.kek) {
|
|
6153
6074
|
throw new ValidationError(
|
|
6154
6075
|
"issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (passphrase) first."
|
|
@@ -6170,7 +6091,7 @@ var Vault = class {
|
|
|
6170
6091
|
* if the id does not exist.
|
|
6171
6092
|
*/
|
|
6172
6093
|
async revokeDelegation(id) {
|
|
6173
|
-
const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-
|
|
6094
|
+
const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-42LO4WFO.js");
|
|
6174
6095
|
await revokeDelegation(this.adapter, this.name, id);
|
|
6175
6096
|
void DELEGATIONS_COLLECTION;
|
|
6176
6097
|
}
|
|
@@ -6430,7 +6351,7 @@ var Vault = class {
|
|
|
6430
6351
|
const all = await this._loadPeriodsCache();
|
|
6431
6352
|
return all.find((p) => p.name === name) ?? null;
|
|
6432
6353
|
}
|
|
6433
|
-
/** @internal —
|
|
6354
|
+
/** @internal — called by the gate bus before put/delete. */
|
|
6434
6355
|
async _assertTsWritable(existing, incoming) {
|
|
6435
6356
|
if (existing === null && incoming === null) return;
|
|
6436
6357
|
if (this.periodCache === null) {
|
|
@@ -6518,7 +6439,7 @@ var Vault = class {
|
|
|
6518
6439
|
return dumpVaultSchema(this, opts);
|
|
6519
6440
|
}
|
|
6520
6441
|
/**
|
|
6521
|
-
* Lightweight read of the vault's registered schema
|
|
6442
|
+
* Lightweight read of the vault's registered schema: collections
|
|
6522
6443
|
* (+ doc counts), guards, materialized views, schema-update strategies,
|
|
6523
6444
|
* and the unlocked user's grants. Cheap — one `adapter.list` per
|
|
6524
6445
|
* collection, no decryption. For a full snapshot + stats use dumpSchema().
|
|
@@ -6639,7 +6560,7 @@ var Vault = class {
|
|
|
6639
6560
|
* @see docs/subsystems/public-envelope.md
|
|
6640
6561
|
*/
|
|
6641
6562
|
async getPublicEnvelope(opts = {}) {
|
|
6642
|
-
const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-
|
|
6563
|
+
const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-YKHKP74C.js");
|
|
6643
6564
|
return readPublicEnvelope2(this.adapter, this.name, opts);
|
|
6644
6565
|
}
|
|
6645
6566
|
/**
|
|
@@ -7305,6 +7226,110 @@ var WriteHookRegistry = class {
|
|
|
7305
7226
|
}
|
|
7306
7227
|
};
|
|
7307
7228
|
|
|
7229
|
+
// src/subsystem-bus.ts
|
|
7230
|
+
var SubsystemBus = class {
|
|
7231
|
+
#handlers = /* @__PURE__ */ new Map();
|
|
7232
|
+
#gateHandlers = /* @__PURE__ */ new Map();
|
|
7233
|
+
#depth = 0;
|
|
7234
|
+
/** Register a handler for an observe point. Returns an unsubscribe fn. */
|
|
7235
|
+
register(point, handler) {
|
|
7236
|
+
let arr = this.#handlers.get(point);
|
|
7237
|
+
if (!arr) {
|
|
7238
|
+
arr = [];
|
|
7239
|
+
this.#handlers.set(point, arr);
|
|
7240
|
+
}
|
|
7241
|
+
arr.push(handler);
|
|
7242
|
+
return () => {
|
|
7243
|
+
const a = this.#handlers.get(point);
|
|
7244
|
+
if (!a) return;
|
|
7245
|
+
const i = a.indexOf(handler);
|
|
7246
|
+
if (i >= 0) a.splice(i, 1);
|
|
7247
|
+
};
|
|
7248
|
+
}
|
|
7249
|
+
/** Cheap gate for the write path — true when any handler is registered for the point. */
|
|
7250
|
+
hasHandlers(point) {
|
|
7251
|
+
const a = this.#handlers.get(point);
|
|
7252
|
+
return a !== void 0 && a.length > 0;
|
|
7253
|
+
}
|
|
7254
|
+
/**
|
|
7255
|
+
* True while one or more dispatches are in flight. Backed by a depth counter
|
|
7256
|
+
* so that two concurrent async dispatches (`Promise.all([put('a'), put('b')])`
|
|
7257
|
+
* each captured `busAfterPut=true` at their respective put() tops while depth
|
|
7258
|
+
* was 0) both proceed independently — the counter stays > 0 until BOTH finish,
|
|
7259
|
+
* so any nested write attempted by a handler still sees `dispatching === true`
|
|
7260
|
+
* and is suppressed by the write-path gate in `collection.ts`
|
|
7261
|
+
* (`busAfterPut = hasHandlers('afterPut') && !dispatching`). Re-entrancy
|
|
7262
|
+
* suppression lives exclusively on that write-path gate; concurrent independent
|
|
7263
|
+
* dispatches must not drop each other's events.
|
|
7264
|
+
*/
|
|
7265
|
+
get dispatching() {
|
|
7266
|
+
return this.#depth > 0;
|
|
7267
|
+
}
|
|
7268
|
+
/**
|
|
7269
|
+
* Dispatch in registration order, awaited. Per-handler errors are warned, not
|
|
7270
|
+
* thrown — an observe handler must never abort a completed write. A
|
|
7271
|
+
* re-entrancy guard suppresses nested firing so a handler that itself writes
|
|
7272
|
+
* cannot loop (same rationale as WriteHookRegistry.#suppressed).
|
|
7273
|
+
*/
|
|
7274
|
+
async dispatch(point, event) {
|
|
7275
|
+
const a = this.#handlers.get(point);
|
|
7276
|
+
if (!a || a.length === 0) return;
|
|
7277
|
+
this.#depth++;
|
|
7278
|
+
try {
|
|
7279
|
+
for (const h of a.slice()) {
|
|
7280
|
+
try {
|
|
7281
|
+
await h(event);
|
|
7282
|
+
} catch (err) {
|
|
7283
|
+
console.warn(
|
|
7284
|
+
`[noy-db] subsystem observe handler failed at ${point}: ` + (err instanceof Error ? err.message : String(err))
|
|
7285
|
+
);
|
|
7286
|
+
}
|
|
7287
|
+
}
|
|
7288
|
+
} finally {
|
|
7289
|
+
this.#depth--;
|
|
7290
|
+
}
|
|
7291
|
+
}
|
|
7292
|
+
/** Register a write-gating handler. A throw from the handler ABORTS the write. Returns an unsubscribe fn. */
|
|
7293
|
+
registerGate(point, handler) {
|
|
7294
|
+
let arr = this.#gateHandlers.get(point);
|
|
7295
|
+
if (!arr) {
|
|
7296
|
+
arr = [];
|
|
7297
|
+
this.#gateHandlers.set(point, arr);
|
|
7298
|
+
}
|
|
7299
|
+
arr.push(handler);
|
|
7300
|
+
return () => {
|
|
7301
|
+
const a = this.#gateHandlers.get(point);
|
|
7302
|
+
if (!a) return;
|
|
7303
|
+
const i = a.indexOf(handler);
|
|
7304
|
+
if (i >= 0) a.splice(i, 1);
|
|
7305
|
+
};
|
|
7306
|
+
}
|
|
7307
|
+
/** Cheap gate for the write path — true when any gate handler is registered for the point. */
|
|
7308
|
+
hasGateHandlers(point) {
|
|
7309
|
+
const a = this.#gateHandlers.get(point);
|
|
7310
|
+
return a !== void 0 && a.length > 0;
|
|
7311
|
+
}
|
|
7312
|
+
/**
|
|
7313
|
+
* Run gate handlers in registration order, awaited. Unlike `dispatch`
|
|
7314
|
+
* (observe), a handler throw is NOT swallowed — it PROPAGATES, aborting the
|
|
7315
|
+
* write before it reaches the store. The first throw stops the remaining
|
|
7316
|
+
* handlers (fail-fast). This is the seam guards/periods migrate onto.
|
|
7317
|
+
*
|
|
7318
|
+
* Note: gate handlers are validators that read, not write. A gate handler
|
|
7319
|
+
* that writes back into the same collection would re-enter the write path
|
|
7320
|
+
* and re-dispatch this point; loop-suppression for that case is deferred to
|
|
7321
|
+
* the migration slice (contract: gate handlers must not perform writes that
|
|
7322
|
+
* re-trigger their own point).
|
|
7323
|
+
*/
|
|
7324
|
+
async dispatchGate(point, event) {
|
|
7325
|
+
const a = this.#gateHandlers.get(point);
|
|
7326
|
+
if (!a || a.length === 0) return;
|
|
7327
|
+
for (const h of a.slice()) {
|
|
7328
|
+
await h(event);
|
|
7329
|
+
}
|
|
7330
|
+
}
|
|
7331
|
+
};
|
|
7332
|
+
|
|
7308
7333
|
// src/tab-coordination.ts
|
|
7309
7334
|
var TabCoordinator = class {
|
|
7310
7335
|
tabId;
|
|
@@ -7661,9 +7686,9 @@ var PERSONAL_POLICY = Object.freeze({
|
|
|
7661
7686
|
minTier: 1,
|
|
7662
7687
|
enabled: true
|
|
7663
7688
|
},
|
|
7664
|
-
// rotate-recovery
|
|
7665
|
-
// when the user remembers their passphrase. PERSONAL
|
|
7666
|
-
//
|
|
7689
|
+
// rotate-recovery: deliberate paper-sheet regeneration
|
|
7690
|
+
// when the user remembers their passphrase. PERSONAL allows tier-1 —
|
|
7691
|
+
// knowing the passphrase is enough.
|
|
7667
7692
|
"rotate-recovery": { minTier: 1 },
|
|
7668
7693
|
"enroll-authenticator": { minTier: 1 },
|
|
7669
7694
|
"remove-authenticator": { minTier: 1 },
|
|
@@ -7697,7 +7722,7 @@ var PERSONAL_POLICY = Object.freeze({
|
|
|
7697
7722
|
minTier: 1,
|
|
7698
7723
|
enabled: false
|
|
7699
7724
|
},
|
|
7700
|
-
// ─── User envelope gates
|
|
7725
|
+
// ─── User envelope gates ──────────────────────────────────────────
|
|
7701
7726
|
// edit-own-profile: tier 3 floor — any active session can edit their
|
|
7702
7727
|
// own profile/preferences. Tightening to require a TOTP for
|
|
7703
7728
|
// profile changes is a one-line override.
|
|
@@ -7724,7 +7749,7 @@ var STRICT_POLICY = Object.freeze({
|
|
|
7724
7749
|
minTier: 1,
|
|
7725
7750
|
enabled: true
|
|
7726
7751
|
},
|
|
7727
|
-
// rotate-recovery
|
|
7752
|
+
// rotate-recovery: STRICT requires an off-device factor —
|
|
7728
7753
|
// rotating recovery is an off-site-trust event; a stolen unlocked
|
|
7729
7754
|
// laptop must not be able to silently mint a new sheet for the
|
|
7730
7755
|
// attacker. Matches the `peer-recover-user` STRICT default.
|
|
@@ -7797,7 +7822,7 @@ var STRICT_POLICY = Object.freeze({
|
|
|
7797
7822
|
minTier: 1,
|
|
7798
7823
|
enabled: false
|
|
7799
7824
|
},
|
|
7800
|
-
// ─── User envelope gates
|
|
7825
|
+
// ─── User envelope gates ──────────────────────────────────────────
|
|
7801
7826
|
// STRICT: profile edits require a TOTP/email-OTP factor (typical
|
|
7802
7827
|
// shared-workstation hardening — your name/avatar shouldn't change
|
|
7803
7828
|
// without a fresh second-factor proof).
|
|
@@ -7908,13 +7933,14 @@ var Noydb = class {
|
|
|
7908
7933
|
emitter = new NoydbEventEmitter();
|
|
7909
7934
|
writeQueueTracker = new WriteQueueTracker();
|
|
7910
7935
|
writeHooks = new WriteHookRegistry();
|
|
7936
|
+
subsystemBus = new SubsystemBus();
|
|
7911
7937
|
clientId = generateULID();
|
|
7912
7938
|
vaultCache = /* @__PURE__ */ new Map();
|
|
7913
7939
|
keyringCache = /* @__PURE__ */ new Map();
|
|
7914
7940
|
syncEngines = /* @__PURE__ */ new Map();
|
|
7915
7941
|
/**
|
|
7916
7942
|
* Per-vault active session tier — defaults to `1` after a passphrase
|
|
7917
|
-
* unlock; tier-2 / tier-3 unlocks
|
|
7943
|
+
* unlock; tier-2 / tier-3 unlocks downgrade it. Used by
|
|
7918
7944
|
* {@link checkGate} to evaluate `gate.minTier`.
|
|
7919
7945
|
*/
|
|
7920
7946
|
activeTier = /* @__PURE__ */ new Map();
|
|
@@ -7924,14 +7950,14 @@ var Noydb = class {
|
|
|
7924
7950
|
*/
|
|
7925
7951
|
policyCache = /* @__PURE__ */ new Map();
|
|
7926
7952
|
/**
|
|
7927
|
-
* One-shot bypass for the managed-mode strong-recovery check
|
|
7953
|
+
* One-shot bypass for the managed-mode strong-recovery check.
|
|
7928
7954
|
* Set true by {@link openVaultAndEnrollRecovery} for the duration of
|
|
7929
7955
|
* the bootstrap window so the keyring can be created before the
|
|
7930
7956
|
* strong recovery is enrolled. Always cleared (try/finally).
|
|
7931
7957
|
* @internal
|
|
7932
7958
|
*/
|
|
7933
7959
|
_skipNextManagedRecoveryCheck = false;
|
|
7934
|
-
/** Per-vault tier-3 (PIN / quick-resume) state
|
|
7960
|
+
/** Per-vault tier-3 (PIN / quick-resume) state. */
|
|
7935
7961
|
quickUnlock = new QuickUnlockStore();
|
|
7936
7962
|
/**
|
|
7937
7963
|
* Resolved public-envelope schema. Lazily computed once from
|
|
@@ -7941,9 +7967,9 @@ var Noydb = class {
|
|
|
7941
7967
|
publicEnvelopeSchema;
|
|
7942
7968
|
closed = false;
|
|
7943
7969
|
sessionTimer = null;
|
|
7944
|
-
/** Same-device multi-tab coordinator
|
|
7970
|
+
/** Same-device multi-tab coordinator; created on `enableTabCoordination()`. */
|
|
7945
7971
|
tabCoordinator;
|
|
7946
|
-
/** Cross-tab write relay
|
|
7972
|
+
/** Cross-tab write relay; created on `enableTabCoordination()`. */
|
|
7947
7973
|
writeRelay;
|
|
7948
7974
|
/** Per-vault policy enforcers. */
|
|
7949
7975
|
policyEnforcers = /* @__PURE__ */ new Map();
|
|
@@ -7956,8 +7982,8 @@ var Noydb = class {
|
|
|
7956
7982
|
* the same function's `finally` block. Side-effect writes triggered
|
|
7957
7983
|
* during a staged op's `Collection.put` (today: eager derivation
|
|
7958
7984
|
* outputs) register their pre-write envelope on `_executed` here so
|
|
7959
|
-
* a mid-batch failure rolls them back alongside the main staged ops
|
|
7960
|
-
*
|
|
7985
|
+
* a mid-batch failure rolls them back alongside the main staged ops.
|
|
7986
|
+
* `null` outside of Phase 2.
|
|
7961
7987
|
* @internal
|
|
7962
7988
|
*/
|
|
7963
7989
|
_activeTxContext = null;
|
|
@@ -7978,8 +8004,95 @@ var Noydb = class {
|
|
|
7978
8004
|
if (options.sessionPolicy) {
|
|
7979
8005
|
this.sessionStrategy.validateSessionPolicy(options.sessionPolicy);
|
|
7980
8006
|
}
|
|
8007
|
+
this.#registerGuardGate();
|
|
8008
|
+
this.#registerPeriodGate();
|
|
7981
8009
|
this.resetSessionTimer();
|
|
7982
8010
|
}
|
|
8011
|
+
// Track A — guards migration. Registers record-lock / field-freeze / onDelete
|
|
8012
|
+
// / amendment-collect as gate-bus handlers (only when guards are opted in, so
|
|
8013
|
+
// the write path is zero-cost otherwise). Resolves the live vault's
|
|
8014
|
+
// GuardRegistry per dispatch. Registered BEFORE the period gate so guard
|
|
8015
|
+
// checks run first. The amendment branch is a side-effect (collectChange),
|
|
8016
|
+
// NOT a throw — and runs even for internal deletes (an amendment invariant
|
|
8017
|
+
// must see system housekeeping tombstones); onDelete/checks run only for
|
|
8018
|
+
// user (non-internal) operations.
|
|
8019
|
+
#registerGuardGate() {
|
|
8020
|
+
if (this.options.guardStrategies === void 0) return;
|
|
8021
|
+
this.subsystemBus.registerGate("beforePut", async (e) => {
|
|
8022
|
+
const v = this.vaultCache.get(e.vault);
|
|
8023
|
+
if (!v) return;
|
|
8024
|
+
const registry = v._getGuardRegistry();
|
|
8025
|
+
if (!registry) return;
|
|
8026
|
+
const guards = registry.guardsFor(e.collection);
|
|
8027
|
+
if (guards.length === 0) return;
|
|
8028
|
+
const existing = e.existing ?? null;
|
|
8029
|
+
const incoming = e.incoming;
|
|
8030
|
+
if (registry.isAmendmentActive()) {
|
|
8031
|
+
registry.collectChange(e.collection, e.docId, existing, incoming, e.existingVersion, e.existingVersion + 1);
|
|
8032
|
+
return;
|
|
8033
|
+
}
|
|
8034
|
+
const facade = v._getReadOnlyFacade();
|
|
8035
|
+
if (!facade) return;
|
|
8036
|
+
const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
|
|
8037
|
+
await registry.runChecks(e.collection, incoming, ctx);
|
|
8038
|
+
const { GuardExecutor } = await import("./executor-AWCHQ2KN.js");
|
|
8039
|
+
for (const g of guards) {
|
|
8040
|
+
await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming);
|
|
8041
|
+
}
|
|
8042
|
+
});
|
|
8043
|
+
this.subsystemBus.registerGate("beforeDelete", async (e) => {
|
|
8044
|
+
const v = this.vaultCache.get(e.vault);
|
|
8045
|
+
if (!v) return;
|
|
8046
|
+
const registry = v._getGuardRegistry();
|
|
8047
|
+
if (!registry) return;
|
|
8048
|
+
const guards = registry.guardsFor(e.collection);
|
|
8049
|
+
if (guards.length === 0) return;
|
|
8050
|
+
const existing = e.existing ?? null;
|
|
8051
|
+
if (registry.isAmendmentActive()) {
|
|
8052
|
+
registry.collectChange(e.collection, e.docId, existing, null, e.existingVersion, e.existingVersion);
|
|
8053
|
+
return;
|
|
8054
|
+
}
|
|
8055
|
+
if (e.internal) return;
|
|
8056
|
+
const facade = v._getReadOnlyFacade();
|
|
8057
|
+
if (!facade) return;
|
|
8058
|
+
const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
|
|
8059
|
+
await registry.runOnDelete(e.collection, existing ?? {}, ctx);
|
|
8060
|
+
});
|
|
8061
|
+
}
|
|
8062
|
+
/**
|
|
8063
|
+
* Register closed-period write guards on the subsystem bus when a
|
|
8064
|
+
* periodsStrategy is configured. Handlers resolve the live Vault from
|
|
8065
|
+
* vaultCache so they always use the up-to-date period cache.
|
|
8066
|
+
*/
|
|
8067
|
+
// Track A — periods migration. Registers the closed-period write guard as a
|
|
8068
|
+
// gate-bus handler (only when periods is opted in, so the write path is
|
|
8069
|
+
// zero-cost otherwise). Each handler resolves the LIVE vault from the cache
|
|
8070
|
+
// per dispatch and delegates to its `_assertTsWritable`, which owns all
|
|
8071
|
+
// period logic. Resolving the live vault makes eviction/re-creation
|
|
8072
|
+
// transparent. Semantics note: if a write reaches the gate through a retained
|
|
8073
|
+
// collection handle whose vault has been evicted from `vaultCache` (e.g. a
|
|
8074
|
+
// post-revocation write on a stale handle), the period check is skipped — the
|
|
8075
|
+
// guard binds to the live vault, not a captured instance. Periods is a
|
|
8076
|
+
// write-integrity guard, not a security boundary, and a re-open reloads the
|
|
8077
|
+
// period cache; the trade-off is intentional.
|
|
8078
|
+
#registerPeriodGate() {
|
|
8079
|
+
if (this.options.periodsStrategy === void 0) return;
|
|
8080
|
+
this.subsystemBus.registerGate("beforePut", async (e) => {
|
|
8081
|
+
const v = this.vaultCache.get(e.vault);
|
|
8082
|
+
if (!v) return;
|
|
8083
|
+
const existing = e.op === "create" ? null : { ts: e.existingTs ?? null, record: e.existing ?? null };
|
|
8084
|
+
await v._assertTsWritable(existing, e.incoming);
|
|
8085
|
+
});
|
|
8086
|
+
this.subsystemBus.registerGate("beforeDelete", async (e) => {
|
|
8087
|
+
if (e.internal) return;
|
|
8088
|
+
const v = this.vaultCache.get(e.vault);
|
|
8089
|
+
if (!v) return;
|
|
8090
|
+
await v._assertTsWritable(
|
|
8091
|
+
{ ts: e.existingTs ?? null, record: e.existing ?? null },
|
|
8092
|
+
null
|
|
8093
|
+
);
|
|
8094
|
+
});
|
|
8095
|
+
}
|
|
7983
8096
|
resetSessionTimer() {
|
|
7984
8097
|
if (this.sessionTimer) clearTimeout(this.sessionTimer);
|
|
7985
8098
|
const idleMs = this.options.sessionPolicy?.idleTimeoutMs ?? this.options.sessionTimeout;
|
|
@@ -8269,8 +8382,6 @@ var Noydb = class {
|
|
|
8269
8382
|
* @throws `NoAccessError` when no keyring exists for the target.
|
|
8270
8383
|
* @throws `PermissionDeniedError` when the role hierarchy rejects.
|
|
8271
8384
|
* @throws `ValidationError` when no field is provided.
|
|
8272
|
-
*
|
|
8273
|
-
* @see #54
|
|
8274
8385
|
*/
|
|
8275
8386
|
async updateUser(vault, options, factors) {
|
|
8276
8387
|
await this.checkGate(vault, "update-user", factors);
|
|
@@ -8606,7 +8717,7 @@ var Noydb = class {
|
|
|
8606
8717
|
* Phase 2. `Collection.dispatchDerivations` consults this so a
|
|
8607
8718
|
* recursive derived-output write inside `Collection.put` can register
|
|
8608
8719
|
* its envelope onto `ctx._executed` and roll back with the main
|
|
8609
|
-
* staged ops on mid-batch failure
|
|
8720
|
+
* staged ops on mid-batch failure.
|
|
8610
8721
|
*
|
|
8611
8722
|
* @internal
|
|
8612
8723
|
*/
|
|
@@ -8635,7 +8746,7 @@ var Noydb = class {
|
|
|
8635
8746
|
* `Collection.putManyAtomic` (via `derivationSource.createTxContext`)
|
|
8636
8747
|
* to publish an active context for the duration of its bulk-atomic
|
|
8637
8748
|
* Phase 2 loop, so recursive derivation-output writes register on
|
|
8638
|
-
* `ctx._executed` and roll back together with the source ops
|
|
8749
|
+
* `ctx._executed` and roll back together with the source ops.
|
|
8639
8750
|
*
|
|
8640
8751
|
* @internal
|
|
8641
8752
|
*/
|
|
@@ -8706,26 +8817,26 @@ var Noydb = class {
|
|
|
8706
8817
|
return this.writeQueueTracker;
|
|
8707
8818
|
}
|
|
8708
8819
|
/**
|
|
8709
|
-
* Register a hook that runs before each write
|
|
8820
|
+
* Register a hook that runs before each write. Awaited; a throw
|
|
8710
8821
|
* aborts the write. Returns an unsubscribe function.
|
|
8711
8822
|
*/
|
|
8712
8823
|
onBeforeWrite(handler) {
|
|
8713
8824
|
return this.writeHooks.onBeforeWrite(handler);
|
|
8714
8825
|
}
|
|
8715
8826
|
/**
|
|
8716
|
-
* Register a hook that runs after each committed write
|
|
8827
|
+
* Register a hook that runs after each committed write. Awaited;
|
|
8717
8828
|
* a handler error is warned, never rolled back. Returns an unsubscribe fn.
|
|
8718
8829
|
*/
|
|
8719
8830
|
onAfterWrite(handler) {
|
|
8720
8831
|
return this.writeHooks.onAfterWrite(handler);
|
|
8721
8832
|
}
|
|
8722
|
-
/** Subscribe to cross-tab write conflicts
|
|
8833
|
+
/** Subscribe to cross-tab write conflicts. Returns an unsubscribe. */
|
|
8723
8834
|
onWriteConflict(fn) {
|
|
8724
8835
|
this.on("write:conflict", fn);
|
|
8725
8836
|
return () => this.off("write:conflict", fn);
|
|
8726
8837
|
}
|
|
8727
8838
|
/**
|
|
8728
|
-
* Enable same-device multi-tab coordination
|
|
8839
|
+
* Enable same-device multi-tab coordination: primary/secondary
|
|
8729
8840
|
* election + presence. Browser-only — a graceful no-op (role 'unknown')
|
|
8730
8841
|
* when Web Locks / BroadcastChannel are unavailable and nothing is
|
|
8731
8842
|
* injected. Idempotent; returns a disposer.
|
|
@@ -8808,7 +8919,11 @@ var Noydb = class {
|
|
|
8808
8919
|
get _writeHooks() {
|
|
8809
8920
|
return this.writeHooks;
|
|
8810
8921
|
}
|
|
8811
|
-
/** @internal
|
|
8922
|
+
/** @internal The observe bus, threaded into every Collection. */
|
|
8923
|
+
get _subsystemBus() {
|
|
8924
|
+
return this.subsystemBus;
|
|
8925
|
+
}
|
|
8926
|
+
/** @internal Stable per-instance id for schema-cutover coordination. */
|
|
8812
8927
|
get _clientId() {
|
|
8813
8928
|
return this.clientId;
|
|
8814
8929
|
}
|
|
@@ -8828,10 +8943,6 @@ var Noydb = class {
|
|
|
8828
8943
|
* survives lock; nothing about it changes when DEKs are scrubbed).
|
|
8829
8944
|
*
|
|
8830
8945
|
* No-op when `vault` is not currently in cache (idempotent).
|
|
8831
|
-
*
|
|
8832
|
-
* Unblocks vLannaAi/niwat#33.
|
|
8833
|
-
*
|
|
8834
|
-
* @see #17
|
|
8835
8946
|
*/
|
|
8836
8947
|
lockVault(vault) {
|
|
8837
8948
|
this.syncEngines.get(vault)?.stopAutoSync();
|
|
@@ -8946,7 +9057,7 @@ var Noydb = class {
|
|
|
8946
9057
|
return merged;
|
|
8947
9058
|
}
|
|
8948
9059
|
/**
|
|
8949
|
-
* Read the current vault-level user-directory toggle
|
|
9060
|
+
* Read the current vault-level user-directory toggle. Returns
|
|
8950
9061
|
* the default-on shape (`{ enabled: true }`) when no `_meta/directory`
|
|
8951
9062
|
* document has been persisted yet.
|
|
8952
9063
|
*
|
|
@@ -8958,7 +9069,7 @@ var Noydb = class {
|
|
|
8958
9069
|
return persisted?.enabled ?? true;
|
|
8959
9070
|
}
|
|
8960
9071
|
/**
|
|
8961
|
-
* Toggle the vault's user-directory listing on or off
|
|
9072
|
+
* Toggle the vault's user-directory listing on or off.
|
|
8962
9073
|
* Owner-only. When disabled, `listUsersWithEnvelopes()` throws
|
|
8963
9074
|
* {@link import('./errors.js').DirectoryDisabledError} for callers
|
|
8964
9075
|
* whose role is neither `owner` nor `admin`.
|
|
@@ -9018,7 +9129,7 @@ var Noydb = class {
|
|
|
9018
9129
|
*
|
|
9019
9130
|
* Two enforcement modes:
|
|
9020
9131
|
*
|
|
9021
|
-
* 1. **Managed-mode mandatory strong-recovery
|
|
9132
|
+
* 1. **Managed-mode mandatory strong-recovery.** When
|
|
9022
9133
|
* `passphraseMode === 'managed'`, the vault MUST have at least
|
|
9023
9134
|
* one **strong** recovery profile (Shamir today). Paper alone is
|
|
9024
9135
|
* rejected because under managed mode the user has no memorized
|
|
@@ -9052,14 +9163,14 @@ var Noydb = class {
|
|
|
9052
9163
|
throw new RecoveryNotEnrolledError();
|
|
9053
9164
|
}
|
|
9054
9165
|
/**
|
|
9055
|
-
* Internal accessor used by tier-2/tier-3 unlock paths
|
|
9166
|
+
* Internal accessor used by tier-2/tier-3 unlock paths
|
|
9056
9167
|
* to mark the active session tier.
|
|
9057
9168
|
* @internal
|
|
9058
9169
|
*/
|
|
9059
9170
|
_setActiveTier(vault, tier) {
|
|
9060
9171
|
this.activeTier.set(vault, tier);
|
|
9061
9172
|
}
|
|
9062
|
-
// ─── Tier-2 enroll / remove
|
|
9173
|
+
// ─── Tier-2 enroll / remove ─────────────────────────────────────
|
|
9063
9174
|
/**
|
|
9064
9175
|
* Add a tier-2 authenticator slot to the calling user's keyring.
|
|
9065
9176
|
* Each slot independently wraps the SAME KEK under a method-specific
|
|
@@ -9089,7 +9200,7 @@ var Noydb = class {
|
|
|
9089
9200
|
const next = await removeAuthenticator(this.options.store, vault, keyring, slotId);
|
|
9090
9201
|
this.keyringCache.set(vault, next);
|
|
9091
9202
|
}
|
|
9092
|
-
/** Read the slot list for a vault. Internal — `describeAuthConfig`
|
|
9203
|
+
/** Read the slot list for a vault. Internal — `describeAuthConfig` consumes this. */
|
|
9093
9204
|
async listAuthenticators(vault) {
|
|
9094
9205
|
const keyring = await this.getKeyringInternal(vault);
|
|
9095
9206
|
return keyring.authenticators;
|
|
@@ -9101,7 +9212,7 @@ var Noydb = class {
|
|
|
9101
9212
|
* are immutable through this method. Anti-slot-swap is structural,
|
|
9102
9213
|
* not gate-driven.
|
|
9103
9214
|
*
|
|
9104
|
-
* `meta` patch semantics (
|
|
9215
|
+
* `meta` patch semantics (top-level merge):
|
|
9105
9216
|
* - Top-level merge — absent keys preserved
|
|
9106
9217
|
* - `null` value — delete that meta key
|
|
9107
9218
|
* - Other values — replace verbatim
|
|
@@ -9119,8 +9230,6 @@ var Noydb = class {
|
|
|
9119
9230
|
*
|
|
9120
9231
|
* @throws `NoAccessError` when no slot with the given id exists.
|
|
9121
9232
|
* @throws `ValidationError` when no patch field is provided.
|
|
9122
|
-
*
|
|
9123
|
-
* @see #55
|
|
9124
9233
|
*/
|
|
9125
9234
|
async updateAuthenticator(vault, slotId, options, factors) {
|
|
9126
9235
|
await this.checkGate(vault, "update-authenticator", factors);
|
|
@@ -9129,7 +9238,7 @@ var Noydb = class {
|
|
|
9129
9238
|
this.keyringCache.set(vault, next);
|
|
9130
9239
|
}
|
|
9131
9240
|
/**
|
|
9132
|
-
* Native WebAuthn enrollment using the **real** internal keyring
|
|
9241
|
+
* Native WebAuthn enrollment using the **real** internal keyring.
|
|
9133
9242
|
*
|
|
9134
9243
|
* Why this exists: when a consumer is using `createNoydb({ secret })`,
|
|
9135
9244
|
* they cannot reach the live `UnlockedKeyring` to feed it to
|
|
@@ -9172,8 +9281,6 @@ var Noydb = class {
|
|
|
9172
9281
|
* a server-side allowlist).
|
|
9173
9282
|
*
|
|
9174
9283
|
* Gated by `enroll-authenticator` like `enrollAuthenticator()` itself.
|
|
9175
|
-
*
|
|
9176
|
-
* @see #16
|
|
9177
9284
|
*/
|
|
9178
9285
|
async enrollWebAuthn(vault, ceremony, factors) {
|
|
9179
9286
|
await this.checkGate(vault, "enroll-authenticator", factors);
|
|
@@ -9200,8 +9307,6 @@ var Noydb = class {
|
|
|
9200
9307
|
* deciding when a new device prompt should appear. Identity is
|
|
9201
9308
|
* `id` + `enrolled_at`; the `meta.credentialId` (base64) is used by
|
|
9202
9309
|
* `allowCredentials` at unlock time.
|
|
9203
|
-
*
|
|
9204
|
-
* @see #16
|
|
9205
9310
|
*/
|
|
9206
9311
|
async listWebAuthnSlots(vault) {
|
|
9207
9312
|
const keyring = await this.getKeyringInternal(vault);
|
|
@@ -9283,7 +9388,7 @@ var Noydb = class {
|
|
|
9283
9388
|
async getPublicEnvelope(vault, opts = {}) {
|
|
9284
9389
|
return readPublicEnvelope(this.options.store, vault, opts);
|
|
9285
9390
|
}
|
|
9286
|
-
// ─── Auth introspection
|
|
9391
|
+
// ─── Auth introspection ─────────────────────────────────────────
|
|
9287
9392
|
/** English summary of the configured auth model. */
|
|
9288
9393
|
async describeAuthConfig(vault) {
|
|
9289
9394
|
return describeAuthConfig(this.options.store, vault);
|
|
@@ -9306,7 +9411,7 @@ var Noydb = class {
|
|
|
9306
9411
|
await this.checkGate(vault, "view-user-auth", factors);
|
|
9307
9412
|
return describeAllUsersAuth(this.options.store, vault);
|
|
9308
9413
|
}
|
|
9309
|
-
// ─── Tier-1 change flows
|
|
9414
|
+
// ─── Tier-1 change flows ────────────────────────────────────────
|
|
9310
9415
|
/**
|
|
9311
9416
|
* Rotate the user's passphrase (user remembers old). Validates the
|
|
9312
9417
|
* new phrase against the configured `passphrase` policy, runs the
|
|
@@ -9314,8 +9419,7 @@ var Noydb = class {
|
|
|
9314
9419
|
*
|
|
9315
9420
|
* Tier-2 authenticator slots are dropped — each slot wraps the old
|
|
9316
9421
|
* KEK and would need its derivation key to be re-presented. Re-enrol
|
|
9317
|
-
* via `db.enrollAuthenticator` after rotation.
|
|
9318
|
-
* v0.1.0-pre.5 limitation.
|
|
9422
|
+
* via `db.enrollAuthenticator` after rotation.
|
|
9319
9423
|
*
|
|
9320
9424
|
* @throws `WeakPassphraseError` on a weak new phrase.
|
|
9321
9425
|
* @throws `PolicyDeniedError` when the gate denies (missing factor, …).
|
|
@@ -9337,8 +9441,8 @@ var Noydb = class {
|
|
|
9337
9441
|
}
|
|
9338
9442
|
/**
|
|
9339
9443
|
* Reset the passphrase using a recovery proof (user forgot the old).
|
|
9340
|
-
*
|
|
9341
|
-
* other
|
|
9444
|
+
* Currently supports the `'paper'` profile end-to-end; the
|
|
9445
|
+
* other profiles throw {@link RecoveryProfileNotImplementedError}.
|
|
9342
9446
|
*
|
|
9343
9447
|
* Burns the used recovery entry on success.
|
|
9344
9448
|
*/
|
|
@@ -9367,7 +9471,7 @@ var Noydb = class {
|
|
|
9367
9471
|
return { newCodes: codes };
|
|
9368
9472
|
}
|
|
9369
9473
|
/**
|
|
9370
|
-
* Deliberate paper-recovery-code regeneration
|
|
9474
|
+
* Deliberate paper-recovery-code regeneration. User knows their
|
|
9371
9475
|
* passphrase but wants a fresh sheet — they lost the printout or
|
|
9372
9476
|
* suspect compromise of the off-site copy.
|
|
9373
9477
|
*
|
|
@@ -9377,7 +9481,7 @@ var Noydb = class {
|
|
|
9377
9481
|
*
|
|
9378
9482
|
* Gated by the `rotate-recovery` policy gate:
|
|
9379
9483
|
* - PERSONAL_POLICY: `{ minTier: 1 }` — knowing the passphrase
|
|
9380
|
-
* suffices, matching the
|
|
9484
|
+
* suffices, matching the lower-level flow's bar.
|
|
9381
9485
|
* - STRICT_POLICY: `{ minTier: 1, factors: [{ anyOf: ['totp',
|
|
9382
9486
|
* 'email-otp', 'webauthn-roaming'] }] }` — rotation is an
|
|
9383
9487
|
* off-site-trust event; require an off-device factor so a
|
|
@@ -9482,7 +9586,7 @@ var Noydb = class {
|
|
|
9482
9586
|
return { newShares: shareStrings, entryId: targetEntryId };
|
|
9483
9587
|
}
|
|
9484
9588
|
/**
|
|
9485
|
-
* **Atomic create-and-enroll for managed-mode vaults
|
|
9589
|
+
* **Atomic create-and-enroll for managed-mode vaults.**
|
|
9486
9590
|
*
|
|
9487
9591
|
* Bootstraps a managed-mode vault and enrolls strong recovery in
|
|
9488
9592
|
* a single ceremony. Under `passphraseMode: 'managed'`, every
|
|
@@ -9553,7 +9657,7 @@ var Noydb = class {
|
|
|
9553
9657
|
return { vault: vaultHandle, recoveryEnrollments };
|
|
9554
9658
|
}
|
|
9555
9659
|
/**
|
|
9556
|
-
* **Recovery flow under managed-passphrase mode
|
|
9660
|
+
* **Recovery flow under managed-passphrase mode.**
|
|
9557
9661
|
*
|
|
9558
9662
|
* Replaces the sealed passphrase of a managed-mode vault with a
|
|
9559
9663
|
* fresh 256-bit random, sealed under the configured
|
|
@@ -9570,7 +9674,7 @@ var Noydb = class {
|
|
|
9570
9674
|
* 5. Drop the keyring cache so the next operation re-derives.
|
|
9571
9675
|
*
|
|
9572
9676
|
* The vault's strong-recovery enrollment is preserved across
|
|
9573
|
-
* recovery (Shamir entries are not burned on use
|
|
9677
|
+
* recovery (Shamir entries are not burned on use).
|
|
9574
9678
|
*
|
|
9575
9679
|
* @throws ValidationError if the Noydb instance is not in managed mode.
|
|
9576
9680
|
*/
|
|
@@ -9618,7 +9722,7 @@ var Noydb = class {
|
|
|
9618
9722
|
}
|
|
9619
9723
|
/**
|
|
9620
9724
|
* Atomic peer-recovery — re-wraps an EXISTING user's keyring under
|
|
9621
|
-
* a fresh temp passphrase in a single store write. Closes
|
|
9725
|
+
* a fresh temp passphrase in a single store write. Closes the
|
|
9622
9726
|
* partial-failure window (the previous compose-from-primitives
|
|
9623
9727
|
* pattern was `db.revoke + db.grant`, two writes — if the issuer
|
|
9624
9728
|
* cancelled between them the target was locked out entirely).
|
|
@@ -9628,7 +9732,7 @@ var Noydb = class {
|
|
|
9628
9732
|
* - Same `userId`, role, permissions, capabilities preserved.
|
|
9629
9733
|
* - DEKs unchanged → every other principal in the vault keeps
|
|
9630
9734
|
* access. No key rotation.
|
|
9631
|
-
* - Allows owner→owner natively
|
|
9735
|
+
* - Allows owner→owner natively. The existing
|
|
9632
9736
|
* `db.revoke` retains its block — peer-recovery is a separate,
|
|
9633
9737
|
* intentionally-named operation.
|
|
9634
9738
|
* - Tier-2 slots dropped (they wrap the old KEK).
|
|
@@ -9657,7 +9761,6 @@ var Noydb = class {
|
|
|
9657
9761
|
* @throws `PrivilegeEscalationError` when the caller lacks a DEK
|
|
9658
9762
|
* the target previously had access to.
|
|
9659
9763
|
*
|
|
9660
|
-
* @see #33 #34 — the issues this method closes.
|
|
9661
9764
|
*/
|
|
9662
9765
|
async recoverUser(vault, options, factors) {
|
|
9663
9766
|
await this.checkGate(vault, "peer-recover-user", factors);
|
|
@@ -9668,7 +9771,7 @@ var Noydb = class {
|
|
|
9668
9771
|
}
|
|
9669
9772
|
}
|
|
9670
9773
|
/**
|
|
9671
|
-
* Persist a recovery enrollment.
|
|
9774
|
+
* Persist a recovery enrollment. Accepts the `'paper'`
|
|
9672
9775
|
* profile.
|
|
9673
9776
|
*
|
|
9674
9777
|
* The hub wraps the user's DEK set (not the KEK) under a code-derived
|
|
@@ -9688,7 +9791,7 @@ var Noydb = class {
|
|
|
9688
9791
|
* showCodesToUser(codes)
|
|
9689
9792
|
* ```
|
|
9690
9793
|
*
|
|
9691
|
-
*
|
|
9794
|
+
* `@noy-db/on-recovery`'s `generateRecoveryCodeSet`
|
|
9692
9795
|
* delegates to `mintPaperRecoveryEntry` internally — its output is
|
|
9693
9796
|
* fed directly to this API. Pick whichever fits your code-gen layer:
|
|
9694
9797
|
*
|
|
@@ -9728,13 +9831,13 @@ var Noydb = class {
|
|
|
9728
9831
|
"#196"
|
|
9729
9832
|
);
|
|
9730
9833
|
}
|
|
9731
|
-
/** Read the persisted recovery entries (paper + Shamir). Used by `describeAuthConfig
|
|
9834
|
+
/** Read the persisted recovery entries (paper + Shamir). Used by `describeAuthConfig`. */
|
|
9732
9835
|
async listRecoveryEntries(vault) {
|
|
9733
9836
|
const paper = await loadPaperRecoveryEntries(this.options.store, vault);
|
|
9734
9837
|
const shamir = await loadShamirRecoveryEntries(this.options.store, vault);
|
|
9735
9838
|
return { paper, shamir };
|
|
9736
9839
|
}
|
|
9737
|
-
// ─── Tier-3 enroll / unlock
|
|
9840
|
+
// ─── Tier-3 enroll / unlock ─────────────────────────────────────
|
|
9738
9841
|
/**
|
|
9739
9842
|
* Register a tier-3 quick-unlock state for the vault. The state is
|
|
9740
9843
|
* an opaque blob produced by `@noy-db/on-pin/enrollPin` (or any
|
|
@@ -9770,11 +9873,11 @@ var Noydb = class {
|
|
|
9770
9873
|
this.quickUnlock.delete(vault);
|
|
9771
9874
|
}
|
|
9772
9875
|
/**
|
|
9773
|
-
* Public accessor for the unlocked keyring of a vault
|
|
9876
|
+
* Public accessor for the unlocked keyring of a vault.
|
|
9774
9877
|
*
|
|
9775
9878
|
* Returns a **defensive shallow copy** so consumers can read the DEK
|
|
9776
9879
|
* map and authenticator list without the risk of mutating the hub's
|
|
9777
|
-
* internal cache
|
|
9880
|
+
* internal cache. Internal hub code paths use a live reference
|
|
9778
9881
|
* via `getKeyringInternal`; ceremonies and external consumers always
|
|
9779
9882
|
* get a snapshot.
|
|
9780
9883
|
*
|
|
@@ -9957,4 +10060,4 @@ export {
|
|
|
9957
10060
|
Noydb,
|
|
9958
10061
|
createNoydb
|
|
9959
10062
|
};
|
|
9960
|
-
//# sourceMappingURL=chunk-
|
|
10063
|
+
//# sourceMappingURL=chunk-W277AG6N.js.map
|