@noy-db/hub 0.2.0-pre.21 → 0.2.0-pre.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aggregate/index.cjs.map +1 -1
- package/dist/aggregate/index.d.cts +3 -3
- package/dist/aggregate/index.d.ts +3 -3
- package/dist/aggregate/index.js +5 -5
- 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 +6 -6
- package/dist/blobs/index.d.ts +6 -6
- package/dist/blobs/index.js +6 -6
- package/dist/bundle/index.cjs +21173 -21341
- package/dist/bundle/index.cjs.map +1 -1
- package/dist/bundle/index.d.cts +15 -6
- package/dist/bundle/index.d.ts +15 -6
- package/dist/bundle/index.js +58 -193
- package/dist/bundle/index.js.map +1 -1
- package/dist/{chunk-CQYEDODS.js → chunk-35U5YNRR.js} +3 -3
- package/dist/{chunk-NV4IHBZS.js → chunk-3XJU3OHE.js} +5 -5
- package/dist/{chunk-OTWT6BAJ.js → chunk-4BB4T3O7.js} +12 -2
- package/dist/chunk-4BB4T3O7.js.map +1 -0
- package/dist/{chunk-IVZWHIEK.js → chunk-4HEGG5NJ.js} +5 -5
- package/dist/{chunk-WE2BUQD2.js → chunk-4TCMCCC3.js} +5 -3
- package/dist/{chunk-5YTXYPES.js → chunk-5A2FVGHT.js} +5 -5
- package/dist/{chunk-NSXNXLYM.js → chunk-5GZC2ZM3.js} +2 -2
- package/dist/{chunk-JYNH4FIM.js → chunk-77WF53XY.js} +4 -4
- package/dist/{chunk-O5XKZCUD.js → chunk-7X4EF35A.js} +5 -5
- package/dist/{chunk-SQKAECUL.js → chunk-7ZCTUI26.js} +2 -2
- package/dist/{chunk-J6RGRZOY.js → chunk-AO3QSMCU.js} +2 -2
- package/dist/{chunk-JDCPRJVS.js → chunk-AONK5GCC.js} +4 -4
- package/dist/{chunk-FRRJIUSI.js → chunk-B5CSNGSE.js} +17 -9
- package/dist/chunk-B5CSNGSE.js.map +1 -0
- package/dist/{chunk-IY24WS2P.js → chunk-BCMHJYVT.js} +4 -4
- package/dist/{chunk-IY24WS2P.js.map → chunk-BCMHJYVT.js.map} +1 -1
- package/dist/{chunk-TYMDCIQM.js → chunk-C472BRJ4.js} +4 -4
- package/dist/{chunk-MBXKRHSS.js → chunk-CCNRFAL3.js} +2 -2
- package/dist/{chunk-BZW5IL43.js → chunk-DCA2BDHA.js} +4 -4
- package/dist/{chunk-JBBWALNI.js → chunk-DCICHSRS.js} +2 -2
- package/dist/{chunk-2XA2ZML4.js → chunk-FG6IQ3ZL.js} +3 -3
- package/dist/{chunk-C2RJVZZL.js → chunk-G4GW5VOS.js} +2 -2
- package/dist/{chunk-U2XSUCDF.js → chunk-GEWIFM4J.js} +2 -2
- package/dist/{chunk-TNH5SLCD.js → chunk-HD4QCT2O.js} +2 -2
- package/dist/{chunk-I3IYTUUI.js → chunk-HHJ5DZCZ.js} +3 -3
- package/dist/{chunk-6QAZ5O6X.js → chunk-IEIADIPM.js} +2 -2
- package/dist/{chunk-YPIOFSN3.js → chunk-IHAISFXP.js} +2 -2
- package/dist/{chunk-GJTKMME7.js → chunk-JKM2AVVH.js} +2 -2
- package/dist/{chunk-EYK72OTL.js → chunk-JRMOSIH4.js} +5 -5
- package/dist/chunk-JRMOSIH4.js.map +1 -0
- package/dist/{chunk-S45MDEEF.js → chunk-LMWVNF6X.js} +2 -2
- package/dist/{chunk-TA6HPKWQ.js → chunk-LR7CODVN.js} +1 -1
- package/dist/chunk-LR7CODVN.js.map +1 -0
- package/dist/{chunk-TAMRU7A2.js → chunk-OKV7S356.js} +4 -4
- package/dist/{chunk-HYJMAV53.js → chunk-OWAMTSAI.js} +93 -93
- package/dist/chunk-OWAMTSAI.js.map +1 -0
- package/dist/{chunk-IW4L4X65.js → chunk-P5A4E53B.js} +2 -2
- package/dist/{chunk-JOK73NDT.js → chunk-P7OL22JP.js} +3 -3
- package/dist/{chunk-7PH4OPBZ.js → chunk-QOXZM3L2.js} +762 -134
- package/dist/chunk-QOXZM3L2.js.map +1 -0
- package/dist/chunk-R43KS34V.js +399 -0
- package/dist/chunk-R43KS34V.js.map +1 -0
- package/dist/{chunk-TGIJTNM3.js → chunk-R5ZECURV.js} +2 -2
- package/dist/{chunk-KOAJ3TZM.js → chunk-RFEXGW3L.js} +2 -2
- package/dist/{chunk-F5ILTHMU.js → chunk-RNQPDV75.js} +5 -5
- package/dist/{chunk-WWVJXBOT.js → chunk-SGM7CK7R.js} +5 -5
- package/dist/{chunk-7MRT7EPB.js → chunk-SOQE5DUV.js} +3 -3
- package/dist/{chunk-F5GWNSE2.js → chunk-TOMSCJRV.js} +3 -3
- package/dist/{chunk-F5GWNSE2.js.map → chunk-TOMSCJRV.js.map} +1 -1
- package/dist/{chunk-ZONKSLF2.js → chunk-TQMQZOMX.js} +2 -2
- package/dist/{chunk-3HNKR65T.js → chunk-U6LTLN7O.js} +3 -3
- package/dist/{chunk-UU6M64HI.js → chunk-UAK2AMO2.js} +4 -4
- package/dist/{chunk-37VGJM3T.js → chunk-WQ3KAGOV.js} +2 -2
- package/dist/{chunk-C6W5KVDV.js → chunk-XC32SZPW.js} +35 -35
- package/dist/chunk-XC32SZPW.js.map +1 -0
- package/dist/{chunk-AI4USDRI.js → chunk-XQO4TAJS.js} +4 -4
- package/dist/{chunk-SQOK5UM6.js → chunk-ZBENTRFS.js} +2 -2
- package/dist/{chunk-6QE4DUYC.js → chunk-ZDITTESU.js} +2 -2
- 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-456N7UVX.js → crypto-2LU6XUFF.js} +3 -3
- package/dist/{delegation-DP4COTXB.js → delegation-6ABSJGXV.js} +5 -5
- package/dist/derivations/index.cjs.map +1 -1
- package/dist/derivations/index.d.cts +6 -6
- package/dist/derivations/index.d.ts +6 -6
- package/dist/derivations/index.js +4 -4
- package/dist/{dev-unlock-CpKSkl2c.d.ts → dev-unlock-BlhRHr6p.d.ts} +1 -1
- package/dist/{dev-unlock-CY0HIZA0.d.cts → dev-unlock-DURe4IvF.d.cts} +1 -1
- package/dist/{errors-Dkc_fi-S.d.cts → errors-B2tUcRPg.d.cts} +19 -5
- package/dist/{errors-Dkc_fi-S.d.ts → errors-B2tUcRPg.d.ts} +19 -5
- package/dist/executor-JKMSEB34.js +8 -0
- package/dist/executor-UYXSQB4D.js +12 -0
- package/dist/executor-VJSCTBWY.js +8 -0
- package/dist/{fanout-sidecar-YXNAEZ33.js → fanout-sidecar-ZQT4Y7PF.js} +2 -2
- package/dist/forget/index.js +4 -4
- 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 +6 -6
- package/dist/{hash-BSd0-_L8.d.cts → hash-CqRZfDZH.d.cts} +1 -1
- package/dist/{hash-BnBQx39y.d.ts → hash-cF4iWaBV.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 +5 -5
- 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 +6 -6
- package/dist/index-B8MoIS7B.d.ts +70 -0
- package/dist/{index-Bm9hIY7t.d.ts → index-BLff_E35.d.ts} +2 -2
- package/dist/{index-tZqVB9g5.d.cts → index-BthnP2MA.d.cts} +2 -2
- package/dist/index-da0M3NnR.d.cts +70 -0
- package/dist/index.cjs +25861 -25119
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +135 -80
- package/dist/index.d.ts +135 -80
- package/dist/index.js +93 -52
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.cjs.map +1 -1
- package/dist/indexing/index.js +4 -4
- package/dist/issue-KLRMW5DH.js +12 -0
- package/dist/kernel/index.cjs +657 -0
- package/dist/kernel/index.cjs.map +1 -0
- package/dist/kernel/index.d.cts +11 -0
- package/dist/kernel/index.d.ts +11 -0
- package/dist/kernel/index.js +40 -0
- package/dist/{ledger-I7JUYP4L.js → ledger-VOS2X3WJ.js} +5 -5
- package/dist/materialized-views/index.cjs.map +1 -1
- package/dist/materialized-views/index.d.cts +6 -6
- package/dist/materialized-views/index.d.ts +6 -6
- package/dist/materialized-views/index.js +8 -8
- package/dist/{mime-magic-CjSyakO4.d.ts → mime-magic-BswIvWkR.d.ts} +1 -1
- package/dist/{mime-magic-BnJCGJzB.d.cts → mime-magic-CCrP-iXJ.d.cts} +1 -1
- package/dist/{ulid-B2L_aqVA.d.ts → multi-bundle-6s5nKAZX.d.ts} +114 -58
- package/dist/{ulid-LaxfH2tK.d.cts → multi-bundle-WhYiJEgV.d.cts} +114 -58
- package/dist/noydb-2PI2ZBX6.js +38 -0
- package/dist/overlay-views/index.cjs.map +1 -1
- package/dist/overlay-views/index.d.cts +6 -6
- package/dist/overlay-views/index.d.ts +6 -6
- 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 +5 -5
- package/dist/{public-envelope-5XRTUNKF.js → public-envelope-IJJMWSTJ.js} +4 -4
- package/dist/query/index.cjs.map +1 -1
- package/dist/query/index.d.cts +3 -3
- package/dist/query/index.d.ts +3 -3
- package/dist/query/index.js +7 -7
- package/dist/registry-GAIFVWXF.js +8 -0
- package/dist/registry-J77ZUQ7G.js +8 -0
- package/dist/{registry-NWHOLD5M.js → registry-JGEVJ6YC.js} +3 -3
- package/dist/{revoke-5IEK22KT.js → revoke-WUY4AYRJ.js} +6 -6
- package/dist/sealed-record/index.cjs.map +1 -1
- package/dist/sealed-record/index.d.cts +1 -1
- package/dist/sealed-record/index.d.ts +1 -1
- package/dist/sealed-record/index.js +2 -2
- 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-I6YARZQA.js → signer-UJF3CFDC.js} +5 -5
- package/dist/snapshots/index.cjs.map +1 -1
- package/dist/snapshots/index.d.cts +5 -5
- package/dist/snapshots/index.d.ts +5 -5
- package/dist/snapshots/index.js +4 -4
- package/dist/{stale-CPESGAPL.js → stale-PW6VBGSP.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/{strategy-WtB-jXYv.d.cts → strategy-BWmgRPA2.d.cts} +1 -1
- package/dist/{strategy-54eIwox5.d.ts → strategy-D47TC5X6.d.ts} +1 -1
- 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 +10 -3
- 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/{transition-guard-Dmpqzg-_.d.cts → transition-guard-C3NxfVKk.d.cts} +1 -1
- package/dist/{transition-guard-D4bfIAiW.d.ts → transition-guard-CQH5263l.d.ts} +1 -1
- package/dist/tx/index.cjs +1 -1
- 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/{types-DLfWFr6U.d.ts → types-BGRX6sPT.d.ts} +546 -580
- package/dist/{types-DyOI6XZ_.d.cts → types-COQ6qJZh.d.cts} +546 -580
- package/dist/ulid-DRH25k3y.d.cts +66 -0
- package/dist/ulid-DRH25k3y.d.ts +66 -0
- package/dist/util/index.cjs.map +1 -1
- package/dist/util/index.js +1 -1
- package/dist/{with-materialized-view-DNULSxoP.d.ts → with-materialized-view-Cj-6fuav.d.ts} +1 -1
- package/dist/{with-materialized-view-CeZYGJVf.d.cts → with-materialized-view-D4U-KrBH.d.cts} +1 -1
- package/dist/{with-overlayed-view-kdcPGHih.d.cts → with-overlayed-view-BKjdUPRx.d.cts} +1 -1
- package/dist/{with-overlayed-view-C9joG7UZ.d.ts → with-overlayed-view-COp_7EEy.d.ts} +1 -1
- package/dist/{with-rollup-DJDbrxjf.d.ts → with-rollup-B1_ZjG02.d.ts} +1 -1
- package/dist/{with-rollup-s58XAeWO.d.cts → with-rollup-C-Bok_o2.d.cts} +1 -1
- package/package.json +13 -3
- package/dist/chunk-7PH4OPBZ.js.map +0 -1
- package/dist/chunk-C6W5KVDV.js.map +0 -1
- package/dist/chunk-EYK72OTL.js.map +0 -1
- package/dist/chunk-FRRJIUSI.js.map +0 -1
- package/dist/chunk-HYJMAV53.js.map +0 -1
- package/dist/chunk-JTI57WRT.js +0 -164
- package/dist/chunk-JTI57WRT.js.map +0 -1
- package/dist/chunk-OTWT6BAJ.js.map +0 -1
- package/dist/chunk-TA6HPKWQ.js.map +0 -1
- package/dist/chunk-ZC7J6ZYV.js +0 -7
- package/dist/chunk-ZC7J6ZYV.js.map +0 -1
- package/dist/executor-4IEW4KG5.js +0 -8
- package/dist/executor-KYJCJCIN.js +0 -12
- package/dist/executor-W7VIBOBZ.js +0 -8
- package/dist/issue-JXC6T2QR.js +0 -12
- package/dist/noydb-ZZCRF6TE.js +0 -38
- package/dist/registry-ATRHOG5B.js +0 -8
- package/dist/registry-LEHB26TY.js +0 -8
- package/dist/state-vault-JR3CFGNP.js +0 -14
- package/dist/vault-group-BB246VIM.js +0 -804
- package/dist/vault-group-BB246VIM.js.map +0 -1
- /package/dist/{chunk-CQYEDODS.js.map → chunk-35U5YNRR.js.map} +0 -0
- /package/dist/{chunk-NV4IHBZS.js.map → chunk-3XJU3OHE.js.map} +0 -0
- /package/dist/{chunk-IVZWHIEK.js.map → chunk-4HEGG5NJ.js.map} +0 -0
- /package/dist/{chunk-WE2BUQD2.js.map → chunk-4TCMCCC3.js.map} +0 -0
- /package/dist/{chunk-5YTXYPES.js.map → chunk-5A2FVGHT.js.map} +0 -0
- /package/dist/{chunk-NSXNXLYM.js.map → chunk-5GZC2ZM3.js.map} +0 -0
- /package/dist/{chunk-JYNH4FIM.js.map → chunk-77WF53XY.js.map} +0 -0
- /package/dist/{chunk-O5XKZCUD.js.map → chunk-7X4EF35A.js.map} +0 -0
- /package/dist/{chunk-SQKAECUL.js.map → chunk-7ZCTUI26.js.map} +0 -0
- /package/dist/{chunk-J6RGRZOY.js.map → chunk-AO3QSMCU.js.map} +0 -0
- /package/dist/{chunk-JDCPRJVS.js.map → chunk-AONK5GCC.js.map} +0 -0
- /package/dist/{chunk-TYMDCIQM.js.map → chunk-C472BRJ4.js.map} +0 -0
- /package/dist/{chunk-MBXKRHSS.js.map → chunk-CCNRFAL3.js.map} +0 -0
- /package/dist/{chunk-BZW5IL43.js.map → chunk-DCA2BDHA.js.map} +0 -0
- /package/dist/{chunk-JBBWALNI.js.map → chunk-DCICHSRS.js.map} +0 -0
- /package/dist/{chunk-2XA2ZML4.js.map → chunk-FG6IQ3ZL.js.map} +0 -0
- /package/dist/{chunk-C2RJVZZL.js.map → chunk-G4GW5VOS.js.map} +0 -0
- /package/dist/{chunk-U2XSUCDF.js.map → chunk-GEWIFM4J.js.map} +0 -0
- /package/dist/{chunk-TNH5SLCD.js.map → chunk-HD4QCT2O.js.map} +0 -0
- /package/dist/{chunk-I3IYTUUI.js.map → chunk-HHJ5DZCZ.js.map} +0 -0
- /package/dist/{chunk-6QAZ5O6X.js.map → chunk-IEIADIPM.js.map} +0 -0
- /package/dist/{chunk-YPIOFSN3.js.map → chunk-IHAISFXP.js.map} +0 -0
- /package/dist/{chunk-GJTKMME7.js.map → chunk-JKM2AVVH.js.map} +0 -0
- /package/dist/{chunk-S45MDEEF.js.map → chunk-LMWVNF6X.js.map} +0 -0
- /package/dist/{chunk-TAMRU7A2.js.map → chunk-OKV7S356.js.map} +0 -0
- /package/dist/{chunk-IW4L4X65.js.map → chunk-P5A4E53B.js.map} +0 -0
- /package/dist/{chunk-JOK73NDT.js.map → chunk-P7OL22JP.js.map} +0 -0
- /package/dist/{chunk-TGIJTNM3.js.map → chunk-R5ZECURV.js.map} +0 -0
- /package/dist/{chunk-KOAJ3TZM.js.map → chunk-RFEXGW3L.js.map} +0 -0
- /package/dist/{chunk-F5ILTHMU.js.map → chunk-RNQPDV75.js.map} +0 -0
- /package/dist/{chunk-WWVJXBOT.js.map → chunk-SGM7CK7R.js.map} +0 -0
- /package/dist/{chunk-7MRT7EPB.js.map → chunk-SOQE5DUV.js.map} +0 -0
- /package/dist/{chunk-ZONKSLF2.js.map → chunk-TQMQZOMX.js.map} +0 -0
- /package/dist/{chunk-3HNKR65T.js.map → chunk-U6LTLN7O.js.map} +0 -0
- /package/dist/{chunk-UU6M64HI.js.map → chunk-UAK2AMO2.js.map} +0 -0
- /package/dist/{chunk-37VGJM3T.js.map → chunk-WQ3KAGOV.js.map} +0 -0
- /package/dist/{chunk-AI4USDRI.js.map → chunk-XQO4TAJS.js.map} +0 -0
- /package/dist/{chunk-SQOK5UM6.js.map → chunk-ZBENTRFS.js.map} +0 -0
- /package/dist/{chunk-6QE4DUYC.js.map → chunk-ZDITTESU.js.map} +0 -0
- /package/dist/{crypto-456N7UVX.js.map → crypto-2LU6XUFF.js.map} +0 -0
- /package/dist/{delegation-DP4COTXB.js.map → delegation-6ABSJGXV.js.map} +0 -0
- /package/dist/{executor-4IEW4KG5.js.map → executor-JKMSEB34.js.map} +0 -0
- /package/dist/{executor-KYJCJCIN.js.map → executor-UYXSQB4D.js.map} +0 -0
- /package/dist/{executor-W7VIBOBZ.js.map → executor-VJSCTBWY.js.map} +0 -0
- /package/dist/{fanout-sidecar-YXNAEZ33.js.map → fanout-sidecar-ZQT4Y7PF.js.map} +0 -0
- /package/dist/{issue-JXC6T2QR.js.map → issue-KLRMW5DH.js.map} +0 -0
- /package/dist/{ledger-I7JUYP4L.js.map → kernel/index.js.map} +0 -0
- /package/dist/{noydb-ZZCRF6TE.js.map → ledger-VOS2X3WJ.js.map} +0 -0
- /package/dist/{public-envelope-5XRTUNKF.js.map → noydb-2PI2ZBX6.js.map} +0 -0
- /package/dist/{registry-ATRHOG5B.js.map → public-envelope-IJJMWSTJ.js.map} +0 -0
- /package/dist/{registry-LEHB26TY.js.map → registry-GAIFVWXF.js.map} +0 -0
- /package/dist/{registry-NWHOLD5M.js.map → registry-J77ZUQ7G.js.map} +0 -0
- /package/dist/{revoke-5IEK22KT.js.map → registry-JGEVJ6YC.js.map} +0 -0
- /package/dist/{signer-I6YARZQA.js.map → revoke-WUY4AYRJ.js.map} +0 -0
- /package/dist/{stale-CPESGAPL.js.map → signer-UJF3CFDC.js.map} +0 -0
- /package/dist/{state-vault-JR3CFGNP.js.map → stale-PW6VBGSP.js.map} +0 -0
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
STATE_VAULT_NAME
|
|
3
|
-
} from "./chunk-ZC7J6ZYV.js";
|
|
4
1
|
import {
|
|
5
2
|
resolveSchema
|
|
6
3
|
} from "./chunk-EMIGCR7X.js";
|
|
7
4
|
import {
|
|
8
5
|
TxContext,
|
|
9
6
|
revertExecuted
|
|
10
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-BCMHJYVT.js";
|
|
11
8
|
import {
|
|
12
9
|
OverlayedCollection
|
|
13
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-CCNRFAL3.js";
|
|
14
11
|
import {
|
|
15
12
|
NO_AGGREGATE,
|
|
16
13
|
Query,
|
|
@@ -20,36 +17,39 @@ import {
|
|
|
20
17
|
decodeMoneyFields,
|
|
21
18
|
quantizeMoneyFields,
|
|
22
19
|
validateMoneyFieldPaths
|
|
23
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-3XJU3OHE.js";
|
|
24
21
|
import {
|
|
25
22
|
EXPORT_AUDIT_COLLECTION,
|
|
26
23
|
createExportBlobsHandle,
|
|
27
24
|
runCompaction
|
|
28
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-FG6IQ3ZL.js";
|
|
29
26
|
import {
|
|
30
27
|
LazyQuery,
|
|
31
28
|
decodeIdxId,
|
|
32
29
|
encodeIdxId
|
|
33
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-U6LTLN7O.js";
|
|
34
31
|
import {
|
|
35
32
|
canonicalGroupKey
|
|
36
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-77WF53XY.js";
|
|
37
34
|
import {
|
|
38
35
|
readPath
|
|
39
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-GEWIFM4J.js";
|
|
40
37
|
import {
|
|
41
38
|
SCHEMAS_COLLECTION,
|
|
42
39
|
loadPersistedSchema,
|
|
43
40
|
resolveManagedSecret,
|
|
44
41
|
savePersistedSchema,
|
|
45
42
|
saveSealedPassphrase
|
|
46
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-XC32SZPW.js";
|
|
44
|
+
import {
|
|
45
|
+
writeNoydbBundle
|
|
46
|
+
} from "./chunk-4TCMCCC3.js";
|
|
47
47
|
import {
|
|
48
48
|
loadPublicEnvelope,
|
|
49
49
|
readPublicEnvelope,
|
|
50
50
|
savePublicEnvelope,
|
|
51
51
|
validatePublicEnvelopeInput
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-P7OL22JP.js";
|
|
53
53
|
import {
|
|
54
54
|
buildTombstone,
|
|
55
55
|
isTombstone,
|
|
@@ -58,19 +58,19 @@ import {
|
|
|
58
58
|
rewrapBodyToDek,
|
|
59
59
|
rotateRecordCek,
|
|
60
60
|
sealRecordToHost
|
|
61
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-DCA2BDHA.js";
|
|
62
62
|
import {
|
|
63
63
|
PERIODS_COLLECTION
|
|
64
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-HHJ5DZCZ.js";
|
|
65
65
|
import {
|
|
66
66
|
isDictCollectionName,
|
|
67
67
|
isStaticDictDescriptor
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-7X4EF35A.js";
|
|
69
69
|
import {
|
|
70
70
|
getAtPath,
|
|
71
71
|
resolvePolicy,
|
|
72
72
|
setAtPathInPlace
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-HD4QCT2O.js";
|
|
74
74
|
import {
|
|
75
75
|
ManagedRecoveryNotEnrolledError,
|
|
76
76
|
PolicyDeniedError,
|
|
@@ -92,11 +92,11 @@ import {
|
|
|
92
92
|
saveShamirRecoveryEntries,
|
|
93
93
|
updateAuthenticator,
|
|
94
94
|
writeMagicLinkGrant
|
|
95
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-OWAMTSAI.js";
|
|
96
96
|
import {
|
|
97
97
|
assertTierAccess,
|
|
98
98
|
dekKey
|
|
99
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-TOMSCJRV.js";
|
|
100
100
|
import {
|
|
101
101
|
USER_ENVELOPE_COLLECTION,
|
|
102
102
|
assertKeyringOpenAllowed,
|
|
@@ -121,7 +121,7 @@ import {
|
|
|
121
121
|
rotateKeys,
|
|
122
122
|
saveUserEnvelope,
|
|
123
123
|
updateKeyringIdentity
|
|
124
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-B5CSNGSE.js";
|
|
125
125
|
import {
|
|
126
126
|
INDEXED_STORE_POLICY
|
|
127
127
|
} from "./chunk-2QR2PQTT.js";
|
|
@@ -131,7 +131,7 @@ import {
|
|
|
131
131
|
import {
|
|
132
132
|
LEDGER_COLLECTION,
|
|
133
133
|
LEDGER_DELTAS_COLLECTION
|
|
134
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-AONK5GCC.js";
|
|
135
135
|
import {
|
|
136
136
|
sha256Hex as sha256Hex2
|
|
137
137
|
} from "./chunk-PDVP3C2I.js";
|
|
@@ -143,19 +143,20 @@ import {
|
|
|
143
143
|
readDottedPath,
|
|
144
144
|
rebuildSubjectIndex,
|
|
145
145
|
removeSubjectRef
|
|
146
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-35U5YNRR.js";
|
|
147
147
|
import {
|
|
148
148
|
NOYDB_BACKUP_VERSION,
|
|
149
149
|
NOYDB_FORMAT_VERSION
|
|
150
|
-
} from "./chunk-
|
|
150
|
+
} from "./chunk-LR7CODVN.js";
|
|
151
151
|
import {
|
|
152
152
|
decrypt,
|
|
153
153
|
encrypt,
|
|
154
154
|
encryptDeterministic,
|
|
155
155
|
sha256Hex,
|
|
156
156
|
unwrapCek,
|
|
157
|
-
wrapCek
|
|
158
|
-
|
|
157
|
+
wrapCek,
|
|
158
|
+
wrapKey
|
|
159
|
+
} from "./chunk-WQ3KAGOV.js";
|
|
159
160
|
import {
|
|
160
161
|
AlreadyElevatedError,
|
|
161
162
|
AttestationError,
|
|
@@ -167,6 +168,7 @@ import {
|
|
|
167
168
|
DerivationCapExceededError,
|
|
168
169
|
ElevationExpiredError,
|
|
169
170
|
ExportCapabilityError,
|
|
171
|
+
FederationMovedError,
|
|
170
172
|
ForgetStrategyNotConfiguredError,
|
|
171
173
|
ImportCapabilityError,
|
|
172
174
|
IndexWriteFailureError,
|
|
@@ -181,7 +183,6 @@ import {
|
|
|
181
183
|
QuiesceTimeoutError,
|
|
182
184
|
ReadOnlyError,
|
|
183
185
|
ReservedCollectionNameError,
|
|
184
|
-
ReservedVaultNameError,
|
|
185
186
|
SchemaFenceError,
|
|
186
187
|
SchemaValidationError,
|
|
187
188
|
SequenceContentionError,
|
|
@@ -194,9 +195,8 @@ import {
|
|
|
194
195
|
UniqueConstraintError,
|
|
195
196
|
UnknownDictCodeError,
|
|
196
197
|
UnsupportedIndexOptionError,
|
|
197
|
-
ValidationError
|
|
198
|
-
|
|
199
|
-
} from "./chunk-OTWT6BAJ.js";
|
|
198
|
+
ValidationError
|
|
199
|
+
} from "./chunk-4BB4T3O7.js";
|
|
200
200
|
|
|
201
201
|
// src/policy/storage.ts
|
|
202
202
|
var META_COLLECTION = "_meta";
|
|
@@ -910,7 +910,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
|
|
|
910
910
|
}
|
|
911
911
|
const sourceWithId = { ...source, id };
|
|
912
912
|
if (DerivationExecutor === null) {
|
|
913
|
-
({ DerivationExecutor } = await import("./executor-
|
|
913
|
+
({ DerivationExecutor } = await import("./executor-VJSCTBWY.js"));
|
|
914
914
|
}
|
|
915
915
|
const ctx = { vault: accessor.getReadOnlyFacade() };
|
|
916
916
|
const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx);
|
|
@@ -1156,6 +1156,13 @@ var Collection = class {
|
|
|
1156
1156
|
* flag) still decrypts CEK records.
|
|
1157
1157
|
*/
|
|
1158
1158
|
perRecordCek;
|
|
1159
|
+
/**
|
|
1160
|
+
* Per-record provenance opt-in (`provenance: true`). When set, `put()` calls
|
|
1161
|
+
* that supply a `source` option stamp `_source`/`_sourceTs` onto the
|
|
1162
|
+
* unencrypted envelope metadata. Off by default — zero cost for collections
|
|
1163
|
+
* that don't need lineage tracking (FR-5, #445).
|
|
1164
|
+
*/
|
|
1165
|
+
provenance;
|
|
1159
1166
|
/**
|
|
1160
1167
|
* Session-scoped `(id) → CEK` cache for this collection. Lets updates
|
|
1161
1168
|
* reuse a record's stable CEK and lets repeated reads skip the AES-KW
|
|
@@ -1315,6 +1322,7 @@ var Collection = class {
|
|
|
1315
1322
|
}
|
|
1316
1323
|
this.perRecordCek = opts.perRecordKeys === true;
|
|
1317
1324
|
this.cekCache = this.perRecordCek ? new Lru({ maxRecords: 4096 }) : null;
|
|
1325
|
+
this.provenance = opts.provenance === true;
|
|
1318
1326
|
if (opts.crdt && opts.onRegisterConflictResolver) {
|
|
1319
1327
|
const crdtMode = opts.crdt;
|
|
1320
1328
|
const crdtResolver = async (id, local, remote) => {
|
|
@@ -1459,7 +1467,7 @@ var Collection = class {
|
|
|
1459
1467
|
}
|
|
1460
1468
|
}
|
|
1461
1469
|
if (this.materializedViewSource !== void 0) {
|
|
1462
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
1470
|
+
const { resolveStaleMVOnRead } = await import("./stale-PW6VBGSP.js");
|
|
1463
1471
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name);
|
|
1464
1472
|
}
|
|
1465
1473
|
let record;
|
|
@@ -1502,6 +1510,33 @@ var Collection = class {
|
|
|
1502
1510
|
if (json === null) return null;
|
|
1503
1511
|
return JSON.parse(json);
|
|
1504
1512
|
}
|
|
1513
|
+
/**
|
|
1514
|
+
* Read a record's unencrypted envelope metadata (version, timestamps,
|
|
1515
|
+
* provenance) without decrypting the body.
|
|
1516
|
+
*
|
|
1517
|
+
* Returns `null` when no envelope exists for `id` (record absent or never
|
|
1518
|
+
* written). Only `_source`/`_sourceTs` fields are populated when the
|
|
1519
|
+
* collection was opened with `provenance: true` AND the record was written
|
|
1520
|
+
* with a `source` option — but this method works on any collection because
|
|
1521
|
+
* it reads the raw envelope directly.
|
|
1522
|
+
*
|
|
1523
|
+
* @returns `{ version, timestamp, by?, source?, sourceTs? }` or `null`.
|
|
1524
|
+
*
|
|
1525
|
+
* @example
|
|
1526
|
+
* const meta = await clients.getMetadata('c1')
|
|
1527
|
+
* if (meta) console.log(meta.source, meta.timestamp)
|
|
1528
|
+
*/
|
|
1529
|
+
async getMetadata(id) {
|
|
1530
|
+
const env = await this.adapter.get(this.vault, this.name, id);
|
|
1531
|
+
if (!env) return null;
|
|
1532
|
+
return {
|
|
1533
|
+
version: env._v,
|
|
1534
|
+
timestamp: env._ts,
|
|
1535
|
+
...env._by !== void 0 ? { by: env._by } : {},
|
|
1536
|
+
...env._source !== void 0 ? { source: env._source } : {},
|
|
1537
|
+
...env._sourceTs !== void 0 ? { sourceTs: env._sourceTs } : {}
|
|
1538
|
+
};
|
|
1539
|
+
}
|
|
1505
1540
|
/**
|
|
1506
1541
|
* Return a presence handle for this collection.
|
|
1507
1542
|
*
|
|
@@ -1539,6 +1574,14 @@ var Collection = class {
|
|
|
1539
1574
|
* `reason` is stamped onto the resulting ledger entry
|
|
1540
1575
|
* so audit consumers can filter via
|
|
1541
1576
|
* `entries.filter(e => e.reason?.startsWith('import:'))`.
|
|
1577
|
+
* `source` is an opaque source id (e.g. `'crm-sync'`, `'firm-A'`)
|
|
1578
|
+
* stamped onto the envelope as `_source`/`_sourceTs` when
|
|
1579
|
+
* the collection has `provenance: true`. Ignored otherwise
|
|
1580
|
+
* (zero cost). (FR-5, #445)
|
|
1581
|
+
* `sourceTs` is an optional ISO-8601 origin timestamp override;
|
|
1582
|
+
* when supplied together with `source` on a provenance collection,
|
|
1583
|
+
* replaces the machine-stamped `now()` so re-merges preserve the
|
|
1584
|
+
* ORIGIN refresh time across vaults. (FR-4)
|
|
1542
1585
|
*/
|
|
1543
1586
|
async put(id, record, options) {
|
|
1544
1587
|
await this.schemaUpdateGate?.assertWritable();
|
|
@@ -1570,6 +1613,20 @@ var Collection = class {
|
|
|
1570
1613
|
if (busAfterPut) await this.subsystemBus.dispatch("afterPut", event);
|
|
1571
1614
|
}
|
|
1572
1615
|
}
|
|
1616
|
+
/**
|
|
1617
|
+
* Validate a record against this collection's schema WITHOUT writing it.
|
|
1618
|
+
* Returns the (possibly coerced) record on success; throws
|
|
1619
|
+
* {@link SchemaValidationError} (direction: `'input'`) on violation.
|
|
1620
|
+
* A no-op pass-through when no schema is declared.
|
|
1621
|
+
*
|
|
1622
|
+
* Used by FR-8 migrate-then-merge to pre-validate all staged records
|
|
1623
|
+
* before `mergeDecryptedRecords` writes anything — so a failed upgrade
|
|
1624
|
+
* never half-writes the receiver.
|
|
1625
|
+
*/
|
|
1626
|
+
async validateInput(record) {
|
|
1627
|
+
if (this.schema === void 0) return record;
|
|
1628
|
+
return validateSchemaInput(this.schema, record, `validateInput(${this.name})`);
|
|
1629
|
+
}
|
|
1573
1630
|
/** @internal — true when hooks should fire for this write (handlers exist, not re-entrant). */
|
|
1574
1631
|
#hooksActive() {
|
|
1575
1632
|
return this.writeHooks !== void 0 && this.writeHooks.hasHandlers && !this.writeHooks.suppressed;
|
|
@@ -1727,7 +1784,7 @@ var Collection = class {
|
|
|
1727
1784
|
}
|
|
1728
1785
|
const version2 = existingVersion + 1;
|
|
1729
1786
|
const cek2 = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
|
|
1730
|
-
const envelope2 = await this.encryptJsonString(JSON.stringify(crdtState), version2, cek2);
|
|
1787
|
+
const envelope2 = await this.encryptJsonString(JSON.stringify(crdtState), version2, cek2, options?.source, options?.sourceTs);
|
|
1731
1788
|
await this.adapter.put(this.vault, this.name, id, envelope2);
|
|
1732
1789
|
const resolvedRecord = this.crdtStrategy.resolveCrdtSnapshot(crdtState);
|
|
1733
1790
|
const existingResolvedRecord = existingEnvelope ? await this.decryptRecord(existingEnvelope, { skipValidation: true }) : null;
|
|
@@ -1806,7 +1863,7 @@ var Collection = class {
|
|
|
1806
1863
|
});
|
|
1807
1864
|
}
|
|
1808
1865
|
}
|
|
1809
|
-
const envelope = await this.encryptRecord(record, version, cek);
|
|
1866
|
+
const envelope = await this.encryptRecord(record, version, cek, options?.source, options?.sourceTs);
|
|
1810
1867
|
await this.adapter.put(this.vault, this.name, id, envelope);
|
|
1811
1868
|
if (this.ledger) {
|
|
1812
1869
|
const appendInput = {
|
|
@@ -1869,7 +1926,7 @@ var Collection = class {
|
|
|
1869
1926
|
if (mode === "eager") {
|
|
1870
1927
|
if (executor === null) {
|
|
1871
1928
|
;
|
|
1872
|
-
({ MaterializedViewExecutor: executor } = await import("./executor-
|
|
1929
|
+
({ MaterializedViewExecutor: executor } = await import("./executor-UYXSQB4D.js"));
|
|
1873
1930
|
}
|
|
1874
1931
|
await executor.refresh(reg, {
|
|
1875
1932
|
getCollection: (name) => this.materializedViewSource.getCollection(name),
|
|
@@ -1878,7 +1935,7 @@ var Collection = class {
|
|
|
1878
1935
|
});
|
|
1879
1936
|
} else if (mode === "lazy") {
|
|
1880
1937
|
if (staleHelpers === null) {
|
|
1881
|
-
staleHelpers = await import("./stale-
|
|
1938
|
+
staleHelpers = await import("./stale-PW6VBGSP.js");
|
|
1882
1939
|
}
|
|
1883
1940
|
staleHelpers.markMVStale(registry, reg.spec.name);
|
|
1884
1941
|
}
|
|
@@ -2052,7 +2109,7 @@ var Collection = class {
|
|
|
2052
2109
|
continue;
|
|
2053
2110
|
}
|
|
2054
2111
|
if (DerivationExecutor === null) {
|
|
2055
|
-
({ DerivationExecutor } = await import("./executor-
|
|
2112
|
+
({ DerivationExecutor } = await import("./executor-VJSCTBWY.js"));
|
|
2056
2113
|
}
|
|
2057
2114
|
for (const run of runs) {
|
|
2058
2115
|
const ctx = { vault: this.derivationSource.getReadOnlyFacade() };
|
|
@@ -2071,7 +2128,7 @@ var Collection = class {
|
|
|
2071
2128
|
const outputCollection = this.derivationSource.getCollection(outSpec.collection);
|
|
2072
2129
|
const txCtx = this.derivationSource.getActiveTxContext();
|
|
2073
2130
|
if (out.kind === "array") {
|
|
2074
|
-
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-
|
|
2131
|
+
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-ZQT4Y7PF.js");
|
|
2075
2132
|
const prior = await loadFanoutSidecar(
|
|
2076
2133
|
this.adapter,
|
|
2077
2134
|
this.vault,
|
|
@@ -2099,7 +2156,7 @@ var Collection = class {
|
|
|
2099
2156
|
priorEnvelope
|
|
2100
2157
|
});
|
|
2101
2158
|
}
|
|
2102
|
-
await outputCollection.put(entry.key, entry.value);
|
|
2159
|
+
await outputCollection.put(entry.key, entry.value, { source: "derived" });
|
|
2103
2160
|
}
|
|
2104
2161
|
await saveFanoutSidecar(this.adapter, this.vault, {
|
|
2105
2162
|
source: spec.source,
|
|
@@ -2132,7 +2189,7 @@ var Collection = class {
|
|
|
2132
2189
|
priorEnvelope: prior
|
|
2133
2190
|
});
|
|
2134
2191
|
}
|
|
2135
|
-
await outputCollection.put(run.runId, patched);
|
|
2192
|
+
await outputCollection.put(run.runId, patched, { source: "derived" });
|
|
2136
2193
|
continue;
|
|
2137
2194
|
}
|
|
2138
2195
|
if (txCtx !== null) {
|
|
@@ -2147,7 +2204,7 @@ var Collection = class {
|
|
|
2147
2204
|
priorEnvelope: prior
|
|
2148
2205
|
});
|
|
2149
2206
|
}
|
|
2150
|
-
await outputCollection.put(run.runId, out.value);
|
|
2207
|
+
await outputCollection.put(run.runId, out.value, { source: "derived" });
|
|
2151
2208
|
}
|
|
2152
2209
|
}
|
|
2153
2210
|
}
|
|
@@ -2434,7 +2491,7 @@ var Collection = class {
|
|
|
2434
2491
|
for (const [outputKey, outSpec] of Object.entries(spec.outputs)) {
|
|
2435
2492
|
if (outSpec.shape !== "array") continue;
|
|
2436
2493
|
if (helpers === null) {
|
|
2437
|
-
helpers = await import("./fanout-sidecar-
|
|
2494
|
+
helpers = await import("./fanout-sidecar-ZQT4Y7PF.js");
|
|
2438
2495
|
}
|
|
2439
2496
|
const sidecar = await helpers.loadFanoutSidecar(
|
|
2440
2497
|
this.adapter,
|
|
@@ -2474,7 +2531,7 @@ var Collection = class {
|
|
|
2474
2531
|
if (mode === "eager") {
|
|
2475
2532
|
if (executor === null) {
|
|
2476
2533
|
;
|
|
2477
|
-
({ MaterializedViewExecutor: executor } = await import("./executor-
|
|
2534
|
+
({ MaterializedViewExecutor: executor } = await import("./executor-UYXSQB4D.js"));
|
|
2478
2535
|
}
|
|
2479
2536
|
await executor.refresh(reg, {
|
|
2480
2537
|
getCollection: (name) => this.materializedViewSource.getCollection(name),
|
|
@@ -2483,7 +2540,7 @@ var Collection = class {
|
|
|
2483
2540
|
});
|
|
2484
2541
|
} else if (mode === "lazy") {
|
|
2485
2542
|
if (staleHelpers === null) {
|
|
2486
|
-
staleHelpers = await import("./stale-
|
|
2543
|
+
staleHelpers = await import("./stale-PW6VBGSP.js");
|
|
2487
2544
|
}
|
|
2488
2545
|
staleHelpers.markMVStale(registry, reg.spec.name);
|
|
2489
2546
|
}
|
|
@@ -2506,7 +2563,7 @@ var Collection = class {
|
|
|
2506
2563
|
);
|
|
2507
2564
|
}
|
|
2508
2565
|
if (this.materializedViewSource !== void 0) {
|
|
2509
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
2566
|
+
const { resolveStaleMVOnRead } = await import("./stale-PW6VBGSP.js");
|
|
2510
2567
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name);
|
|
2511
2568
|
}
|
|
2512
2569
|
await this.ensureHydrated();
|
|
@@ -3810,7 +3867,7 @@ var Collection = class {
|
|
|
3810
3867
|
* (see {@link encryptRecord}). Rejects `_`-prefixed record fields, which
|
|
3811
3868
|
* would collide with the reserved metadata namespace.
|
|
3812
3869
|
*/
|
|
3813
|
-
buildDebugEnvelope(record, version) {
|
|
3870
|
+
buildDebugEnvelope(record, version, source, sourceTs) {
|
|
3814
3871
|
const rec = record;
|
|
3815
3872
|
for (const key of Object.keys(rec)) {
|
|
3816
3873
|
if (key.startsWith("_")) throw new DebugReservedFieldError(this.name, key);
|
|
@@ -3823,11 +3880,13 @@ var Collection = class {
|
|
|
3823
3880
|
_data: "",
|
|
3824
3881
|
_by: this.keyring.userId,
|
|
3825
3882
|
_debug: NOYDB_FORMAT_VERSION,
|
|
3883
|
+
...this.provenance && source !== void 0 ? { _source: source, _sourceTs: sourceTs ?? (/* @__PURE__ */ new Date()).toISOString() } : {},
|
|
3826
3884
|
...rec
|
|
3827
3885
|
};
|
|
3828
3886
|
}
|
|
3829
|
-
async encryptJsonString(json, version, cek) {
|
|
3887
|
+
async encryptJsonString(json, version, cek, source, sourceTs) {
|
|
3830
3888
|
const by = this.keyring.userId;
|
|
3889
|
+
const provenanceFields = this.provenance && source !== void 0 ? { _source: source, _sourceTs: sourceTs ?? (/* @__PURE__ */ new Date()).toISOString() } : {};
|
|
3831
3890
|
if (!this.encrypted) {
|
|
3832
3891
|
return {
|
|
3833
3892
|
_noydb: NOYDB_FORMAT_VERSION,
|
|
@@ -3835,7 +3894,8 @@ var Collection = class {
|
|
|
3835
3894
|
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3836
3895
|
_iv: "",
|
|
3837
3896
|
_data: json,
|
|
3838
|
-
_by: by
|
|
3897
|
+
_by: by,
|
|
3898
|
+
...provenanceFields
|
|
3839
3899
|
};
|
|
3840
3900
|
}
|
|
3841
3901
|
const dek = await this.getDEK(this.name);
|
|
@@ -3849,7 +3909,8 @@ var Collection = class {
|
|
|
3849
3909
|
_iv: iv2,
|
|
3850
3910
|
_data: data2,
|
|
3851
3911
|
_by: by,
|
|
3852
|
-
_cek: wrapped
|
|
3912
|
+
_cek: wrapped,
|
|
3913
|
+
...provenanceFields
|
|
3853
3914
|
};
|
|
3854
3915
|
}
|
|
3855
3916
|
const { iv, data } = await encrypt(json, dek);
|
|
@@ -3859,14 +3920,15 @@ var Collection = class {
|
|
|
3859
3920
|
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3860
3921
|
_iv: iv,
|
|
3861
3922
|
_data: data,
|
|
3862
|
-
_by: by
|
|
3923
|
+
_by: by,
|
|
3924
|
+
...provenanceFields
|
|
3863
3925
|
};
|
|
3864
3926
|
}
|
|
3865
|
-
async encryptRecord(record, version, cek) {
|
|
3927
|
+
async encryptRecord(record, version, cek, source, sourceTs) {
|
|
3866
3928
|
if (!this.encrypted && this.keyring.debugPlaintext === true && !this.name.startsWith("_")) {
|
|
3867
|
-
return this.buildDebugEnvelope(record, version);
|
|
3929
|
+
return this.buildDebugEnvelope(record, version, source, sourceTs);
|
|
3868
3930
|
}
|
|
3869
|
-
const base = await this.encryptJsonString(JSON.stringify(record), version, cek);
|
|
3931
|
+
const base = await this.encryptJsonString(JSON.stringify(record), version, cek, source, sourceTs);
|
|
3870
3932
|
if (!this.deterministicFields || !this.encrypted) return base;
|
|
3871
3933
|
const dek = await this.getDEK(this.name);
|
|
3872
3934
|
const rec = record;
|
|
@@ -4000,7 +4062,8 @@ var Collection = class {
|
|
|
4000
4062
|
_iv: iv,
|
|
4001
4063
|
_data: data,
|
|
4002
4064
|
_by: this.keyring.userId,
|
|
4003
|
-
...tier > 0 && { _tier: tier }
|
|
4065
|
+
...tier > 0 && { _tier: tier },
|
|
4066
|
+
...this.provenance && opts?.source !== void 0 ? { _source: opts.source, _sourceTs: opts.sourceTs ?? (/* @__PURE__ */ new Date()).toISOString() } : {}
|
|
4004
4067
|
};
|
|
4005
4068
|
await this.adapter.put(this.vault, this.name, id, envelope);
|
|
4006
4069
|
if (tier > 0) {
|
|
@@ -4296,6 +4359,276 @@ function valuesMatch(stored, live) {
|
|
|
4296
4359
|
}
|
|
4297
4360
|
}
|
|
4298
4361
|
|
|
4362
|
+
// src/bundle/export-accessible.ts
|
|
4363
|
+
function resolveAccessibleCollections(keyring, scope, writableOnly = false) {
|
|
4364
|
+
let collections;
|
|
4365
|
+
if (keyring.role === "operator" || keyring.role === "client") {
|
|
4366
|
+
collections = Object.entries(keyring.permissions).filter(([, mode]) => !writableOnly || mode === "rw").map(([c]) => c);
|
|
4367
|
+
}
|
|
4368
|
+
if (scope?.collections) {
|
|
4369
|
+
const allow = new Set(scope.collections);
|
|
4370
|
+
collections = (collections ?? [...scope.collections]).filter((c) => allow.has(c));
|
|
4371
|
+
}
|
|
4372
|
+
return collections;
|
|
4373
|
+
}
|
|
4374
|
+
async function buildAccessibleBundle(vault, collections, reKey, compression = "auto") {
|
|
4375
|
+
return writeNoydbBundle(vault, {
|
|
4376
|
+
compression,
|
|
4377
|
+
...collections !== void 0 ? { collections } : {},
|
|
4378
|
+
...reKey ? { exportPassphrase: reKey.passphrase } : {}
|
|
4379
|
+
});
|
|
4380
|
+
}
|
|
4381
|
+
async function exportAccessibleData(vault, opts = {}) {
|
|
4382
|
+
const { keyring } = vault._introspectState();
|
|
4383
|
+
const collections = resolveAccessibleCollections(keyring, opts.scope);
|
|
4384
|
+
const bytes = await buildAccessibleBundle(vault, collections, opts.reKey, opts.compression ?? "auto");
|
|
4385
|
+
await vault._getLedgerOrNull()?.append({
|
|
4386
|
+
op: "lifecycle",
|
|
4387
|
+
collection: "",
|
|
4388
|
+
id: "",
|
|
4389
|
+
version: 0,
|
|
4390
|
+
actor: keyring.userId,
|
|
4391
|
+
payloadHash: "",
|
|
4392
|
+
reason: `user-export:${keyring.userId}`
|
|
4393
|
+
});
|
|
4394
|
+
return bytes;
|
|
4395
|
+
}
|
|
4396
|
+
|
|
4397
|
+
// src/bundle/withdraw-accessible.ts
|
|
4398
|
+
var FROZEN_SNAPSHOTS_COLLECTION = "_frozen_snapshots";
|
|
4399
|
+
var ENC = new TextEncoder();
|
|
4400
|
+
function randomId() {
|
|
4401
|
+
const b = globalThis.crypto.getRandomValues(new Uint8Array(12));
|
|
4402
|
+
return Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
|
|
4403
|
+
}
|
|
4404
|
+
async function freezeSnapshotOnly(vault, collections, opts) {
|
|
4405
|
+
const { name: vaultName, adapter } = vault._introspectState();
|
|
4406
|
+
const closure = [];
|
|
4407
|
+
for (const c of collections) {
|
|
4408
|
+
for (const id of await adapter.list(vaultName, c)) closure.push({ collection: c, id });
|
|
4409
|
+
}
|
|
4410
|
+
const withdrawalId = opts.withdrawalId ?? `wd-${randomId()}`;
|
|
4411
|
+
const snap = {};
|
|
4412
|
+
for (const { collection, id } of closure) {
|
|
4413
|
+
const env = await adapter.get(vaultName, collection, id);
|
|
4414
|
+
if (env) (snap[collection] ??= {})[id] = env;
|
|
4415
|
+
}
|
|
4416
|
+
const frozenAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4417
|
+
const body = JSON.stringify({ withdrawalId, frozenAt, by: opts.actorUserId, collections: snap });
|
|
4418
|
+
const sha = await sha256Hex(ENC.encode(body));
|
|
4419
|
+
await adapter.put(
|
|
4420
|
+
vaultName,
|
|
4421
|
+
FROZEN_SNAPSHOTS_COLLECTION,
|
|
4422
|
+
withdrawalId,
|
|
4423
|
+
{ _noydb: NOYDB_FORMAT_VERSION, _v: 1, _ts: frozenAt, _iv: "", _data: body, _by: opts.actorUserId },
|
|
4424
|
+
0
|
|
4425
|
+
);
|
|
4426
|
+
await vault._getLedgerOrNull()?.append({
|
|
4427
|
+
op: "lifecycle",
|
|
4428
|
+
collection: "",
|
|
4429
|
+
id: "",
|
|
4430
|
+
version: 0,
|
|
4431
|
+
actor: opts.actorUserId,
|
|
4432
|
+
payloadHash: "",
|
|
4433
|
+
reason: `withdrawal-frozen-snapshot:${withdrawalId}:${sha}`
|
|
4434
|
+
});
|
|
4435
|
+
return { withdrawalId, sha256: sha, recordCount: closure.length, frozenAt };
|
|
4436
|
+
}
|
|
4437
|
+
async function freezeAndDeleteClosure(vault, collections, opts) {
|
|
4438
|
+
const snapshot = opts.disposition === "freeze" ? await freezeSnapshotOnly(vault, collections, {
|
|
4439
|
+
actorUserId: opts.actorUserId,
|
|
4440
|
+
...opts.withdrawalId ? { withdrawalId: opts.withdrawalId } : {}
|
|
4441
|
+
}) : void 0;
|
|
4442
|
+
const { name: vaultName, adapter } = vault._introspectState();
|
|
4443
|
+
for (const c of collections) {
|
|
4444
|
+
for (const id of await adapter.list(vaultName, c)) {
|
|
4445
|
+
await vault.collection(c).delete(id);
|
|
4446
|
+
}
|
|
4447
|
+
}
|
|
4448
|
+
return snapshot;
|
|
4449
|
+
}
|
|
4450
|
+
async function withdrawAccessibleData(vault, opts) {
|
|
4451
|
+
const { keyring } = vault._introspectState();
|
|
4452
|
+
const disposition = opts.disposition ?? "delete";
|
|
4453
|
+
if (keyring.role === "owner" || keyring.role === "admin") {
|
|
4454
|
+
throw new ReadOnlyError(
|
|
4455
|
+
"unilateralWithdrawal is the scoped self-service path; an owner/admin should use extractPartition"
|
|
4456
|
+
);
|
|
4457
|
+
}
|
|
4458
|
+
if (keyring.role === "custodian") {
|
|
4459
|
+
throw new ReadOnlyError(
|
|
4460
|
+
"a custodian cannot destructively withdraw/sever; use vault.custody.liberate for an audited ownership claim"
|
|
4461
|
+
);
|
|
4462
|
+
}
|
|
4463
|
+
if (keyring.role === "client" || keyring.role === "viewer") {
|
|
4464
|
+
throw new ReadOnlyError(
|
|
4465
|
+
"read-only role cannot self-serve a destructive withdrawal \u2014 use requestWithdrawal (two-party)"
|
|
4466
|
+
);
|
|
4467
|
+
}
|
|
4468
|
+
const collections = resolveAccessibleCollections(keyring, opts.scope, true);
|
|
4469
|
+
if (!collections || collections.length === 0) {
|
|
4470
|
+
throw new ReadOnlyError(
|
|
4471
|
+
"unilateralWithdrawal requires rw access on the withdrawn collections \u2014 use requestWithdrawal for read-only scope"
|
|
4472
|
+
);
|
|
4473
|
+
}
|
|
4474
|
+
const bundle = await buildAccessibleBundle(vault, collections, opts.reKey);
|
|
4475
|
+
const snapshot = await freezeAndDeleteClosure(vault, collections, {
|
|
4476
|
+
disposition,
|
|
4477
|
+
actorUserId: keyring.userId,
|
|
4478
|
+
...opts.withdrawalId ? { withdrawalId: opts.withdrawalId } : {}
|
|
4479
|
+
});
|
|
4480
|
+
await vault._getLedgerOrNull()?.append({
|
|
4481
|
+
op: "lifecycle",
|
|
4482
|
+
collection: "",
|
|
4483
|
+
id: "",
|
|
4484
|
+
version: 0,
|
|
4485
|
+
actor: keyring.userId,
|
|
4486
|
+
payloadHash: "",
|
|
4487
|
+
reason: `user-unilateral-withdrawal:${keyring.userId}:${disposition}:${opts.legalBasis}`
|
|
4488
|
+
});
|
|
4489
|
+
return snapshot ? { bundle, snapshot } : { bundle };
|
|
4490
|
+
}
|
|
4491
|
+
|
|
4492
|
+
// src/bundle/request-withdrawal.ts
|
|
4493
|
+
var WITHDRAWAL_REQUESTS_COLLECTION = "_user_withdrawal_requests";
|
|
4494
|
+
var WithdrawalRequestError = class extends NoydbError {
|
|
4495
|
+
constructor(message) {
|
|
4496
|
+
super("WITHDRAWAL_REQUEST", message);
|
|
4497
|
+
this.name = "WithdrawalRequestError";
|
|
4498
|
+
}
|
|
4499
|
+
};
|
|
4500
|
+
function writeRequest(vault, req, expectedVersion) {
|
|
4501
|
+
const { name: vaultName, adapter } = vault._introspectState();
|
|
4502
|
+
const body = JSON.stringify(req);
|
|
4503
|
+
const env = {
|
|
4504
|
+
_noydb: NOYDB_FORMAT_VERSION,
|
|
4505
|
+
_v: expectedVersion + 1,
|
|
4506
|
+
_ts: req.decidedAt ?? req.requestedAt,
|
|
4507
|
+
_iv: "",
|
|
4508
|
+
_data: body,
|
|
4509
|
+
_by: req.decidedBy ?? req.requester
|
|
4510
|
+
};
|
|
4511
|
+
return adapter.put(vaultName, WITHDRAWAL_REQUESTS_COLLECTION, req.requestId, env, expectedVersion);
|
|
4512
|
+
}
|
|
4513
|
+
async function readRequest(vault, requestId) {
|
|
4514
|
+
const { name: vaultName, adapter } = vault._introspectState();
|
|
4515
|
+
const env = await adapter.get(vaultName, WITHDRAWAL_REQUESTS_COLLECTION, requestId);
|
|
4516
|
+
if (!env) throw new WithdrawalRequestError(`withdrawal request "${requestId}" not found`);
|
|
4517
|
+
return { req: JSON.parse(env._data), version: env._v };
|
|
4518
|
+
}
|
|
4519
|
+
async function requestWithdrawal(vault, opts = {}) {
|
|
4520
|
+
const { keyring } = vault._introspectState();
|
|
4521
|
+
const collections = resolveAccessibleCollections(keyring, opts.scope, false);
|
|
4522
|
+
if (!collections || collections.length === 0) {
|
|
4523
|
+
throw new WithdrawalRequestError(
|
|
4524
|
+
"requestWithdrawal needs a concrete scope.collections (the caller has all-collection access \u2014 name the collections to withdraw)"
|
|
4525
|
+
);
|
|
4526
|
+
}
|
|
4527
|
+
const requestId = `wr-${randomId()}`;
|
|
4528
|
+
const requestedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4529
|
+
const req = {
|
|
4530
|
+
requestId,
|
|
4531
|
+
requester: keyring.userId,
|
|
4532
|
+
collections,
|
|
4533
|
+
disposition: opts.disposition ?? "delete",
|
|
4534
|
+
status: "pending",
|
|
4535
|
+
requestedAt,
|
|
4536
|
+
...opts.legalBasis ? { legalBasis: opts.legalBasis } : {},
|
|
4537
|
+
...opts.expiresInMs ? { expiresAt: new Date(Date.parse(requestedAt) + opts.expiresInMs).toISOString() } : {}
|
|
4538
|
+
};
|
|
4539
|
+
await writeRequest(vault, req, 0);
|
|
4540
|
+
await vault._getLedgerOrNull()?.append({
|
|
4541
|
+
op: "lifecycle",
|
|
4542
|
+
collection: "",
|
|
4543
|
+
id: "",
|
|
4544
|
+
version: 0,
|
|
4545
|
+
actor: keyring.userId,
|
|
4546
|
+
payloadHash: "",
|
|
4547
|
+
reason: `user-withdrawal-request:${requestId}:${keyring.userId}`
|
|
4548
|
+
});
|
|
4549
|
+
return { requestId, status: "pending", ...req.expiresAt ? { expiresAt: req.expiresAt } : {} };
|
|
4550
|
+
}
|
|
4551
|
+
async function listWithdrawalRequests(vault, opts = {}) {
|
|
4552
|
+
const { name: vaultName, adapter } = vault._introspectState();
|
|
4553
|
+
const ids = await adapter.list(vaultName, WITHDRAWAL_REQUESTS_COLLECTION);
|
|
4554
|
+
const out = [];
|
|
4555
|
+
for (const id of ids) {
|
|
4556
|
+
const env = await adapter.get(vaultName, WITHDRAWAL_REQUESTS_COLLECTION, id);
|
|
4557
|
+
if (!env) continue;
|
|
4558
|
+
const req = JSON.parse(env._data);
|
|
4559
|
+
if (!opts.status || req.status === opts.status) out.push(req);
|
|
4560
|
+
}
|
|
4561
|
+
return out;
|
|
4562
|
+
}
|
|
4563
|
+
function assertApprover(vault) {
|
|
4564
|
+
const { keyring } = vault._introspectState();
|
|
4565
|
+
if (keyring.role !== "owner" && keyring.role !== "admin") {
|
|
4566
|
+
throw new WithdrawalRequestError("approveWithdrawal / rejectWithdrawal require an owner or admin");
|
|
4567
|
+
}
|
|
4568
|
+
return keyring.userId;
|
|
4569
|
+
}
|
|
4570
|
+
function assertPending(req) {
|
|
4571
|
+
if (req.status !== "pending") {
|
|
4572
|
+
throw new WithdrawalRequestError(`withdrawal request "${req.requestId}" is already ${req.status}`);
|
|
4573
|
+
}
|
|
4574
|
+
if (req.expiresAt && Date.now() > Date.parse(req.expiresAt)) {
|
|
4575
|
+
throw new WithdrawalRequestError(`withdrawal request "${req.requestId}" expired at ${req.expiresAt}`);
|
|
4576
|
+
}
|
|
4577
|
+
}
|
|
4578
|
+
async function approveWithdrawal(vault, requestId, opts = {}) {
|
|
4579
|
+
const approver = assertApprover(vault);
|
|
4580
|
+
const { req, version } = await readRequest(vault, requestId);
|
|
4581
|
+
assertPending(req);
|
|
4582
|
+
const bundle = await buildAccessibleBundle(vault, [...req.collections], opts.reKey);
|
|
4583
|
+
const snapshot = await freezeAndDeleteClosure(vault, req.collections, {
|
|
4584
|
+
disposition: req.disposition,
|
|
4585
|
+
actorUserId: approver,
|
|
4586
|
+
withdrawalId: `wd-${requestId}`
|
|
4587
|
+
});
|
|
4588
|
+
const decidedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4589
|
+
await writeRequest(vault, {
|
|
4590
|
+
...req,
|
|
4591
|
+
status: "approved",
|
|
4592
|
+
decidedAt,
|
|
4593
|
+
decidedBy: approver,
|
|
4594
|
+
...snapshot ? { snapshotSha256: snapshot.sha256 } : {}
|
|
4595
|
+
}, version);
|
|
4596
|
+
await vault._getLedgerOrNull()?.append({
|
|
4597
|
+
op: "lifecycle",
|
|
4598
|
+
collection: "",
|
|
4599
|
+
id: "",
|
|
4600
|
+
version: 0,
|
|
4601
|
+
actor: approver,
|
|
4602
|
+
payloadHash: "",
|
|
4603
|
+
reason: `user-withdrawal-approved:${requestId}:${req.requester}:${req.disposition}`
|
|
4604
|
+
});
|
|
4605
|
+
return snapshot ? { bundle, snapshot } : { bundle };
|
|
4606
|
+
}
|
|
4607
|
+
async function rejectWithdrawal(vault, requestId, opts = {}) {
|
|
4608
|
+
const approver = assertApprover(vault);
|
|
4609
|
+
const { req, version } = await readRequest(vault, requestId);
|
|
4610
|
+
assertPending(req);
|
|
4611
|
+
const decidedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4612
|
+
const updated = {
|
|
4613
|
+
...req,
|
|
4614
|
+
status: "rejected",
|
|
4615
|
+
decidedAt,
|
|
4616
|
+
decidedBy: approver,
|
|
4617
|
+
...opts.reason ? { rejectReason: opts.reason } : {}
|
|
4618
|
+
};
|
|
4619
|
+
await writeRequest(vault, updated, version);
|
|
4620
|
+
await vault._getLedgerOrNull()?.append({
|
|
4621
|
+
op: "lifecycle",
|
|
4622
|
+
collection: "",
|
|
4623
|
+
id: "",
|
|
4624
|
+
version: 0,
|
|
4625
|
+
actor: approver,
|
|
4626
|
+
payloadHash: "",
|
|
4627
|
+
reason: `user-withdrawal-rejected:${requestId}:${req.requester}`
|
|
4628
|
+
});
|
|
4629
|
+
return updated;
|
|
4630
|
+
}
|
|
4631
|
+
|
|
4299
4632
|
// src/archive/engine.ts
|
|
4300
4633
|
function isHeld(policy, record) {
|
|
4301
4634
|
if (!policy.legalHold) return false;
|
|
@@ -4971,20 +5304,99 @@ var LinkIntegrityError = class extends NoydbError {
|
|
|
4971
5304
|
|
|
4972
5305
|
// src/meta/user-envelope/api.ts
|
|
4973
5306
|
var UserApi = class {
|
|
4974
|
-
constructor(adapter, vaultName, writerKeyringId, getDek, checkGate2) {
|
|
5307
|
+
constructor(adapter, vaultName, writerKeyringId, getDek, checkGate2, exportAccessible, unilateralWithdraw, requestWithdraw, listWithdrawals, approveWithdraw, rejectWithdraw) {
|
|
4975
5308
|
this.adapter = adapter;
|
|
4976
5309
|
this.vaultName = vaultName;
|
|
4977
5310
|
this.writerKeyringId = writerKeyringId;
|
|
4978
5311
|
this.getDek = getDek;
|
|
4979
5312
|
this.checkGate = checkGate2;
|
|
5313
|
+
this.exportAccessible = exportAccessible;
|
|
5314
|
+
this.unilateralWithdraw = unilateralWithdraw;
|
|
5315
|
+
this.requestWithdraw = requestWithdraw;
|
|
5316
|
+
this.listWithdrawals = listWithdrawals;
|
|
5317
|
+
this.approveWithdraw = approveWithdraw;
|
|
5318
|
+
this.rejectWithdraw = rejectWithdraw;
|
|
4980
5319
|
}
|
|
4981
5320
|
adapter;
|
|
4982
5321
|
vaultName;
|
|
4983
5322
|
writerKeyringId;
|
|
4984
5323
|
getDek;
|
|
4985
5324
|
checkGate;
|
|
5325
|
+
exportAccessible;
|
|
5326
|
+
unilateralWithdraw;
|
|
5327
|
+
requestWithdraw;
|
|
5328
|
+
listWithdrawals;
|
|
5329
|
+
approveWithdraw;
|
|
5330
|
+
rejectWithdraw;
|
|
4986
5331
|
/** keyringId → set of listeners. Wildcard '*' fires on every change. */
|
|
4987
5332
|
listeners = /* @__PURE__ */ new Map();
|
|
5333
|
+
/**
|
|
5334
|
+
* #199 P3 — file a two-party withdrawal request for the caller's accessible
|
|
5335
|
+
* scope. Non-destructive (writes a pending request); an owner later approves
|
|
5336
|
+
* or rejects. This is the path for read-only roles (`client`/`viewer`) that
|
|
5337
|
+
* cannot self-serve a destructive `unilateralWithdrawal`. Gated by
|
|
5338
|
+
* `user-request-withdrawal` (enabled by default).
|
|
5339
|
+
*/
|
|
5340
|
+
async requestWithdrawal(opts = {}) {
|
|
5341
|
+
if (this.checkGate) await this.checkGate("user-request-withdrawal");
|
|
5342
|
+
if (!this.requestWithdraw) {
|
|
5343
|
+
throw new Error("requestWithdrawal requires a Noydb-backed vault (not a bare UserApi)");
|
|
5344
|
+
}
|
|
5345
|
+
return this.requestWithdraw(opts);
|
|
5346
|
+
}
|
|
5347
|
+
/** #199 P3 — owner side: list filed withdrawal requests (optionally by status). */
|
|
5348
|
+
async listWithdrawalRequests(opts = {}) {
|
|
5349
|
+
if (!this.listWithdrawals) {
|
|
5350
|
+
throw new Error("listWithdrawalRequests requires a Noydb-backed vault (not a bare UserApi)");
|
|
5351
|
+
}
|
|
5352
|
+
return this.listWithdrawals(opts);
|
|
5353
|
+
}
|
|
5354
|
+
/**
|
|
5355
|
+
* #199 P3 — owner side: approve a pending request. Extracts the requester's
|
|
5356
|
+
* recorded scope under firm authority, disposes of the source per the
|
|
5357
|
+
* request's disposition, and returns the re-keyed bundle to hand back. Gated
|
|
5358
|
+
* by `approve-user-withdrawal` (tier-2 default) + owner/admin role.
|
|
5359
|
+
*/
|
|
5360
|
+
async approveWithdrawal(requestId, opts = {}) {
|
|
5361
|
+
if (this.checkGate) await this.checkGate("approve-user-withdrawal");
|
|
5362
|
+
if (!this.approveWithdraw) {
|
|
5363
|
+
throw new Error("approveWithdrawal requires a Noydb-backed vault (not a bare UserApi)");
|
|
5364
|
+
}
|
|
5365
|
+
return this.approveWithdraw(requestId, opts);
|
|
5366
|
+
}
|
|
5367
|
+
/** #199 P3 — owner side: reject a pending request (no data is touched). */
|
|
5368
|
+
async rejectWithdrawal(requestId, opts = {}) {
|
|
5369
|
+
if (this.checkGate) await this.checkGate("approve-user-withdrawal");
|
|
5370
|
+
if (!this.rejectWithdraw) {
|
|
5371
|
+
throw new Error("rejectWithdrawal requires a Noydb-backed vault (not a bare UserApi)");
|
|
5372
|
+
}
|
|
5373
|
+
return this.rejectWithdraw(requestId, opts);
|
|
5374
|
+
}
|
|
5375
|
+
/**
|
|
5376
|
+
* #199 P2 — single-party withdrawal: export the caller's accessible scope
|
|
5377
|
+
* (re-keyed) and dispose of the source (`delete` or `freeze`). Gated by the
|
|
5378
|
+
* fail-closed built-in `client-unilateral-withdraw` policy — undefined or
|
|
5379
|
+
* disabled → throws (use `requestWithdrawal`). The firm enables it at vault
|
|
5380
|
+
* creation.
|
|
5381
|
+
*/
|
|
5382
|
+
async unilateralWithdrawal(opts) {
|
|
5383
|
+
if (this.checkGate) await this.checkGate("client-unilateral-withdraw");
|
|
5384
|
+
if (!this.unilateralWithdraw) {
|
|
5385
|
+
throw new Error("unilateralWithdrawal requires a Noydb-backed vault (not a bare UserApi)");
|
|
5386
|
+
}
|
|
5387
|
+
return this.unilateralWithdraw(opts);
|
|
5388
|
+
}
|
|
5389
|
+
/**
|
|
5390
|
+
* #199 — export the calling user's accessible scope as a portable, re-keyed
|
|
5391
|
+
* `.noydb` bundle. Non-destructive and **always allowed** (data sovereignty
|
|
5392
|
+
* by construction, §11.11) but audited. Scope = the caller's DEK access set.
|
|
5393
|
+
*/
|
|
5394
|
+
async exportMyAccessibleData(opts = {}) {
|
|
5395
|
+
if (!this.exportAccessible) {
|
|
5396
|
+
throw new Error("exportMyAccessibleData requires a Noydb-backed vault (not a bare UserApi)");
|
|
5397
|
+
}
|
|
5398
|
+
return this.exportAccessible(opts);
|
|
5399
|
+
}
|
|
4988
5400
|
// ─── Write-self ──────────────────────────────────────────────────────
|
|
4989
5401
|
/** Read the writer's own envelope. Returns null if never written. */
|
|
4990
5402
|
async me() {
|
|
@@ -5237,6 +5649,148 @@ function isPlainObject(x) {
|
|
|
5237
5649
|
return proto === Object.prototype || proto === null;
|
|
5238
5650
|
}
|
|
5239
5651
|
|
|
5652
|
+
// src/custody/index.ts
|
|
5653
|
+
var CustodyApi = class {
|
|
5654
|
+
constructor(_grantCustodian, _revokeCustodian, _liberate) {
|
|
5655
|
+
this._grantCustodian = _grantCustodian;
|
|
5656
|
+
this._revokeCustodian = _revokeCustodian;
|
|
5657
|
+
this._liberate = _liberate;
|
|
5658
|
+
}
|
|
5659
|
+
_grantCustodian;
|
|
5660
|
+
_revokeCustodian;
|
|
5661
|
+
_liberate;
|
|
5662
|
+
/**
|
|
5663
|
+
* Owner-only: grant the FR-6 `custodian` role. The custodian operates every
|
|
5664
|
+
* collection (rw + access) but is provably unable to grant / revoke / rotate /
|
|
5665
|
+
* extract-and-sever. Defended in depth (gate + owner-only role check) inside
|
|
5666
|
+
* the injected `Noydb.grantCustodian`.
|
|
5667
|
+
*/
|
|
5668
|
+
async grantCustodian(options, factors) {
|
|
5669
|
+
return this._grantCustodian(options, factors);
|
|
5670
|
+
}
|
|
5671
|
+
/** Owner-only: revoke a custodian. */
|
|
5672
|
+
async revokeCustodian(options, factors) {
|
|
5673
|
+
return this._revokeCustodian(options, factors);
|
|
5674
|
+
}
|
|
5675
|
+
/**
|
|
5676
|
+
* Custodian-only: the audited claim of ownership over a sealed-owner (Deed)
|
|
5677
|
+
* vault. Mints a DISTINCT new owner re-wrapping the incumbent DEKs under a
|
|
5678
|
+
* fresh KEK (the latent owner is never impersonated), ledger-audited. See
|
|
5679
|
+
* {@link liberateVault}.
|
|
5680
|
+
*/
|
|
5681
|
+
async liberate(opts) {
|
|
5682
|
+
return this._liberate(opts);
|
|
5683
|
+
}
|
|
5684
|
+
};
|
|
5685
|
+
|
|
5686
|
+
// src/team/deed.ts
|
|
5687
|
+
var DEED_RECORD_ID = "deed";
|
|
5688
|
+
async function createDeedOwner(store, vault, ownerUserId, sealing) {
|
|
5689
|
+
const passphrase = await resolveManagedSecret(store, vault, sealing);
|
|
5690
|
+
const keyring = await createOwnerKeyring(store, vault, ownerUserId, passphrase);
|
|
5691
|
+
await saveDeedMarker(store, vault, {
|
|
5692
|
+
ownerUserId,
|
|
5693
|
+
sealedUnder: sealing.id,
|
|
5694
|
+
latent: true,
|
|
5695
|
+
issuedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5696
|
+
});
|
|
5697
|
+
return keyring;
|
|
5698
|
+
}
|
|
5699
|
+
async function loadDeedMarker(store, vault) {
|
|
5700
|
+
const envelope = await store.get(vault, "_meta", DEED_RECORD_ID);
|
|
5701
|
+
if (!envelope) return null;
|
|
5702
|
+
let payload;
|
|
5703
|
+
try {
|
|
5704
|
+
payload = JSON.parse(envelope._data);
|
|
5705
|
+
} catch {
|
|
5706
|
+
return null;
|
|
5707
|
+
}
|
|
5708
|
+
if (typeof payload !== "object" || payload === null) return null;
|
|
5709
|
+
const r = payload;
|
|
5710
|
+
if (r._noydb_deed !== 1) return null;
|
|
5711
|
+
if (typeof r.ownerUserId !== "string" || typeof r.sealedUnder !== "string" || r.latent !== true || typeof r.issuedAt !== "string") {
|
|
5712
|
+
return null;
|
|
5713
|
+
}
|
|
5714
|
+
const marker = {
|
|
5715
|
+
ownerUserId: r.ownerUserId,
|
|
5716
|
+
sealedUnder: r.sealedUnder,
|
|
5717
|
+
latent: true,
|
|
5718
|
+
issuedAt: r.issuedAt,
|
|
5719
|
+
...typeof r.liberatedAt === "string" ? { liberatedAt: r.liberatedAt } : {}
|
|
5720
|
+
};
|
|
5721
|
+
return marker;
|
|
5722
|
+
}
|
|
5723
|
+
async function isDeedVault(store, vault) {
|
|
5724
|
+
return await loadDeedMarker(store, vault) !== null;
|
|
5725
|
+
}
|
|
5726
|
+
async function saveDeedMarker(store, vault, marker) {
|
|
5727
|
+
const persisted = { _noydb_deed: 1, ...marker };
|
|
5728
|
+
const prior = await store.get(vault, "_meta", DEED_RECORD_ID);
|
|
5729
|
+
const env = {
|
|
5730
|
+
_noydb: NOYDB_FORMAT_VERSION,
|
|
5731
|
+
_v: (prior?._v ?? 0) + 1,
|
|
5732
|
+
_ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5733
|
+
// AES-GCM bypassed — the marker is plaintext audit metadata.
|
|
5734
|
+
_iv: "",
|
|
5735
|
+
_data: JSON.stringify(persisted)
|
|
5736
|
+
};
|
|
5737
|
+
await store.put(vault, "_meta", DEED_RECORD_ID, env);
|
|
5738
|
+
}
|
|
5739
|
+
|
|
5740
|
+
// src/custody/liberate.ts
|
|
5741
|
+
async function liberateVault(vault, opts) {
|
|
5742
|
+
await vault.noydb.checkGate(vault.name, "liberate-vault", opts.factors);
|
|
5743
|
+
const { name: vaultName, adapter, keyring } = vault._introspectState();
|
|
5744
|
+
if (keyring.role !== "custodian") {
|
|
5745
|
+
throw new PermissionDeniedError(
|
|
5746
|
+
"liberation is claimed only by the custodian (the de-facto authority holding the DEKs)"
|
|
5747
|
+
);
|
|
5748
|
+
}
|
|
5749
|
+
const existing = await adapter.get(vaultName, "_keyring", opts.newOwnerId);
|
|
5750
|
+
if (existing) {
|
|
5751
|
+
throw new PermissionDeniedError(
|
|
5752
|
+
`liberateVault: newOwnerId "${opts.newOwnerId}" already exists as a principal; choose a fresh id (liberation mints a distinct owner, it never overwrites an existing keyring)`
|
|
5753
|
+
);
|
|
5754
|
+
}
|
|
5755
|
+
const collections = await listOperationalCollections(vault);
|
|
5756
|
+
const snapshot = await freezeSnapshotOnly(vault, collections, { actorUserId: keyring.userId });
|
|
5757
|
+
const newOwner = await createOwnerKeyring(adapter, vaultName, opts.newOwnerId, opts.newOwnerPassphrase);
|
|
5758
|
+
if (!newOwner.kek) {
|
|
5759
|
+
throw new PermissionDeniedError(
|
|
5760
|
+
`new owner keyring for "${opts.newOwnerId}" has no KEK to re-wrap the incumbent DEKs under`
|
|
5761
|
+
);
|
|
5762
|
+
}
|
|
5763
|
+
const env = await adapter.get(vaultName, "_keyring", opts.newOwnerId);
|
|
5764
|
+
if (!env) {
|
|
5765
|
+
throw new PermissionDeniedError(`new owner keyring for "${opts.newOwnerId}" did not persist`);
|
|
5766
|
+
}
|
|
5767
|
+
const keyringFile = JSON.parse(env._data);
|
|
5768
|
+
const mergedDeks = { ...keyringFile.deks };
|
|
5769
|
+
for (const [collection, dek] of keyring.deks) {
|
|
5770
|
+
mergedDeks[collection] = await wrapKey(dek, newOwner.kek);
|
|
5771
|
+
}
|
|
5772
|
+
const mergedFile = { ...keyringFile, deks: mergedDeks };
|
|
5773
|
+
await adapter.put(vaultName, "_keyring", opts.newOwnerId, { ...env, _data: JSON.stringify(mergedFile) });
|
|
5774
|
+
await vault._getLedgerOrNull()?.append({
|
|
5775
|
+
op: "lifecycle",
|
|
5776
|
+
collection: "",
|
|
5777
|
+
id: "",
|
|
5778
|
+
version: 0,
|
|
5779
|
+
actor: opts.newOwnerId,
|
|
5780
|
+
payloadHash: "",
|
|
5781
|
+
reason: `liberation-claimed:${opts.newOwnerId}:${opts.legalBasis}`
|
|
5782
|
+
});
|
|
5783
|
+
const marker = await loadDeedMarker(adapter, vaultName);
|
|
5784
|
+
if (marker) {
|
|
5785
|
+
await saveDeedMarker(adapter, vaultName, { ...marker, liberatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
5786
|
+
}
|
|
5787
|
+
return { snapshot };
|
|
5788
|
+
}
|
|
5789
|
+
async function listOperationalCollections(vault) {
|
|
5790
|
+
const { keyring } = vault._introspectState();
|
|
5791
|
+
return [...keyring.deks.keys()].filter((c) => !c.startsWith("_"));
|
|
5792
|
+
}
|
|
5793
|
+
|
|
5240
5794
|
// src/persisted-schemas/canonicalize.ts
|
|
5241
5795
|
function canonicalize(value) {
|
|
5242
5796
|
if (value === null || typeof value !== "object") {
|
|
@@ -6019,6 +6573,18 @@ var Vault = class {
|
|
|
6019
6573
|
* @see docs/superpowers/specs/2026-05-05-user-envelope-design.md
|
|
6020
6574
|
*/
|
|
6021
6575
|
user;
|
|
6576
|
+
/**
|
|
6577
|
+
* FR-6 custody API — the sovereign-custody surface, mirroring `vault.user.*`.
|
|
6578
|
+
*
|
|
6579
|
+
* - `grantCustodian(opts)` / `revokeCustodian(opts)` — owner-only: mint /
|
|
6580
|
+
* remove a `custodian` who operates the vault fully but can never grant /
|
|
6581
|
+
* rotate / sever / extract.
|
|
6582
|
+
* - `liberate(opts)` — custodian-only: the audited claim of ownership over a
|
|
6583
|
+
* sealed-owner (Deed) vault (mints a DISTINCT new owner; ledger-audited).
|
|
6584
|
+
*
|
|
6585
|
+
* @see docs/superpowers/specs/2026-06-17-fr6-deed-custodian-liberate-design.md
|
|
6586
|
+
*/
|
|
6587
|
+
custody;
|
|
6022
6588
|
/**
|
|
6023
6589
|
* Optional callback that re-derives an UnlockedKeyring from the
|
|
6024
6590
|
* adapter using the active user's passphrase. Called by `load()`
|
|
@@ -6221,7 +6787,18 @@ var Vault = class {
|
|
|
6221
6787
|
this.name,
|
|
6222
6788
|
this.keyring.userId,
|
|
6223
6789
|
() => this.getDEK(USER_ENVELOPE_COLLECTION),
|
|
6224
|
-
(gate, presented) => this.noydb.checkGate(this.name, gate, presented)
|
|
6790
|
+
(gate, presented) => this.noydb.checkGate(this.name, gate, presented),
|
|
6791
|
+
(opts2) => exportAccessibleData(this, opts2),
|
|
6792
|
+
(opts2) => withdrawAccessibleData(this, opts2),
|
|
6793
|
+
(opts2) => requestWithdrawal(this, opts2),
|
|
6794
|
+
(opts2) => listWithdrawalRequests(this, opts2),
|
|
6795
|
+
(requestId, opts2) => approveWithdrawal(this, requestId, opts2),
|
|
6796
|
+
(requestId, opts2) => rejectWithdrawal(this, requestId, opts2)
|
|
6797
|
+
);
|
|
6798
|
+
this.custody = new CustodyApi(
|
|
6799
|
+
(options, factors) => this.noydb.grantCustodian(this.name, options, factors),
|
|
6800
|
+
(options, factors) => this.noydb.revokeCustodian(this.name, options, factors),
|
|
6801
|
+
(opts2) => liberateVault(this, opts2)
|
|
6225
6802
|
);
|
|
6226
6803
|
}
|
|
6227
6804
|
/**
|
|
@@ -6450,6 +7027,7 @@ var Vault = class {
|
|
|
6450
7027
|
}
|
|
6451
7028
|
collOpts.perRecordKeys = true;
|
|
6452
7029
|
}
|
|
7030
|
+
if (options?.provenance !== void 0) collOpts.provenance = options.provenance;
|
|
6453
7031
|
if (options?.tiers !== void 0) collOpts.tiers = options.tiers;
|
|
6454
7032
|
if (options?.tierMode !== void 0) collOpts.tierMode = options.tierMode;
|
|
6455
7033
|
collOpts.onCrossTierAccess = (event) => this.emitCrossTier(event);
|
|
@@ -7134,12 +7712,12 @@ var Vault = class {
|
|
|
7134
7712
|
if (!fieldSchema) {
|
|
7135
7713
|
throw new AttestationError(`issueAttestation: collection '${collectionName}' has no attestation field-schema. Declare it via vault.collection('${collectionName}', { attestation: { fields: [...] } }).`);
|
|
7136
7714
|
}
|
|
7137
|
-
const { issueAttestationCore } = await import("./issue-
|
|
7715
|
+
const { issueAttestationCore } = await import("./issue-KLRMW5DH.js");
|
|
7138
7716
|
const out = await issueAttestationCore(this.makeIssueContext(), { collection: collectionName, id, fieldSchema });
|
|
7139
7717
|
return { docId: out.docId, qr: out.qr, keyId: out.keyId, publicKeyB64: out.publicKeyB64 };
|
|
7140
7718
|
}
|
|
7141
7719
|
async getDocumentSigningPublicKey() {
|
|
7142
|
-
const { loadSigner, loadOrCreateSigner } = await import("./signer-
|
|
7720
|
+
const { loadSigner, loadOrCreateSigner } = await import("./signer-UJF3CFDC.js");
|
|
7143
7721
|
const existing = await loadSigner(this.adapter, this.name, this.getDEK);
|
|
7144
7722
|
if (existing) return { keyId: existing.keyId, publicKeyB64: existing.publicKeyB64 };
|
|
7145
7723
|
if (this.keyring.role !== "owner") {
|
|
@@ -7165,19 +7743,19 @@ var Vault = class {
|
|
|
7165
7743
|
};
|
|
7166
7744
|
}
|
|
7167
7745
|
async revokeAttestation(docId) {
|
|
7168
|
-
const { revokeDocCore } = await import("./revoke-
|
|
7746
|
+
const { revokeDocCore } = await import("./revoke-WUY4AYRJ.js");
|
|
7169
7747
|
await revokeDocCore(this.makeRevokeContext(), docId);
|
|
7170
7748
|
}
|
|
7171
7749
|
async unrevokeAttestation(docId) {
|
|
7172
|
-
const { unrevokeDocCore } = await import("./revoke-
|
|
7750
|
+
const { unrevokeDocCore } = await import("./revoke-WUY4AYRJ.js");
|
|
7173
7751
|
await unrevokeDocCore(this.makeRevokeContext(), docId);
|
|
7174
7752
|
}
|
|
7175
7753
|
async getRevokedDocIds() {
|
|
7176
|
-
const { getRevokedDocIdsCore } = await import("./revoke-
|
|
7754
|
+
const { getRevokedDocIdsCore } = await import("./revoke-WUY4AYRJ.js");
|
|
7177
7755
|
return getRevokedDocIdsCore(this.makeRevokeContext());
|
|
7178
7756
|
}
|
|
7179
7757
|
async publishRevocationList() {
|
|
7180
|
-
const { publishRevocationListCore } = await import("./revoke-
|
|
7758
|
+
const { publishRevocationListCore } = await import("./revoke-WUY4AYRJ.js");
|
|
7181
7759
|
return publishRevocationListCore(this.makeRevokeContext());
|
|
7182
7760
|
}
|
|
7183
7761
|
makeRevokeContext() {
|
|
@@ -7836,7 +8414,7 @@ var Vault = class {
|
|
|
7836
8414
|
async _initDerivations(handles) {
|
|
7837
8415
|
if (handles.length === 0) return;
|
|
7838
8416
|
const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
|
|
7839
|
-
import("./registry-
|
|
8417
|
+
import("./registry-GAIFVWXF.js"),
|
|
7840
8418
|
import("./read-only-facade-EX6WZZBP.js")
|
|
7841
8419
|
]);
|
|
7842
8420
|
const registry = new DerivationRegistry();
|
|
@@ -7867,7 +8445,7 @@ var Vault = class {
|
|
|
7867
8445
|
*/
|
|
7868
8446
|
async _initMaterializedViews(handles) {
|
|
7869
8447
|
if (handles.length === 0) return;
|
|
7870
|
-
const { MaterializedViewRegistry } = await import("./registry-
|
|
8448
|
+
const { MaterializedViewRegistry } = await import("./registry-JGEVJ6YC.js");
|
|
7871
8449
|
const registry = new MaterializedViewRegistry();
|
|
7872
8450
|
this.materializedViewRegistry = registry;
|
|
7873
8451
|
const db = this;
|
|
@@ -7891,7 +8469,7 @@ var Vault = class {
|
|
|
7891
8469
|
*/
|
|
7892
8470
|
async _initOverlayedViews(handles) {
|
|
7893
8471
|
if (handles.length === 0) return;
|
|
7894
|
-
const { OverlayedViewRegistry } = await import("./registry-
|
|
8472
|
+
const { OverlayedViewRegistry } = await import("./registry-J77ZUQ7G.js");
|
|
7895
8473
|
const registry = new OverlayedViewRegistry();
|
|
7896
8474
|
const mvRegistry = this.materializedViewRegistry;
|
|
7897
8475
|
const overlayNames = /* @__PURE__ */ new Set();
|
|
@@ -7938,13 +8516,13 @@ var Vault = class {
|
|
|
7938
8516
|
if (!reg) {
|
|
7939
8517
|
throw new Error(`refreshView: no MV registered with name "${name}"`);
|
|
7940
8518
|
}
|
|
7941
|
-
const { MaterializedViewExecutor } = await import("./executor-
|
|
8519
|
+
const { MaterializedViewExecutor } = await import("./executor-UYXSQB4D.js");
|
|
7942
8520
|
const result = await MaterializedViewExecutor.refresh(reg, {
|
|
7943
8521
|
getCollection: (n) => this.collection(n),
|
|
7944
8522
|
getActiveTxContext: () => this.noydb._activeTxContextOrNull,
|
|
7945
8523
|
getQueryContext: () => this
|
|
7946
8524
|
});
|
|
7947
|
-
const { clearMVStale } = await import("./stale-
|
|
8525
|
+
const { clearMVStale } = await import("./stale-PW6VBGSP.js");
|
|
7948
8526
|
clearMVStale(registry, name);
|
|
7949
8527
|
return result;
|
|
7950
8528
|
}
|
|
@@ -7960,7 +8538,7 @@ var Vault = class {
|
|
|
7960
8538
|
if (registry === null) return { derived: 0, failed: 0 };
|
|
7961
8539
|
const strategies = registry.strategiesForSource(sourceCollection);
|
|
7962
8540
|
if (strategies.length === 0) return { derived: 0, failed: 0 };
|
|
7963
|
-
const { DerivationExecutor } = await import("./executor-
|
|
8541
|
+
const { DerivationExecutor } = await import("./executor-VJSCTBWY.js");
|
|
7964
8542
|
const sourceColl = this.collection(sourceCollection);
|
|
7965
8543
|
const records = await sourceColl.list();
|
|
7966
8544
|
const ctx = { vault: this.derivationFacade ?? new (await import("./read-only-facade-EX6WZZBP.js")).ReadOnlyVaultFacade(this, "derivation") };
|
|
@@ -7985,7 +8563,7 @@ var Vault = class {
|
|
|
7985
8563
|
if (!outSpec) continue;
|
|
7986
8564
|
const outputColl = this.collection(outSpec.collection);
|
|
7987
8565
|
if (out.kind === "array") {
|
|
7988
|
-
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-
|
|
8566
|
+
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-ZQT4Y7PF.js");
|
|
7989
8567
|
const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key);
|
|
7990
8568
|
const prevKeys = new Set(prior?.keys ?? []);
|
|
7991
8569
|
const newKeysList = out.entries.map((e) => e.key);
|
|
@@ -8207,7 +8785,7 @@ var Vault = class {
|
|
|
8207
8785
|
* collection.
|
|
8208
8786
|
*/
|
|
8209
8787
|
async delegate(opts) {
|
|
8210
|
-
const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-
|
|
8788
|
+
const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-6ABSJGXV.js");
|
|
8211
8789
|
if (!this.keyring.kek) {
|
|
8212
8790
|
throw new ValidationError(
|
|
8213
8791
|
"issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (passphrase) first."
|
|
@@ -8229,7 +8807,7 @@ var Vault = class {
|
|
|
8229
8807
|
* if the id does not exist.
|
|
8230
8808
|
*/
|
|
8231
8809
|
async revokeDelegation(id) {
|
|
8232
|
-
const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-
|
|
8810
|
+
const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-6ABSJGXV.js");
|
|
8233
8811
|
await revokeDelegation(this.adapter, this.name, id);
|
|
8234
8812
|
void DELEGATIONS_COLLECTION;
|
|
8235
8813
|
}
|
|
@@ -8272,7 +8850,7 @@ var Vault = class {
|
|
|
8272
8850
|
if (this.activeElevation) {
|
|
8273
8851
|
throw new AlreadyElevatedError(this.activeElevation.tier);
|
|
8274
8852
|
}
|
|
8275
|
-
if (this.keyring.role !== "owner" && this.keyring.role !== "admin") {
|
|
8853
|
+
if (this.keyring.role !== "owner" && this.keyring.role !== "admin" && this.keyring.role !== "custodian") {
|
|
8276
8854
|
const suffix = `#${tier}`;
|
|
8277
8855
|
let found = false;
|
|
8278
8856
|
for (const k of this.keyring.deks.keys()) {
|
|
@@ -8612,6 +9190,7 @@ var Vault = class {
|
|
|
8612
9190
|
collectionCache: this.collectionCache,
|
|
8613
9191
|
refRegistry: this.refRegistry,
|
|
8614
9192
|
getDEK: this.getDEK,
|
|
9193
|
+
keyring: this.keyring,
|
|
8615
9194
|
subsystems: {
|
|
8616
9195
|
guards: this.guardRegistry !== null,
|
|
8617
9196
|
derivations: this.derivationRegistry !== null,
|
|
@@ -8698,7 +9277,7 @@ var Vault = class {
|
|
|
8698
9277
|
* @see docs/subsystems/public-envelope.md
|
|
8699
9278
|
*/
|
|
8700
9279
|
async getPublicEnvelope(opts = {}) {
|
|
8701
|
-
const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-
|
|
9280
|
+
const { readPublicEnvelope: readPublicEnvelope2 } = await import("./public-envelope-IJJMWSTJ.js");
|
|
8702
9281
|
return readPublicEnvelope2(this.adapter, this.name, opts);
|
|
8703
9282
|
}
|
|
8704
9283
|
/**
|
|
@@ -10005,7 +10584,18 @@ var PERSONAL_POLICY = Object.freeze({
|
|
|
10005
10584
|
// Setting `enabled: false` makes vault.user.list() return only
|
|
10006
10585
|
// self (privacy-strict opt-out).
|
|
10007
10586
|
"edit-own-profile": { minTier: 3 },
|
|
10008
|
-
"view-team-profiles": { minTier: 2 }
|
|
10587
|
+
"view-team-profiles": { minTier: 2 },
|
|
10588
|
+
// client-unilateral-withdraw: a non-owner's self-service DESTRUCTIVE
|
|
10589
|
+
// withdrawal (export-and-delete/freeze, #199). Fail-closed by default —
|
|
10590
|
+
// the firm opts in per jurisdiction/contract (e.g. GDPR Art. 17).
|
|
10591
|
+
// Listed explicitly (not just relying on the built-in default) so it is
|
|
10592
|
+
// discoverable in describeGate / policy dumps.
|
|
10593
|
+
"client-unilateral-withdraw": { minTier: 1, enabled: false },
|
|
10594
|
+
// Two-party withdrawal (#199 P3): filing a request is non-destructive
|
|
10595
|
+
// (tier-1, enabled so a read-only client can ask); deciding it is the
|
|
10596
|
+
// destructive step (tier-2 floor + owner/admin role, enforced in code).
|
|
10597
|
+
"user-request-withdrawal": { minTier: 1 },
|
|
10598
|
+
"approve-user-withdrawal": { minTier: 2 }
|
|
10009
10599
|
}
|
|
10010
10600
|
});
|
|
10011
10601
|
var STRICT_POLICY = Object.freeze({
|
|
@@ -10104,7 +10694,24 @@ var STRICT_POLICY = Object.freeze({
|
|
|
10104
10694
|
minTier: 2,
|
|
10105
10695
|
factors: [{ anyOf: ["totp", "email-otp"] }]
|
|
10106
10696
|
},
|
|
10107
|
-
"view-team-profiles": { minTier: 2 }
|
|
10697
|
+
"view-team-profiles": { minTier: 2 },
|
|
10698
|
+
// STRICT: still fail-closed, but if a regulated firm flips enabled:true
|
|
10699
|
+
// they inherit a two-factor proof + shared-device block for the
|
|
10700
|
+
// destructive withdrawal (mirrors export-plaintext's hardening).
|
|
10701
|
+
"client-unilateral-withdraw": {
|
|
10702
|
+
minTier: 1,
|
|
10703
|
+
enabled: false,
|
|
10704
|
+
factors: [{ anyOf: ["totp", "email-otp"], count: 2 }],
|
|
10705
|
+
warn: { sharedDevice: "block" }
|
|
10706
|
+
},
|
|
10707
|
+
// STRICT: filing stays tier-1; the destructive APPROVE demands an
|
|
10708
|
+
// off-device factor + shared-device block (mirrors export-bundle).
|
|
10709
|
+
"user-request-withdrawal": { minTier: 1 },
|
|
10710
|
+
"approve-user-withdrawal": {
|
|
10711
|
+
minTier: 2,
|
|
10712
|
+
factors: [{ anyOf: ["totp", "email-otp"] }],
|
|
10713
|
+
warn: { sharedDevice: "block" }
|
|
10714
|
+
}
|
|
10108
10715
|
}
|
|
10109
10716
|
});
|
|
10110
10717
|
function mergePolicy(base, override) {
|
|
@@ -10187,6 +10794,12 @@ var ROLE_RANK = {
|
|
|
10187
10794
|
client: 1,
|
|
10188
10795
|
viewer: 2,
|
|
10189
10796
|
operator: 3,
|
|
10797
|
+
// FR-6: custodian is operationally admin-rank (rw + access on every
|
|
10798
|
+
// collection) — it ranks alongside admin for "how much can this
|
|
10799
|
+
// principal see/operate." It is NOT above admin, and explicitly below
|
|
10800
|
+
// owner: a custodian can never grant/revoke/rotate/sever (those are
|
|
10801
|
+
// owner meta-capabilities), so it must not outrank or equal the owner.
|
|
10802
|
+
custodian: 4,
|
|
10190
10803
|
admin: 4,
|
|
10191
10804
|
owner: 5
|
|
10192
10805
|
};
|
|
@@ -10248,7 +10861,6 @@ var Noydb = class {
|
|
|
10248
10861
|
writeRelay;
|
|
10249
10862
|
/** Per-vault policy enforcers. */
|
|
10250
10863
|
policyEnforcers = /* @__PURE__ */ new Map();
|
|
10251
|
-
vaultTemplates = /* @__PURE__ */ new Map();
|
|
10252
10864
|
txStrategy;
|
|
10253
10865
|
forgetStrategy;
|
|
10254
10866
|
sessionStrategy;
|
|
@@ -10379,7 +10991,7 @@ var Noydb = class {
|
|
|
10379
10991
|
if (!facade) return;
|
|
10380
10992
|
const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
|
|
10381
10993
|
await registry.runChecks(e.collection, incoming, ctx);
|
|
10382
|
-
const { GuardExecutor } = await import("./executor-
|
|
10994
|
+
const { GuardExecutor } = await import("./executor-JKMSEB34.js");
|
|
10383
10995
|
for (const g of guards) {
|
|
10384
10996
|
await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming, e.computedFieldNames);
|
|
10385
10997
|
}
|
|
@@ -10698,6 +11310,37 @@ var Noydb = class {
|
|
|
10698
11310
|
const keyring = await this.getKeyringInternal(vault);
|
|
10699
11311
|
await revoke(this.options.store, vault, keyring, options);
|
|
10700
11312
|
}
|
|
11313
|
+
/**
|
|
11314
|
+
* Grant the FR-6 `custodian` role to a user (owner-only custody API).
|
|
11315
|
+
*
|
|
11316
|
+
* A custodian operates every collection (rw + access) but is provably
|
|
11317
|
+
* unable to grant / revoke / rotate / extract-and-sever. Only the Deed
|
|
11318
|
+
* owner may mint one. Defended in depth: the `grant-custodian` gate
|
|
11319
|
+
* (fail-closed) AND an explicit `keyring.role !== 'owner'` check — the
|
|
11320
|
+
* gate enforces host policy, the role check enforces the cryptographic
|
|
11321
|
+
* owner-only invariant even if a host mis-configures the gate.
|
|
11322
|
+
*/
|
|
11323
|
+
async grantCustodian(vault, options, factors) {
|
|
11324
|
+
this.checkPolicyOperation(vault, "grant");
|
|
11325
|
+
await this.checkGate(vault, "grant-custodian", factors);
|
|
11326
|
+
const keyring = await this.getKeyringInternal(vault);
|
|
11327
|
+
if (keyring.role !== "owner") throw new PermissionDeniedError("only the Deed owner can grant a custodian");
|
|
11328
|
+
await grant(this.options.store, vault, keyring, { ...options, role: "custodian" });
|
|
11329
|
+
}
|
|
11330
|
+
/**
|
|
11331
|
+
* Revoke a custodian (owner-only custody API).
|
|
11332
|
+
*
|
|
11333
|
+
* Mirrors {@link revoke} but pins the caller to the Deed owner: defended
|
|
11334
|
+
* in depth by the `revoke-user` gate AND an explicit `keyring.role !==
|
|
11335
|
+
* 'owner'` check, so an admin cannot unwind a custodianship.
|
|
11336
|
+
*/
|
|
11337
|
+
async revokeCustodian(vault, options, factors) {
|
|
11338
|
+
this.checkPolicyOperation(vault, "revoke");
|
|
11339
|
+
await this.checkGate(vault, "revoke-user", factors);
|
|
11340
|
+
const keyring = await this.getKeyringInternal(vault);
|
|
11341
|
+
if (keyring.role !== "owner") throw new PermissionDeniedError("only the Deed owner can revoke a custodian");
|
|
11342
|
+
await revoke(this.options.store, vault, keyring, options);
|
|
11343
|
+
}
|
|
10701
11344
|
/**
|
|
10702
11345
|
* Mutate post-grant identity fields on an existing keyring — `role`,
|
|
10703
11346
|
* `displayName`, and/or `permissions`. Pure plaintext-header rewrite:
|
|
@@ -10967,52 +11610,24 @@ var Noydb = class {
|
|
|
10967
11610
|
return results;
|
|
10968
11611
|
}
|
|
10969
11612
|
/**
|
|
10970
|
-
*
|
|
10971
|
-
*
|
|
11613
|
+
* @internal True once `close()` has been called. Read by
|
|
11614
|
+
* `@klum-db/lobby`'s Lobby entry points (which can't see the private
|
|
11615
|
+
* `closed` field).
|
|
10972
11616
|
*/
|
|
10973
|
-
|
|
10974
|
-
this.
|
|
11617
|
+
get isClosed() {
|
|
11618
|
+
return this.closed;
|
|
10975
11619
|
}
|
|
10976
|
-
/**
|
|
10977
|
-
|
|
10978
|
-
|
|
10979
|
-
* collection.
|
|
10980
|
-
*/
|
|
10981
|
-
async openVaultGroup(name, opts) {
|
|
10982
|
-
if (this.closed) throw new ValidationError("Instance is closed");
|
|
10983
|
-
if (name === STATE_VAULT_NAME) throw new ReservedVaultNameError(name);
|
|
10984
|
-
const template = this.vaultTemplates.get(opts.sharding.vaultTemplate);
|
|
10985
|
-
if (!template) throw new VaultTemplateNotFoundError(opts.sharding.vaultTemplate);
|
|
10986
|
-
const { VaultGroup } = await import("./vault-group-BB246VIM.js");
|
|
10987
|
-
const { StateManagementVault } = await import("./state-vault-JR3CFGNP.js");
|
|
10988
|
-
const stateVault = opts.registry ? void 0 : await StateManagementVault.open(this);
|
|
10989
|
-
const registry = opts.registry ?? stateVault.registry;
|
|
10990
|
-
const group = new VaultGroup(this, name, registry, opts.sharding, template, opts.migrateOnOpen ?? false);
|
|
10991
|
-
if (stateVault) {
|
|
10992
|
-
group._attachStateVault(stateVault);
|
|
10993
|
-
await stateVault.recordManifest(opts.sharding.vaultTemplate, template);
|
|
10994
|
-
try {
|
|
10995
|
-
await stateVault.appendEvent({
|
|
10996
|
-
type: "manifest-recorded",
|
|
10997
|
-
group: name,
|
|
10998
|
-
templateName: opts.sharding.vaultTemplate,
|
|
10999
|
-
version: template.version
|
|
11000
|
-
});
|
|
11001
|
-
await stateVault.appendEvent({ type: "group-opened", group: name });
|
|
11002
|
-
} catch {
|
|
11003
|
-
}
|
|
11004
|
-
}
|
|
11005
|
-
return group;
|
|
11620
|
+
/** @deprecated Federation moved to @klum-db/lobby. Use `createLobby(db).withVaultTemplate(...)`. */
|
|
11621
|
+
withVaultTemplate() {
|
|
11622
|
+
throw new FederationMovedError("withVaultTemplate");
|
|
11006
11623
|
}
|
|
11007
|
-
/**
|
|
11008
|
-
|
|
11009
|
-
|
|
11010
|
-
|
|
11011
|
-
|
|
11624
|
+
/** @deprecated Federation moved to @klum-db/lobby. Use `createLobby(db).openVaultGroup(...)`. */
|
|
11625
|
+
async openVaultGroup() {
|
|
11626
|
+
throw new FederationMovedError("openVaultGroup");
|
|
11627
|
+
}
|
|
11628
|
+
/** @deprecated Federation moved to @klum-db/lobby. Use `createLobby(db).openStateManagementVault()`. */
|
|
11012
11629
|
async openStateManagementVault() {
|
|
11013
|
-
|
|
11014
|
-
const { StateManagementVault } = await import("./state-vault-JR3CFGNP.js");
|
|
11015
|
-
return StateManagementVault.open(this);
|
|
11630
|
+
throw new FederationMovedError("openStateManagementVault");
|
|
11016
11631
|
}
|
|
11017
11632
|
/**
|
|
11018
11633
|
* @internal — true when an encrypted shard vault is provisioned
|
|
@@ -12526,22 +13141,13 @@ export {
|
|
|
12526
13141
|
compileSequenceFormat,
|
|
12527
13142
|
resolveSequenceKey,
|
|
12528
13143
|
SequenceStore,
|
|
12529
|
-
|
|
12530
|
-
|
|
12531
|
-
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
|
|
12535
|
-
|
|
12536
|
-
RefScopeError,
|
|
12537
|
-
ref,
|
|
12538
|
-
refArray,
|
|
12539
|
-
RefRegistry,
|
|
12540
|
-
isLinkCollectionName,
|
|
12541
|
-
LinkEndpointError,
|
|
12542
|
-
LinkIntegrityError,
|
|
12543
|
-
QuickUnlockStore,
|
|
12544
|
-
UserApi,
|
|
13144
|
+
exportAccessibleData,
|
|
13145
|
+
withdrawAccessibleData,
|
|
13146
|
+
WithdrawalRequestError,
|
|
13147
|
+
requestWithdrawal,
|
|
13148
|
+
listWithdrawalRequests,
|
|
13149
|
+
approveWithdrawal,
|
|
13150
|
+
rejectWithdrawal,
|
|
12545
13151
|
META_COLLECTION,
|
|
12546
13152
|
POLICY_RECORD_ID,
|
|
12547
13153
|
loadVaultPolicy,
|
|
@@ -12552,14 +13158,36 @@ export {
|
|
|
12552
13158
|
describeAllUsersAuth,
|
|
12553
13159
|
ComputedFieldError,
|
|
12554
13160
|
evalComputedFields,
|
|
13161
|
+
validateSchemaInput,
|
|
13162
|
+
validateSchemaOutput,
|
|
12555
13163
|
tokenize,
|
|
12556
13164
|
Lru,
|
|
12557
13165
|
parseBytes,
|
|
12558
13166
|
estimateRecordBytes,
|
|
12559
13167
|
Collection,
|
|
13168
|
+
isRefArray,
|
|
13169
|
+
RefIntegrityError,
|
|
13170
|
+
RefScopeError,
|
|
13171
|
+
ref,
|
|
13172
|
+
refArray,
|
|
13173
|
+
RefRegistry,
|
|
13174
|
+
isLinkCollectionName,
|
|
13175
|
+
LinkEndpointError,
|
|
13176
|
+
LinkIntegrityError,
|
|
13177
|
+
UserApi,
|
|
13178
|
+
CustodyApi,
|
|
13179
|
+
DEED_RECORD_ID,
|
|
13180
|
+
createDeedOwner,
|
|
13181
|
+
loadDeedMarker,
|
|
13182
|
+
isDeedVault,
|
|
13183
|
+
liberateVault,
|
|
13184
|
+
isZodSchema,
|
|
13185
|
+
derivePersistedSchema,
|
|
13186
|
+
persistSchemaIfNeeded,
|
|
12560
13187
|
Vault,
|
|
12561
13188
|
ELEVATION_AUDIT_COLLECTION,
|
|
12562
13189
|
ElevatedHandle,
|
|
13190
|
+
QuickUnlockStore,
|
|
12563
13191
|
PERSONAL_POLICY,
|
|
12564
13192
|
STRICT_POLICY,
|
|
12565
13193
|
mergePolicy,
|
|
@@ -12569,4 +13197,4 @@ export {
|
|
|
12569
13197
|
Noydb,
|
|
12570
13198
|
createNoydb
|
|
12571
13199
|
};
|
|
12572
|
-
//# sourceMappingURL=chunk-
|
|
13200
|
+
//# sourceMappingURL=chunk-QOXZM3L2.js.map
|