@noy-db/hub 0.2.0-pre.4 → 0.2.0-pre.5
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 +443 -338
- 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-T6HQMVML.js → chunk-BT7544RM.js} +399 -301
- package/dist/chunk-BT7544RM.js.map +1 -0
- 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-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-A6SWRXUQ.js → chunk-NONMIU6C.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-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-KMI2NBBF.js → chunk-YZ6JETII.js} +6 -6
- 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--ahUTrhc.d.ts} +1 -1
- package/dist/{dev-unlock-De3mjQWv.d.cts → dev-unlock-BIwt2V3p.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-vBCB0-Ps.d.cts → hash-BQVrGV-t.d.cts} +1 -1
- package/dist/{hash-gVn_uKhp.d.ts → hash-CJEFQxSD.d.ts} +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.map +1 -1
- package/dist/i18n/index.d.cts +5 -5
- package/dist/i18n/index.d.ts +5 -5
- package/dist/i18n/index.js +7 -7
- 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 +362 -264
- 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 +45 -45
- 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-6TADQIYH.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-D9eB0Rvh.d.ts → types-BV4AZKmx.d.ts} +340 -302
- package/dist/{types-CSLcfytP.d.cts → types-BeKi0hCx.d.cts} +340 -302
- package/dist/{ulid-CiM2OAeM.d.ts → ulid-CQc0eBxE.d.ts} +19 -19
- package/dist/{ulid-CG2YvAbg.d.cts → ulid-Cvljl7ZZ.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-BWcwmevt.d.ts} +1 -1
- package/dist/{with-derivation-DWajFh4K.d.cts → with-derivation-BkOBDhsu.d.cts} +1 -1
- package/dist/{with-guard-DF_Ul3DT.d.cts → with-guard-BD4Hyu8s.d.cts} +1 -1
- package/dist/{with-guard-DR7U-l4v.d.ts → with-guard-Du54s3Ti.d.ts} +1 -1
- package/dist/{with-materialized-view-qtoJ3xKJ.d.ts → with-materialized-view-B5W4wFAC.d.ts} +2 -2
- package/dist/{with-materialized-view-_piodoIz.d.cts → with-materialized-view-BCPPZdjC.d.cts} +2 -2
- package/dist/{with-overlayed-view-DFaRfgMr.d.ts → with-overlayed-view-B8RrlLsG.d.cts} +2 -2
- package/dist/{with-overlayed-view-DwzCKxn2.d.cts → with-overlayed-view-Cw-h9p9N.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-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-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-A6SWRXUQ.js.map → chunk-NONMIU6C.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-KMI2NBBF.js.map → chunk-YZ6JETII.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-6TADQIYH.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,34 @@ 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
33
|
isDictCollectionName
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-YZ6JETII.js";
|
|
35
35
|
import {
|
|
36
36
|
ManagedRecoveryNotEnrolledError,
|
|
37
37
|
PolicyDeniedError,
|
|
@@ -53,11 +53,11 @@ import {
|
|
|
53
53
|
saveShamirRecoveryEntries,
|
|
54
54
|
updateAuthenticator,
|
|
55
55
|
writeMagicLinkGrant
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-Y3P5DEMZ.js";
|
|
57
57
|
import {
|
|
58
58
|
assertTierAccess,
|
|
59
59
|
dekKey
|
|
60
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-TNBIWSQ7.js";
|
|
61
61
|
import {
|
|
62
62
|
USER_ENVELOPE_COLLECTION,
|
|
63
63
|
buildRecipientKeyringFile,
|
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
rotateKeys,
|
|
82
82
|
saveUserEnvelope,
|
|
83
83
|
updateKeyringIdentity
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-T6MTNGBM.js";
|
|
85
85
|
import {
|
|
86
86
|
INDEXED_STORE_POLICY
|
|
87
87
|
} from "./chunk-2QR2PQTT.js";
|
|
@@ -91,30 +91,30 @@ import {
|
|
|
91
91
|
import {
|
|
92
92
|
LEDGER_COLLECTION,
|
|
93
93
|
LEDGER_DELTAS_COLLECTION
|
|
94
|
-
} from "./chunk-
|
|
94
|
+
} from "./chunk-6A4AMQ2H.js";
|
|
95
95
|
import {
|
|
96
96
|
sha256Hex as sha256Hex2
|
|
97
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-Z6FNBOTC.js";
|
|
98
98
|
import {
|
|
99
99
|
NO_AGGREGATE,
|
|
100
100
|
Query,
|
|
101
101
|
ScanBuilder
|
|
102
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-XDW37COG.js";
|
|
103
103
|
import {
|
|
104
104
|
EXPORT_AUDIT_COLLECTION,
|
|
105
105
|
createExportBlobsHandle,
|
|
106
106
|
runCompaction
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-JSYTGEX4.js";
|
|
108
108
|
import {
|
|
109
109
|
NOYDB_BACKUP_VERSION,
|
|
110
110
|
NOYDB_FORMAT_VERSION
|
|
111
|
-
} from "./chunk-
|
|
111
|
+
} from "./chunk-5OVIFUQE.js";
|
|
112
112
|
import {
|
|
113
113
|
decrypt,
|
|
114
114
|
encrypt,
|
|
115
115
|
encryptDeterministic,
|
|
116
116
|
sha256Hex
|
|
117
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-EKTOYEZ3.js";
|
|
118
118
|
import {
|
|
119
119
|
AlreadyElevatedError,
|
|
120
120
|
AttestationError,
|
|
@@ -141,7 +141,7 @@ import {
|
|
|
141
141
|
TierNotGrantedError,
|
|
142
142
|
TranslatorNotConfiguredError,
|
|
143
143
|
ValidationError
|
|
144
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-6HJ2ZALB.js";
|
|
145
145
|
|
|
146
146
|
// src/policy/storage.ts
|
|
147
147
|
var META_COLLECTION = "_meta";
|
|
@@ -644,7 +644,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
|
|
|
644
644
|
}
|
|
645
645
|
const sourceWithId = { ...source, id };
|
|
646
646
|
if (DerivationExecutor === null) {
|
|
647
|
-
({ DerivationExecutor } = await import("./executor-
|
|
647
|
+
({ DerivationExecutor } = await import("./executor-SOLEQVUB.js"));
|
|
648
648
|
}
|
|
649
649
|
const ctx = { vault: accessor.getReadOnlyFacade() };
|
|
650
650
|
const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx);
|
|
@@ -664,7 +664,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
|
|
|
664
664
|
}
|
|
665
665
|
if (out.kind === "array") {
|
|
666
666
|
console.warn(
|
|
667
|
-
`[derivation] unexpected array-shape output "${key}" in lazy resolve path; array-shape derivations require lifecycle: "eager"
|
|
667
|
+
`[derivation] unexpected array-shape output "${key}" in lazy resolve path; array-shape derivations require lifecycle: "eager".`
|
|
668
668
|
);
|
|
669
669
|
continue;
|
|
670
670
|
}
|
|
@@ -702,6 +702,7 @@ var Collection = class {
|
|
|
702
702
|
schemaUpdateGate;
|
|
703
703
|
schemaFence;
|
|
704
704
|
writeHooks;
|
|
705
|
+
subsystemBus;
|
|
705
706
|
activeTxId;
|
|
706
707
|
getDEK;
|
|
707
708
|
onDirty;
|
|
@@ -890,42 +891,14 @@ var Collection = class {
|
|
|
890
891
|
syncAdapter;
|
|
891
892
|
/** — consent-audit hook, no-op when no scope is active. */
|
|
892
893
|
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
894
|
/**
|
|
920
895
|
* Vault-internal hook for derivation dispatch. When set,
|
|
921
896
|
* `Collection.put` consults the registry after the source-write
|
|
922
897
|
* commits and writes derived outputs through `getCollection(name).put`.
|
|
923
|
-
* Same structural-interface pattern as `guardSource` to avoid a
|
|
924
|
-
* circular Vault import.
|
|
925
898
|
*/
|
|
926
899
|
derivationSource;
|
|
927
900
|
/**
|
|
928
|
-
* Vault-internal hook for materialized-view dispatch
|
|
901
|
+
* Vault-internal hook for materialized-view dispatch.
|
|
929
902
|
* Parallel to `derivationSource` — when set, `Collection.put` fires
|
|
930
903
|
* `MaterializedViewRegistry.onSourceWrite` after the source-write
|
|
931
904
|
* commits + after `dispatchDerivations` has run.
|
|
@@ -981,6 +954,7 @@ var Collection = class {
|
|
|
981
954
|
this.schemaUpdateGate = opts.schemaUpdateGate;
|
|
982
955
|
this.schemaFence = opts.schemaFence;
|
|
983
956
|
this.writeHooks = opts.writeHooks;
|
|
957
|
+
this.subsystemBus = opts.subsystemBus;
|
|
984
958
|
this.activeTxId = opts.activeTxId;
|
|
985
959
|
this.blobStrategy = opts.blobStrategy ?? NO_BLOBS;
|
|
986
960
|
this.aggregateStrategy = opts.aggregateStrategy ?? NO_AGGREGATE;
|
|
@@ -1005,8 +979,6 @@ var Collection = class {
|
|
|
1005
979
|
this.crdtMode = opts.crdt;
|
|
1006
980
|
this.syncAdapter = opts.syncAdapter;
|
|
1007
981
|
this.onAccess = opts.onAccess;
|
|
1008
|
-
this.periodGuard = opts.periodGuard;
|
|
1009
|
-
this.guardSource = opts.guardSource;
|
|
1010
982
|
this.derivationSource = opts.derivationSource;
|
|
1011
983
|
this.materializedViewSource = opts.materializedViewSource;
|
|
1012
984
|
this.tiers = opts.tiers && opts.tiers.length > 0 ? new Set(opts.tiers) : null;
|
|
@@ -1140,7 +1112,7 @@ var Collection = class {
|
|
|
1140
1112
|
}
|
|
1141
1113
|
}
|
|
1142
1114
|
if (this.materializedViewSource !== void 0) {
|
|
1143
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
1115
|
+
const { resolveStaleMVOnRead } = await import("./stale-74WGLVZ2.js");
|
|
1144
1116
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name);
|
|
1145
1117
|
}
|
|
1146
1118
|
let record;
|
|
@@ -1208,21 +1180,23 @@ var Collection = class {
|
|
|
1208
1180
|
}
|
|
1209
1181
|
/**
|
|
1210
1182
|
* Create or update a record. Runs inside the hub's write-queue tracker
|
|
1211
|
-
*
|
|
1183
|
+
* so `hub.writeQueue.pending` reflects this write.
|
|
1212
1184
|
*
|
|
1213
1185
|
* @param id Record identifier.
|
|
1214
1186
|
* @param record The record body (validated by the collection's schema
|
|
1215
1187
|
* if one was attached at `vault.collection(...)` time).
|
|
1216
1188
|
* @param options Optional metadata for audit + import workflows.
|
|
1217
1189
|
* `reason` is stamped onto the resulting ledger entry
|
|
1218
|
-
*
|
|
1190
|
+
* so audit consumers can filter via
|
|
1219
1191
|
* `entries.filter(e => e.reason?.startsWith('import:'))`.
|
|
1220
1192
|
*/
|
|
1221
1193
|
async put(id, record, options) {
|
|
1222
1194
|
await this.schemaUpdateGate?.assertWritable();
|
|
1223
1195
|
await this.schemaFence?.assertWritable(this.name);
|
|
1196
|
+
const hooksActive = this.#hooksActive();
|
|
1197
|
+
const busAfterPut = (this.subsystemBus?.hasHandlers("afterPut") ?? false) && !(this.subsystemBus?.dispatching ?? false);
|
|
1224
1198
|
let event;
|
|
1225
|
-
if (
|
|
1199
|
+
if (hooksActive || busAfterPut) {
|
|
1226
1200
|
const prior = await this.#priorForHook(id);
|
|
1227
1201
|
event = {
|
|
1228
1202
|
op: prior.record === null ? "create" : "update",
|
|
@@ -1237,23 +1211,26 @@ var Collection = class {
|
|
|
1237
1211
|
baseVersion: prior.version,
|
|
1238
1212
|
version: prior.version + 1
|
|
1239
1213
|
};
|
|
1240
|
-
await this.writeHooks.runBefore(event);
|
|
1214
|
+
if (hooksActive) await this.writeHooks.runBefore(event);
|
|
1241
1215
|
}
|
|
1242
1216
|
if (this.writeQueue) await this.writeQueue.track(() => this.putInternal(id, record, options));
|
|
1243
1217
|
else await this.putInternal(id, record, options);
|
|
1244
|
-
if (event)
|
|
1218
|
+
if (event) {
|
|
1219
|
+
if (hooksActive) await this.writeHooks.runAfter(event);
|
|
1220
|
+
if (busAfterPut) await this.subsystemBus.dispatch("afterPut", event);
|
|
1221
|
+
}
|
|
1245
1222
|
}
|
|
1246
|
-
/** @internal
|
|
1223
|
+
/** @internal — true when hooks should fire for this write (handlers exist, not re-entrant). */
|
|
1247
1224
|
#hooksActive() {
|
|
1248
1225
|
return this.writeHooks !== void 0 && this.writeHooks.hasHandlers && !this.writeHooks.suppressed;
|
|
1249
1226
|
}
|
|
1250
1227
|
/**
|
|
1251
|
-
* @internal
|
|
1228
|
+
* @internal — resolve the prior record for a hook's `before` and
|
|
1252
1229
|
* its version. Critically, this uses the SAME basis `putInternal` writes from
|
|
1253
1230
|
* (the in-memory cache in eager mode; lru-then-adapter in lazy) — NOT a fresh
|
|
1254
1231
|
* store read — so `baseVersion`/`version` match the version actually written.
|
|
1255
1232
|
* A separate store read would diverge once another tab has advanced the shared
|
|
1256
|
-
* store past this tab's cache, breaking
|
|
1233
|
+
* store past this tab's cache, breaking cross-tab conflict detection.
|
|
1257
1234
|
*/
|
|
1258
1235
|
async #priorForHook(id) {
|
|
1259
1236
|
if (this.lazy && this.lru) {
|
|
@@ -1275,52 +1252,28 @@ var Collection = class {
|
|
|
1275
1252
|
if (!hasWritePermission(this.keyring, this.name)) {
|
|
1276
1253
|
throw new ReadOnlyError();
|
|
1277
1254
|
}
|
|
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) {
|
|
1255
|
+
if (this.subsystemBus?.hasGateHandlers("beforePut")) {
|
|
1311
1256
|
const existingEnv = await this.adapter.get(this.vault, this.name, id);
|
|
1312
|
-
let
|
|
1257
|
+
let existingRecord = null;
|
|
1313
1258
|
if (existingEnv) {
|
|
1314
1259
|
try {
|
|
1315
|
-
|
|
1260
|
+
existingRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
|
|
1316
1261
|
} catch {
|
|
1317
|
-
|
|
1262
|
+
existingRecord = null;
|
|
1318
1263
|
}
|
|
1319
1264
|
}
|
|
1320
|
-
await this.
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1265
|
+
await this.subsystemBus.dispatchGate("beforePut", {
|
|
1266
|
+
op: existingEnv ? "update" : "create",
|
|
1267
|
+
vault: this.vault,
|
|
1268
|
+
collection: this.name,
|
|
1269
|
+
docId: id,
|
|
1270
|
+
incoming: record,
|
|
1271
|
+
existing: existingRecord,
|
|
1272
|
+
existingVersion: existingEnv?._v ?? 0,
|
|
1273
|
+
existingTs: existingEnv?._ts,
|
|
1274
|
+
userId: this.keyring.userId,
|
|
1275
|
+
role: this.keyring.role
|
|
1276
|
+
});
|
|
1324
1277
|
}
|
|
1325
1278
|
if (this.schema !== void 0) {
|
|
1326
1279
|
record = await validateSchemaInput(this.schema, record, `put(${id})`);
|
|
@@ -1506,7 +1459,7 @@ var Collection = class {
|
|
|
1506
1459
|
* Fire registered MV strategies whose dependency set includes this
|
|
1507
1460
|
* collection. Eager-mode MVs re-materialize inline via
|
|
1508
1461
|
* `MaterializedViewExecutor.refresh`; lazy / manual modes are
|
|
1509
|
-
* no-ops in the foundation
|
|
1462
|
+
* no-ops in the foundation; wired in the lazy-mode implementation.
|
|
1510
1463
|
*
|
|
1511
1464
|
* Skips entirely when the record being written is itself an
|
|
1512
1465
|
* MV-emitted row (carries `_materializedFrom`) — defensive guard
|
|
@@ -1529,7 +1482,7 @@ var Collection = class {
|
|
|
1529
1482
|
if (mode === "eager") {
|
|
1530
1483
|
if (executor === null) {
|
|
1531
1484
|
;
|
|
1532
|
-
({ MaterializedViewExecutor: executor } = await import("./executor-
|
|
1485
|
+
({ MaterializedViewExecutor: executor } = await import("./executor-RWICJI7J.js"));
|
|
1533
1486
|
}
|
|
1534
1487
|
await executor.refresh(reg, {
|
|
1535
1488
|
getCollection: (name) => this.materializedViewSource.getCollection(name),
|
|
@@ -1538,7 +1491,7 @@ var Collection = class {
|
|
|
1538
1491
|
});
|
|
1539
1492
|
} else if (mode === "lazy") {
|
|
1540
1493
|
if (staleHelpers === null) {
|
|
1541
|
-
staleHelpers = await import("./stale-
|
|
1494
|
+
staleHelpers = await import("./stale-74WGLVZ2.js");
|
|
1542
1495
|
}
|
|
1543
1496
|
staleHelpers.markMVStale(registry, reg.spec.name);
|
|
1544
1497
|
}
|
|
@@ -1567,7 +1520,7 @@ var Collection = class {
|
|
|
1567
1520
|
const mode = typeof spec.lifecycle === "string" ? spec.lifecycle : spec.lifecycle.mode;
|
|
1568
1521
|
if (mode === "eager") {
|
|
1569
1522
|
if (DerivationExecutor === null) {
|
|
1570
|
-
({ DerivationExecutor } = await import("./executor-
|
|
1523
|
+
({ DerivationExecutor } = await import("./executor-SOLEQVUB.js"));
|
|
1571
1524
|
}
|
|
1572
1525
|
const sourceWithId = { ...incoming, id };
|
|
1573
1526
|
const ctx = { vault: this.derivationSource.getReadOnlyFacade() };
|
|
@@ -1586,7 +1539,7 @@ var Collection = class {
|
|
|
1586
1539
|
const outputCollection = this.derivationSource.getCollection(outSpec.collection);
|
|
1587
1540
|
const txCtx = this.derivationSource.getActiveTxContext();
|
|
1588
1541
|
if (out.kind === "array") {
|
|
1589
|
-
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-
|
|
1542
|
+
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-EVICRM46.js");
|
|
1590
1543
|
const prior = await loadFanoutSidecar(
|
|
1591
1544
|
this.adapter,
|
|
1592
1545
|
this.vault,
|
|
@@ -1650,13 +1603,15 @@ var Collection = class {
|
|
|
1650
1603
|
}
|
|
1651
1604
|
/**
|
|
1652
1605
|
* Delete a record by ID. Runs inside the hub's write-queue tracker
|
|
1653
|
-
*
|
|
1606
|
+
* so `hub.writeQueue.pending` reflects this write.
|
|
1654
1607
|
*/
|
|
1655
1608
|
async delete(id) {
|
|
1656
1609
|
await this.schemaUpdateGate?.assertWritable();
|
|
1657
1610
|
await this.schemaFence?.assertWritable(this.name);
|
|
1611
|
+
const hooksActive = this.#hooksActive();
|
|
1612
|
+
const busAfterDelete = (this.subsystemBus?.hasHandlers("afterDelete") ?? false) && !(this.subsystemBus?.dispatching ?? false);
|
|
1658
1613
|
let event;
|
|
1659
|
-
if (
|
|
1614
|
+
if (hooksActive || busAfterDelete) {
|
|
1660
1615
|
const prior = await this.#priorForHook(id);
|
|
1661
1616
|
event = {
|
|
1662
1617
|
op: "delete",
|
|
@@ -1671,14 +1626,17 @@ var Collection = class {
|
|
|
1671
1626
|
baseVersion: prior.version,
|
|
1672
1627
|
version: prior.version + 1
|
|
1673
1628
|
};
|
|
1674
|
-
await this.writeHooks.runBefore(event);
|
|
1629
|
+
if (hooksActive) await this.writeHooks.runBefore(event);
|
|
1675
1630
|
}
|
|
1676
1631
|
if (this.writeQueue) await this.writeQueue.track(() => this.deleteInternal(id));
|
|
1677
1632
|
else await this.deleteInternal(id);
|
|
1678
|
-
if (event)
|
|
1633
|
+
if (event) {
|
|
1634
|
+
if (hooksActive) await this.writeHooks.runAfter(event);
|
|
1635
|
+
if (busAfterDelete) await this.subsystemBus.dispatch("afterDelete", event);
|
|
1636
|
+
}
|
|
1679
1637
|
}
|
|
1680
1638
|
/**
|
|
1681
|
-
* @internal
|
|
1639
|
+
* @internal — bulk-rewrite every record through a cutover transform.
|
|
1682
1640
|
* Raw adapter path (bypasses the write gate + guards — the transform is
|
|
1683
1641
|
* trusted and runs only during the `migrating` phase). Bumps each
|
|
1684
1642
|
* record's `_v` and appends a ledger `op:'migration'` entry.
|
|
@@ -1717,8 +1675,7 @@ var Collection = class {
|
|
|
1717
1675
|
}
|
|
1718
1676
|
/**
|
|
1719
1677
|
* @internal — system-internal delete that bypasses user-facing
|
|
1720
|
-
* delete hooks (`onDelete`,
|
|
1721
|
-
* enforcer). Used by derivation tombstones (#144) and MV refresh
|
|
1678
|
+
* delete hooks (`onDelete`, FK ref enforcer). Used by derivation tombstones and MV refresh
|
|
1722
1679
|
* (Dim 14 v2) — system housekeeping shouldn't trip user invariants
|
|
1723
1680
|
* registered against the output collection. The ledger entry and
|
|
1724
1681
|
* history snapshot still fire so backup integrity and time-travel
|
|
@@ -1730,7 +1687,7 @@ var Collection = class {
|
|
|
1730
1687
|
*
|
|
1731
1688
|
* When a `txCtx` is supplied, the prior envelope is captured and
|
|
1732
1689
|
* pushed onto `txCtx._executed` BEFORE the delete fires — mirrors
|
|
1733
|
-
* the
|
|
1690
|
+
* the rollback hardening for puts. Callers outside a
|
|
1734
1691
|
* multi-record transaction pass `null` and skip the tracking.
|
|
1735
1692
|
*
|
|
1736
1693
|
* Amendment composition: if `_internalDelete` runs while a vault's
|
|
@@ -1773,58 +1730,27 @@ var Collection = class {
|
|
|
1773
1730
|
if (!hasWritePermission(this.keyring, this.name)) {
|
|
1774
1731
|
throw new ReadOnlyError();
|
|
1775
1732
|
}
|
|
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) {
|
|
1733
|
+
if (this.subsystemBus?.hasGateHandlers("beforeDelete")) {
|
|
1815
1734
|
const existingEnv = await this.adapter.get(this.vault, this.name, id);
|
|
1816
|
-
let priorRecord = null;
|
|
1817
1735
|
if (existingEnv) {
|
|
1736
|
+
let existingRecord = null;
|
|
1818
1737
|
try {
|
|
1819
|
-
|
|
1738
|
+
existingRecord = await this.decryptRecord(existingEnv, { skipValidation: true });
|
|
1820
1739
|
} catch {
|
|
1821
|
-
|
|
1740
|
+
existingRecord = null;
|
|
1822
1741
|
}
|
|
1742
|
+
await this.subsystemBus.dispatchGate("beforeDelete", {
|
|
1743
|
+
vault: this.vault,
|
|
1744
|
+
collection: this.name,
|
|
1745
|
+
docId: id,
|
|
1746
|
+
existing: existingRecord,
|
|
1747
|
+
existingVersion: existingEnv._v,
|
|
1748
|
+
existingTs: existingEnv._ts,
|
|
1749
|
+
internal,
|
|
1750
|
+
userId: this.keyring.userId,
|
|
1751
|
+
role: this.keyring.role
|
|
1752
|
+
});
|
|
1823
1753
|
}
|
|
1824
|
-
await this.periodGuard(
|
|
1825
|
-
existingEnv ? { ts: existingEnv._ts, record: priorRecord } : null,
|
|
1826
|
-
null
|
|
1827
|
-
);
|
|
1828
1754
|
}
|
|
1829
1755
|
if (!internal && this.refEnforcer !== void 0) {
|
|
1830
1756
|
await this.refEnforcer.enforceRefsOnDelete(this.name, id);
|
|
@@ -1885,7 +1811,7 @@ var Collection = class {
|
|
|
1885
1811
|
}
|
|
1886
1812
|
/**
|
|
1887
1813
|
* Cascade deletes of array-shape derived rows when a source row is
|
|
1888
|
-
* deleted
|
|
1814
|
+
* deleted. Reads each registered strategy's fanout sidecar
|
|
1889
1815
|
* for this source id, deletes every listed derived row, then
|
|
1890
1816
|
* deletes the sidecar itself.
|
|
1891
1817
|
*
|
|
@@ -1905,7 +1831,7 @@ var Collection = class {
|
|
|
1905
1831
|
for (const [outputKey, outSpec] of Object.entries(spec.outputs)) {
|
|
1906
1832
|
if (outSpec.shape !== "array") continue;
|
|
1907
1833
|
if (helpers === null) {
|
|
1908
|
-
helpers = await import("./fanout-sidecar-
|
|
1834
|
+
helpers = await import("./fanout-sidecar-EVICRM46.js");
|
|
1909
1835
|
}
|
|
1910
1836
|
const sidecar = await helpers.loadFanoutSidecar(
|
|
1911
1837
|
this.adapter,
|
|
@@ -1924,8 +1850,8 @@ var Collection = class {
|
|
|
1924
1850
|
}
|
|
1925
1851
|
}
|
|
1926
1852
|
/**
|
|
1927
|
-
* Mirror of {@link dispatchMaterializedViews} for the delete path
|
|
1928
|
-
*
|
|
1853
|
+
* Mirror of {@link dispatchMaterializedViews} for the delete path.
|
|
1854
|
+
* No record content is available (it's gone), so the
|
|
1929
1855
|
* `_materializedFrom` skip used by the put-side dispatch doesn't
|
|
1930
1856
|
* apply here — instead, the recursion guard is the `internal` gate
|
|
1931
1857
|
* at the `_doDelete` call site above.
|
|
@@ -1945,7 +1871,7 @@ var Collection = class {
|
|
|
1945
1871
|
if (mode === "eager") {
|
|
1946
1872
|
if (executor === null) {
|
|
1947
1873
|
;
|
|
1948
|
-
({ MaterializedViewExecutor: executor } = await import("./executor-
|
|
1874
|
+
({ MaterializedViewExecutor: executor } = await import("./executor-RWICJI7J.js"));
|
|
1949
1875
|
}
|
|
1950
1876
|
await executor.refresh(reg, {
|
|
1951
1877
|
getCollection: (name) => this.materializedViewSource.getCollection(name),
|
|
@@ -1954,7 +1880,7 @@ var Collection = class {
|
|
|
1954
1880
|
});
|
|
1955
1881
|
} else if (mode === "lazy") {
|
|
1956
1882
|
if (staleHelpers === null) {
|
|
1957
|
-
staleHelpers = await import("./stale-
|
|
1883
|
+
staleHelpers = await import("./stale-74WGLVZ2.js");
|
|
1958
1884
|
}
|
|
1959
1885
|
staleHelpers.markMVStale(registry, reg.spec.name);
|
|
1960
1886
|
}
|
|
@@ -1977,7 +1903,7 @@ var Collection = class {
|
|
|
1977
1903
|
);
|
|
1978
1904
|
}
|
|
1979
1905
|
if (this.materializedViewSource !== void 0) {
|
|
1980
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
1906
|
+
const { resolveStaleMVOnRead } = await import("./stale-74WGLVZ2.js");
|
|
1981
1907
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name);
|
|
1982
1908
|
}
|
|
1983
1909
|
await this.ensureHydrated();
|
|
@@ -2455,7 +2381,7 @@ var Collection = class {
|
|
|
2455
2381
|
* .aggregate({ total: sum('amount'), n: count() })
|
|
2456
2382
|
* ```
|
|
2457
2383
|
*
|
|
2458
|
-
* **Lazy-MV gap
|
|
2384
|
+
* **Lazy-MV gap:** `scan()` is synchronous-build and does
|
|
2459
2385
|
* NOT trigger lazy materialized-view resolve-on-read. For lazy
|
|
2460
2386
|
* MVs, call `list()` (which DOES resolve) or `vault.refreshView(name)`
|
|
2461
2387
|
* before scanning. Same shape as the `query()` limitation.
|
|
@@ -2536,7 +2462,7 @@ var Collection = class {
|
|
|
2536
2462
|
this.indexes?.upsert(id, record, previous ? previous.record : null);
|
|
2537
2463
|
}
|
|
2538
2464
|
/**
|
|
2539
|
-
*
|
|
2465
|
+
* Apply a peer tab's committed write to THIS tab's in-memory view:
|
|
2540
2466
|
* re-read the (already-persisted) envelope from the shared store + refresh
|
|
2541
2467
|
* cache/indexes, then emit a `change` event so reactive consumers re-render.
|
|
2542
2468
|
* Never writes to the store and never fires write hooks, so it cannot loop.
|
|
@@ -2545,7 +2471,7 @@ var Collection = class {
|
|
|
2545
2471
|
await this._invalidateCacheEntry(id);
|
|
2546
2472
|
this.emitter.emit("change", { vault: this.vault, collection: this.name, id, action });
|
|
2547
2473
|
}
|
|
2548
|
-
/** @internal
|
|
2474
|
+
/** @internal — the current in-memory record without a store read (for conflict capture). */
|
|
2549
2475
|
_peekCached(id) {
|
|
2550
2476
|
const entry = this.lazy && this.lru ? this.lru.get(id) : this.cache.get(id);
|
|
2551
2477
|
return entry ? entry.record : null;
|
|
@@ -3648,7 +3574,7 @@ var UserApi = class {
|
|
|
3648
3574
|
* the envelope on first call. Optimistic-concurrency safe — a stale
|
|
3649
3575
|
* `_v` (parallel writer on another device) throws `ConflictError`.
|
|
3650
3576
|
*
|
|
3651
|
-
* Patch semantics
|
|
3577
|
+
* Patch semantics:
|
|
3652
3578
|
* - `undefined` (or omitted key) — skip; existing value preserved
|
|
3653
3579
|
* - `null` — delete the field from the merged result
|
|
3654
3580
|
* - any other value — overwrite (deep-merge for plain objects,
|
|
@@ -3704,7 +3630,7 @@ var UserApi = class {
|
|
|
3704
3630
|
this.fireChange(this.writerKeyringId, written);
|
|
3705
3631
|
return written;
|
|
3706
3632
|
}
|
|
3707
|
-
// ─── Visibility
|
|
3633
|
+
// ─── Visibility ──────────────────────────────────────────────────────
|
|
3708
3634
|
/**
|
|
3709
3635
|
* Read the current user's visibility flag from
|
|
3710
3636
|
* `_meta/visibility/<keyringId>`. Returns `{ hidden: false }` when no
|
|
@@ -4554,23 +4480,23 @@ var Vault = class {
|
|
|
4554
4480
|
* `null` for vaults that never register any guard strategy. The
|
|
4555
4481
|
* runtime class is dynamic-imported on demand so consumers that
|
|
4556
4482
|
* never use guards don't pull `GuardRegistry`/`GuardExecutor` into
|
|
4557
|
-
* their bundle
|
|
4483
|
+
* their bundle.
|
|
4558
4484
|
*/
|
|
4559
4485
|
guardRegistry = null;
|
|
4560
4486
|
/**
|
|
4561
4487
|
* Per-vault derivation registry. Same lazy-load contract as
|
|
4562
4488
|
* `guardRegistry` — `null` until `_initDerivations()` runs with at
|
|
4563
|
-
* least one strategy handle.
|
|
4489
|
+
* least one strategy handle.
|
|
4564
4490
|
*/
|
|
4565
4491
|
derivationRegistry = null;
|
|
4566
4492
|
/**
|
|
4567
|
-
* Per-vault materialized-view registry
|
|
4493
|
+
* Per-vault materialized-view registry. Same lazy-load
|
|
4568
4494
|
* contract as `derivationRegistry` — `null` until
|
|
4569
4495
|
* `_initMaterializedViews()` runs with at least one MV handle.
|
|
4570
4496
|
*/
|
|
4571
4497
|
materializedViewRegistry = null;
|
|
4572
4498
|
/**
|
|
4573
|
-
* Per-vault overlay registry
|
|
4499
|
+
* Per-vault overlay registry. Same lazy-load contract as
|
|
4574
4500
|
* `materializedViewRegistry` — `null` until `_initOverlayedViews()`
|
|
4575
4501
|
* runs with at least one handle.
|
|
4576
4502
|
*/
|
|
@@ -4591,7 +4517,7 @@ var Vault = class {
|
|
|
4591
4517
|
* target this vault session's keyringId. There is no method to write
|
|
4592
4518
|
* another principal's envelope (own-only write rule, structural).
|
|
4593
4519
|
* - Read-anyone: `get(keyringId)`, `list()` — read other principals'
|
|
4594
|
-
* envelopes, subject to the `view-team-profiles` policy gate
|
|
4520
|
+
* envelopes, subject to the `view-team-profiles` policy gate.
|
|
4595
4521
|
* - Reactive: `subscribe(id, cb)`, `live(id)` — fire on local writes.
|
|
4596
4522
|
*
|
|
4597
4523
|
* @see docs/superpowers/specs/2026-05-05-user-envelope-design.md
|
|
@@ -4611,12 +4537,12 @@ var Vault = class {
|
|
|
4611
4537
|
*/
|
|
4612
4538
|
reloadKeyring;
|
|
4613
4539
|
collectionCache = /* @__PURE__ */ new Map();
|
|
4614
|
-
/**
|
|
4540
|
+
/** Vault-level schema cutover fence/controller. */
|
|
4615
4541
|
schemaFence;
|
|
4616
|
-
/**
|
|
4542
|
+
/** Per-client heartbeat/watcher; started lazily on cutover registration. */
|
|
4617
4543
|
#fenceWatcher;
|
|
4618
4544
|
#fenceCoordinationStarted = false;
|
|
4619
|
-
/**
|
|
4545
|
+
/** Per-collection registered schema-update strategy names. */
|
|
4620
4546
|
#schemaUpdateNames = /* @__PURE__ */ new Map();
|
|
4621
4547
|
/**
|
|
4622
4548
|
* per-collection `blobFields` retention/TTL config.
|
|
@@ -4690,8 +4616,7 @@ var Vault = class {
|
|
|
4690
4616
|
* Cache of closed/opened accounting periods.
|
|
4691
4617
|
* Populated on first `closePeriod` / `openPeriod` / `listPeriods` /
|
|
4692
4618
|
* per-collection write call. Kept in memory as an ordered list (by
|
|
4693
|
-
* `closedAt`) so
|
|
4694
|
-
* each collection's put/delete path.
|
|
4619
|
+
* `closedAt`) so period checks run fast when the gate bus fires.
|
|
4695
4620
|
*
|
|
4696
4621
|
* Sentinel `null` means "not yet loaded" — the first consumer
|
|
4697
4622
|
* triggers a one-time `loadPeriods()` pass. Every subsequent
|
|
@@ -4886,6 +4811,7 @@ var Vault = class {
|
|
|
4886
4811
|
emitter: this.emitter,
|
|
4887
4812
|
writeQueue: this.noydb._writeQueueTracker,
|
|
4888
4813
|
writeHooks: this.noydb._writeHooks,
|
|
4814
|
+
subsystemBus: this.noydb._subsystemBus,
|
|
4889
4815
|
activeTxId: () => this.noydb._activeTxContextOrNull?.txId ?? null,
|
|
4890
4816
|
schemaUpdateGate,
|
|
4891
4817
|
schemaFence: this.schemaFence,
|
|
@@ -4908,18 +4834,12 @@ var Vault = class {
|
|
|
4908
4834
|
defaultLocale: this.locale,
|
|
4909
4835
|
onRegisterConflictResolver: this.onRegisterConflictResolver,
|
|
4910
4836
|
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
|
-
} : {},
|
|
4837
|
+
// Derivation source is only wired when the corresponding registry
|
|
4838
|
+
// has been initialised. Guard source was removed in Track A slice 3b
|
|
4839
|
+
// — guards now run via the gate bus in Noydb.#registerGuardGate.
|
|
4840
|
+
// Vaults without derivations skip this so `Collection.put`'s
|
|
4841
|
+
// `if (this.derivationSource)` branch no-ops without touching the
|
|
4842
|
+
// derivation subsystem code.
|
|
4923
4843
|
...this.derivationRegistry !== null ? {
|
|
4924
4844
|
derivationSource: {
|
|
4925
4845
|
registry: () => this.derivationRegistry,
|
|
@@ -5009,7 +4929,7 @@ var Vault = class {
|
|
|
5009
4929
|
await Promise.allSettled(pending);
|
|
5010
4930
|
}
|
|
5011
4931
|
/**
|
|
5012
|
-
* Run a coordinated schema cutover
|
|
4932
|
+
* Run a coordinated schema cutover. Drains pending writes, waits
|
|
5013
4933
|
* for the active client set to quiesce (the ack-barrier), applies every
|
|
5014
4934
|
* pending collection transform in bulk, bumps the vault schema generation,
|
|
5015
4935
|
* and clears the fence. Returns the count of collections migrated.
|
|
@@ -5027,9 +4947,9 @@ var Vault = class {
|
|
|
5027
4947
|
await coll._applyCutoverTransform(transform);
|
|
5028
4948
|
}
|
|
5029
4949
|
/**
|
|
5030
|
-
*
|
|
4950
|
+
* Refresh a loaded collection's view of one document from a peer
|
|
5031
4951
|
* tab's broadcast. No-op when the collection isn't loaded in this tab
|
|
5032
|
-
* (it will read fresh on next open). Mirrors
|
|
4952
|
+
* (it will read fresh on next open). Mirrors `#runCutoverTransform`'s guard.
|
|
5033
4953
|
*/
|
|
5034
4954
|
async _applyRemoteWrite(collectionName, docId, action) {
|
|
5035
4955
|
const coll = this.collectionCache.get(collectionName);
|
|
@@ -5037,9 +4957,9 @@ var Vault = class {
|
|
|
5037
4957
|
await coll._applyRemoteChange(docId, action);
|
|
5038
4958
|
}
|
|
5039
4959
|
/**
|
|
5040
|
-
*
|
|
4960
|
+
* For a detected conflict: capture this tab's clobbered record,
|
|
5041
4961
|
* read the common ancestor from history, converge the cache to the store's
|
|
5042
|
-
* authoritative value (the
|
|
4962
|
+
* authoritative value (the re-read), and return all three for the
|
|
5043
4963
|
* WriteConflict payload. Returns null when the collection isn't loaded.
|
|
5044
4964
|
*/
|
|
5045
4965
|
async _captureAndConverge(collectionName, docId, action, baseV) {
|
|
@@ -5056,15 +4976,15 @@ var Vault = class {
|
|
|
5056
4976
|
const remote = await coll.get(docId);
|
|
5057
4977
|
return { local, remote, base };
|
|
5058
4978
|
}
|
|
5059
|
-
/** Recover a stuck cutover fence
|
|
4979
|
+
/** Recover a stuck cutover fence — reset to normal without bumping. */
|
|
5060
4980
|
async abortSchemaCutover() {
|
|
5061
4981
|
await this.schemaFence.abort();
|
|
5062
4982
|
}
|
|
5063
|
-
/** Current schema-cutover fence state for this vault
|
|
4983
|
+
/** Current schema-cutover fence state for this vault. Thin live read. */
|
|
5064
4984
|
async schemaFenceState() {
|
|
5065
4985
|
return loadFence(this.adapter, this.name);
|
|
5066
4986
|
}
|
|
5067
|
-
/** @internal Start the per-client heartbeat + fence watcher once a cutover is registered
|
|
4987
|
+
/** @internal Start the per-client heartbeat + fence watcher once a cutover is registered. */
|
|
5068
4988
|
_ensureFenceCoordination() {
|
|
5069
4989
|
if (this.#fenceCoordinationStarted) return;
|
|
5070
4990
|
this.#fenceCoordinationStarted = true;
|
|
@@ -5414,12 +5334,12 @@ var Vault = class {
|
|
|
5414
5334
|
if (!fieldSchema) {
|
|
5415
5335
|
throw new AttestationError(`issueAttestation: collection '${collectionName}' has no attestation field-schema. Declare it via vault.collection('${collectionName}', { attestation: { fields: [...] } }).`);
|
|
5416
5336
|
}
|
|
5417
|
-
const { issueAttestationCore } = await import("./issue-
|
|
5337
|
+
const { issueAttestationCore } = await import("./issue-IODMTPME.js");
|
|
5418
5338
|
const out = await issueAttestationCore(this.makeIssueContext(), { collection: collectionName, id, fieldSchema });
|
|
5419
5339
|
return { docId: out.docId, qr: out.qr, keyId: out.keyId, publicKeyB64: out.publicKeyB64 };
|
|
5420
5340
|
}
|
|
5421
5341
|
async getDocumentSigningPublicKey() {
|
|
5422
|
-
const { loadSigner, loadOrCreateSigner } = await import("./signer-
|
|
5342
|
+
const { loadSigner, loadOrCreateSigner } = await import("./signer-WGDJNWSU.js");
|
|
5423
5343
|
const existing = await loadSigner(this.adapter, this.name, this.getDEK);
|
|
5424
5344
|
if (existing) return { keyId: existing.keyId, publicKeyB64: existing.publicKeyB64 };
|
|
5425
5345
|
if (this.keyring.role !== "owner") {
|
|
@@ -5445,19 +5365,19 @@ var Vault = class {
|
|
|
5445
5365
|
};
|
|
5446
5366
|
}
|
|
5447
5367
|
async revokeAttestation(docId) {
|
|
5448
|
-
const { revokeDocCore } = await import("./revoke-
|
|
5368
|
+
const { revokeDocCore } = await import("./revoke-R5NIQ74J.js");
|
|
5449
5369
|
await revokeDocCore(this.makeRevokeContext(), docId);
|
|
5450
5370
|
}
|
|
5451
5371
|
async unrevokeAttestation(docId) {
|
|
5452
|
-
const { unrevokeDocCore } = await import("./revoke-
|
|
5372
|
+
const { unrevokeDocCore } = await import("./revoke-R5NIQ74J.js");
|
|
5453
5373
|
await unrevokeDocCore(this.makeRevokeContext(), docId);
|
|
5454
5374
|
}
|
|
5455
5375
|
async getRevokedDocIds() {
|
|
5456
|
-
const { getRevokedDocIdsCore } = await import("./revoke-
|
|
5376
|
+
const { getRevokedDocIdsCore } = await import("./revoke-R5NIQ74J.js");
|
|
5457
5377
|
return getRevokedDocIdsCore(this.makeRevokeContext());
|
|
5458
5378
|
}
|
|
5459
5379
|
async publishRevocationList() {
|
|
5460
|
-
const { publishRevocationListCore } = await import("./revoke-
|
|
5380
|
+
const { publishRevocationListCore } = await import("./revoke-R5NIQ74J.js");
|
|
5461
5381
|
return publishRevocationListCore(this.makeRevokeContext());
|
|
5462
5382
|
}
|
|
5463
5383
|
makeRevokeContext() {
|
|
@@ -5737,7 +5657,7 @@ var Vault = class {
|
|
|
5737
5657
|
* Dynamic-imports `GuardRegistry` + `ReadOnlyVaultFacade` and seeds
|
|
5738
5658
|
* the registry with the supplied strategy handles. No-op when the
|
|
5739
5659
|
* handles array is empty — keeps the guard subsystem out of the
|
|
5740
|
-
* floor bundle for consumers that don't use guards
|
|
5660
|
+
* floor bundle for consumers that don't use guards.
|
|
5741
5661
|
*
|
|
5742
5662
|
* The read-only facade is eagerly instantiated here so the sync
|
|
5743
5663
|
* accessor `_getReadOnlyFacade()` (called from the tx amendment
|
|
@@ -5746,7 +5666,7 @@ var Vault = class {
|
|
|
5746
5666
|
async _initGuards(handles) {
|
|
5747
5667
|
if (handles.length === 0) return;
|
|
5748
5668
|
const [{ GuardRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
|
|
5749
|
-
import("./registry-
|
|
5669
|
+
import("./registry-DKEXOJVO.js"),
|
|
5750
5670
|
import("./read-only-facade-ITU6L7BL.js")
|
|
5751
5671
|
]);
|
|
5752
5672
|
const registry = new GuardRegistry();
|
|
@@ -5755,10 +5675,9 @@ var Vault = class {
|
|
|
5755
5675
|
this.readOnlyFacade = new ReadOnlyVaultFacade(this);
|
|
5756
5676
|
}
|
|
5757
5677
|
/**
|
|
5758
|
-
* @internal —
|
|
5759
|
-
* vaults that never registered any guard
|
|
5760
|
-
* gate on null
|
|
5761
|
-
* `Collection` already do this transitively).
|
|
5678
|
+
* @internal — The gate handler in Noydb.#registerGuardGate calls into
|
|
5679
|
+
* this. Returns `null` for vaults that never registered any guard
|
|
5680
|
+
* strategy. Callers MUST gate on null.
|
|
5762
5681
|
*/
|
|
5763
5682
|
_getGuardRegistry() {
|
|
5764
5683
|
return this.guardRegistry;
|
|
@@ -5769,13 +5688,13 @@ var Vault = class {
|
|
|
5769
5688
|
* derivation strategies (async because `strategyHash` computation
|
|
5770
5689
|
* goes through `crypto.subtle.digest`). No-op when the handles
|
|
5771
5690
|
* array is empty — keeps the derivation subsystem out of the floor
|
|
5772
|
-
* bundle for consumers that don't use derivations
|
|
5691
|
+
* bundle for consumers that don't use derivations. Throws
|
|
5773
5692
|
* `DerivationCycleError` if a cycle is detected after registration.
|
|
5774
5693
|
*/
|
|
5775
5694
|
async _initDerivations(handles) {
|
|
5776
5695
|
if (handles.length === 0) return;
|
|
5777
5696
|
const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
|
|
5778
|
-
import("./registry-
|
|
5697
|
+
import("./registry-446I2NMN.js"),
|
|
5779
5698
|
import("./read-only-facade-ITU6L7BL.js")
|
|
5780
5699
|
]);
|
|
5781
5700
|
const registry = new DerivationRegistry();
|
|
@@ -5801,12 +5720,12 @@ var Vault = class {
|
|
|
5801
5720
|
* MV spec (which invokes its `query()` once for dependency
|
|
5802
5721
|
* analysis), then runs the unified cycle detection across the MV +
|
|
5803
5722
|
* derivation graphs. No-op when the handles array is empty — keeps
|
|
5804
|
-
* the MV subsystem out of the floor bundle (mirrors
|
|
5723
|
+
* the MV subsystem out of the floor bundle (mirrors the derivation lazy-import pattern).
|
|
5805
5724
|
* Throws `MaterializedViewCycleError` if a cycle is detected.
|
|
5806
5725
|
*/
|
|
5807
5726
|
async _initMaterializedViews(handles) {
|
|
5808
5727
|
if (handles.length === 0) return;
|
|
5809
|
-
const { MaterializedViewRegistry } = await import("./registry-
|
|
5728
|
+
const { MaterializedViewRegistry } = await import("./registry-4NEW7LQY.js");
|
|
5810
5729
|
const registry = new MaterializedViewRegistry();
|
|
5811
5730
|
this.materializedViewRegistry = registry;
|
|
5812
5731
|
const db = this;
|
|
@@ -5830,7 +5749,7 @@ var Vault = class {
|
|
|
5830
5749
|
*/
|
|
5831
5750
|
async _initOverlayedViews(handles) {
|
|
5832
5751
|
if (handles.length === 0) return;
|
|
5833
|
-
const { OverlayedViewRegistry } = await import("./registry-
|
|
5752
|
+
const { OverlayedViewRegistry } = await import("./registry-524KJZG4.js");
|
|
5834
5753
|
const registry = new OverlayedViewRegistry();
|
|
5835
5754
|
const mvRegistry = this.materializedViewRegistry;
|
|
5836
5755
|
const overlayNames = /* @__PURE__ */ new Set();
|
|
@@ -5858,13 +5777,13 @@ var Vault = class {
|
|
|
5858
5777
|
return this.overlayedViewRegistry;
|
|
5859
5778
|
}
|
|
5860
5779
|
/**
|
|
5861
|
-
* Manual re-materialize for a single registered MV
|
|
5780
|
+
* Manual re-materialize for a single registered MV. Useful
|
|
5862
5781
|
* for `refresh: 'manual'` MVs (whose consumer drives refreshes
|
|
5863
5782
|
* externally), for stale-bit recovery on vault re-open, and as the
|
|
5864
5783
|
* explicit bulk-recompute escape hatch after a strategy change.
|
|
5865
5784
|
*
|
|
5866
|
-
* Returns `{ written, deleted, failed }`. `deleted` is always 0
|
|
5867
|
-
*
|
|
5785
|
+
* Returns `{ written, deleted, failed }`. `deleted` is always 0
|
|
5786
|
+
* when tombstoning is not enabled.
|
|
5868
5787
|
*
|
|
5869
5788
|
* Throws if `name` is not a registered MV.
|
|
5870
5789
|
*/
|
|
@@ -5877,13 +5796,13 @@ var Vault = class {
|
|
|
5877
5796
|
if (!reg) {
|
|
5878
5797
|
throw new Error(`refreshView: no MV registered with name "${name}"`);
|
|
5879
5798
|
}
|
|
5880
|
-
const { MaterializedViewExecutor } = await import("./executor-
|
|
5799
|
+
const { MaterializedViewExecutor } = await import("./executor-RWICJI7J.js");
|
|
5881
5800
|
const result = await MaterializedViewExecutor.refresh(reg, {
|
|
5882
5801
|
getCollection: (n) => this.collection(n),
|
|
5883
5802
|
getActiveTxContext: () => this.noydb._activeTxContextOrNull,
|
|
5884
5803
|
getQueryContext: () => this
|
|
5885
5804
|
});
|
|
5886
|
-
const { clearMVStale } = await import("./stale-
|
|
5805
|
+
const { clearMVStale } = await import("./stale-74WGLVZ2.js");
|
|
5887
5806
|
clearMVStale(registry, name);
|
|
5888
5807
|
return result;
|
|
5889
5808
|
}
|
|
@@ -5899,7 +5818,7 @@ var Vault = class {
|
|
|
5899
5818
|
if (registry === null) return { derived: 0, failed: 0 };
|
|
5900
5819
|
const strategies = registry.strategiesForSource(sourceCollection);
|
|
5901
5820
|
if (strategies.length === 0) return { derived: 0, failed: 0 };
|
|
5902
|
-
const { DerivationExecutor } = await import("./executor-
|
|
5821
|
+
const { DerivationExecutor } = await import("./executor-SOLEQVUB.js");
|
|
5903
5822
|
const sourceColl = this.collection(sourceCollection);
|
|
5904
5823
|
const records = await sourceColl.list();
|
|
5905
5824
|
const ctx = { vault: this.readOnlyFacade ?? new (await import("./read-only-facade-ITU6L7BL.js")).ReadOnlyVaultFacade(this) };
|
|
@@ -5924,7 +5843,7 @@ var Vault = class {
|
|
|
5924
5843
|
if (!outSpec) continue;
|
|
5925
5844
|
const outputColl = this.collection(outSpec.collection);
|
|
5926
5845
|
if (out.kind === "array") {
|
|
5927
|
-
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-
|
|
5846
|
+
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-EVICRM46.js");
|
|
5928
5847
|
const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key);
|
|
5929
5848
|
const prevKeys = new Set(prior?.keys ?? []);
|
|
5930
5849
|
const newKeysList = out.entries.map((e) => e.key);
|
|
@@ -5960,22 +5879,19 @@ var Vault = class {
|
|
|
5960
5879
|
/**
|
|
5961
5880
|
* @internal — exposed for `runTransaction({ amendment: true })` so
|
|
5962
5881
|
* the amendment invariant runner can pass the SAME read-only vault
|
|
5963
|
-
* facade that the
|
|
5964
|
-
*
|
|
5965
|
-
* `
|
|
5966
|
-
*
|
|
5967
|
-
*
|
|
5882
|
+
* facade that the gate handler in Noydb.#registerGuardGate uses.
|
|
5883
|
+
* Eagerly instantiated by `_initGuards()` so this accessor stays
|
|
5884
|
+
* synchronous; returns `null` for vaults that never registered any
|
|
5885
|
+
* guard (amendments require at least one guard, so the caller should
|
|
5886
|
+
* never see null).
|
|
5968
5887
|
*/
|
|
5969
5888
|
_getReadOnlyFacade() {
|
|
5970
5889
|
return this.readOnlyFacade;
|
|
5971
5890
|
}
|
|
5972
5891
|
/**
|
|
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").
|
|
5892
|
+
* Internal lazy-allocator for the read-only facade. Used as a
|
|
5893
|
+
* defensive fallback; in practice `_initGuards()` eagerly
|
|
5894
|
+
* instantiates this, so the lazy path is a no-op.
|
|
5979
5895
|
*/
|
|
5980
5896
|
_ensureReadOnlyFacade() {
|
|
5981
5897
|
if (this.readOnlyFacade !== null) return this.readOnlyFacade;
|
|
@@ -6148,7 +6064,7 @@ var Vault = class {
|
|
|
6148
6064
|
* collection.
|
|
6149
6065
|
*/
|
|
6150
6066
|
async delegate(opts) {
|
|
6151
|
-
const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-
|
|
6067
|
+
const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-42LO4WFO.js");
|
|
6152
6068
|
if (!this.keyring.kek) {
|
|
6153
6069
|
throw new ValidationError(
|
|
6154
6070
|
"issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (passphrase) first."
|
|
@@ -6170,7 +6086,7 @@ var Vault = class {
|
|
|
6170
6086
|
* if the id does not exist.
|
|
6171
6087
|
*/
|
|
6172
6088
|
async revokeDelegation(id) {
|
|
6173
|
-
const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-
|
|
6089
|
+
const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-42LO4WFO.js");
|
|
6174
6090
|
await revokeDelegation(this.adapter, this.name, id);
|
|
6175
6091
|
void DELEGATIONS_COLLECTION;
|
|
6176
6092
|
}
|
|
@@ -6430,7 +6346,7 @@ var Vault = class {
|
|
|
6430
6346
|
const all = await this._loadPeriodsCache();
|
|
6431
6347
|
return all.find((p) => p.name === name) ?? null;
|
|
6432
6348
|
}
|
|
6433
|
-
/** @internal —
|
|
6349
|
+
/** @internal — called by the gate bus before put/delete. */
|
|
6434
6350
|
async _assertTsWritable(existing, incoming) {
|
|
6435
6351
|
if (existing === null && incoming === null) return;
|
|
6436
6352
|
if (this.periodCache === null) {
|
|
@@ -6518,7 +6434,7 @@ var Vault = class {
|
|
|
6518
6434
|
return dumpVaultSchema(this, opts);
|
|
6519
6435
|
}
|
|
6520
6436
|
/**
|
|
6521
|
-
* Lightweight read of the vault's registered schema
|
|
6437
|
+
* Lightweight read of the vault's registered schema: collections
|
|
6522
6438
|
* (+ doc counts), guards, materialized views, schema-update strategies,
|
|
6523
6439
|
* and the unlocked user's grants. Cheap — one `adapter.list` per
|
|
6524
6440
|
* collection, no decryption. For a full snapshot + stats use dumpSchema().
|
|
@@ -6639,7 +6555,7 @@ var Vault = class {
|
|
|
6639
6555
|
* @see docs/subsystems/public-envelope.md
|
|
6640
6556
|
*/
|
|
6641
6557
|
async getPublicEnvelope(opts = {}) {
|
|
6642
|
-
const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-
|
|
6558
|
+
const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-YKHKP74C.js");
|
|
6643
6559
|
return readPublicEnvelope2(this.adapter, this.name, opts);
|
|
6644
6560
|
}
|
|
6645
6561
|
/**
|
|
@@ -7305,6 +7221,110 @@ var WriteHookRegistry = class {
|
|
|
7305
7221
|
}
|
|
7306
7222
|
};
|
|
7307
7223
|
|
|
7224
|
+
// src/subsystem-bus.ts
|
|
7225
|
+
var SubsystemBus = class {
|
|
7226
|
+
#handlers = /* @__PURE__ */ new Map();
|
|
7227
|
+
#gateHandlers = /* @__PURE__ */ new Map();
|
|
7228
|
+
#depth = 0;
|
|
7229
|
+
/** Register a handler for an observe point. Returns an unsubscribe fn. */
|
|
7230
|
+
register(point, handler) {
|
|
7231
|
+
let arr = this.#handlers.get(point);
|
|
7232
|
+
if (!arr) {
|
|
7233
|
+
arr = [];
|
|
7234
|
+
this.#handlers.set(point, arr);
|
|
7235
|
+
}
|
|
7236
|
+
arr.push(handler);
|
|
7237
|
+
return () => {
|
|
7238
|
+
const a = this.#handlers.get(point);
|
|
7239
|
+
if (!a) return;
|
|
7240
|
+
const i = a.indexOf(handler);
|
|
7241
|
+
if (i >= 0) a.splice(i, 1);
|
|
7242
|
+
};
|
|
7243
|
+
}
|
|
7244
|
+
/** Cheap gate for the write path — true when any handler is registered for the point. */
|
|
7245
|
+
hasHandlers(point) {
|
|
7246
|
+
const a = this.#handlers.get(point);
|
|
7247
|
+
return a !== void 0 && a.length > 0;
|
|
7248
|
+
}
|
|
7249
|
+
/**
|
|
7250
|
+
* True while one or more dispatches are in flight. Backed by a depth counter
|
|
7251
|
+
* so that two concurrent async dispatches (`Promise.all([put('a'), put('b')])`
|
|
7252
|
+
* each captured `busAfterPut=true` at their respective put() tops while depth
|
|
7253
|
+
* was 0) both proceed independently — the counter stays > 0 until BOTH finish,
|
|
7254
|
+
* so any nested write attempted by a handler still sees `dispatching === true`
|
|
7255
|
+
* and is suppressed by the write-path gate in `collection.ts`
|
|
7256
|
+
* (`busAfterPut = hasHandlers('afterPut') && !dispatching`). Re-entrancy
|
|
7257
|
+
* suppression lives exclusively on that write-path gate; concurrent independent
|
|
7258
|
+
* dispatches must not drop each other's events.
|
|
7259
|
+
*/
|
|
7260
|
+
get dispatching() {
|
|
7261
|
+
return this.#depth > 0;
|
|
7262
|
+
}
|
|
7263
|
+
/**
|
|
7264
|
+
* Dispatch in registration order, awaited. Per-handler errors are warned, not
|
|
7265
|
+
* thrown — an observe handler must never abort a completed write. A
|
|
7266
|
+
* re-entrancy guard suppresses nested firing so a handler that itself writes
|
|
7267
|
+
* cannot loop (same rationale as WriteHookRegistry.#suppressed).
|
|
7268
|
+
*/
|
|
7269
|
+
async dispatch(point, event) {
|
|
7270
|
+
const a = this.#handlers.get(point);
|
|
7271
|
+
if (!a || a.length === 0) return;
|
|
7272
|
+
this.#depth++;
|
|
7273
|
+
try {
|
|
7274
|
+
for (const h of a.slice()) {
|
|
7275
|
+
try {
|
|
7276
|
+
await h(event);
|
|
7277
|
+
} catch (err) {
|
|
7278
|
+
console.warn(
|
|
7279
|
+
`[noy-db] subsystem observe handler failed at ${point}: ` + (err instanceof Error ? err.message : String(err))
|
|
7280
|
+
);
|
|
7281
|
+
}
|
|
7282
|
+
}
|
|
7283
|
+
} finally {
|
|
7284
|
+
this.#depth--;
|
|
7285
|
+
}
|
|
7286
|
+
}
|
|
7287
|
+
/** Register a write-gating handler. A throw from the handler ABORTS the write. Returns an unsubscribe fn. */
|
|
7288
|
+
registerGate(point, handler) {
|
|
7289
|
+
let arr = this.#gateHandlers.get(point);
|
|
7290
|
+
if (!arr) {
|
|
7291
|
+
arr = [];
|
|
7292
|
+
this.#gateHandlers.set(point, arr);
|
|
7293
|
+
}
|
|
7294
|
+
arr.push(handler);
|
|
7295
|
+
return () => {
|
|
7296
|
+
const a = this.#gateHandlers.get(point);
|
|
7297
|
+
if (!a) return;
|
|
7298
|
+
const i = a.indexOf(handler);
|
|
7299
|
+
if (i >= 0) a.splice(i, 1);
|
|
7300
|
+
};
|
|
7301
|
+
}
|
|
7302
|
+
/** Cheap gate for the write path — true when any gate handler is registered for the point. */
|
|
7303
|
+
hasGateHandlers(point) {
|
|
7304
|
+
const a = this.#gateHandlers.get(point);
|
|
7305
|
+
return a !== void 0 && a.length > 0;
|
|
7306
|
+
}
|
|
7307
|
+
/**
|
|
7308
|
+
* Run gate handlers in registration order, awaited. Unlike `dispatch`
|
|
7309
|
+
* (observe), a handler throw is NOT swallowed — it PROPAGATES, aborting the
|
|
7310
|
+
* write before it reaches the store. The first throw stops the remaining
|
|
7311
|
+
* handlers (fail-fast). This is the seam guards/periods migrate onto.
|
|
7312
|
+
*
|
|
7313
|
+
* Note: gate handlers are validators that read, not write. A gate handler
|
|
7314
|
+
* that writes back into the same collection would re-enter the write path
|
|
7315
|
+
* and re-dispatch this point; loop-suppression for that case is deferred to
|
|
7316
|
+
* the migration slice (contract: gate handlers must not perform writes that
|
|
7317
|
+
* re-trigger their own point).
|
|
7318
|
+
*/
|
|
7319
|
+
async dispatchGate(point, event) {
|
|
7320
|
+
const a = this.#gateHandlers.get(point);
|
|
7321
|
+
if (!a || a.length === 0) return;
|
|
7322
|
+
for (const h of a.slice()) {
|
|
7323
|
+
await h(event);
|
|
7324
|
+
}
|
|
7325
|
+
}
|
|
7326
|
+
};
|
|
7327
|
+
|
|
7308
7328
|
// src/tab-coordination.ts
|
|
7309
7329
|
var TabCoordinator = class {
|
|
7310
7330
|
tabId;
|
|
@@ -7661,9 +7681,9 @@ var PERSONAL_POLICY = Object.freeze({
|
|
|
7661
7681
|
minTier: 1,
|
|
7662
7682
|
enabled: true
|
|
7663
7683
|
},
|
|
7664
|
-
// rotate-recovery
|
|
7665
|
-
// when the user remembers their passphrase. PERSONAL
|
|
7666
|
-
//
|
|
7684
|
+
// rotate-recovery: deliberate paper-sheet regeneration
|
|
7685
|
+
// when the user remembers their passphrase. PERSONAL allows tier-1 —
|
|
7686
|
+
// knowing the passphrase is enough.
|
|
7667
7687
|
"rotate-recovery": { minTier: 1 },
|
|
7668
7688
|
"enroll-authenticator": { minTier: 1 },
|
|
7669
7689
|
"remove-authenticator": { minTier: 1 },
|
|
@@ -7697,7 +7717,7 @@ var PERSONAL_POLICY = Object.freeze({
|
|
|
7697
7717
|
minTier: 1,
|
|
7698
7718
|
enabled: false
|
|
7699
7719
|
},
|
|
7700
|
-
// ─── User envelope gates
|
|
7720
|
+
// ─── User envelope gates ──────────────────────────────────────────
|
|
7701
7721
|
// edit-own-profile: tier 3 floor — any active session can edit their
|
|
7702
7722
|
// own profile/preferences. Tightening to require a TOTP for
|
|
7703
7723
|
// profile changes is a one-line override.
|
|
@@ -7724,7 +7744,7 @@ var STRICT_POLICY = Object.freeze({
|
|
|
7724
7744
|
minTier: 1,
|
|
7725
7745
|
enabled: true
|
|
7726
7746
|
},
|
|
7727
|
-
// rotate-recovery
|
|
7747
|
+
// rotate-recovery: STRICT requires an off-device factor —
|
|
7728
7748
|
// rotating recovery is an off-site-trust event; a stolen unlocked
|
|
7729
7749
|
// laptop must not be able to silently mint a new sheet for the
|
|
7730
7750
|
// attacker. Matches the `peer-recover-user` STRICT default.
|
|
@@ -7797,7 +7817,7 @@ var STRICT_POLICY = Object.freeze({
|
|
|
7797
7817
|
minTier: 1,
|
|
7798
7818
|
enabled: false
|
|
7799
7819
|
},
|
|
7800
|
-
// ─── User envelope gates
|
|
7820
|
+
// ─── User envelope gates ──────────────────────────────────────────
|
|
7801
7821
|
// STRICT: profile edits require a TOTP/email-OTP factor (typical
|
|
7802
7822
|
// shared-workstation hardening — your name/avatar shouldn't change
|
|
7803
7823
|
// without a fresh second-factor proof).
|
|
@@ -7908,13 +7928,14 @@ var Noydb = class {
|
|
|
7908
7928
|
emitter = new NoydbEventEmitter();
|
|
7909
7929
|
writeQueueTracker = new WriteQueueTracker();
|
|
7910
7930
|
writeHooks = new WriteHookRegistry();
|
|
7931
|
+
subsystemBus = new SubsystemBus();
|
|
7911
7932
|
clientId = generateULID();
|
|
7912
7933
|
vaultCache = /* @__PURE__ */ new Map();
|
|
7913
7934
|
keyringCache = /* @__PURE__ */ new Map();
|
|
7914
7935
|
syncEngines = /* @__PURE__ */ new Map();
|
|
7915
7936
|
/**
|
|
7916
7937
|
* Per-vault active session tier — defaults to `1` after a passphrase
|
|
7917
|
-
* unlock; tier-2 / tier-3 unlocks
|
|
7938
|
+
* unlock; tier-2 / tier-3 unlocks downgrade it. Used by
|
|
7918
7939
|
* {@link checkGate} to evaluate `gate.minTier`.
|
|
7919
7940
|
*/
|
|
7920
7941
|
activeTier = /* @__PURE__ */ new Map();
|
|
@@ -7924,14 +7945,14 @@ var Noydb = class {
|
|
|
7924
7945
|
*/
|
|
7925
7946
|
policyCache = /* @__PURE__ */ new Map();
|
|
7926
7947
|
/**
|
|
7927
|
-
* One-shot bypass for the managed-mode strong-recovery check
|
|
7948
|
+
* One-shot bypass for the managed-mode strong-recovery check.
|
|
7928
7949
|
* Set true by {@link openVaultAndEnrollRecovery} for the duration of
|
|
7929
7950
|
* the bootstrap window so the keyring can be created before the
|
|
7930
7951
|
* strong recovery is enrolled. Always cleared (try/finally).
|
|
7931
7952
|
* @internal
|
|
7932
7953
|
*/
|
|
7933
7954
|
_skipNextManagedRecoveryCheck = false;
|
|
7934
|
-
/** Per-vault tier-3 (PIN / quick-resume) state
|
|
7955
|
+
/** Per-vault tier-3 (PIN / quick-resume) state. */
|
|
7935
7956
|
quickUnlock = new QuickUnlockStore();
|
|
7936
7957
|
/**
|
|
7937
7958
|
* Resolved public-envelope schema. Lazily computed once from
|
|
@@ -7941,9 +7962,9 @@ var Noydb = class {
|
|
|
7941
7962
|
publicEnvelopeSchema;
|
|
7942
7963
|
closed = false;
|
|
7943
7964
|
sessionTimer = null;
|
|
7944
|
-
/** Same-device multi-tab coordinator
|
|
7965
|
+
/** Same-device multi-tab coordinator; created on `enableTabCoordination()`. */
|
|
7945
7966
|
tabCoordinator;
|
|
7946
|
-
/** Cross-tab write relay
|
|
7967
|
+
/** Cross-tab write relay; created on `enableTabCoordination()`. */
|
|
7947
7968
|
writeRelay;
|
|
7948
7969
|
/** Per-vault policy enforcers. */
|
|
7949
7970
|
policyEnforcers = /* @__PURE__ */ new Map();
|
|
@@ -7956,8 +7977,8 @@ var Noydb = class {
|
|
|
7956
7977
|
* the same function's `finally` block. Side-effect writes triggered
|
|
7957
7978
|
* during a staged op's `Collection.put` (today: eager derivation
|
|
7958
7979
|
* outputs) register their pre-write envelope on `_executed` here so
|
|
7959
|
-
* a mid-batch failure rolls them back alongside the main staged ops
|
|
7960
|
-
*
|
|
7980
|
+
* a mid-batch failure rolls them back alongside the main staged ops.
|
|
7981
|
+
* `null` outside of Phase 2.
|
|
7961
7982
|
* @internal
|
|
7962
7983
|
*/
|
|
7963
7984
|
_activeTxContext = null;
|
|
@@ -7978,8 +7999,95 @@ var Noydb = class {
|
|
|
7978
7999
|
if (options.sessionPolicy) {
|
|
7979
8000
|
this.sessionStrategy.validateSessionPolicy(options.sessionPolicy);
|
|
7980
8001
|
}
|
|
8002
|
+
this.#registerGuardGate();
|
|
8003
|
+
this.#registerPeriodGate();
|
|
7981
8004
|
this.resetSessionTimer();
|
|
7982
8005
|
}
|
|
8006
|
+
// Track A — guards migration. Registers record-lock / field-freeze / onDelete
|
|
8007
|
+
// / amendment-collect as gate-bus handlers (only when guards are opted in, so
|
|
8008
|
+
// the write path is zero-cost otherwise). Resolves the live vault's
|
|
8009
|
+
// GuardRegistry per dispatch. Registered BEFORE the period gate so guard
|
|
8010
|
+
// checks run first. The amendment branch is a side-effect (collectChange),
|
|
8011
|
+
// NOT a throw — and runs even for internal deletes (an amendment invariant
|
|
8012
|
+
// must see system housekeeping tombstones); onDelete/checks run only for
|
|
8013
|
+
// user (non-internal) operations.
|
|
8014
|
+
#registerGuardGate() {
|
|
8015
|
+
if (this.options.guardStrategies === void 0) return;
|
|
8016
|
+
this.subsystemBus.registerGate("beforePut", async (e) => {
|
|
8017
|
+
const v = this.vaultCache.get(e.vault);
|
|
8018
|
+
if (!v) return;
|
|
8019
|
+
const registry = v._getGuardRegistry();
|
|
8020
|
+
if (!registry) return;
|
|
8021
|
+
const guards = registry.guardsFor(e.collection);
|
|
8022
|
+
if (guards.length === 0) return;
|
|
8023
|
+
const existing = e.existing ?? null;
|
|
8024
|
+
const incoming = e.incoming;
|
|
8025
|
+
if (registry.isAmendmentActive()) {
|
|
8026
|
+
registry.collectChange(e.collection, e.docId, existing, incoming, e.existingVersion, e.existingVersion + 1);
|
|
8027
|
+
return;
|
|
8028
|
+
}
|
|
8029
|
+
const facade = v._getReadOnlyFacade();
|
|
8030
|
+
if (!facade) return;
|
|
8031
|
+
const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
|
|
8032
|
+
await registry.runChecks(e.collection, incoming, ctx);
|
|
8033
|
+
const { GuardExecutor } = await import("./executor-AWCHQ2KN.js");
|
|
8034
|
+
for (const g of guards) {
|
|
8035
|
+
await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming);
|
|
8036
|
+
}
|
|
8037
|
+
});
|
|
8038
|
+
this.subsystemBus.registerGate("beforeDelete", async (e) => {
|
|
8039
|
+
const v = this.vaultCache.get(e.vault);
|
|
8040
|
+
if (!v) return;
|
|
8041
|
+
const registry = v._getGuardRegistry();
|
|
8042
|
+
if (!registry) return;
|
|
8043
|
+
const guards = registry.guardsFor(e.collection);
|
|
8044
|
+
if (guards.length === 0) return;
|
|
8045
|
+
const existing = e.existing ?? null;
|
|
8046
|
+
if (registry.isAmendmentActive()) {
|
|
8047
|
+
registry.collectChange(e.collection, e.docId, existing, null, e.existingVersion, e.existingVersion);
|
|
8048
|
+
return;
|
|
8049
|
+
}
|
|
8050
|
+
if (e.internal) return;
|
|
8051
|
+
const facade = v._getReadOnlyFacade();
|
|
8052
|
+
if (!facade) return;
|
|
8053
|
+
const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
|
|
8054
|
+
await registry.runOnDelete(e.collection, existing ?? {}, ctx);
|
|
8055
|
+
});
|
|
8056
|
+
}
|
|
8057
|
+
/**
|
|
8058
|
+
* Register closed-period write guards on the subsystem bus when a
|
|
8059
|
+
* periodsStrategy is configured. Handlers resolve the live Vault from
|
|
8060
|
+
* vaultCache so they always use the up-to-date period cache.
|
|
8061
|
+
*/
|
|
8062
|
+
// Track A — periods migration. Registers the closed-period write guard as a
|
|
8063
|
+
// gate-bus handler (only when periods is opted in, so the write path is
|
|
8064
|
+
// zero-cost otherwise). Each handler resolves the LIVE vault from the cache
|
|
8065
|
+
// per dispatch and delegates to its `_assertTsWritable`, which owns all
|
|
8066
|
+
// period logic. Resolving the live vault makes eviction/re-creation
|
|
8067
|
+
// transparent. Semantics note: if a write reaches the gate through a retained
|
|
8068
|
+
// collection handle whose vault has been evicted from `vaultCache` (e.g. a
|
|
8069
|
+
// post-revocation write on a stale handle), the period check is skipped — the
|
|
8070
|
+
// guard binds to the live vault, not a captured instance. Periods is a
|
|
8071
|
+
// write-integrity guard, not a security boundary, and a re-open reloads the
|
|
8072
|
+
// period cache; the trade-off is intentional.
|
|
8073
|
+
#registerPeriodGate() {
|
|
8074
|
+
if (this.options.periodsStrategy === void 0) return;
|
|
8075
|
+
this.subsystemBus.registerGate("beforePut", async (e) => {
|
|
8076
|
+
const v = this.vaultCache.get(e.vault);
|
|
8077
|
+
if (!v) return;
|
|
8078
|
+
const existing = e.op === "create" ? null : { ts: e.existingTs ?? null, record: e.existing ?? null };
|
|
8079
|
+
await v._assertTsWritable(existing, e.incoming);
|
|
8080
|
+
});
|
|
8081
|
+
this.subsystemBus.registerGate("beforeDelete", async (e) => {
|
|
8082
|
+
if (e.internal) return;
|
|
8083
|
+
const v = this.vaultCache.get(e.vault);
|
|
8084
|
+
if (!v) return;
|
|
8085
|
+
await v._assertTsWritable(
|
|
8086
|
+
{ ts: e.existingTs ?? null, record: e.existing ?? null },
|
|
8087
|
+
null
|
|
8088
|
+
);
|
|
8089
|
+
});
|
|
8090
|
+
}
|
|
7983
8091
|
resetSessionTimer() {
|
|
7984
8092
|
if (this.sessionTimer) clearTimeout(this.sessionTimer);
|
|
7985
8093
|
const idleMs = this.options.sessionPolicy?.idleTimeoutMs ?? this.options.sessionTimeout;
|
|
@@ -8269,8 +8377,6 @@ var Noydb = class {
|
|
|
8269
8377
|
* @throws `NoAccessError` when no keyring exists for the target.
|
|
8270
8378
|
* @throws `PermissionDeniedError` when the role hierarchy rejects.
|
|
8271
8379
|
* @throws `ValidationError` when no field is provided.
|
|
8272
|
-
*
|
|
8273
|
-
* @see #54
|
|
8274
8380
|
*/
|
|
8275
8381
|
async updateUser(vault, options, factors) {
|
|
8276
8382
|
await this.checkGate(vault, "update-user", factors);
|
|
@@ -8606,7 +8712,7 @@ var Noydb = class {
|
|
|
8606
8712
|
* Phase 2. `Collection.dispatchDerivations` consults this so a
|
|
8607
8713
|
* recursive derived-output write inside `Collection.put` can register
|
|
8608
8714
|
* its envelope onto `ctx._executed` and roll back with the main
|
|
8609
|
-
* staged ops on mid-batch failure
|
|
8715
|
+
* staged ops on mid-batch failure.
|
|
8610
8716
|
*
|
|
8611
8717
|
* @internal
|
|
8612
8718
|
*/
|
|
@@ -8635,7 +8741,7 @@ var Noydb = class {
|
|
|
8635
8741
|
* `Collection.putManyAtomic` (via `derivationSource.createTxContext`)
|
|
8636
8742
|
* to publish an active context for the duration of its bulk-atomic
|
|
8637
8743
|
* Phase 2 loop, so recursive derivation-output writes register on
|
|
8638
|
-
* `ctx._executed` and roll back together with the source ops
|
|
8744
|
+
* `ctx._executed` and roll back together with the source ops.
|
|
8639
8745
|
*
|
|
8640
8746
|
* @internal
|
|
8641
8747
|
*/
|
|
@@ -8706,26 +8812,26 @@ var Noydb = class {
|
|
|
8706
8812
|
return this.writeQueueTracker;
|
|
8707
8813
|
}
|
|
8708
8814
|
/**
|
|
8709
|
-
* Register a hook that runs before each write
|
|
8815
|
+
* Register a hook that runs before each write. Awaited; a throw
|
|
8710
8816
|
* aborts the write. Returns an unsubscribe function.
|
|
8711
8817
|
*/
|
|
8712
8818
|
onBeforeWrite(handler) {
|
|
8713
8819
|
return this.writeHooks.onBeforeWrite(handler);
|
|
8714
8820
|
}
|
|
8715
8821
|
/**
|
|
8716
|
-
* Register a hook that runs after each committed write
|
|
8822
|
+
* Register a hook that runs after each committed write. Awaited;
|
|
8717
8823
|
* a handler error is warned, never rolled back. Returns an unsubscribe fn.
|
|
8718
8824
|
*/
|
|
8719
8825
|
onAfterWrite(handler) {
|
|
8720
8826
|
return this.writeHooks.onAfterWrite(handler);
|
|
8721
8827
|
}
|
|
8722
|
-
/** Subscribe to cross-tab write conflicts
|
|
8828
|
+
/** Subscribe to cross-tab write conflicts. Returns an unsubscribe. */
|
|
8723
8829
|
onWriteConflict(fn) {
|
|
8724
8830
|
this.on("write:conflict", fn);
|
|
8725
8831
|
return () => this.off("write:conflict", fn);
|
|
8726
8832
|
}
|
|
8727
8833
|
/**
|
|
8728
|
-
* Enable same-device multi-tab coordination
|
|
8834
|
+
* Enable same-device multi-tab coordination: primary/secondary
|
|
8729
8835
|
* election + presence. Browser-only — a graceful no-op (role 'unknown')
|
|
8730
8836
|
* when Web Locks / BroadcastChannel are unavailable and nothing is
|
|
8731
8837
|
* injected. Idempotent; returns a disposer.
|
|
@@ -8808,7 +8914,11 @@ var Noydb = class {
|
|
|
8808
8914
|
get _writeHooks() {
|
|
8809
8915
|
return this.writeHooks;
|
|
8810
8916
|
}
|
|
8811
|
-
/** @internal
|
|
8917
|
+
/** @internal The observe bus, threaded into every Collection. */
|
|
8918
|
+
get _subsystemBus() {
|
|
8919
|
+
return this.subsystemBus;
|
|
8920
|
+
}
|
|
8921
|
+
/** @internal Stable per-instance id for schema-cutover coordination. */
|
|
8812
8922
|
get _clientId() {
|
|
8813
8923
|
return this.clientId;
|
|
8814
8924
|
}
|
|
@@ -8828,10 +8938,6 @@ var Noydb = class {
|
|
|
8828
8938
|
* survives lock; nothing about it changes when DEKs are scrubbed).
|
|
8829
8939
|
*
|
|
8830
8940
|
* No-op when `vault` is not currently in cache (idempotent).
|
|
8831
|
-
*
|
|
8832
|
-
* Unblocks vLannaAi/niwat#33.
|
|
8833
|
-
*
|
|
8834
|
-
* @see #17
|
|
8835
8941
|
*/
|
|
8836
8942
|
lockVault(vault) {
|
|
8837
8943
|
this.syncEngines.get(vault)?.stopAutoSync();
|
|
@@ -8946,7 +9052,7 @@ var Noydb = class {
|
|
|
8946
9052
|
return merged;
|
|
8947
9053
|
}
|
|
8948
9054
|
/**
|
|
8949
|
-
* Read the current vault-level user-directory toggle
|
|
9055
|
+
* Read the current vault-level user-directory toggle. Returns
|
|
8950
9056
|
* the default-on shape (`{ enabled: true }`) when no `_meta/directory`
|
|
8951
9057
|
* document has been persisted yet.
|
|
8952
9058
|
*
|
|
@@ -8958,7 +9064,7 @@ var Noydb = class {
|
|
|
8958
9064
|
return persisted?.enabled ?? true;
|
|
8959
9065
|
}
|
|
8960
9066
|
/**
|
|
8961
|
-
* Toggle the vault's user-directory listing on or off
|
|
9067
|
+
* Toggle the vault's user-directory listing on or off.
|
|
8962
9068
|
* Owner-only. When disabled, `listUsersWithEnvelopes()` throws
|
|
8963
9069
|
* {@link import('./errors.js').DirectoryDisabledError} for callers
|
|
8964
9070
|
* whose role is neither `owner` nor `admin`.
|
|
@@ -9018,7 +9124,7 @@ var Noydb = class {
|
|
|
9018
9124
|
*
|
|
9019
9125
|
* Two enforcement modes:
|
|
9020
9126
|
*
|
|
9021
|
-
* 1. **Managed-mode mandatory strong-recovery
|
|
9127
|
+
* 1. **Managed-mode mandatory strong-recovery.** When
|
|
9022
9128
|
* `passphraseMode === 'managed'`, the vault MUST have at least
|
|
9023
9129
|
* one **strong** recovery profile (Shamir today). Paper alone is
|
|
9024
9130
|
* rejected because under managed mode the user has no memorized
|
|
@@ -9052,14 +9158,14 @@ var Noydb = class {
|
|
|
9052
9158
|
throw new RecoveryNotEnrolledError();
|
|
9053
9159
|
}
|
|
9054
9160
|
/**
|
|
9055
|
-
* Internal accessor used by tier-2/tier-3 unlock paths
|
|
9161
|
+
* Internal accessor used by tier-2/tier-3 unlock paths
|
|
9056
9162
|
* to mark the active session tier.
|
|
9057
9163
|
* @internal
|
|
9058
9164
|
*/
|
|
9059
9165
|
_setActiveTier(vault, tier) {
|
|
9060
9166
|
this.activeTier.set(vault, tier);
|
|
9061
9167
|
}
|
|
9062
|
-
// ─── Tier-2 enroll / remove
|
|
9168
|
+
// ─── Tier-2 enroll / remove ─────────────────────────────────────
|
|
9063
9169
|
/**
|
|
9064
9170
|
* Add a tier-2 authenticator slot to the calling user's keyring.
|
|
9065
9171
|
* Each slot independently wraps the SAME KEK under a method-specific
|
|
@@ -9089,7 +9195,7 @@ var Noydb = class {
|
|
|
9089
9195
|
const next = await removeAuthenticator(this.options.store, vault, keyring, slotId);
|
|
9090
9196
|
this.keyringCache.set(vault, next);
|
|
9091
9197
|
}
|
|
9092
|
-
/** Read the slot list for a vault. Internal — `describeAuthConfig`
|
|
9198
|
+
/** Read the slot list for a vault. Internal — `describeAuthConfig` consumes this. */
|
|
9093
9199
|
async listAuthenticators(vault) {
|
|
9094
9200
|
const keyring = await this.getKeyringInternal(vault);
|
|
9095
9201
|
return keyring.authenticators;
|
|
@@ -9101,7 +9207,7 @@ var Noydb = class {
|
|
|
9101
9207
|
* are immutable through this method. Anti-slot-swap is structural,
|
|
9102
9208
|
* not gate-driven.
|
|
9103
9209
|
*
|
|
9104
|
-
* `meta` patch semantics (
|
|
9210
|
+
* `meta` patch semantics (top-level merge):
|
|
9105
9211
|
* - Top-level merge — absent keys preserved
|
|
9106
9212
|
* - `null` value — delete that meta key
|
|
9107
9213
|
* - Other values — replace verbatim
|
|
@@ -9119,8 +9225,6 @@ var Noydb = class {
|
|
|
9119
9225
|
*
|
|
9120
9226
|
* @throws `NoAccessError` when no slot with the given id exists.
|
|
9121
9227
|
* @throws `ValidationError` when no patch field is provided.
|
|
9122
|
-
*
|
|
9123
|
-
* @see #55
|
|
9124
9228
|
*/
|
|
9125
9229
|
async updateAuthenticator(vault, slotId, options, factors) {
|
|
9126
9230
|
await this.checkGate(vault, "update-authenticator", factors);
|
|
@@ -9129,7 +9233,7 @@ var Noydb = class {
|
|
|
9129
9233
|
this.keyringCache.set(vault, next);
|
|
9130
9234
|
}
|
|
9131
9235
|
/**
|
|
9132
|
-
* Native WebAuthn enrollment using the **real** internal keyring
|
|
9236
|
+
* Native WebAuthn enrollment using the **real** internal keyring.
|
|
9133
9237
|
*
|
|
9134
9238
|
* Why this exists: when a consumer is using `createNoydb({ secret })`,
|
|
9135
9239
|
* they cannot reach the live `UnlockedKeyring` to feed it to
|
|
@@ -9172,8 +9276,6 @@ var Noydb = class {
|
|
|
9172
9276
|
* a server-side allowlist).
|
|
9173
9277
|
*
|
|
9174
9278
|
* Gated by `enroll-authenticator` like `enrollAuthenticator()` itself.
|
|
9175
|
-
*
|
|
9176
|
-
* @see #16
|
|
9177
9279
|
*/
|
|
9178
9280
|
async enrollWebAuthn(vault, ceremony, factors) {
|
|
9179
9281
|
await this.checkGate(vault, "enroll-authenticator", factors);
|
|
@@ -9200,8 +9302,6 @@ var Noydb = class {
|
|
|
9200
9302
|
* deciding when a new device prompt should appear. Identity is
|
|
9201
9303
|
* `id` + `enrolled_at`; the `meta.credentialId` (base64) is used by
|
|
9202
9304
|
* `allowCredentials` at unlock time.
|
|
9203
|
-
*
|
|
9204
|
-
* @see #16
|
|
9205
9305
|
*/
|
|
9206
9306
|
async listWebAuthnSlots(vault) {
|
|
9207
9307
|
const keyring = await this.getKeyringInternal(vault);
|
|
@@ -9283,7 +9383,7 @@ var Noydb = class {
|
|
|
9283
9383
|
async getPublicEnvelope(vault, opts = {}) {
|
|
9284
9384
|
return readPublicEnvelope(this.options.store, vault, opts);
|
|
9285
9385
|
}
|
|
9286
|
-
// ─── Auth introspection
|
|
9386
|
+
// ─── Auth introspection ─────────────────────────────────────────
|
|
9287
9387
|
/** English summary of the configured auth model. */
|
|
9288
9388
|
async describeAuthConfig(vault) {
|
|
9289
9389
|
return describeAuthConfig(this.options.store, vault);
|
|
@@ -9306,7 +9406,7 @@ var Noydb = class {
|
|
|
9306
9406
|
await this.checkGate(vault, "view-user-auth", factors);
|
|
9307
9407
|
return describeAllUsersAuth(this.options.store, vault);
|
|
9308
9408
|
}
|
|
9309
|
-
// ─── Tier-1 change flows
|
|
9409
|
+
// ─── Tier-1 change flows ────────────────────────────────────────
|
|
9310
9410
|
/**
|
|
9311
9411
|
* Rotate the user's passphrase (user remembers old). Validates the
|
|
9312
9412
|
* new phrase against the configured `passphrase` policy, runs the
|
|
@@ -9314,8 +9414,7 @@ var Noydb = class {
|
|
|
9314
9414
|
*
|
|
9315
9415
|
* Tier-2 authenticator slots are dropped — each slot wraps the old
|
|
9316
9416
|
* 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.
|
|
9417
|
+
* via `db.enrollAuthenticator` after rotation.
|
|
9319
9418
|
*
|
|
9320
9419
|
* @throws `WeakPassphraseError` on a weak new phrase.
|
|
9321
9420
|
* @throws `PolicyDeniedError` when the gate denies (missing factor, …).
|
|
@@ -9337,8 +9436,8 @@ var Noydb = class {
|
|
|
9337
9436
|
}
|
|
9338
9437
|
/**
|
|
9339
9438
|
* Reset the passphrase using a recovery proof (user forgot the old).
|
|
9340
|
-
*
|
|
9341
|
-
* other
|
|
9439
|
+
* Currently supports the `'paper'` profile end-to-end; the
|
|
9440
|
+
* other profiles throw {@link RecoveryProfileNotImplementedError}.
|
|
9342
9441
|
*
|
|
9343
9442
|
* Burns the used recovery entry on success.
|
|
9344
9443
|
*/
|
|
@@ -9367,7 +9466,7 @@ var Noydb = class {
|
|
|
9367
9466
|
return { newCodes: codes };
|
|
9368
9467
|
}
|
|
9369
9468
|
/**
|
|
9370
|
-
* Deliberate paper-recovery-code regeneration
|
|
9469
|
+
* Deliberate paper-recovery-code regeneration. User knows their
|
|
9371
9470
|
* passphrase but wants a fresh sheet — they lost the printout or
|
|
9372
9471
|
* suspect compromise of the off-site copy.
|
|
9373
9472
|
*
|
|
@@ -9377,7 +9476,7 @@ var Noydb = class {
|
|
|
9377
9476
|
*
|
|
9378
9477
|
* Gated by the `rotate-recovery` policy gate:
|
|
9379
9478
|
* - PERSONAL_POLICY: `{ minTier: 1 }` — knowing the passphrase
|
|
9380
|
-
* suffices, matching the
|
|
9479
|
+
* suffices, matching the lower-level flow's bar.
|
|
9381
9480
|
* - STRICT_POLICY: `{ minTier: 1, factors: [{ anyOf: ['totp',
|
|
9382
9481
|
* 'email-otp', 'webauthn-roaming'] }] }` — rotation is an
|
|
9383
9482
|
* off-site-trust event; require an off-device factor so a
|
|
@@ -9482,7 +9581,7 @@ var Noydb = class {
|
|
|
9482
9581
|
return { newShares: shareStrings, entryId: targetEntryId };
|
|
9483
9582
|
}
|
|
9484
9583
|
/**
|
|
9485
|
-
* **Atomic create-and-enroll for managed-mode vaults
|
|
9584
|
+
* **Atomic create-and-enroll for managed-mode vaults.**
|
|
9486
9585
|
*
|
|
9487
9586
|
* Bootstraps a managed-mode vault and enrolls strong recovery in
|
|
9488
9587
|
* a single ceremony. Under `passphraseMode: 'managed'`, every
|
|
@@ -9553,7 +9652,7 @@ var Noydb = class {
|
|
|
9553
9652
|
return { vault: vaultHandle, recoveryEnrollments };
|
|
9554
9653
|
}
|
|
9555
9654
|
/**
|
|
9556
|
-
* **Recovery flow under managed-passphrase mode
|
|
9655
|
+
* **Recovery flow under managed-passphrase mode.**
|
|
9557
9656
|
*
|
|
9558
9657
|
* Replaces the sealed passphrase of a managed-mode vault with a
|
|
9559
9658
|
* fresh 256-bit random, sealed under the configured
|
|
@@ -9570,7 +9669,7 @@ var Noydb = class {
|
|
|
9570
9669
|
* 5. Drop the keyring cache so the next operation re-derives.
|
|
9571
9670
|
*
|
|
9572
9671
|
* The vault's strong-recovery enrollment is preserved across
|
|
9573
|
-
* recovery (Shamir entries are not burned on use
|
|
9672
|
+
* recovery (Shamir entries are not burned on use).
|
|
9574
9673
|
*
|
|
9575
9674
|
* @throws ValidationError if the Noydb instance is not in managed mode.
|
|
9576
9675
|
*/
|
|
@@ -9618,7 +9717,7 @@ var Noydb = class {
|
|
|
9618
9717
|
}
|
|
9619
9718
|
/**
|
|
9620
9719
|
* Atomic peer-recovery — re-wraps an EXISTING user's keyring under
|
|
9621
|
-
* a fresh temp passphrase in a single store write. Closes
|
|
9720
|
+
* a fresh temp passphrase in a single store write. Closes the
|
|
9622
9721
|
* partial-failure window (the previous compose-from-primitives
|
|
9623
9722
|
* pattern was `db.revoke + db.grant`, two writes — if the issuer
|
|
9624
9723
|
* cancelled between them the target was locked out entirely).
|
|
@@ -9628,7 +9727,7 @@ var Noydb = class {
|
|
|
9628
9727
|
* - Same `userId`, role, permissions, capabilities preserved.
|
|
9629
9728
|
* - DEKs unchanged → every other principal in the vault keeps
|
|
9630
9729
|
* access. No key rotation.
|
|
9631
|
-
* - Allows owner→owner natively
|
|
9730
|
+
* - Allows owner→owner natively. The existing
|
|
9632
9731
|
* `db.revoke` retains its block — peer-recovery is a separate,
|
|
9633
9732
|
* intentionally-named operation.
|
|
9634
9733
|
* - Tier-2 slots dropped (they wrap the old KEK).
|
|
@@ -9657,7 +9756,6 @@ var Noydb = class {
|
|
|
9657
9756
|
* @throws `PrivilegeEscalationError` when the caller lacks a DEK
|
|
9658
9757
|
* the target previously had access to.
|
|
9659
9758
|
*
|
|
9660
|
-
* @see #33 #34 — the issues this method closes.
|
|
9661
9759
|
*/
|
|
9662
9760
|
async recoverUser(vault, options, factors) {
|
|
9663
9761
|
await this.checkGate(vault, "peer-recover-user", factors);
|
|
@@ -9668,7 +9766,7 @@ var Noydb = class {
|
|
|
9668
9766
|
}
|
|
9669
9767
|
}
|
|
9670
9768
|
/**
|
|
9671
|
-
* Persist a recovery enrollment.
|
|
9769
|
+
* Persist a recovery enrollment. Accepts the `'paper'`
|
|
9672
9770
|
* profile.
|
|
9673
9771
|
*
|
|
9674
9772
|
* The hub wraps the user's DEK set (not the KEK) under a code-derived
|
|
@@ -9688,7 +9786,7 @@ var Noydb = class {
|
|
|
9688
9786
|
* showCodesToUser(codes)
|
|
9689
9787
|
* ```
|
|
9690
9788
|
*
|
|
9691
|
-
*
|
|
9789
|
+
* `@noy-db/on-recovery`'s `generateRecoveryCodeSet`
|
|
9692
9790
|
* delegates to `mintPaperRecoveryEntry` internally — its output is
|
|
9693
9791
|
* fed directly to this API. Pick whichever fits your code-gen layer:
|
|
9694
9792
|
*
|
|
@@ -9728,13 +9826,13 @@ var Noydb = class {
|
|
|
9728
9826
|
"#196"
|
|
9729
9827
|
);
|
|
9730
9828
|
}
|
|
9731
|
-
/** Read the persisted recovery entries (paper + Shamir). Used by `describeAuthConfig
|
|
9829
|
+
/** Read the persisted recovery entries (paper + Shamir). Used by `describeAuthConfig`. */
|
|
9732
9830
|
async listRecoveryEntries(vault) {
|
|
9733
9831
|
const paper = await loadPaperRecoveryEntries(this.options.store, vault);
|
|
9734
9832
|
const shamir = await loadShamirRecoveryEntries(this.options.store, vault);
|
|
9735
9833
|
return { paper, shamir };
|
|
9736
9834
|
}
|
|
9737
|
-
// ─── Tier-3 enroll / unlock
|
|
9835
|
+
// ─── Tier-3 enroll / unlock ─────────────────────────────────────
|
|
9738
9836
|
/**
|
|
9739
9837
|
* Register a tier-3 quick-unlock state for the vault. The state is
|
|
9740
9838
|
* an opaque blob produced by `@noy-db/on-pin/enrollPin` (or any
|
|
@@ -9770,11 +9868,11 @@ var Noydb = class {
|
|
|
9770
9868
|
this.quickUnlock.delete(vault);
|
|
9771
9869
|
}
|
|
9772
9870
|
/**
|
|
9773
|
-
* Public accessor for the unlocked keyring of a vault
|
|
9871
|
+
* Public accessor for the unlocked keyring of a vault.
|
|
9774
9872
|
*
|
|
9775
9873
|
* Returns a **defensive shallow copy** so consumers can read the DEK
|
|
9776
9874
|
* map and authenticator list without the risk of mutating the hub's
|
|
9777
|
-
* internal cache
|
|
9875
|
+
* internal cache. Internal hub code paths use a live reference
|
|
9778
9876
|
* via `getKeyringInternal`; ceremonies and external consumers always
|
|
9779
9877
|
* get a snapshot.
|
|
9780
9878
|
*
|
|
@@ -9957,4 +10055,4 @@ export {
|
|
|
9957
10055
|
Noydb,
|
|
9958
10056
|
createNoydb
|
|
9959
10057
|
};
|
|
9960
|
-
//# sourceMappingURL=chunk-
|
|
10058
|
+
//# sourceMappingURL=chunk-BT7544RM.js.map
|