@noy-db/hub 0.4.0-pre.3 → 0.4.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/README.md +2 -2
- package/dist/aggregate/index.js +4 -4
- package/dist/api-22ES33N3.js +20 -0
- package/dist/as/index.js +11 -11
- package/dist/attestation/index.js +20 -20
- package/dist/{backup-JL2GOTYQ.js → backup-YCHAC575.js} +11 -11
- package/dist/blobs/index.js +12 -12
- package/dist/broker/index.js +12 -12
- package/dist/by/index.js +2 -2
- package/dist/cargo/index.js +29 -29
- package/dist/{chunk-2RMDVWGB.js → chunk-2CRZOVDI.js} +2 -2
- package/dist/{chunk-T7S4V52L.js → chunk-2PDBYF2O.js} +4 -4
- package/dist/{chunk-WJDYZP3U.js → chunk-3LJYHE7S.js} +36 -36
- package/dist/chunk-3LJYHE7S.js.map +1 -0
- package/dist/{chunk-CCT4WZI6.js → chunk-3OWYOECI.js} +5 -5
- package/dist/chunk-3OWYOECI.js.map +1 -0
- package/dist/{chunk-L4OA7G5T.js → chunk-522MBPE5.js} +2 -2
- package/dist/{chunk-ZJGZDOQO.js → chunk-5ATANZSW.js} +6 -6
- package/dist/{chunk-M25ZIEB2.js → chunk-5HSSTOOG.js} +2 -2
- package/dist/{chunk-LLVW4V7R.js → chunk-5WLDZZ6S.js} +3 -3
- package/dist/{chunk-7B4GPCX7.js → chunk-6RPWILRH.js} +5 -5
- package/dist/{chunk-IGM563N5.js → chunk-6SYOHUHM.js} +6 -6
- package/dist/chunk-6SYOHUHM.js.map +1 -0
- package/dist/{chunk-HGVFJL63.js → chunk-7BIJS6II.js} +15 -5
- package/dist/{chunk-HGVFJL63.js.map → chunk-7BIJS6II.js.map} +1 -1
- package/dist/{chunk-KR5EGWI4.js → chunk-7ICV4ASA.js} +5 -5
- package/dist/{chunk-J3VW4J4E.js → chunk-7LP7FFJ2.js} +2 -2
- package/dist/chunk-7LP7FFJ2.js.map +1 -0
- package/dist/{chunk-5P5AAXYA.js → chunk-7U6AB7DZ.js} +7 -7
- package/dist/chunk-7U6AB7DZ.js.map +1 -0
- package/dist/{chunk-KMONEHDJ.js → chunk-AFAPBZAA.js} +2 -2
- package/dist/{chunk-GBEXTC6Z.js → chunk-BAAUFCJK.js} +3 -3
- package/dist/chunk-BAAUFCJK.js.map +1 -0
- package/dist/{chunk-CGPO3ZYB.js → chunk-BY5YBSXA.js} +2 -2
- package/dist/{chunk-3O62PVDW.js → chunk-CJVEAVYH.js} +5 -5
- package/dist/chunk-CJVEAVYH.js.map +1 -0
- package/dist/{chunk-3XVOLB75.js → chunk-CKUYQO2P.js} +3 -3
- package/dist/{chunk-2JZ763FV.js → chunk-D4LAJ737.js} +2 -2
- package/dist/{chunk-OOTTXUNV.js → chunk-DYZ5CCVM.js} +2 -2
- package/dist/{chunk-LUH2MPEF.js → chunk-EEZCB74X.js} +808 -1175
- package/dist/chunk-EEZCB74X.js.map +1 -0
- package/dist/{chunk-N4FZ6ITM.js → chunk-EGU4PWQW.js} +2 -2
- package/dist/{chunk-JKWNG3TM.js → chunk-FHHYCBBP.js} +2 -2
- package/dist/{chunk-UBF7HTOR.js → chunk-FIP7KI2P.js} +40 -40
- package/dist/chunk-FIP7KI2P.js.map +1 -0
- package/dist/{chunk-N4A3DCBT.js → chunk-FTCGEUOY.js} +8 -8
- package/dist/{chunk-5BB3N4KU.js → chunk-G4MFQXYX.js} +2 -2
- package/dist/{chunk-PEY6ZTCF.js → chunk-GEEJPID6.js} +9 -9
- package/dist/{chunk-PEY6ZTCF.js.map → chunk-GEEJPID6.js.map} +1 -1
- package/dist/{chunk-KVHWEPT2.js → chunk-GHEMAVTN.js} +2 -2
- package/dist/{chunk-OVFCAS7U.js → chunk-GP54LU5N.js} +9 -9
- package/dist/{chunk-XW7NWO4A.js → chunk-GTNRMJYH.js} +2 -2
- package/dist/{chunk-J6U4BOKP.js → chunk-HAPY7WFP.js} +12 -12
- package/dist/{chunk-GU5AYA2Q.js → chunk-HQKRZIX6.js} +5 -5
- package/dist/{chunk-OWE4BNTM.js → chunk-I2XEBEEF.js} +4 -4
- package/dist/{chunk-WEC3JGBA.js → chunk-IGLU4ME7.js} +3 -3
- package/dist/{chunk-BZK6JEX4.js → chunk-ILM6X6CP.js} +5 -5
- package/dist/{chunk-2KL6NDD4.js → chunk-J5TEU77Q.js} +4 -4
- package/dist/{chunk-UEO5CHOP.js → chunk-JAMDDLIM.js} +13 -13
- package/dist/chunk-JAMDDLIM.js.map +1 -0
- package/dist/{chunk-V7RGFJ3Z.js → chunk-JIHH26WQ.js} +6 -6
- package/dist/{chunk-XGVDLQJE.js → chunk-JN3SGXJE.js} +3 -3
- package/dist/{chunk-XULHFSHO.js → chunk-K4BWPNJO.js} +5 -5
- package/dist/chunk-K4BWPNJO.js.map +1 -0
- package/dist/{chunk-BZEPJJOK.js → chunk-K7BADAOS.js} +4 -4
- package/dist/{chunk-OWLPX2GI.js → chunk-KJTIAECI.js} +17 -17
- package/dist/chunk-KJTIAECI.js.map +1 -0
- package/dist/{chunk-SN75YVM5.js → chunk-L2CAWCQL.js} +18 -18
- package/dist/{chunk-SN75YVM5.js.map → chunk-L2CAWCQL.js.map} +1 -1
- package/dist/{chunk-MSO2C3KG.js → chunk-LC7DSMHR.js} +2 -2
- package/dist/{chunk-JA5B3SLH.js → chunk-M6QA2KK2.js} +2 -2
- package/dist/{chunk-IUIVDVXM.js → chunk-MUPZ6IZX.js} +2 -2
- package/dist/{chunk-QAFWRGVD.js → chunk-OGVE4IJW.js} +7 -7
- package/dist/{chunk-BCOKZC4B.js → chunk-OHV6T5JB.js} +19 -19
- package/dist/chunk-OHV6T5JB.js.map +1 -0
- package/dist/{chunk-25ZDB25Z.js → chunk-OMSKGLYA.js} +3 -3
- package/dist/chunk-OMSKGLYA.js.map +1 -0
- package/dist/{chunk-2U7Y7BNJ.js → chunk-ONB627HU.js} +2 -2
- package/dist/{chunk-GYB2QK5H.js → chunk-OWLZONGX.js} +2 -2
- package/dist/{chunk-YHPUDB7Q.js → chunk-OWOT7CFC.js} +2 -2
- package/dist/{chunk-VEX6G3YL.js → chunk-P4NUJVWL.js} +2 -2
- package/dist/{chunk-NM4LVUXH.js → chunk-PTT2NB46.js} +2 -2
- package/dist/{chunk-2ITLQZV5.js → chunk-PWWWMRT7.js} +2 -2
- package/dist/{chunk-GS3Q2KOZ.js → chunk-QBOQI6PG.js} +2 -2
- package/dist/{chunk-JIMEB4C6.js → chunk-QMMOMBH6.js} +4 -4
- package/dist/{chunk-QDNVHA2F.js → chunk-QMZ5A6FQ.js} +2 -2
- package/dist/{chunk-FLHOTGOO.js → chunk-QVGEVZ5F.js} +3 -3
- package/dist/{chunk-AFBJHD55.js → chunk-QZJEYZ4I.js} +5 -5
- package/dist/{chunk-V3YB7RGR.js → chunk-R2N37AA6.js} +3 -3
- package/dist/{chunk-JLHKBAFY.js → chunk-RWW3I3PO.js} +3 -3
- package/dist/{chunk-IGAIOGCN.js → chunk-S4YERMGJ.js} +4 -4
- package/dist/{chunk-OGFPMCSP.js → chunk-SBOHNJUD.js} +2 -2
- package/dist/{chunk-QXPOEAKR.js → chunk-SC4JLMZI.js} +2 -2
- package/dist/{chunk-EDC6MLXV.js → chunk-SEU6QHH4.js} +2 -2
- package/dist/{chunk-F4COUZLL.js → chunk-TMR64XPL.js} +2 -2
- package/dist/{chunk-DEQ2JTBR.js → chunk-TNATF3HB.js} +3 -3
- package/dist/{chunk-GZ2GKOF6.js → chunk-TNJVDG2B.js} +3 -3
- package/dist/{chunk-5OZCCLNC.js → chunk-TSNRZSRC.js} +2 -2
- package/dist/{chunk-QCUH2G77.js → chunk-UTEATWHO.js} +6 -6
- package/dist/{chunk-JA5O7UEZ.js → chunk-UVBHM7AK.js} +6 -6
- package/dist/chunk-UVBHM7AK.js.map +1 -0
- package/dist/{chunk-HKR25MGX.js → chunk-V5JUAW4M.js} +10 -10
- package/dist/chunk-V5JUAW4M.js.map +1 -0
- package/dist/{chunk-YGBIBOCR.js → chunk-VEGQYPCP.js} +7 -7
- package/dist/{chunk-25G7U6RD.js → chunk-WQN5SM7P.js} +2 -2
- package/dist/{chunk-NOT7XA7Q.js → chunk-X3MWEFPT.js} +5 -5
- package/dist/chunk-XUFAFHQM.js +78 -0
- package/dist/chunk-XUFAFHQM.js.map +1 -0
- package/dist/{chunk-MEKAMERX.js → chunk-YCAJDK4O.js} +29 -29
- package/dist/chunk-YCAJDK4O.js.map +1 -0
- package/dist/{chunk-BVZGNMVM.js → chunk-YFFEF6HR.js} +3 -3
- package/dist/{chunk-H4SMS4O2.js → chunk-YJ3TREAC.js} +2 -2
- package/dist/{chunk-5SZ24DL5.js → chunk-YQQPNXNO.js} +6 -6
- package/dist/{chunk-5BHNQNBI.js → chunk-YTW6ZIPD.js} +1 -1
- package/dist/chunk-YTW6ZIPD.js.map +1 -0
- package/dist/{chunk-EW4HFWGJ.js → chunk-YWZEDG7F.js} +6 -6
- package/dist/{chunk-2VUISNGP.js → chunk-YXIVUWDU.js} +5 -5
- package/dist/{chunk-YG2EG6CB.js → chunk-YXZNGHID.js} +4 -4
- package/dist/{chunk-QYJIOWKN.js → chunk-YZN6NRTR.js} +9 -9
- package/dist/{chunk-IZX3WZBF.js → chunk-YZNKFYDC.js} +4 -4
- package/dist/{chunk-E2R5NRZD.js → chunk-Z4D3YGAB.js} +2 -2
- package/dist/{chunk-STR7WBOB.js → chunk-ZUDAK436.js} +2 -2
- package/dist/{chunk-ITI3SJRB.js → chunk-ZX5FNWH7.js} +2 -2
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-7S5IEP6Q.js → classified-marker-52P3D72W.js} +3 -3
- package/dist/collection-facade-XKCFHSLR.js +44 -0
- package/dist/{computed-WZNKRLCY.js → computed-33DRJDOC.js} +3 -3
- package/dist/consent/index.js +9 -9
- package/dist/{cover-B5MY43CK.js → cover-5BSNJREH.js} +4 -4
- package/dist/{dead-filter-KRRD57MR.js → dead-filter-JXVCKS6W.js} +2 -2
- package/dist/delegation-WWZPEDK2.js +25 -0
- package/dist/derivations/index.js +12 -12
- package/dist/derive-CWWFEQ4N.js +21 -0
- package/dist/dispatch-PKQQFDBT.js +193 -0
- package/dist/dispatch-PKQQFDBT.js.map +1 -0
- package/dist/dispatch-SMXUO7W5.js +72 -0
- package/dist/dispatch-SMXUO7W5.js.map +1 -0
- package/dist/{enclave-YFKA3GJT.js → enclave-I5H3GINP.js} +11 -11
- package/dist/executor-FCJEH3FU.js +9 -0
- package/dist/executor-OHET7TF7.js +9 -0
- package/dist/executor-SHYLIBOM.js +26 -0
- package/dist/export-accessible-FBL6TDSK.js +23 -0
- package/dist/extract-partition-ZYIRYMTI.js +38 -0
- package/dist/{fanout-sidecar-HJV3A7PM.js → fanout-sidecar-WWXVHHUH.js} +9 -9
- package/dist/find-LEBUXVL7.js +11 -0
- package/dist/forget/index.js +9 -9
- package/dist/guards/index.js +3 -3
- package/dist/history/index.js +12 -12
- package/dist/i18n/index.js +14 -14
- package/dist/index.d.ts +13 -9
- package/dist/index.js +119 -118
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +2 -2
- package/dist/issue-F76PAGIR.js +19 -0
- package/dist/kernel/collection-config.d.ts +11 -69
- package/dist/kernel/collection.d.ts +10 -22
- package/dist/kernel/enclave/crypto.d.ts +8 -8
- package/dist/kernel/enclave/index.d.ts +2 -2
- package/dist/kernel/errors.d.ts +20 -20
- package/dist/kernel/noydb.d.ts +43 -103
- package/dist/kernel/types.d.ts +82 -41
- package/dist/kernel/validation.d.ts +33 -33
- package/dist/kernel/vault.d.ts +31 -215
- package/dist/kernel/via/dispatch.d.ts +7 -0
- package/dist/{ledger-SW6QQOAV.js → ledger-M2BKCNVS.js} +11 -11
- package/dist/liberate-ZP7UB57K.js +24 -0
- package/dist/{link-set-GNGGCFI4.js → link-set-ZU4E5J5S.js} +11 -11
- package/dist/materialized-views/index.js +19 -19
- package/dist/noydb-BNDGEK5X.js +71 -0
- package/dist/on/index.js +9 -9
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +13 -13
- package/dist/pod/index.js +11 -11
- package/dist/{policy-EAXSJNOT.js → policy-IY2YEA3A.js} +5 -5
- package/dist/port/at/index.d.ts +4 -4
- package/dist/port/with/archive-strategy.d.ts +31 -0
- package/dist/port/with/collection-options.d.ts +171 -0
- package/dist/port/with/strategies.d.ts +134 -0
- package/dist/port/with/team-strategy.d.ts +1 -1
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-A7HCFBP5.js → post-register-XIAHB6KF.js} +6 -6
- package/dist/query/index.js +6 -6
- package/dist/register-HB4TQZSV.js +23 -0
- package/dist/registry-6BMBFEXT.js +19 -0
- package/dist/registry-7CZWF3EQ.js +9 -0
- package/dist/registry-JOFO7RAH.js +18 -0
- package/dist/request-withdrawal-UN3TRHWI.js +31 -0
- package/dist/{reveal-PB3YG544.js → reveal-VWXRV2XU.js} +6 -6
- package/dist/revoke-OLO2OVR7.js +24 -0
- package/dist/satellites/index.js +1 -1
- package/dist/sealed-record/index.js +12 -12
- package/dist/{seed-EKF4DIBB.js → seed-CDBFOTIK.js} +12 -12
- package/dist/seed-CDBFOTIK.js.map +1 -0
- package/dist/session/index.js +9 -9
- package/dist/shadow/index.js +2 -2
- package/dist/signer-MGGKPYAN.js +25 -0
- package/dist/snapshots/index.js +10 -10
- package/dist/{stale-4UNPHWOU.js → stale-NBROTA66.js} +10 -10
- package/dist/storage-3R37QZLA.js +23 -0
- package/dist/{store-coordination-provider-3AELCZ4Y.js → store-coordination-provider-P3IU5JHD.js} +3 -3
- package/dist/sync/index.js +10 -10
- package/dist/team/index.js +20 -20
- package/dist/tiers/index.js +10 -10
- package/dist/to/index.js +1 -1
- package/dist/tx/index.js +3 -3
- package/dist/util/index.js +1 -1
- package/dist/{verify-MXN66IIH.js → verify-5X37OXRY.js} +5 -5
- package/dist/{walk-H4YE52S2.js → walk-E3OVLBFR.js} +11 -11
- package/dist/with/index.js +11 -11
- package/dist/with-audit/portability/export-accessible.d.ts +4 -4
- package/dist/with-audit/portability/request-withdrawal.d.ts +3 -3
- package/dist/with-audit/portability/withdraw-accessible.d.ts +2 -2
- package/dist/with-audit/sealed-record/strategy.d.ts +1 -1
- package/dist/with-cargo/adopt-partition.d.ts +7 -7
- package/dist/with-cargo/index.d.ts +1 -1
- package/dist/with-commit/history/time-machine.d.ts +2 -2
- package/dist/with-formula/derivations/dispatch.d.ts +98 -0
- package/dist/with-formula/materialized-views/dispatch.d.ts +75 -0
- package/dist/with-party/custody/liberate.d.ts +3 -3
- package/dist/with-party/session/dev-unlock.d.ts +2 -2
- package/dist/with-party/session/session.d.ts +2 -2
- package/dist/with-party/team/deed.d.ts +8 -8
- package/dist/with-party/team/index.d.ts +2 -2
- package/dist/with-party/team/keyring.d.ts +19 -19
- package/dist/with-party/team/{managed-passphrase.d.ts → managed-secret.d.ts} +27 -27
- package/dist/with-party/team/noydb-facade.d.ts +41 -41
- package/dist/with-party/team/peer-recover.d.ts +13 -13
- package/dist/with-party/team/recovery.d.ts +5 -5
- package/dist/with-party/team/rotate-recover.d.ts +30 -30
- package/dist/with-pod/bundle.d.ts +30 -30
- package/dist/with-pod/format.d.ts +2 -2
- package/dist/withdraw-accessible-Q2EMATCU.js +28 -0
- package/package.json +3 -3
- package/dist/api-UPAT2O3M.js +0 -20
- package/dist/chunk-25ZDB25Z.js.map +0 -1
- package/dist/chunk-3O62PVDW.js.map +0 -1
- package/dist/chunk-5BHNQNBI.js.map +0 -1
- package/dist/chunk-5P5AAXYA.js.map +0 -1
- package/dist/chunk-BCOKZC4B.js.map +0 -1
- package/dist/chunk-CCT4WZI6.js.map +0 -1
- package/dist/chunk-GBEXTC6Z.js.map +0 -1
- package/dist/chunk-HKR25MGX.js.map +0 -1
- package/dist/chunk-IGM563N5.js.map +0 -1
- package/dist/chunk-J3VW4J4E.js.map +0 -1
- package/dist/chunk-JA5O7UEZ.js.map +0 -1
- package/dist/chunk-LUH2MPEF.js.map +0 -1
- package/dist/chunk-MEKAMERX.js.map +0 -1
- package/dist/chunk-OWLPX2GI.js.map +0 -1
- package/dist/chunk-UBF7HTOR.js.map +0 -1
- package/dist/chunk-UEO5CHOP.js.map +0 -1
- package/dist/chunk-WJDYZP3U.js.map +0 -1
- package/dist/chunk-XULHFSHO.js.map +0 -1
- package/dist/collection-facade-ENLTJZBT.js +0 -44
- package/dist/delegation-UT76AQIG.js +0 -25
- package/dist/derive-SGRCCKVP.js +0 -21
- package/dist/executor-TEZYRDN3.js +0 -9
- package/dist/executor-WQQRU6DO.js +0 -9
- package/dist/executor-YORMIBWV.js +0 -26
- package/dist/export-accessible-HXMKW5LJ.js +0 -23
- package/dist/extract-partition-QGQ2R42J.js +0 -38
- package/dist/find-VV6PBIHK.js +0 -11
- package/dist/issue-7JJ4Z7E2.js +0 -19
- package/dist/liberate-FK7JI2QX.js +0 -24
- package/dist/noydb-KUX2TJMX.js +0 -70
- package/dist/register-YBMRLZLO.js +0 -23
- package/dist/registry-3LXKNXWI.js +0 -9
- package/dist/registry-4V4YQCXJ.js +0 -19
- package/dist/registry-ZULMLCJK.js +0 -18
- package/dist/request-withdrawal-SEVUEUDG.js +0 -31
- package/dist/revoke-5QULL5GT.js +0 -24
- package/dist/seed-EKF4DIBB.js.map +0 -1
- package/dist/signer-ZMH35FT4.js +0 -25
- package/dist/storage-QOZKQMID.js +0 -23
- package/dist/withdraw-accessible-HPOVNG2G.js +0 -28
- /package/dist/{api-UPAT2O3M.js.map → api-22ES33N3.js.map} +0 -0
- /package/dist/{backup-JL2GOTYQ.js.map → backup-YCHAC575.js.map} +0 -0
- /package/dist/{chunk-2RMDVWGB.js.map → chunk-2CRZOVDI.js.map} +0 -0
- /package/dist/{chunk-T7S4V52L.js.map → chunk-2PDBYF2O.js.map} +0 -0
- /package/dist/{chunk-L4OA7G5T.js.map → chunk-522MBPE5.js.map} +0 -0
- /package/dist/{chunk-ZJGZDOQO.js.map → chunk-5ATANZSW.js.map} +0 -0
- /package/dist/{chunk-M25ZIEB2.js.map → chunk-5HSSTOOG.js.map} +0 -0
- /package/dist/{chunk-LLVW4V7R.js.map → chunk-5WLDZZ6S.js.map} +0 -0
- /package/dist/{chunk-7B4GPCX7.js.map → chunk-6RPWILRH.js.map} +0 -0
- /package/dist/{chunk-KR5EGWI4.js.map → chunk-7ICV4ASA.js.map} +0 -0
- /package/dist/{chunk-KMONEHDJ.js.map → chunk-AFAPBZAA.js.map} +0 -0
- /package/dist/{chunk-CGPO3ZYB.js.map → chunk-BY5YBSXA.js.map} +0 -0
- /package/dist/{chunk-3XVOLB75.js.map → chunk-CKUYQO2P.js.map} +0 -0
- /package/dist/{chunk-2JZ763FV.js.map → chunk-D4LAJ737.js.map} +0 -0
- /package/dist/{chunk-OOTTXUNV.js.map → chunk-DYZ5CCVM.js.map} +0 -0
- /package/dist/{chunk-N4FZ6ITM.js.map → chunk-EGU4PWQW.js.map} +0 -0
- /package/dist/{chunk-JKWNG3TM.js.map → chunk-FHHYCBBP.js.map} +0 -0
- /package/dist/{chunk-N4A3DCBT.js.map → chunk-FTCGEUOY.js.map} +0 -0
- /package/dist/{chunk-5BB3N4KU.js.map → chunk-G4MFQXYX.js.map} +0 -0
- /package/dist/{chunk-KVHWEPT2.js.map → chunk-GHEMAVTN.js.map} +0 -0
- /package/dist/{chunk-OVFCAS7U.js.map → chunk-GP54LU5N.js.map} +0 -0
- /package/dist/{chunk-XW7NWO4A.js.map → chunk-GTNRMJYH.js.map} +0 -0
- /package/dist/{chunk-J6U4BOKP.js.map → chunk-HAPY7WFP.js.map} +0 -0
- /package/dist/{chunk-GU5AYA2Q.js.map → chunk-HQKRZIX6.js.map} +0 -0
- /package/dist/{chunk-OWE4BNTM.js.map → chunk-I2XEBEEF.js.map} +0 -0
- /package/dist/{chunk-WEC3JGBA.js.map → chunk-IGLU4ME7.js.map} +0 -0
- /package/dist/{chunk-BZK6JEX4.js.map → chunk-ILM6X6CP.js.map} +0 -0
- /package/dist/{chunk-2KL6NDD4.js.map → chunk-J5TEU77Q.js.map} +0 -0
- /package/dist/{chunk-V7RGFJ3Z.js.map → chunk-JIHH26WQ.js.map} +0 -0
- /package/dist/{chunk-XGVDLQJE.js.map → chunk-JN3SGXJE.js.map} +0 -0
- /package/dist/{chunk-BZEPJJOK.js.map → chunk-K7BADAOS.js.map} +0 -0
- /package/dist/{chunk-MSO2C3KG.js.map → chunk-LC7DSMHR.js.map} +0 -0
- /package/dist/{chunk-JA5B3SLH.js.map → chunk-M6QA2KK2.js.map} +0 -0
- /package/dist/{chunk-IUIVDVXM.js.map → chunk-MUPZ6IZX.js.map} +0 -0
- /package/dist/{chunk-QAFWRGVD.js.map → chunk-OGVE4IJW.js.map} +0 -0
- /package/dist/{chunk-2U7Y7BNJ.js.map → chunk-ONB627HU.js.map} +0 -0
- /package/dist/{chunk-GYB2QK5H.js.map → chunk-OWLZONGX.js.map} +0 -0
- /package/dist/{chunk-YHPUDB7Q.js.map → chunk-OWOT7CFC.js.map} +0 -0
- /package/dist/{chunk-VEX6G3YL.js.map → chunk-P4NUJVWL.js.map} +0 -0
- /package/dist/{chunk-NM4LVUXH.js.map → chunk-PTT2NB46.js.map} +0 -0
- /package/dist/{chunk-2ITLQZV5.js.map → chunk-PWWWMRT7.js.map} +0 -0
- /package/dist/{chunk-GS3Q2KOZ.js.map → chunk-QBOQI6PG.js.map} +0 -0
- /package/dist/{chunk-JIMEB4C6.js.map → chunk-QMMOMBH6.js.map} +0 -0
- /package/dist/{chunk-QDNVHA2F.js.map → chunk-QMZ5A6FQ.js.map} +0 -0
- /package/dist/{chunk-FLHOTGOO.js.map → chunk-QVGEVZ5F.js.map} +0 -0
- /package/dist/{chunk-AFBJHD55.js.map → chunk-QZJEYZ4I.js.map} +0 -0
- /package/dist/{chunk-V3YB7RGR.js.map → chunk-R2N37AA6.js.map} +0 -0
- /package/dist/{chunk-JLHKBAFY.js.map → chunk-RWW3I3PO.js.map} +0 -0
- /package/dist/{chunk-IGAIOGCN.js.map → chunk-S4YERMGJ.js.map} +0 -0
- /package/dist/{chunk-OGFPMCSP.js.map → chunk-SBOHNJUD.js.map} +0 -0
- /package/dist/{chunk-QXPOEAKR.js.map → chunk-SC4JLMZI.js.map} +0 -0
- /package/dist/{chunk-EDC6MLXV.js.map → chunk-SEU6QHH4.js.map} +0 -0
- /package/dist/{chunk-F4COUZLL.js.map → chunk-TMR64XPL.js.map} +0 -0
- /package/dist/{chunk-DEQ2JTBR.js.map → chunk-TNATF3HB.js.map} +0 -0
- /package/dist/{chunk-GZ2GKOF6.js.map → chunk-TNJVDG2B.js.map} +0 -0
- /package/dist/{chunk-5OZCCLNC.js.map → chunk-TSNRZSRC.js.map} +0 -0
- /package/dist/{chunk-QCUH2G77.js.map → chunk-UTEATWHO.js.map} +0 -0
- /package/dist/{chunk-YGBIBOCR.js.map → chunk-VEGQYPCP.js.map} +0 -0
- /package/dist/{chunk-25G7U6RD.js.map → chunk-WQN5SM7P.js.map} +0 -0
- /package/dist/{chunk-NOT7XA7Q.js.map → chunk-X3MWEFPT.js.map} +0 -0
- /package/dist/{chunk-BVZGNMVM.js.map → chunk-YFFEF6HR.js.map} +0 -0
- /package/dist/{chunk-H4SMS4O2.js.map → chunk-YJ3TREAC.js.map} +0 -0
- /package/dist/{chunk-5SZ24DL5.js.map → chunk-YQQPNXNO.js.map} +0 -0
- /package/dist/{chunk-EW4HFWGJ.js.map → chunk-YWZEDG7F.js.map} +0 -0
- /package/dist/{chunk-2VUISNGP.js.map → chunk-YXIVUWDU.js.map} +0 -0
- /package/dist/{chunk-YG2EG6CB.js.map → chunk-YXZNGHID.js.map} +0 -0
- /package/dist/{chunk-QYJIOWKN.js.map → chunk-YZN6NRTR.js.map} +0 -0
- /package/dist/{chunk-IZX3WZBF.js.map → chunk-YZNKFYDC.js.map} +0 -0
- /package/dist/{chunk-E2R5NRZD.js.map → chunk-Z4D3YGAB.js.map} +0 -0
- /package/dist/{chunk-STR7WBOB.js.map → chunk-ZUDAK436.js.map} +0 -0
- /package/dist/{chunk-ITI3SJRB.js.map → chunk-ZX5FNWH7.js.map} +0 -0
- /package/dist/{classified-marker-7S5IEP6Q.js.map → classified-marker-52P3D72W.js.map} +0 -0
- /package/dist/{collection-facade-ENLTJZBT.js.map → collection-facade-XKCFHSLR.js.map} +0 -0
- /package/dist/{computed-WZNKRLCY.js.map → computed-33DRJDOC.js.map} +0 -0
- /package/dist/{cover-B5MY43CK.js.map → cover-5BSNJREH.js.map} +0 -0
- /package/dist/{dead-filter-KRRD57MR.js.map → dead-filter-JXVCKS6W.js.map} +0 -0
- /package/dist/{delegation-UT76AQIG.js.map → delegation-WWZPEDK2.js.map} +0 -0
- /package/dist/{derive-SGRCCKVP.js.map → derive-CWWFEQ4N.js.map} +0 -0
- /package/dist/{enclave-YFKA3GJT.js.map → enclave-I5H3GINP.js.map} +0 -0
- /package/dist/{executor-TEZYRDN3.js.map → executor-FCJEH3FU.js.map} +0 -0
- /package/dist/{executor-WQQRU6DO.js.map → executor-OHET7TF7.js.map} +0 -0
- /package/dist/{executor-YORMIBWV.js.map → executor-SHYLIBOM.js.map} +0 -0
- /package/dist/{export-accessible-HXMKW5LJ.js.map → export-accessible-FBL6TDSK.js.map} +0 -0
- /package/dist/{extract-partition-QGQ2R42J.js.map → extract-partition-ZYIRYMTI.js.map} +0 -0
- /package/dist/{fanout-sidecar-HJV3A7PM.js.map → fanout-sidecar-WWXVHHUH.js.map} +0 -0
- /package/dist/{find-VV6PBIHK.js.map → find-LEBUXVL7.js.map} +0 -0
- /package/dist/{issue-7JJ4Z7E2.js.map → issue-F76PAGIR.js.map} +0 -0
- /package/dist/{ledger-SW6QQOAV.js.map → ledger-M2BKCNVS.js.map} +0 -0
- /package/dist/{liberate-FK7JI2QX.js.map → liberate-ZP7UB57K.js.map} +0 -0
- /package/dist/{link-set-GNGGCFI4.js.map → link-set-ZU4E5J5S.js.map} +0 -0
- /package/dist/{noydb-KUX2TJMX.js.map → noydb-BNDGEK5X.js.map} +0 -0
- /package/dist/{policy-EAXSJNOT.js.map → policy-IY2YEA3A.js.map} +0 -0
- /package/dist/{post-register-A7HCFBP5.js.map → post-register-XIAHB6KF.js.map} +0 -0
- /package/dist/{register-YBMRLZLO.js.map → register-HB4TQZSV.js.map} +0 -0
- /package/dist/{registry-3LXKNXWI.js.map → registry-6BMBFEXT.js.map} +0 -0
- /package/dist/{registry-4V4YQCXJ.js.map → registry-7CZWF3EQ.js.map} +0 -0
- /package/dist/{registry-ZULMLCJK.js.map → registry-JOFO7RAH.js.map} +0 -0
- /package/dist/{request-withdrawal-SEVUEUDG.js.map → request-withdrawal-UN3TRHWI.js.map} +0 -0
- /package/dist/{reveal-PB3YG544.js.map → reveal-VWXRV2XU.js.map} +0 -0
- /package/dist/{revoke-5QULL5GT.js.map → revoke-OLO2OVR7.js.map} +0 -0
- /package/dist/{signer-ZMH35FT4.js.map → signer-MGGKPYAN.js.map} +0 -0
- /package/dist/{stale-4UNPHWOU.js.map → stale-NBROTA66.js.map} +0 -0
- /package/dist/{storage-QOZKQMID.js.map → storage-3R37QZLA.js.map} +0 -0
- /package/dist/{store-coordination-provider-3AELCZ4Y.js.map → store-coordination-provider-P3IU5JHD.js.map} +0 -0
- /package/dist/{verify-MXN66IIH.js.map → verify-5X37OXRY.js.map} +0 -0
- /package/dist/{walk-H4YE52S2.js.map → walk-E3OVLBFR.js.map} +0 -0
- /package/dist/{withdraw-accessible-HPOVNG2G.js.map → withdraw-accessible-Q2EMATCU.js.map} +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadVaultPolicy
|
|
3
|
+
} from "./chunk-QMZ5A6FQ.js";
|
|
1
4
|
import {
|
|
2
5
|
jsonSchemaToFields
|
|
3
6
|
} from "./chunk-VYYM3MEN.js";
|
|
@@ -6,23 +9,23 @@ import {
|
|
|
6
9
|
SEQUENCE_COLLECTION,
|
|
7
10
|
compileSequenceFormat,
|
|
8
11
|
resolveSequenceKey
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import {
|
|
11
|
-
loadVaultPolicy
|
|
12
|
-
} from "./chunk-QDNVHA2F.js";
|
|
12
|
+
} from "./chunk-X3MWEFPT.js";
|
|
13
13
|
import {
|
|
14
14
|
LinkIntegrityError,
|
|
15
15
|
isLinkCollectionName,
|
|
16
16
|
linkCollectionName,
|
|
17
17
|
linkRowKey
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-MUPZ6IZX.js";
|
|
19
19
|
import {
|
|
20
20
|
hashFields,
|
|
21
21
|
validateSatelliteDeclaration
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-522MBPE5.js";
|
|
23
|
+
import {
|
|
24
|
+
resolveStaleOnRead
|
|
25
|
+
} from "./chunk-XUFAFHQM.js";
|
|
23
26
|
import {
|
|
24
27
|
loadFence
|
|
25
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-M6QA2KK2.js";
|
|
26
29
|
import {
|
|
27
30
|
InvertedIndex,
|
|
28
31
|
MemoryIndexStore,
|
|
@@ -31,11 +34,11 @@ import {
|
|
|
31
34
|
buildPersistedIndexCallbacks,
|
|
32
35
|
encodeVecId,
|
|
33
36
|
syncTierSearch
|
|
34
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-HAPY7WFP.js";
|
|
35
38
|
import {
|
|
36
39
|
derivePersistedSchema,
|
|
37
40
|
isZod4Schema
|
|
38
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-SEU6QHH4.js";
|
|
39
42
|
import {
|
|
40
43
|
isBaseLive,
|
|
41
44
|
liveBaseIdSet
|
|
@@ -44,11 +47,11 @@ import {
|
|
|
44
47
|
CustodyApi,
|
|
45
48
|
NO_CARGO,
|
|
46
49
|
NO_CUSTODY
|
|
47
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-L2CAWCQL.js";
|
|
48
51
|
import {
|
|
49
52
|
resolveManagedSecret,
|
|
50
|
-
|
|
51
|
-
} from "./chunk-
|
|
53
|
+
saveSealedSecret
|
|
54
|
+
} from "./chunk-OHV6T5JB.js";
|
|
52
55
|
import {
|
|
53
56
|
ServiceBus,
|
|
54
57
|
WriteHookRegistry,
|
|
@@ -56,35 +59,35 @@ import {
|
|
|
56
59
|
assertCanImport,
|
|
57
60
|
canExport,
|
|
58
61
|
canImport
|
|
59
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-IGLU4ME7.js";
|
|
60
63
|
import {
|
|
61
64
|
runDrainBarrier
|
|
62
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-AFAPBZAA.js";
|
|
63
66
|
import {
|
|
64
67
|
NO_ATTESTATION
|
|
65
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-GTNRMJYH.js";
|
|
66
69
|
import {
|
|
67
70
|
NO_CLASSIFIED,
|
|
68
71
|
guardClassifiedCompat,
|
|
69
72
|
resolveClassifiedFields
|
|
70
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-YZNKFYDC.js";
|
|
71
74
|
import {
|
|
72
75
|
NO_TIERS,
|
|
73
76
|
classifySealedShred,
|
|
74
77
|
syncDerivedOutputs
|
|
75
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-FTCGEUOY.js";
|
|
76
79
|
import {
|
|
77
80
|
NO_PORTABILITY
|
|
78
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-OWLZONGX.js";
|
|
79
82
|
import {
|
|
80
83
|
TxContext,
|
|
81
84
|
bestEffortRevert,
|
|
82
85
|
revertExecuted
|
|
83
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-QVGEVZ5F.js";
|
|
84
87
|
import {
|
|
85
88
|
DEFAULT_POSTURE,
|
|
86
89
|
ViaGraph
|
|
87
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-Z4D3YGAB.js";
|
|
88
91
|
import {
|
|
89
92
|
buildLookupAltIndex,
|
|
90
93
|
buildLookupSnapshotRows,
|
|
@@ -105,27 +108,28 @@ import {
|
|
|
105
108
|
resolveLabelFromMap,
|
|
106
109
|
resolveRollupDeleteIntents,
|
|
107
110
|
runGraphDispatchWave,
|
|
111
|
+
selfWriteFieldEqual,
|
|
108
112
|
touchFor,
|
|
109
113
|
updateReferencingRecords
|
|
110
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-7BIJS6II.js";
|
|
111
115
|
import {
|
|
112
116
|
OverlayedCollection
|
|
113
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-PWWWMRT7.js";
|
|
114
118
|
import {
|
|
115
119
|
NO_AGGREGATE,
|
|
116
120
|
Query,
|
|
117
121
|
ScanBuilder
|
|
118
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-HQKRZIX6.js";
|
|
119
123
|
import {
|
|
120
124
|
EXPORT_AUDIT_COLLECTION,
|
|
121
125
|
createExportBlobsHandle,
|
|
122
126
|
runCompaction
|
|
123
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-J5TEU77Q.js";
|
|
124
128
|
import {
|
|
125
129
|
LazyQuery,
|
|
126
130
|
decodeIdxId,
|
|
127
131
|
encodeIdxId
|
|
128
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-BY5YBSXA.js";
|
|
129
133
|
import {
|
|
130
134
|
IMPLICIT_LAZY,
|
|
131
135
|
Lru,
|
|
@@ -133,13 +137,13 @@ import {
|
|
|
133
137
|
} from "./chunk-NO272T7Q.js";
|
|
134
138
|
import {
|
|
135
139
|
canonicalGroupKey
|
|
136
|
-
} from "./chunk-
|
|
140
|
+
} from "./chunk-QMMOMBH6.js";
|
|
137
141
|
import {
|
|
138
142
|
readPath
|
|
139
143
|
} from "./chunk-IGJCYUT5.js";
|
|
140
144
|
import {
|
|
141
145
|
dictCollectionName
|
|
142
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-K7BADAOS.js";
|
|
143
147
|
import {
|
|
144
148
|
NO_I18N,
|
|
145
149
|
getAtPath,
|
|
@@ -147,23 +151,23 @@ import {
|
|
|
147
151
|
isDictKeyDescriptor,
|
|
148
152
|
isI18nTextDescriptor,
|
|
149
153
|
isStaticDictDescriptor
|
|
150
|
-
} from "./chunk-
|
|
154
|
+
} from "./chunk-JN3SGXJE.js";
|
|
151
155
|
import {
|
|
152
156
|
installViaBinder,
|
|
153
157
|
isViaInstalled,
|
|
154
158
|
viaBinder
|
|
155
|
-
} from "./chunk-
|
|
159
|
+
} from "./chunk-ZUDAK436.js";
|
|
156
160
|
import {
|
|
157
161
|
NO_TEAM,
|
|
158
162
|
enrollAuthenticator,
|
|
159
163
|
findAuthenticator,
|
|
160
|
-
|
|
164
|
+
recoverSecret,
|
|
161
165
|
recoverUser,
|
|
162
166
|
removeAuthenticator,
|
|
163
|
-
|
|
167
|
+
rotateSecret,
|
|
164
168
|
updateAuthenticator,
|
|
165
169
|
writeMagicLinkGrant
|
|
166
|
-
} from "./chunk-
|
|
170
|
+
} from "./chunk-FIP7KI2P.js";
|
|
167
171
|
import {
|
|
168
172
|
assertKeyringOpenAllowed,
|
|
169
173
|
buildRecipientKeyringFile,
|
|
@@ -176,11 +180,11 @@ import {
|
|
|
176
180
|
listUsers,
|
|
177
181
|
loadKeyring,
|
|
178
182
|
updateKeyringIdentity
|
|
179
|
-
} from "./chunk-
|
|
183
|
+
} from "./chunk-3LJYHE7S.js";
|
|
180
184
|
import {
|
|
181
185
|
persistDirectoryConfig,
|
|
182
186
|
readDirectoryConfig
|
|
183
|
-
} from "./chunk-
|
|
187
|
+
} from "./chunk-6RPWILRH.js";
|
|
184
188
|
import {
|
|
185
189
|
hasRecoveryEnrolled,
|
|
186
190
|
hasStrongRecoveryEnrolled,
|
|
@@ -190,7 +194,7 @@ import {
|
|
|
190
194
|
mintShamirRecoveryEntry,
|
|
191
195
|
savePaperRecoveryEntries,
|
|
192
196
|
saveShamirRecoveryEntries
|
|
193
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-CJVEAVYH.js";
|
|
194
198
|
import {
|
|
195
199
|
INDEXED_STORE_POLICY
|
|
196
200
|
} from "./chunk-VQNJ7UZL.js";
|
|
@@ -200,11 +204,11 @@ import {
|
|
|
200
204
|
PERIOD_FREEZES_COLLECTION,
|
|
201
205
|
PERIOD_TARGET_PURGES_COLLECTION,
|
|
202
206
|
periodExclusiveUpperBound
|
|
203
|
-
} from "./chunk-
|
|
207
|
+
} from "./chunk-TMR64XPL.js";
|
|
204
208
|
import {
|
|
205
209
|
NO_BROKER,
|
|
206
210
|
buildCredentialBrokerHandle
|
|
207
|
-
} from "./chunk-
|
|
211
|
+
} from "./chunk-P4NUJVWL.js";
|
|
208
212
|
import {
|
|
209
213
|
generateULID
|
|
210
214
|
} from "./chunk-ZJADGNYF.js";
|
|
@@ -212,10 +216,10 @@ import {
|
|
|
212
216
|
assertCutoverTierSafe,
|
|
213
217
|
assertTierWritable,
|
|
214
218
|
liveRecordIsElevated
|
|
215
|
-
} from "./chunk-
|
|
219
|
+
} from "./chunk-PTT2NB46.js";
|
|
216
220
|
import {
|
|
217
221
|
sha256Hex
|
|
218
|
-
} from "./chunk-
|
|
222
|
+
} from "./chunk-RWW3I3PO.js";
|
|
219
223
|
import {
|
|
220
224
|
NO_FORGET,
|
|
221
225
|
addSubjectRef,
|
|
@@ -224,10 +228,10 @@ import {
|
|
|
224
228
|
readDottedPath,
|
|
225
229
|
rebuildSubjectIndex,
|
|
226
230
|
removeSubjectRef
|
|
227
|
-
} from "./chunk-
|
|
231
|
+
} from "./chunk-I2XEBEEF.js";
|
|
228
232
|
import {
|
|
229
233
|
NO_SEALED_RECORD
|
|
230
|
-
} from "./chunk-
|
|
234
|
+
} from "./chunk-7LP7FFJ2.js";
|
|
231
235
|
import {
|
|
232
236
|
RecordCodec,
|
|
233
237
|
SEALED_CEK_NS,
|
|
@@ -238,20 +242,20 @@ import {
|
|
|
238
242
|
queryByDet,
|
|
239
243
|
resolveStableCek,
|
|
240
244
|
validateSchemaInput
|
|
241
|
-
} from "./chunk-
|
|
245
|
+
} from "./chunk-GEEJPID6.js";
|
|
242
246
|
import {
|
|
243
247
|
buildDeleteMarker,
|
|
244
248
|
buildTombstone,
|
|
245
249
|
isDeleteMarker,
|
|
246
250
|
isTombstone
|
|
247
|
-
} from "./chunk-
|
|
251
|
+
} from "./chunk-SC4JLMZI.js";
|
|
248
252
|
import {
|
|
249
253
|
encrypt
|
|
250
|
-
} from "./chunk-
|
|
254
|
+
} from "./chunk-7U6AB7DZ.js";
|
|
251
255
|
import {
|
|
252
256
|
NOYDB_FORMAT_VERSION,
|
|
253
257
|
SealedHandle
|
|
254
|
-
} from "./chunk-
|
|
258
|
+
} from "./chunk-YTW6ZIPD.js";
|
|
255
259
|
import {
|
|
256
260
|
AlreadyElevatedError,
|
|
257
261
|
AttestationError,
|
|
@@ -260,7 +264,6 @@ import {
|
|
|
260
264
|
ClassifiedVerifyError,
|
|
261
265
|
ConflictError,
|
|
262
266
|
DebugPlaintextError,
|
|
263
|
-
DerivationCapExceededError,
|
|
264
267
|
DictKeyInUseError,
|
|
265
268
|
ElevationExpiredError,
|
|
266
269
|
FieldNotQueryableError,
|
|
@@ -291,11 +294,289 @@ import {
|
|
|
291
294
|
UnsupportedIndexOptionError,
|
|
292
295
|
UnsupportedTierCompositionError,
|
|
293
296
|
ValidationError
|
|
294
|
-
} from "./chunk-
|
|
297
|
+
} from "./chunk-6SYOHUHM.js";
|
|
298
|
+
|
|
299
|
+
// src/via/blob/binding.ts
|
|
300
|
+
async function eraseBlobs(ctx, cfg) {
|
|
301
|
+
if (cfg.purgeBlobsForRecord) return cfg.purgeBlobsForRecord(ctx.id);
|
|
302
|
+
return { shredded: 0, residue: [] };
|
|
303
|
+
}
|
|
304
|
+
function buildBlobDescribeFragment(fields) {
|
|
305
|
+
return {
|
|
306
|
+
blobFields: Object.fromEntries(
|
|
307
|
+
Object.entries(fields).map(([field, p]) => [field, {
|
|
308
|
+
...p.retainDays !== void 0 ? { retainDays: p.retainDays } : {},
|
|
309
|
+
...p.evictWhen !== void 0 ? { evictWhen: true } : {},
|
|
310
|
+
...p.legalHold !== void 0 ? { legalHold: true } : {},
|
|
311
|
+
...p.retainUntil !== void 0 ? { retainUntil: true } : {},
|
|
312
|
+
...p.external === true ? { external: true } : {},
|
|
313
|
+
...p.public === true ? { public: true } : {},
|
|
314
|
+
...p.backlink !== void 0 ? { backlink: p.backlink } : {}
|
|
315
|
+
}])
|
|
316
|
+
)
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
function blobBinding(cfg) {
|
|
320
|
+
return {
|
|
321
|
+
brand: "blob",
|
|
322
|
+
// encryptedAtRest: 'envelope' — blob chunks are AEAD-encrypted envelopes
|
|
323
|
+
// in `_blob_chunks` (service-side), not sealed record fields; queryable:
|
|
324
|
+
// 'none' — nothing indexes blob content; exportable — vault.exportBlobs()
|
|
325
|
+
// is a first-class door; forgettable — shredAllForRecord participates in
|
|
326
|
+
// vault.forget().
|
|
327
|
+
posture: { encryptedAtRest: "envelope", queryable: "none", exportable: true, forgettable: true },
|
|
328
|
+
covers: (field) => field in cfg.fields,
|
|
329
|
+
erase: (ctx) => eraseBlobs(ctx, cfg),
|
|
330
|
+
describeFragment: () => buildBlobDescribeFragment(cfg.fields)
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
function linkBlobVia() {
|
|
334
|
+
installViaBinder("blob", (c) => blobBinding(c));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// src/port/with/blob-strategy.ts
|
|
338
|
+
linkBlobVia();
|
|
339
|
+
var NO_BLOBS = {
|
|
340
|
+
openSlot() {
|
|
341
|
+
throw new Error(
|
|
342
|
+
'Blob storage is not enabled on this Noydb instance. Import `{ withBlobs }` from "@noy-db/hub/blobs" and pass `withBlobs()` to `createNoydb({ blobStrategy: withBlobs() })`.'
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// src/with-audit/consent/strategy.ts
|
|
348
|
+
var NO_CONSENT = {
|
|
349
|
+
async write() {
|
|
350
|
+
},
|
|
351
|
+
async read() {
|
|
352
|
+
return [];
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// src/with-commit/crdt/strategy.ts
|
|
357
|
+
var NOT_ENABLED = new Error(
|
|
358
|
+
'CRDT mode requires the CRDT strategy. Import `{ withCrdt }` from "@noy-db/hub/crdt" and pass it to `createNoydb({ crdtStrategy: withCrdt() })`.'
|
|
359
|
+
);
|
|
360
|
+
var NO_CRDT = {
|
|
361
|
+
buildLwwMapState() {
|
|
362
|
+
throw NOT_ENABLED;
|
|
363
|
+
},
|
|
364
|
+
buildRgaState() {
|
|
365
|
+
throw NOT_ENABLED;
|
|
366
|
+
},
|
|
367
|
+
mergeCrdtStates() {
|
|
368
|
+
throw NOT_ENABLED;
|
|
369
|
+
},
|
|
370
|
+
resolveCrdtSnapshot() {
|
|
371
|
+
throw NOT_ENABLED;
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
// src/with-commit/history/strategy.ts
|
|
376
|
+
function notEnabled(op) {
|
|
377
|
+
return new Error(
|
|
378
|
+
`${op} requires the history strategy. Import \`{ withHistory }\` from "@noy-db/hub/history" and pass it to \`createNoydb({ historyStrategy: withHistory() })\`.`
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
var NO_HISTORY = {
|
|
382
|
+
async saveHistory() {
|
|
383
|
+
},
|
|
384
|
+
async getHistoryEntries() {
|
|
385
|
+
throw notEnabled("collection.history()");
|
|
386
|
+
},
|
|
387
|
+
async getVersionEnvelope() {
|
|
388
|
+
throw notEnabled("collection.getVersion()");
|
|
389
|
+
},
|
|
390
|
+
async pruneHistory() {
|
|
391
|
+
return 0;
|
|
392
|
+
},
|
|
393
|
+
async clearHistory() {
|
|
394
|
+
return 0;
|
|
395
|
+
},
|
|
396
|
+
async tombstoneHistory() {
|
|
397
|
+
return 0;
|
|
398
|
+
},
|
|
399
|
+
async rewrapHistory() {
|
|
400
|
+
},
|
|
401
|
+
async envelopePayloadHash() {
|
|
402
|
+
return "";
|
|
403
|
+
},
|
|
404
|
+
computePatch() {
|
|
405
|
+
return [];
|
|
406
|
+
},
|
|
407
|
+
diff() {
|
|
408
|
+
throw notEnabled("collection.diff()");
|
|
409
|
+
},
|
|
410
|
+
buildLedger() {
|
|
411
|
+
return null;
|
|
412
|
+
},
|
|
413
|
+
buildVaultInstant() {
|
|
414
|
+
throw notEnabled("vault.at() / vault.timeMachine()");
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
// src/with-lookup/indexing/strategy.ts
|
|
419
|
+
var NO_INDEXING = {
|
|
420
|
+
createState() {
|
|
421
|
+
return DISABLED_STATE;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
var DISABLED_STATE = {
|
|
425
|
+
isEnabled: false,
|
|
426
|
+
getEagerIndexes: () => null,
|
|
427
|
+
getPersistedIndexes: () => null
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
// src/with-audit/periods/strategy.ts
|
|
431
|
+
var NOT_ENABLED2 = new Error(
|
|
432
|
+
'Accounting periods require the periods strategy. Import `{ withPeriods }` from "@noy-db/hub/periods" and pass it to `createNoydb({ periodsStrategy: withPeriods() })`.'
|
|
433
|
+
);
|
|
434
|
+
var NO_PERIODS = {
|
|
435
|
+
async loadPeriods() {
|
|
436
|
+
return [];
|
|
437
|
+
},
|
|
438
|
+
async chainAnchor() {
|
|
439
|
+
return { priorPeriodHash: "" };
|
|
440
|
+
},
|
|
441
|
+
assertTsWritable() {
|
|
442
|
+
},
|
|
443
|
+
validatePeriodName() {
|
|
444
|
+
throw NOT_ENABLED2;
|
|
445
|
+
},
|
|
446
|
+
async appendPeriodLedgerEntry() {
|
|
447
|
+
throw NOT_ENABLED2;
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
// src/with-party/session/strategy.ts
|
|
452
|
+
function notEnabled2(op) {
|
|
453
|
+
return new Error(
|
|
454
|
+
`${op} requires the session strategy. Import \`{ withSession }\` from "@noy-db/hub/session" and pass it to \`createNoydb({ sessionStrategy: withSession() })\`.`
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
var NO_SESSION = {
|
|
458
|
+
validateSessionPolicy() {
|
|
459
|
+
throw notEnabled2("sessionPolicy");
|
|
460
|
+
},
|
|
461
|
+
createEnforcer() {
|
|
462
|
+
throw notEnabled2("session policy enforcement");
|
|
463
|
+
},
|
|
464
|
+
revokeAllSessions() {
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
// src/with-fork/shadow/strategy.ts
|
|
469
|
+
var NOT_ENABLED3 = new Error(
|
|
470
|
+
'VaultFrame requires the shadow strategy. Import `{ withShadow }` from "@noy-db/hub/shadow" and pass it to `createNoydb({ shadowStrategy: withShadow() })`.'
|
|
471
|
+
);
|
|
472
|
+
var NO_SHADOW = {
|
|
473
|
+
buildFrame() {
|
|
474
|
+
throw NOT_ENABLED3;
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// src/with-fork/snapshots/strategy.ts
|
|
479
|
+
var NOT_ENABLED4 = new Error(
|
|
480
|
+
'Snapshots require the snapshot strategy. Import `{ withSnapshots }` from "@noy-db/hub/snapshots" and pass it to `createNoydb({ snapshotStrategy: withSnapshots({ store }) })`.'
|
|
481
|
+
);
|
|
482
|
+
var NO_SNAPSHOTS = {
|
|
483
|
+
async snapshot() {
|
|
484
|
+
throw NOT_ENABLED4;
|
|
485
|
+
},
|
|
486
|
+
async listSnapshots() {
|
|
487
|
+
throw NOT_ENABLED4;
|
|
488
|
+
},
|
|
489
|
+
async restoreSnapshot() {
|
|
490
|
+
throw NOT_ENABLED4;
|
|
491
|
+
},
|
|
492
|
+
async autoSnapshot() {
|
|
493
|
+
throw NOT_ENABLED4;
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
|
|
497
|
+
// src/with-party/team/sync-strategy.ts
|
|
498
|
+
function notEnabled3(op) {
|
|
499
|
+
return new Error(
|
|
500
|
+
`${op} requires the sync strategy. Import \`{ withSync }\` from "@noy-db/hub/sync" and pass it to \`createNoydb({ syncStrategy: withSync() })\`.`
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
var NO_SYNC = {
|
|
504
|
+
buildSyncEngine() {
|
|
505
|
+
throw notEnabled3("SyncEngine");
|
|
506
|
+
},
|
|
507
|
+
buildSyncTransaction() {
|
|
508
|
+
throw notEnabled3("SyncTransaction");
|
|
509
|
+
},
|
|
510
|
+
buildPresence() {
|
|
511
|
+
throw notEnabled3("collection.presence()");
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
// src/with-commit/tx/strategy.ts
|
|
516
|
+
var NOT_ENABLED5 = new Error(
|
|
517
|
+
'Multi-record transactions require the tx strategy. Import `{ withTransactions }` from "@noy-db/hub/tx" and pass it to `createNoydb({ txStrategy: withTransactions() })`.'
|
|
518
|
+
);
|
|
519
|
+
var NO_TX = {
|
|
520
|
+
async runTransaction(_db, _fn, _options, _txInvariants) {
|
|
521
|
+
throw NOT_ENABLED5;
|
|
522
|
+
},
|
|
523
|
+
async runDryRun() {
|
|
524
|
+
throw NOT_ENABLED5;
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
// src/port/with/archive-strategy.ts
|
|
529
|
+
var ARCHIVE_NOT_ENABLED = "vault.archive/restore/listArchived require `archiveStrategy: withArchive({ store })` in createNoydb";
|
|
530
|
+
var NO_ARCHIVE = {
|
|
531
|
+
get store() {
|
|
532
|
+
throw new Error(ARCHIVE_NOT_ENABLED);
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
// src/port/with/strategies.ts
|
|
537
|
+
var STRATEGY_DEFAULTS = {
|
|
538
|
+
aggregate: NO_AGGREGATE,
|
|
539
|
+
archive: NO_ARCHIVE,
|
|
540
|
+
attestation: NO_ATTESTATION,
|
|
541
|
+
blob: NO_BLOBS,
|
|
542
|
+
broker: NO_BROKER,
|
|
543
|
+
cargo: NO_CARGO,
|
|
544
|
+
classified: NO_CLASSIFIED,
|
|
545
|
+
consent: NO_CONSENT,
|
|
546
|
+
crdt: NO_CRDT,
|
|
547
|
+
custody: NO_CUSTODY,
|
|
548
|
+
forget: NO_FORGET,
|
|
549
|
+
history: NO_HISTORY,
|
|
550
|
+
i18n: NO_I18N,
|
|
551
|
+
index: NO_INDEXING,
|
|
552
|
+
lazy: IMPLICIT_LAZY,
|
|
553
|
+
periods: NO_PERIODS,
|
|
554
|
+
portability: NO_PORTABILITY,
|
|
555
|
+
sealedRecord: NO_SEALED_RECORD,
|
|
556
|
+
search: NO_SEARCH,
|
|
557
|
+
sequence: NO_SEQUENCE,
|
|
558
|
+
session: NO_SESSION,
|
|
559
|
+
shadow: NO_SHADOW,
|
|
560
|
+
snapshot: NO_SNAPSHOTS,
|
|
561
|
+
sync: NO_SYNC,
|
|
562
|
+
team: NO_TEAM,
|
|
563
|
+
tiers: NO_TIERS,
|
|
564
|
+
tx: NO_TX
|
|
565
|
+
};
|
|
566
|
+
var STRATEGY_KEYS = Object.keys(STRATEGY_DEFAULTS);
|
|
567
|
+
function resolveStrategies(options) {
|
|
568
|
+
const provided = options;
|
|
569
|
+
const resolved = { ...STRATEGY_DEFAULTS };
|
|
570
|
+
for (const key of STRATEGY_KEYS) {
|
|
571
|
+
const value = provided[`${key}Strategy`];
|
|
572
|
+
if (value !== void 0) resolved[key] = value;
|
|
573
|
+
}
|
|
574
|
+
return resolved;
|
|
575
|
+
}
|
|
295
576
|
|
|
296
577
|
// src/port/by/default-provider.ts
|
|
297
578
|
async function createDefaultCoordinationProvider(store) {
|
|
298
|
-
const { StoreCoordinationProvider } = await import("./store-coordination-provider-
|
|
579
|
+
const { StoreCoordinationProvider } = await import("./store-coordination-provider-P3IU5JHD.js");
|
|
299
580
|
return new StoreCoordinationProvider(store);
|
|
300
581
|
}
|
|
301
582
|
|
|
@@ -964,61 +1245,6 @@ async function resolveTierSyncPrior(ctx, id, priorEnvelope) {
|
|
|
964
1245
|
return await ctx.codec.decryptRecord(priorEnvelope, { skipValidation: true, id });
|
|
965
1246
|
}
|
|
966
1247
|
|
|
967
|
-
// src/with-commit/history/strategy.ts
|
|
968
|
-
function notEnabled(op) {
|
|
969
|
-
return new Error(
|
|
970
|
-
`${op} requires the history strategy. Import \`{ withHistory }\` from "@noy-db/hub/history" and pass it to \`createNoydb({ historyStrategy: withHistory() })\`.`
|
|
971
|
-
);
|
|
972
|
-
}
|
|
973
|
-
var NO_HISTORY = {
|
|
974
|
-
async saveHistory() {
|
|
975
|
-
},
|
|
976
|
-
async getHistoryEntries() {
|
|
977
|
-
throw notEnabled("collection.history()");
|
|
978
|
-
},
|
|
979
|
-
async getVersionEnvelope() {
|
|
980
|
-
throw notEnabled("collection.getVersion()");
|
|
981
|
-
},
|
|
982
|
-
async pruneHistory() {
|
|
983
|
-
return 0;
|
|
984
|
-
},
|
|
985
|
-
async clearHistory() {
|
|
986
|
-
return 0;
|
|
987
|
-
},
|
|
988
|
-
async tombstoneHistory() {
|
|
989
|
-
return 0;
|
|
990
|
-
},
|
|
991
|
-
async rewrapHistory() {
|
|
992
|
-
},
|
|
993
|
-
async envelopePayloadHash() {
|
|
994
|
-
return "";
|
|
995
|
-
},
|
|
996
|
-
computePatch() {
|
|
997
|
-
return [];
|
|
998
|
-
},
|
|
999
|
-
diff() {
|
|
1000
|
-
throw notEnabled("collection.diff()");
|
|
1001
|
-
},
|
|
1002
|
-
buildLedger() {
|
|
1003
|
-
return null;
|
|
1004
|
-
},
|
|
1005
|
-
buildVaultInstant() {
|
|
1006
|
-
throw notEnabled("vault.at() / vault.timeMachine()");
|
|
1007
|
-
}
|
|
1008
|
-
};
|
|
1009
|
-
|
|
1010
|
-
// src/with-lookup/indexing/strategy.ts
|
|
1011
|
-
var NO_INDEXING = {
|
|
1012
|
-
createState() {
|
|
1013
|
-
return DISABLED_STATE;
|
|
1014
|
-
}
|
|
1015
|
-
};
|
|
1016
|
-
var DISABLED_STATE = {
|
|
1017
|
-
isEnabled: false,
|
|
1018
|
-
getEagerIndexes: () => null,
|
|
1019
|
-
getPersistedIndexes: () => null
|
|
1020
|
-
};
|
|
1021
|
-
|
|
1022
1248
|
// src/with-lookup/search/serialize.ts
|
|
1023
1249
|
function serializeIndex(idx) {
|
|
1024
1250
|
return JSON.stringify(idx.toSnapshot());
|
|
@@ -1621,164 +1847,6 @@ function buildDescription(input) {
|
|
|
1621
1847
|
};
|
|
1622
1848
|
}
|
|
1623
1849
|
|
|
1624
|
-
// src/via/blob/binding.ts
|
|
1625
|
-
async function eraseBlobs(ctx, cfg) {
|
|
1626
|
-
if (cfg.purgeBlobsForRecord) return cfg.purgeBlobsForRecord(ctx.id);
|
|
1627
|
-
return { shredded: 0, residue: [] };
|
|
1628
|
-
}
|
|
1629
|
-
function buildBlobDescribeFragment(fields) {
|
|
1630
|
-
return {
|
|
1631
|
-
blobFields: Object.fromEntries(
|
|
1632
|
-
Object.entries(fields).map(([field, p]) => [field, {
|
|
1633
|
-
...p.retainDays !== void 0 ? { retainDays: p.retainDays } : {},
|
|
1634
|
-
...p.evictWhen !== void 0 ? { evictWhen: true } : {},
|
|
1635
|
-
...p.legalHold !== void 0 ? { legalHold: true } : {},
|
|
1636
|
-
...p.retainUntil !== void 0 ? { retainUntil: true } : {},
|
|
1637
|
-
...p.external === true ? { external: true } : {},
|
|
1638
|
-
...p.public === true ? { public: true } : {},
|
|
1639
|
-
...p.backlink !== void 0 ? { backlink: p.backlink } : {}
|
|
1640
|
-
}])
|
|
1641
|
-
)
|
|
1642
|
-
};
|
|
1643
|
-
}
|
|
1644
|
-
function blobBinding(cfg) {
|
|
1645
|
-
return {
|
|
1646
|
-
brand: "blob",
|
|
1647
|
-
// encryptedAtRest: 'envelope' — blob chunks are AEAD-encrypted envelopes
|
|
1648
|
-
// in `_blob_chunks` (service-side), not sealed record fields; queryable:
|
|
1649
|
-
// 'none' — nothing indexes blob content; exportable — vault.exportBlobs()
|
|
1650
|
-
// is a first-class door; forgettable — shredAllForRecord participates in
|
|
1651
|
-
// vault.forget().
|
|
1652
|
-
posture: { encryptedAtRest: "envelope", queryable: "none", exportable: true, forgettable: true },
|
|
1653
|
-
covers: (field) => field in cfg.fields,
|
|
1654
|
-
erase: (ctx) => eraseBlobs(ctx, cfg),
|
|
1655
|
-
describeFragment: () => buildBlobDescribeFragment(cfg.fields)
|
|
1656
|
-
};
|
|
1657
|
-
}
|
|
1658
|
-
function linkBlobVia() {
|
|
1659
|
-
installViaBinder("blob", (c) => blobBinding(c));
|
|
1660
|
-
}
|
|
1661
|
-
|
|
1662
|
-
// src/port/with/blob-strategy.ts
|
|
1663
|
-
linkBlobVia();
|
|
1664
|
-
var NO_BLOBS = {
|
|
1665
|
-
openSlot() {
|
|
1666
|
-
throw new Error(
|
|
1667
|
-
'Blob storage is not enabled on this Noydb instance. Import `{ withBlobs }` from "@noy-db/hub/blobs" and pass `withBlobs()` to `createNoydb({ blobStrategy: withBlobs() })`.'
|
|
1668
|
-
);
|
|
1669
|
-
}
|
|
1670
|
-
};
|
|
1671
|
-
|
|
1672
|
-
// src/with-formula/derivations/stale.ts
|
|
1673
|
-
var _staleByRegistry = /* @__PURE__ */ new WeakMap();
|
|
1674
|
-
var keyFor = (source, sourceId) => `${source}/${sourceId}`;
|
|
1675
|
-
async function markStale(registry, strategy, sourceId) {
|
|
1676
|
-
let map = _staleByRegistry.get(registry);
|
|
1677
|
-
if (!map) {
|
|
1678
|
-
map = /* @__PURE__ */ new Map();
|
|
1679
|
-
_staleByRegistry.set(registry, map);
|
|
1680
|
-
}
|
|
1681
|
-
const k = keyFor(strategy.source, sourceId);
|
|
1682
|
-
let set = map.get(k);
|
|
1683
|
-
if (!set) {
|
|
1684
|
-
set = /* @__PURE__ */ new Set();
|
|
1685
|
-
map.set(k, set);
|
|
1686
|
-
}
|
|
1687
|
-
set.add(strategy);
|
|
1688
|
-
}
|
|
1689
|
-
async function resolveStaleOnRead(accessor, outputCollection, id) {
|
|
1690
|
-
const registry = accessor.registry();
|
|
1691
|
-
const producers = registry.strategiesProducingOutput(outputCollection);
|
|
1692
|
-
if (producers.length === 0) return;
|
|
1693
|
-
const map = _staleByRegistry.get(registry);
|
|
1694
|
-
if (!map) return;
|
|
1695
|
-
let DerivationExecutor = null;
|
|
1696
|
-
for (const { spec, strategyHash } of producers) {
|
|
1697
|
-
const k = keyFor(spec.source, id);
|
|
1698
|
-
const pending = map.get(k);
|
|
1699
|
-
if (!pending || !pending.has(spec)) continue;
|
|
1700
|
-
const sourceColl = accessor.getCollection(spec.source);
|
|
1701
|
-
const source = await sourceColl.get(id);
|
|
1702
|
-
if (!source) {
|
|
1703
|
-
pending.delete(spec);
|
|
1704
|
-
continue;
|
|
1705
|
-
}
|
|
1706
|
-
const sourceWithId = { ...source, id };
|
|
1707
|
-
if (DerivationExecutor === null) {
|
|
1708
|
-
({ DerivationExecutor } = await import("./executor-TEZYRDN3.js"));
|
|
1709
|
-
}
|
|
1710
|
-
const ctx = { vault: accessor.getReadOnlyFacade() };
|
|
1711
|
-
const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx);
|
|
1712
|
-
for (const key of Object.keys(spec.outputs)) {
|
|
1713
|
-
const out = result.outputs[key];
|
|
1714
|
-
if (!out) continue;
|
|
1715
|
-
if (out.kind === "failed") {
|
|
1716
|
-
const err = out.error;
|
|
1717
|
-
if (spec.strict) {
|
|
1718
|
-
throw err;
|
|
1719
|
-
}
|
|
1720
|
-
console.warn(
|
|
1721
|
-
`[derivation] lazy output "${key}" for source "${spec.source}" id="${id}" failed:`,
|
|
1722
|
-
err
|
|
1723
|
-
);
|
|
1724
|
-
continue;
|
|
1725
|
-
}
|
|
1726
|
-
if (out.kind === "array") {
|
|
1727
|
-
console.warn(
|
|
1728
|
-
`[derivation] unexpected array-shape output "${key}" in lazy resolve path; array-shape derivations require lifecycle: "eager".`
|
|
1729
|
-
);
|
|
1730
|
-
continue;
|
|
1731
|
-
}
|
|
1732
|
-
const outSpec = spec.outputs[key];
|
|
1733
|
-
if (!outSpec) continue;
|
|
1734
|
-
const outputColl = accessor.getCollection(outSpec.collection);
|
|
1735
|
-
if (out.skipped === true) {
|
|
1736
|
-
await outputColl._internalDelete(id, accessor.getActiveTxContext());
|
|
1737
|
-
continue;
|
|
1738
|
-
}
|
|
1739
|
-
await outputColl.put(id, out.value);
|
|
1740
|
-
}
|
|
1741
|
-
pending.delete(spec);
|
|
1742
|
-
}
|
|
1743
|
-
}
|
|
1744
|
-
|
|
1745
|
-
// src/with-commit/crdt/strategy.ts
|
|
1746
|
-
var NOT_ENABLED = new Error(
|
|
1747
|
-
'CRDT mode requires the CRDT strategy. Import `{ withCrdt }` from "@noy-db/hub/crdt" and pass it to `createNoydb({ crdtStrategy: withCrdt() })`.'
|
|
1748
|
-
);
|
|
1749
|
-
var NO_CRDT = {
|
|
1750
|
-
buildLwwMapState() {
|
|
1751
|
-
throw NOT_ENABLED;
|
|
1752
|
-
},
|
|
1753
|
-
buildRgaState() {
|
|
1754
|
-
throw NOT_ENABLED;
|
|
1755
|
-
},
|
|
1756
|
-
mergeCrdtStates() {
|
|
1757
|
-
throw NOT_ENABLED;
|
|
1758
|
-
},
|
|
1759
|
-
resolveCrdtSnapshot() {
|
|
1760
|
-
throw NOT_ENABLED;
|
|
1761
|
-
}
|
|
1762
|
-
};
|
|
1763
|
-
|
|
1764
|
-
// src/with-party/team/sync-strategy.ts
|
|
1765
|
-
function notEnabled2(op) {
|
|
1766
|
-
return new Error(
|
|
1767
|
-
`${op} requires the sync strategy. Import \`{ withSync }\` from "@noy-db/hub/sync" and pass it to \`createNoydb({ syncStrategy: withSync() })\`.`
|
|
1768
|
-
);
|
|
1769
|
-
}
|
|
1770
|
-
var NO_SYNC = {
|
|
1771
|
-
buildSyncEngine() {
|
|
1772
|
-
throw notEnabled2("SyncEngine");
|
|
1773
|
-
},
|
|
1774
|
-
buildSyncTransaction() {
|
|
1775
|
-
throw notEnabled2("SyncTransaction");
|
|
1776
|
-
},
|
|
1777
|
-
buildPresence() {
|
|
1778
|
-
throw notEnabled2("collection.presence()");
|
|
1779
|
-
}
|
|
1780
|
-
};
|
|
1781
|
-
|
|
1782
1850
|
// src/kernel/via/compose.ts
|
|
1783
1851
|
function via(...descriptors) {
|
|
1784
1852
|
if (descriptors.length === 0) {
|
|
@@ -1942,7 +2010,7 @@ function compileViaBindings(opts, classifiedGuardCtx, eraseCfgOut) {
|
|
|
1942
2010
|
...i18nFields !== void 0 ? { i18nFields } : {},
|
|
1943
2011
|
...dictKeyFields !== void 0 ? { dictKeyFields } : {},
|
|
1944
2012
|
...i18nDensifyFields !== void 0 ? { i18nDensifyFields } : {},
|
|
1945
|
-
strategy: opts.
|
|
2013
|
+
strategy: opts.strategies.i18n,
|
|
1946
2014
|
...opts.defaultLocale !== void 0 ? { defaultLocale: opts.defaultLocale } : {},
|
|
1947
2015
|
...opts.autoTranslateHook !== void 0 ? { autoTranslateHook: opts.autoTranslateHook } : {},
|
|
1948
2016
|
...opts.dictLabelResolver !== void 0 ? { dictLabelResolver: opts.dictLabelResolver } : {},
|
|
@@ -2177,14 +2245,9 @@ function resolveCollectionConfig(opts) {
|
|
|
2177
2245
|
writeHooks: opts.writeHooks,
|
|
2178
2246
|
subsystemBus: opts.subsystemBus,
|
|
2179
2247
|
activeTxId: opts.activeTxId,
|
|
2180
|
-
|
|
2248
|
+
strategies: opts.strategies,
|
|
2181
2249
|
objectStore: opts.objectStore,
|
|
2182
2250
|
blobFields: opts.blobFields,
|
|
2183
|
-
aggregateStrategy: opts.aggregateStrategy ?? NO_AGGREGATE,
|
|
2184
|
-
crdtStrategy: opts.crdtStrategy ?? NO_CRDT,
|
|
2185
|
-
historyStrategy: opts.historyStrategy ?? NO_HISTORY,
|
|
2186
|
-
i18nStrategy: opts.i18nStrategy ?? NO_I18N,
|
|
2187
|
-
syncStrategy: opts.syncStrategy ?? NO_SYNC,
|
|
2188
2251
|
reconcileOnOpen: opts.reconcileOnOpen ?? "off",
|
|
2189
2252
|
getDEK: opts.getDEK,
|
|
2190
2253
|
onDirty: opts.onDirty,
|
|
@@ -2213,7 +2276,6 @@ function resolveCollectionConfig(opts) {
|
|
|
2213
2276
|
moneyFields: effectiveViaFields.moneyFields,
|
|
2214
2277
|
classified: resolvedClassified,
|
|
2215
2278
|
classifiedGuardCtx,
|
|
2216
|
-
classifiedStrategy: opts.classifiedStrategy ?? NO_CLASSIFIED,
|
|
2217
2279
|
computed: mergedComputed,
|
|
2218
2280
|
computedEdges,
|
|
2219
2281
|
viaDepsEdges,
|
|
@@ -2235,8 +2297,6 @@ function resolveCollectionConfig(opts) {
|
|
|
2235
2297
|
materializedViewSource: opts.materializedViewSource,
|
|
2236
2298
|
graphDispatch: opts.graphDispatch,
|
|
2237
2299
|
tiers: opts.tiers && opts.tiers.length > 0 ? new Set(opts.tiers) : null,
|
|
2238
|
-
tiersStrategy: opts.tiersStrategy ?? NO_TIERS,
|
|
2239
|
-
searchStrategy: opts.searchStrategy ?? NO_SEARCH,
|
|
2240
2300
|
tierMode: opts.tierMode ?? "invisibility",
|
|
2241
2301
|
blobTierPolicy: opts.blobTierPolicy ?? "isolate",
|
|
2242
2302
|
onCrossTierAccess: opts.onCrossTierAccess,
|
|
@@ -2253,20 +2313,11 @@ function resolveCollectionConfig(opts) {
|
|
|
2253
2313
|
// src/with-formula/computed/lazy.ts
|
|
2254
2314
|
var fn = null;
|
|
2255
2315
|
async function loadEvalComputedFields() {
|
|
2256
|
-
fn ??= (await import("./computed-
|
|
2316
|
+
fn ??= (await import("./computed-33DRJDOC.js")).evalComputedFields;
|
|
2257
2317
|
return fn;
|
|
2258
2318
|
}
|
|
2259
2319
|
|
|
2260
2320
|
// src/kernel/collection.ts
|
|
2261
|
-
function selfWriteFieldEqual(a, b) {
|
|
2262
|
-
if (a === b) return true;
|
|
2263
|
-
if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
|
|
2264
|
-
try {
|
|
2265
|
-
return JSON.stringify(a) === JSON.stringify(b);
|
|
2266
|
-
} catch {
|
|
2267
|
-
return false;
|
|
2268
|
-
}
|
|
2269
|
-
}
|
|
2270
2321
|
var fallbackWarned = /* @__PURE__ */ new Set();
|
|
2271
2322
|
function warnOnceFallback(adapterName) {
|
|
2272
2323
|
if (fallbackWarned.has(adapterName)) return;
|
|
@@ -2298,25 +2349,20 @@ var Collection = class {
|
|
|
2298
2349
|
/** True when the caller explicitly provided a `historyConfig` option (vs. inheriting the vault default). */
|
|
2299
2350
|
historyConfigExplicit;
|
|
2300
2351
|
/**
|
|
2301
|
-
*
|
|
2302
|
-
*
|
|
2303
|
-
*
|
|
2304
|
-
*
|
|
2305
|
-
*
|
|
2306
|
-
*
|
|
2307
|
-
* reaches the bundle
|
|
2352
|
+
* Every opt-in service, resolved once by `createNoydb` (#838) and shared by
|
|
2353
|
+
* reference with the owning `Vault` and `Noydb`.
|
|
2354
|
+
*
|
|
2355
|
+
* Each entry is a tree-shake seam. An un-opted-in service resolves to its
|
|
2356
|
+
* `NO_*` stub — a tiny module that throws with an actionable message —
|
|
2357
|
+
* so, for example, none of the BlobSet / chunk / MIME-magic machinery
|
|
2358
|
+
* reaches the bundle unless the consumer imports `@noy-db/hub/blobs` and
|
|
2359
|
+
* passes `blobStrategy: blobs()` to `createNoydb`.
|
|
2308
2360
|
*/
|
|
2309
|
-
|
|
2361
|
+
strategies;
|
|
2310
2362
|
objectStore;
|
|
2311
2363
|
blobFields;
|
|
2312
2364
|
blobTierPolicy;
|
|
2313
2365
|
// #724 T2/T3
|
|
2314
|
-
aggregateStrategy;
|
|
2315
|
-
crdtStrategy;
|
|
2316
|
-
tiersStrategy;
|
|
2317
|
-
searchStrategy;
|
|
2318
|
-
historyStrategy;
|
|
2319
|
-
syncStrategy;
|
|
2320
2366
|
// In-memory cache of decrypted records (eager mode only). Lazy mode
|
|
2321
2367
|
// uses `lru` instead. Both fields exist so a single Collection instance
|
|
2322
2368
|
// doesn't need a runtime branch on every cache access.
|
|
@@ -2486,12 +2532,6 @@ var Collection = class {
|
|
|
2486
2532
|
/** C-A/R10 memoization: marker declared-set lookup (undefined=unresolved) + classified-handle persist-once flag. */
|
|
2487
2533
|
_markerDigestOnlyCache = void 0;
|
|
2488
2534
|
_markerPersisted = false;
|
|
2489
|
-
/**
|
|
2490
|
-
* Tree-shake seam for `reveal()` — defaults to `NO_CLASSIFIED`, which
|
|
2491
|
-
* throws `ClassifiedNotEnabledError`. Set via the `classifiedStrategy`
|
|
2492
|
-
* `createNoydb()` option (opt in with `withClassified()`).
|
|
2493
|
-
*/
|
|
2494
|
-
classifiedStrategy;
|
|
2495
2535
|
/** Async callback provided by the Vault to open a dynamic dictionary handle (for label-map pre-computation in the search index). Only used in `resolveDictLabelMaps()`; static dicts bypass this entirely. Mutable, assign-once — see {@link _reconcileReadState} (#671 item 1). */
|
|
2496
2536
|
getDictionary;
|
|
2497
2537
|
/**
|
|
@@ -2640,16 +2680,10 @@ var Collection = class {
|
|
|
2640
2680
|
this.writeHooks = cfg.writeHooks;
|
|
2641
2681
|
this.subsystemBus = cfg.subsystemBus;
|
|
2642
2682
|
this.activeTxId = cfg.activeTxId;
|
|
2643
|
-
this.
|
|
2683
|
+
this.strategies = cfg.strategies;
|
|
2644
2684
|
this.objectStore = cfg.objectStore;
|
|
2645
2685
|
this.blobFields = cfg.blobFields;
|
|
2646
2686
|
this.blobTierPolicy = cfg.blobTierPolicy ?? "isolate";
|
|
2647
|
-
this.aggregateStrategy = cfg.aggregateStrategy;
|
|
2648
|
-
this.crdtStrategy = cfg.crdtStrategy;
|
|
2649
|
-
this.tiersStrategy = cfg.tiersStrategy;
|
|
2650
|
-
this.searchStrategy = cfg.searchStrategy;
|
|
2651
|
-
this.historyStrategy = cfg.historyStrategy;
|
|
2652
|
-
this.syncStrategy = cfg.syncStrategy;
|
|
2653
2687
|
this.reconcileOnOpen = cfg.reconcileOnOpen;
|
|
2654
2688
|
this.getDEK = cfg.getDEK;
|
|
2655
2689
|
this.onDirty = cfg.onDirty;
|
|
@@ -2676,7 +2710,6 @@ var Collection = class {
|
|
|
2676
2710
|
this.classified = cfg.classified;
|
|
2677
2711
|
this.classifiedGuardCtx = cfg.classifiedGuardCtx;
|
|
2678
2712
|
this.vdigFields = cfg.vdigFields;
|
|
2679
|
-
this.classifiedStrategy = cfg.classifiedStrategy;
|
|
2680
2713
|
this.computed = cfg.computed;
|
|
2681
2714
|
this.getDictionary = cfg.getDictionary;
|
|
2682
2715
|
this.defaultLocale = cfg.defaultLocale;
|
|
@@ -2724,7 +2757,7 @@ var Collection = class {
|
|
|
2724
2757
|
deterministicFields: this.deterministicFields,
|
|
2725
2758
|
vdigFields: this.vdigFields,
|
|
2726
2759
|
crdtMode: this.crdtMode,
|
|
2727
|
-
crdtStrategy: this.
|
|
2760
|
+
crdtStrategy: this.strategies.crdt,
|
|
2728
2761
|
schema: this.schema,
|
|
2729
2762
|
getDEK: (collection) => this.getDEK(collection ?? this.name),
|
|
2730
2763
|
cekCache: this.cekCache,
|
|
@@ -2742,7 +2775,7 @@ var Collection = class {
|
|
|
2742
2775
|
const remoteJson = await this.codec.decryptJsonString(remote, id);
|
|
2743
2776
|
if (localJson === null) return local;
|
|
2744
2777
|
if (remoteJson === null) return remote;
|
|
2745
|
-
const merged = this.
|
|
2778
|
+
const merged = this.strategies.crdt.mergeCrdtStates(JSON.parse(localJson), JSON.parse(remoteJson));
|
|
2746
2779
|
const mergedVersion = Math.max(local._v, remote._v) + 1;
|
|
2747
2780
|
const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
|
|
2748
2781
|
return this.codec.encryptJsonString(JSON.stringify(merged), mergedVersion, cek);
|
|
@@ -2800,12 +2833,12 @@ var Collection = class {
|
|
|
2800
2833
|
}
|
|
2801
2834
|
this.lazy = opts.prefetch === false;
|
|
2802
2835
|
if (this.lazy) {
|
|
2803
|
-
this.lru =
|
|
2836
|
+
this.lru = opts.strategies.lazy.createCache(this.name, opts.cache);
|
|
2804
2837
|
this.hydrated = true;
|
|
2805
2838
|
} else {
|
|
2806
2839
|
this.lru = null;
|
|
2807
2840
|
}
|
|
2808
|
-
const strategy = opts.
|
|
2841
|
+
const strategy = opts.strategies.index;
|
|
2809
2842
|
this.indexState = strategy.createState({
|
|
2810
2843
|
defs: opts.indexes ?? [],
|
|
2811
2844
|
lazy: this.lazy
|
|
@@ -2960,7 +2993,7 @@ var Collection = class {
|
|
|
2960
2993
|
if (spec.storage === "digest-only") {
|
|
2961
2994
|
throw new ClassifiedRevealError(this.name, field, `storage:'digest-only' \u2014 verify-only; nothing recoverable to reveal`);
|
|
2962
2995
|
}
|
|
2963
|
-
return this.
|
|
2996
|
+
return this.strategies.classified.reveal({
|
|
2964
2997
|
collection: this.name,
|
|
2965
2998
|
spec,
|
|
2966
2999
|
encrypted: this.storeCiphertext,
|
|
@@ -2980,7 +3013,7 @@ var Collection = class {
|
|
|
2980
3013
|
throw new ClassifiedVerifyError(this.name, field, `storage:'never' \u2014 nothing is stored to verify against`);
|
|
2981
3014
|
}
|
|
2982
3015
|
const ctx = this._classifiedVerifyCtx(spec);
|
|
2983
|
-
return spec.storage === "digest-only" ? this.
|
|
3016
|
+
return spec.storage === "digest-only" ? this.strategies.classified.verify(ctx, id, field, candidate) : this.strategies.classified.verifyText(ctx, id, field, candidate);
|
|
2984
3017
|
}
|
|
2985
3018
|
/** k-of-n challenge over the collection's secretAnswer members. Requires withClassified(). */
|
|
2986
3019
|
async verifyGroup(id, answers, opts) {
|
|
@@ -2989,7 +3022,7 @@ var Collection = class {
|
|
|
2989
3022
|
throw new ClassifiedVerifyError(this.name, "*", "no groupable digest-only (secretAnswer) fields declared");
|
|
2990
3023
|
}
|
|
2991
3024
|
const ctx = { ...this._classifiedVerifyCtx(members[0].spec), groupMembers: members };
|
|
2992
|
-
return this.
|
|
3025
|
+
return this.strategies.classified.matchGroup(ctx, id, answers, opts);
|
|
2993
3026
|
}
|
|
2994
3027
|
_classifiedVerifyCtx(spec) {
|
|
2995
3028
|
return {
|
|
@@ -3044,7 +3077,7 @@ var Collection = class {
|
|
|
3044
3077
|
if (typeof candidate !== "string") {
|
|
3045
3078
|
throw new ClassifiedVerifyError(this.name, "*", "candidate must be a string");
|
|
3046
3079
|
}
|
|
3047
|
-
const target = await this.
|
|
3080
|
+
const target = await this.strategies.classified.computeTarget(this._classifiedVerifyCtx(spec), field, candidate);
|
|
3048
3081
|
const ids = await this.adapter.list(this.vault, this.name);
|
|
3049
3082
|
const hits = [];
|
|
3050
3083
|
const hitMap = /* @__PURE__ */ new Map();
|
|
@@ -3057,7 +3090,7 @@ var Collection = class {
|
|
|
3057
3090
|
}
|
|
3058
3091
|
await this.onAccess?.("find", "*");
|
|
3059
3092
|
if (hits.length === 0) return [];
|
|
3060
|
-
const { verifyDigestField } = await import("./verify-
|
|
3093
|
+
const { verifyDigestField } = await import("./verify-5X37OXRY.js");
|
|
3061
3094
|
const policy = {
|
|
3062
3095
|
normalize: spec.verifyNormalize ?? "password",
|
|
3063
3096
|
notLastN: spec.notLastN ?? 0,
|
|
@@ -3131,7 +3164,7 @@ var Collection = class {
|
|
|
3131
3164
|
id,
|
|
3132
3165
|
version: scrubbed._v,
|
|
3133
3166
|
actor: this.keyring.userId,
|
|
3134
|
-
payloadHash: await this.
|
|
3167
|
+
payloadHash: await this.strategies.history.envelopePayloadHash(scrubbed),
|
|
3135
3168
|
reason: "classified:scrub-equatable-tags"
|
|
3136
3169
|
});
|
|
3137
3170
|
}
|
|
@@ -3263,7 +3296,7 @@ var Collection = class {
|
|
|
3263
3296
|
}
|
|
3264
3297
|
}
|
|
3265
3298
|
if (this.materializedViewSource !== void 0) {
|
|
3266
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
3299
|
+
const { resolveStaleMVOnRead } = await import("./stale-NBROTA66.js");
|
|
3267
3300
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: "resolve-on-read" }));
|
|
3268
3301
|
}
|
|
3269
3302
|
let record;
|
|
@@ -3357,7 +3390,7 @@ var Collection = class {
|
|
|
3357
3390
|
if (this.syncAdapter !== void 0) presenceOpts.syncAdapter = this.syncAdapter;
|
|
3358
3391
|
if (opts?.staleMs !== void 0) presenceOpts.staleMs = opts.staleMs;
|
|
3359
3392
|
if (opts?.pollIntervalMs !== void 0) presenceOpts.pollIntervalMs = opts.pollIntervalMs;
|
|
3360
|
-
return this.
|
|
3393
|
+
return this.strategies.sync.buildPresence(presenceOpts);
|
|
3361
3394
|
}
|
|
3362
3395
|
/**
|
|
3363
3396
|
* Create or update a record. Runs inside the hub's write-queue tracker
|
|
@@ -3519,6 +3552,103 @@ var Collection = class {
|
|
|
3519
3552
|
return clone;
|
|
3520
3553
|
}
|
|
3521
3554
|
/** @internal Untracked put body — call {@link put}, not this. */
|
|
3555
|
+
/**
|
|
3556
|
+
* Decode a prior envelope's CRDT state, or `undefined` when there is no
|
|
3557
|
+
* usable prior: no envelope, a shredded body decrypting to `null`, or a
|
|
3558
|
+
* payload that is not a CRDT state. The `lww-map` and `rga` branches each
|
|
3559
|
+
* carried a copy, byte-identical apart from the cast (#842).
|
|
3560
|
+
*/
|
|
3561
|
+
async #decodePriorCrdtState(envelope) {
|
|
3562
|
+
if (!envelope) return void 0;
|
|
3563
|
+
const prevJson = await this.codec.decryptJsonString(envelope);
|
|
3564
|
+
if (prevJson === null) return void 0;
|
|
3565
|
+
const prevParsed = JSON.parse(prevJson);
|
|
3566
|
+
if (prevParsed === null || typeof prevParsed !== "object" || !("_crdt" in prevParsed)) {
|
|
3567
|
+
return void 0;
|
|
3568
|
+
}
|
|
3569
|
+
return prevParsed;
|
|
3570
|
+
}
|
|
3571
|
+
/**
|
|
3572
|
+
* Record a write on the active transaction so a mid-batch failure rolls it
|
|
3573
|
+
* back. Four sites in the derivation/MV dispatch hand-built this literal (#842).
|
|
3574
|
+
*/
|
|
3575
|
+
#trackPut(txCtx, collectionName, id, priorEnvelope) {
|
|
3576
|
+
txCtx._executed.push({
|
|
3577
|
+
op: { type: "put", vaultName: this.vault, collectionName, id },
|
|
3578
|
+
priorEnvelope
|
|
3579
|
+
});
|
|
3580
|
+
}
|
|
3581
|
+
/**
|
|
3582
|
+
* Snapshot the PRIOR version into history, emit, and prune.
|
|
3583
|
+
*
|
|
3584
|
+
* Deliberately does NOT carry `source` from the current write — a history
|
|
3585
|
+
* entry describes the version being replaced, not the one replacing it.
|
|
3586
|
+
*
|
|
3587
|
+
* Kept OUT of {@link #commitWriteTail} because the two paths call it at
|
|
3588
|
+
* different points: the normal path snapshots BEFORE `adapter.put` (so a
|
|
3589
|
+
* history failure leaves no write behind), while the CRDT path must merge
|
|
3590
|
+
* and persist first to resolve the prior record at all. Folding it into the
|
|
3591
|
+
* tail would silently reorder one of them (#842).
|
|
3592
|
+
*/
|
|
3593
|
+
async #savePriorHistory(id, prior, cek, vdigCtx) {
|
|
3594
|
+
if (this.historyConfig.enabled === false) return;
|
|
3595
|
+
await this.strategies.history.saveHistory(
|
|
3596
|
+
this.adapter,
|
|
3597
|
+
this.vault,
|
|
3598
|
+
this.name,
|
|
3599
|
+
id,
|
|
3600
|
+
await this.codec.encryptRecord(prior.record, prior.version, cek, void 0, void 0, vdigCtx, id)
|
|
3601
|
+
);
|
|
3602
|
+
this.emitter.emit("history:save", { vault: this.vault, collection: this.name, id, version: prior.version });
|
|
3603
|
+
if (this.historyConfig.maxVersions) {
|
|
3604
|
+
await this.strategies.history.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
|
|
3605
|
+
}
|
|
3606
|
+
}
|
|
3607
|
+
/**
|
|
3608
|
+
* Everything both write paths do once the envelope is on the adapter:
|
|
3609
|
+
* classified marker, embedding sidecar, ledger append, cache/index
|
|
3610
|
+
* maintenance, and the mutation event that drives derivation dispatch.
|
|
3611
|
+
*
|
|
3612
|
+
* The CRDT branch used to re-implement all of it, and in doing so skipped
|
|
3613
|
+
* `_ensureClassifiedMarker`, the unique-constraint upsert and
|
|
3614
|
+
* `_toCacheableRecord` (#835). All three were unreachable — each blocked by
|
|
3615
|
+
* a config-time refusal on CRDT collections — but only by accident of what
|
|
3616
|
+
* that copy happened to omit. One tail makes the divergence unrepresentable
|
|
3617
|
+
* rather than merely unreachable; on a CRDT collection the extra steps are
|
|
3618
|
+
* provably no-ops (classified/unique + crdt are refused at construction, and
|
|
3619
|
+
* a CRDT body never produces a `_sealed` slot, so `_toCacheableRecord` is
|
|
3620
|
+
* the identity).
|
|
3621
|
+
*/
|
|
3622
|
+
async #commitWriteTail(args) {
|
|
3623
|
+
const { id, envelope, version, indexed, event, prior, reason } = args;
|
|
3624
|
+
await this._ensureClassifiedMarker();
|
|
3625
|
+
if (this.embeddings) {
|
|
3626
|
+
await this.strategies.search.embedOnWrite(this.searchContext(), id, indexed, version);
|
|
3627
|
+
}
|
|
3628
|
+
if (this.ledger) {
|
|
3629
|
+
const appendInput = {
|
|
3630
|
+
op: "put",
|
|
3631
|
+
collection: this.name,
|
|
3632
|
+
id,
|
|
3633
|
+
version,
|
|
3634
|
+
actor: this.keyring.userId,
|
|
3635
|
+
payloadHash: await this.strategies.history.envelopePayloadHash(envelope)
|
|
3636
|
+
};
|
|
3637
|
+
if (prior) appendInput.delta = this.strategies.history.computePatch(indexed, prior.record);
|
|
3638
|
+
if (reason !== void 0) appendInput.reason = reason;
|
|
3639
|
+
await this.ledger.append(appendInput);
|
|
3640
|
+
}
|
|
3641
|
+
const cacheable = await this._toCacheableRecord(indexed, envelope, id);
|
|
3642
|
+
if (this.lazy && this.lru) {
|
|
3643
|
+
this.lru.set(id, { record: cacheable, version }, estimateRecordBytes(indexed));
|
|
3644
|
+
await this.maintainPersistedIndexesOnPut(id, indexed, prior ? prior.record : null, version);
|
|
3645
|
+
} else {
|
|
3646
|
+
this.cache.set(id, { record: cacheable, version });
|
|
3647
|
+
this.indexes?.upsert(id, indexed, prior ? prior.record : null);
|
|
3648
|
+
this.uniqueConstraints?.upsert(id, indexed, prior?.record);
|
|
3649
|
+
}
|
|
3650
|
+
await this._onRecordMutated(id, "put", "local-write", { record: event, version });
|
|
3651
|
+
}
|
|
3522
3652
|
async _putInternal(id, record, options) {
|
|
3523
3653
|
if (!hasWritePermission(this.keyring, this.name)) {
|
|
3524
3654
|
throw new ReadOnlyError();
|
|
@@ -3567,29 +3697,11 @@ var Collection = class {
|
|
|
3567
3697
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3568
3698
|
let crdtState;
|
|
3569
3699
|
if (this.crdtMode === "lww-map") {
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
const prevJson = await this.codec.decryptJsonString(existingEnvelope);
|
|
3573
|
-
if (prevJson !== null) {
|
|
3574
|
-
const prevParsed = JSON.parse(prevJson);
|
|
3575
|
-
if (prevParsed !== null && typeof prevParsed === "object" && "_crdt" in prevParsed) {
|
|
3576
|
-
existingState = prevParsed;
|
|
3577
|
-
}
|
|
3578
|
-
}
|
|
3579
|
-
}
|
|
3580
|
-
crdtState = this.crdtStrategy.buildLwwMapState(record, existingState, now);
|
|
3700
|
+
const existingState = await this.#decodePriorCrdtState(existingEnvelope);
|
|
3701
|
+
crdtState = this.strategies.crdt.buildLwwMapState(record, existingState, now);
|
|
3581
3702
|
} else if (this.crdtMode === "rga") {
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
const prevJson = await this.codec.decryptJsonString(existingEnvelope);
|
|
3585
|
-
if (prevJson !== null) {
|
|
3586
|
-
const prevParsed = JSON.parse(prevJson);
|
|
3587
|
-
if (prevParsed !== null && typeof prevParsed === "object" && "_crdt" in prevParsed) {
|
|
3588
|
-
existingState = prevParsed;
|
|
3589
|
-
}
|
|
3590
|
-
}
|
|
3591
|
-
}
|
|
3592
|
-
crdtState = this.crdtStrategy.buildRgaState(Array.isArray(record) ? record : [record], existingState, generateULID);
|
|
3703
|
+
const existingState = await this.#decodePriorCrdtState(existingEnvelope);
|
|
3704
|
+
crdtState = this.strategies.crdt.buildRgaState(Array.isArray(record) ? record : [record], existingState, generateULID);
|
|
3593
3705
|
} else {
|
|
3594
3706
|
crdtState = { _crdt: "yjs", update: record };
|
|
3595
3707
|
}
|
|
@@ -3597,42 +3709,21 @@ var Collection = class {
|
|
|
3597
3709
|
const cek2 = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
|
|
3598
3710
|
const envelope2 = await this.codec.encryptJsonString(JSON.stringify(crdtState), version2, cek2, options?.source, options?.sourceTs);
|
|
3599
3711
|
await this.adapter.put(this.vault, this.name, id, envelope2);
|
|
3600
|
-
const resolvedRecord = this.
|
|
3712
|
+
const resolvedRecord = this.strategies.crdt.resolveCrdtSnapshot(crdtState);
|
|
3601
3713
|
const existingResolvedRecord = existingEnvelope ? await this.codec.decryptRecord(existingEnvelope, { skipValidation: true }) : null;
|
|
3602
3714
|
const existingResolved = existingResolvedRecord !== null ? { record: existingResolvedRecord, version: existingVersion } : void 0;
|
|
3603
|
-
if (existingResolved
|
|
3604
|
-
await this
|
|
3605
|
-
this.emitter.emit("history:save", { vault: this.vault, collection: this.name, id, version: existingResolved.version });
|
|
3606
|
-
if (this.historyConfig.maxVersions) {
|
|
3607
|
-
await this.historyStrategy.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
|
|
3608
|
-
}
|
|
3609
|
-
}
|
|
3610
|
-
if (this.ledger) {
|
|
3611
|
-
const appendInput = {
|
|
3612
|
-
op: "put",
|
|
3613
|
-
collection: this.name,
|
|
3614
|
-
id,
|
|
3615
|
-
version: version2,
|
|
3616
|
-
actor: this.keyring.userId,
|
|
3617
|
-
payloadHash: await this.historyStrategy.envelopePayloadHash(envelope2)
|
|
3618
|
-
};
|
|
3619
|
-
if (existingResolved) appendInput.delta = this.historyStrategy.computePatch(resolvedRecord, existingResolved.record);
|
|
3620
|
-
if (options?.reason !== void 0) appendInput.reason = options.reason;
|
|
3621
|
-
await this.ledger.append(appendInput);
|
|
3622
|
-
}
|
|
3623
|
-
if (this.lazy && this.lru) {
|
|
3624
|
-
this.lru.set(id, { record: resolvedRecord, version: version2 }, estimateRecordBytes(resolvedRecord));
|
|
3625
|
-
await this.maintainPersistedIndexesOnPut(
|
|
3626
|
-
id,
|
|
3627
|
-
resolvedRecord,
|
|
3628
|
-
existingResolved ? existingResolved.record : null,
|
|
3629
|
-
version2
|
|
3630
|
-
);
|
|
3631
|
-
} else {
|
|
3632
|
-
this.cache.set(id, { record: resolvedRecord, version: version2 });
|
|
3633
|
-
this.indexes?.upsert(id, resolvedRecord, existingResolved ? existingResolved.record : null);
|
|
3715
|
+
if (existingResolved) {
|
|
3716
|
+
await this.#savePriorHistory(id, existingResolved, cek2, this.vdigFields !== null ? { id, prev: existingEnvelope } : void 0);
|
|
3634
3717
|
}
|
|
3635
|
-
await this
|
|
3718
|
+
await this.#commitWriteTail({
|
|
3719
|
+
id,
|
|
3720
|
+
envelope: envelope2,
|
|
3721
|
+
version: version2,
|
|
3722
|
+
indexed: resolvedRecord,
|
|
3723
|
+
event: record,
|
|
3724
|
+
prior: existingResolved,
|
|
3725
|
+
reason: options?.reason
|
|
3726
|
+
});
|
|
3636
3727
|
return;
|
|
3637
3728
|
}
|
|
3638
3729
|
let existing;
|
|
@@ -3657,52 +3748,24 @@ var Collection = class {
|
|
|
3657
3748
|
if (priorRaw === null && (this.markerIds.has(id) || this.tabCoordinated?.())) {
|
|
3658
3749
|
priorRaw = await this.adapter.get(this.vault, this.name, id);
|
|
3659
3750
|
}
|
|
3660
|
-
if (priorRaw && isDeleteMarker(priorRaw)) version = priorRaw._v + 1;
|
|
3661
|
-
}
|
|
3662
|
-
this.uniqueConstraints?.check(id, record);
|
|
3663
|
-
const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
|
|
3664
|
-
const vdigCtx = this.vdigFields !== null ? { id, prev: await this.adapter.get(this.vault, this.name, id) } : void 0;
|
|
3665
|
-
if (existing && this.historyConfig.enabled !== false) {
|
|
3666
|
-
await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, await this.codec.encryptRecord(existing.record, existing.version, cek, void 0, void 0, vdigCtx, id));
|
|
3667
|
-
this.emitter.emit("history:save", {
|
|
3668
|
-
vault: this.vault,
|
|
3669
|
-
collection: this.name,
|
|
3670
|
-
id,
|
|
3671
|
-
version: existing.version
|
|
3672
|
-
});
|
|
3673
|
-
if (this.historyConfig.maxVersions) await this.historyStrategy.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
|
|
3674
|
-
}
|
|
3675
|
-
const envelope = await this.codec.encryptRecord(record, version, cek, options?.source, options?.sourceTs, vdigCtx, id);
|
|
3676
|
-
await this.adapter.put(this.vault, this.name, id, envelope);
|
|
3677
|
-
this.markerIds.delete(id);
|
|
3678
|
-
await this._ensureClassifiedMarker();
|
|
3679
|
-
if (this.embeddings) {
|
|
3680
|
-
await this.searchStrategy.embedOnWrite(this.searchContext(), id, record, version);
|
|
3681
|
-
}
|
|
3682
|
-
if (this.ledger) {
|
|
3683
|
-
const appendInput = {
|
|
3684
|
-
op: "put",
|
|
3685
|
-
collection: this.name,
|
|
3686
|
-
id,
|
|
3687
|
-
version,
|
|
3688
|
-
actor: this.keyring.userId,
|
|
3689
|
-
payloadHash: await this.historyStrategy.envelopePayloadHash(envelope)
|
|
3690
|
-
};
|
|
3691
|
-
if (existing) {
|
|
3692
|
-
appendInput.delta = this.historyStrategy.computePatch(record, existing.record);
|
|
3693
|
-
}
|
|
3694
|
-
if (options?.reason !== void 0) appendInput.reason = options.reason;
|
|
3695
|
-
await this.ledger.append(appendInput);
|
|
3696
|
-
}
|
|
3697
|
-
if (this.lazy && this.lru) {
|
|
3698
|
-
this.lru.set(id, { record: await this._toCacheableRecord(record, envelope, id), version }, estimateRecordBytes(record));
|
|
3699
|
-
await this.maintainPersistedIndexesOnPut(id, record, existing ? existing.record : null, version);
|
|
3700
|
-
} else {
|
|
3701
|
-
this.cache.set(id, { record: await this._toCacheableRecord(record, envelope, id), version });
|
|
3702
|
-
this.indexes?.upsert(id, record, existing ? existing.record : null);
|
|
3703
|
-
this.uniqueConstraints?.upsert(id, record, existing?.record);
|
|
3751
|
+
if (priorRaw && isDeleteMarker(priorRaw)) version = priorRaw._v + 1;
|
|
3704
3752
|
}
|
|
3705
|
-
|
|
3753
|
+
this.uniqueConstraints?.check(id, record);
|
|
3754
|
+
const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
|
|
3755
|
+
const vdigCtx = this.vdigFields !== null ? { id, prev: await this.adapter.get(this.vault, this.name, id) } : void 0;
|
|
3756
|
+
if (existing) await this.#savePriorHistory(id, existing, cek, vdigCtx);
|
|
3757
|
+
const envelope = await this.codec.encryptRecord(record, version, cek, options?.source, options?.sourceTs, vdigCtx, id);
|
|
3758
|
+
await this.adapter.put(this.vault, this.name, id, envelope);
|
|
3759
|
+
this.markerIds.delete(id);
|
|
3760
|
+
await this.#commitWriteTail({
|
|
3761
|
+
id,
|
|
3762
|
+
envelope,
|
|
3763
|
+
version,
|
|
3764
|
+
indexed: record,
|
|
3765
|
+
event: record,
|
|
3766
|
+
prior: existing,
|
|
3767
|
+
reason: options?.reason
|
|
3768
|
+
});
|
|
3706
3769
|
}
|
|
3707
3770
|
/**
|
|
3708
3771
|
* Fire registered MV strategies whose dependency set includes this
|
|
@@ -3719,34 +3782,8 @@ var Collection = class {
|
|
|
3719
3782
|
*/
|
|
3720
3783
|
async dispatchMaterializedViews(id, record, wave) {
|
|
3721
3784
|
if (this.materializedViewSource === void 0) return;
|
|
3722
|
-
const
|
|
3723
|
-
|
|
3724
|
-
const registry = this.materializedViewSource.registry();
|
|
3725
|
-
const mvs = registry.mvsForSource(this.name);
|
|
3726
|
-
if (mvs.length === 0) return;
|
|
3727
|
-
let executor = null;
|
|
3728
|
-
let staleHelpers = null;
|
|
3729
|
-
for (const reg of mvs) {
|
|
3730
|
-
const mode = reg.spec.refresh;
|
|
3731
|
-
if (mode === "eager") {
|
|
3732
|
-
if (wave?.seen(`mv\0${reg.spec.name}`)) continue;
|
|
3733
|
-
if (executor === null) {
|
|
3734
|
-
;
|
|
3735
|
-
({ MaterializedViewExecutor: executor } = await import("./executor-YORMIBWV.js"));
|
|
3736
|
-
}
|
|
3737
|
-
await executor.refresh(reg, {
|
|
3738
|
-
getCollection: (name) => this.materializedViewSource.getCollection(name),
|
|
3739
|
-
getActiveTxContext: () => this.materializedViewSource.getActiveTxContext(),
|
|
3740
|
-
getQueryContext: () => this.materializedViewSource.getQueryContext(),
|
|
3741
|
-
dispatchCtx: this.#dispatchCtx({ collection: this.name, id })
|
|
3742
|
-
});
|
|
3743
|
-
} else if (mode === "lazy") {
|
|
3744
|
-
if (staleHelpers === null) {
|
|
3745
|
-
staleHelpers = await import("./stale-4UNPHWOU.js");
|
|
3746
|
-
}
|
|
3747
|
-
staleHelpers.markMVStale(registry, reg.spec.name);
|
|
3748
|
-
}
|
|
3749
|
-
}
|
|
3785
|
+
const { dispatchMaterializedViews } = await import("./dispatch-SMXUO7W5.js");
|
|
3786
|
+
return dispatchMaterializedViews(this.#mvDispatchCtx(this.materializedViewSource), id, record, wave);
|
|
3750
3787
|
}
|
|
3751
3788
|
/**
|
|
3752
3789
|
* Fire registered derivation strategies for this source collection.
|
|
@@ -3834,6 +3871,32 @@ var Collection = class {
|
|
|
3834
3871
|
return out;
|
|
3835
3872
|
}
|
|
3836
3873
|
/** @internal — ctx for `putDerivedOutput`'s frozen-period skip+audit (#638 Task 5). */
|
|
3874
|
+
/** What `with-formula/materialized-views/dispatch.ts` needs from this collection (#842). */
|
|
3875
|
+
#mvDispatchCtx(materializedViewSource) {
|
|
3876
|
+
return {
|
|
3877
|
+
materializedViewSource,
|
|
3878
|
+
collectionName: this.name,
|
|
3879
|
+
dispatchCtx: (source) => this.#dispatchCtx(source)
|
|
3880
|
+
};
|
|
3881
|
+
}
|
|
3882
|
+
/**
|
|
3883
|
+
* What `with-formula/derivations/dispatch.ts` needs from this collection (#842).
|
|
3884
|
+
*
|
|
3885
|
+
* The return type is inferred, not annotated: importing `DerivationDeleteCtx`
|
|
3886
|
+
* would be a STATIC spine→service import, which `port-layering` rejects even
|
|
3887
|
+
* when it is type-only — the guard scans import statements, not their
|
|
3888
|
+
* erasure. The dynamic `import()` at the call site still types the argument.
|
|
3889
|
+
*/
|
|
3890
|
+
#derivationDeleteCtx(derivationSource) {
|
|
3891
|
+
return {
|
|
3892
|
+
derivationSource,
|
|
3893
|
+
collectionName: this.name,
|
|
3894
|
+
adapter: this.adapter,
|
|
3895
|
+
vault: this.vault,
|
|
3896
|
+
getDEK: this.getDEK,
|
|
3897
|
+
storeCiphertext: this.storeCiphertext
|
|
3898
|
+
};
|
|
3899
|
+
}
|
|
3837
3900
|
#dispatchCtx(source) {
|
|
3838
3901
|
return { emit: (e, p) => this.emitter.emit(e, p), source, audit: ledgerAuditHook(this.ledger, this.keyring.userId) };
|
|
3839
3902
|
}
|
|
@@ -3859,11 +3922,7 @@ var Collection = class {
|
|
|
3859
3922
|
const patched = { ...base, [field]: newValue };
|
|
3860
3923
|
const txCtx = this.derivationSource.getActiveTxContext();
|
|
3861
3924
|
if (txCtx !== null) {
|
|
3862
|
-
|
|
3863
|
-
txCtx._executed.push({
|
|
3864
|
-
op: { type: "put", vaultName: this.vault, collectionName: into, id: parentId },
|
|
3865
|
-
priorEnvelope: prior
|
|
3866
|
-
});
|
|
3925
|
+
this.#trackPut(txCtx, into, parentId, await this.adapter.get(this.vault, into, parentId));
|
|
3867
3926
|
}
|
|
3868
3927
|
return putDerivedOutput(intoColl, parentId, patched, this.#dispatchCtx(source));
|
|
3869
3928
|
}
|
|
@@ -3896,150 +3955,14 @@ var Collection = class {
|
|
|
3896
3955
|
* dispatch wave's per-target dedup; `undefined` on the local-write path (byte-identical). */
|
|
3897
3956
|
async dispatchDerivations(id, record, version, wave) {
|
|
3898
3957
|
if (this.derivationSource === void 0) return;
|
|
3899
|
-
const
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
if (spec.rollup) {
|
|
3908
|
-
if (mode !== "eager") continue;
|
|
3909
|
-
let parentId;
|
|
3910
|
-
if (this.name === spec.rollup.from) {
|
|
3911
|
-
const kv = incoming[spec.rollup.key];
|
|
3912
|
-
parentId = typeof kv === "string" || typeof kv === "number" ? String(kv) : null;
|
|
3913
|
-
} else {
|
|
3914
|
-
parentId = id;
|
|
3915
|
-
}
|
|
3916
|
-
if (parentId !== null) await this.recomputeRollup(spec, parentId, { collection: this.name, id }, wave);
|
|
3917
|
-
continue;
|
|
3918
|
-
}
|
|
3919
|
-
const isSource = spec.source === this.name;
|
|
3920
|
-
const isSibling = !isSource && (spec.sources?.includes(this.name) ?? false);
|
|
3921
|
-
const trigger = !isSource && !isSibling ? spec.triggerBy?.find((t) => t.collection === this.name) : void 0;
|
|
3922
|
-
const runs = [];
|
|
3923
|
-
if (isSource) {
|
|
3924
|
-
runs.push({ input: { ...incoming, id }, base: incoming, runId: id, version });
|
|
3925
|
-
} else if (isSibling) {
|
|
3926
|
-
const p = await this.derivationSource.getCollection(spec.source).get(id);
|
|
3927
|
-
if (p !== null && p !== void 0) {
|
|
3928
|
-
const raw = await this.derivationSource.getCollection(spec.source)._getStoredRecord(id);
|
|
3929
|
-
runs.push({ input: { ...p, id }, base: raw ?? p, runId: id, version: 0 });
|
|
3930
|
-
}
|
|
3931
|
-
} else if (trigger) {
|
|
3932
|
-
const srcColl = this.derivationSource.getCollection(spec.source);
|
|
3933
|
-
const ids = await srcColl._findMatchingIds(trigger.on, id);
|
|
3934
|
-
if (trigger.maxFanout !== void 0 && ids.length > trigger.maxFanout) {
|
|
3935
|
-
throw new DerivationCapExceededError(`triggerBy ${this.name}\u2192${spec.source}`, ids.length, trigger.maxFanout);
|
|
3936
|
-
}
|
|
3937
|
-
for (const sid of ids) {
|
|
3938
|
-
const raw = await srcColl._getStoredRecord(sid);
|
|
3939
|
-
if (raw === null) continue;
|
|
3940
|
-
runs.push({ input: { ...raw, id: sid }, base: raw, runId: sid, version: 0 });
|
|
3941
|
-
}
|
|
3942
|
-
}
|
|
3943
|
-
if (runs.length === 0) continue;
|
|
3944
|
-
if (mode !== "eager") {
|
|
3945
|
-
for (const run of runs) await markStale(registry, spec, run.runId);
|
|
3946
|
-
continue;
|
|
3947
|
-
}
|
|
3948
|
-
if (DerivationExecutor === null) {
|
|
3949
|
-
({ DerivationExecutor } = await import("./executor-TEZYRDN3.js"));
|
|
3950
|
-
}
|
|
3951
|
-
for (const run of runs) {
|
|
3952
|
-
const ctx = { vault: this.derivationSource.getReadOnlyFacade() };
|
|
3953
|
-
const outCtx = this.#dispatchCtx({ collection: spec.source, id: run.runId });
|
|
3954
|
-
const result = await DerivationExecutor.run(spec, run.input, run.version, strategyHash, ctx);
|
|
3955
|
-
for (const key of Object.keys(spec.outputs)) {
|
|
3956
|
-
const out = result.outputs[key];
|
|
3957
|
-
if (!out) continue;
|
|
3958
|
-
if (out.kind === "failed") {
|
|
3959
|
-
const err = out.error;
|
|
3960
|
-
if (spec.strict) throw err;
|
|
3961
|
-
console.warn(`[derivation] output "${key}" for source "${spec.source}" id="${run.runId}" failed:`, err);
|
|
3962
|
-
continue;
|
|
3963
|
-
}
|
|
3964
|
-
const outSpec = spec.outputs[key];
|
|
3965
|
-
if (!outSpec) continue;
|
|
3966
|
-
const outputCollection = this.derivationSource.getCollection(outSpec.collection);
|
|
3967
|
-
const txCtx = this.derivationSource.getActiveTxContext();
|
|
3968
|
-
if (out.kind === "array") {
|
|
3969
|
-
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-HJV3A7PM.js");
|
|
3970
|
-
const prior = await loadFanoutSidecar(this.adapter, this.vault, spec.source, run.runId, key, this.getDEK, this.storeCiphertext);
|
|
3971
|
-
const prevKeys = new Set(prior?.keys ?? []);
|
|
3972
|
-
const newKeysList = out.entries.map((e) => e.key);
|
|
3973
|
-
const newKeysSet = new Set(newKeysList);
|
|
3974
|
-
for (const k of prevKeys) {
|
|
3975
|
-
if (newKeysSet.has(k)) continue;
|
|
3976
|
-
await outputCollection._internalDelete(k, txCtx);
|
|
3977
|
-
}
|
|
3978
|
-
for (const entry of out.entries) {
|
|
3979
|
-
if (txCtx !== null) {
|
|
3980
|
-
const priorEnvelope = await this.adapter.get(this.vault, outSpec.collection, entry.key);
|
|
3981
|
-
txCtx._executed.push({
|
|
3982
|
-
op: {
|
|
3983
|
-
type: "put",
|
|
3984
|
-
vaultName: this.vault,
|
|
3985
|
-
collectionName: outSpec.collection,
|
|
3986
|
-
id: entry.key
|
|
3987
|
-
},
|
|
3988
|
-
priorEnvelope
|
|
3989
|
-
});
|
|
3990
|
-
}
|
|
3991
|
-
await putDerivedOutput(outputCollection, entry.key, entry.value, outCtx, { source: "derived" });
|
|
3992
|
-
}
|
|
3993
|
-
await saveFanoutSidecar(this.adapter, this.vault, {
|
|
3994
|
-
source: spec.source,
|
|
3995
|
-
sourceId: run.runId,
|
|
3996
|
-
outputKey: key,
|
|
3997
|
-
outputCollection: outSpec.collection,
|
|
3998
|
-
keys: newKeysList
|
|
3999
|
-
}, this.getDEK, this.storeCiphertext);
|
|
4000
|
-
continue;
|
|
4001
|
-
}
|
|
4002
|
-
if (out.skipped === true) {
|
|
4003
|
-
await outputCollection._internalDelete(run.runId, txCtx);
|
|
4004
|
-
continue;
|
|
4005
|
-
}
|
|
4006
|
-
if (outSpec.shape === "record" && outSpec.denorm !== void 0 && outSpec.collection === spec.source) {
|
|
4007
|
-
const value = out.value;
|
|
4008
|
-
const patched = { ...run.base };
|
|
4009
|
-
let changed = false;
|
|
4010
|
-
for (const f of outSpec.denorm) {
|
|
4011
|
-
if (!selfWriteFieldEqual(run.base[f], value[f])) {
|
|
4012
|
-
patched[f] = value[f];
|
|
4013
|
-
changed = true;
|
|
4014
|
-
}
|
|
4015
|
-
}
|
|
4016
|
-
if (!changed) continue;
|
|
4017
|
-
if (txCtx !== null) {
|
|
4018
|
-
const prior = await this.adapter.get(this.vault, outSpec.collection, run.runId);
|
|
4019
|
-
txCtx._executed.push({
|
|
4020
|
-
op: { type: "put", vaultName: this.vault, collectionName: outSpec.collection, id: run.runId },
|
|
4021
|
-
priorEnvelope: prior
|
|
4022
|
-
});
|
|
4023
|
-
}
|
|
4024
|
-
await putDerivedOutput(outputCollection, run.runId, patched, outCtx, { source: "derived" });
|
|
4025
|
-
continue;
|
|
4026
|
-
}
|
|
4027
|
-
if (txCtx !== null) {
|
|
4028
|
-
const prior = await this.adapter.get(this.vault, outSpec.collection, run.runId);
|
|
4029
|
-
txCtx._executed.push({
|
|
4030
|
-
op: {
|
|
4031
|
-
type: "put",
|
|
4032
|
-
vaultName: this.vault,
|
|
4033
|
-
collectionName: outSpec.collection,
|
|
4034
|
-
id: run.runId
|
|
4035
|
-
},
|
|
4036
|
-
priorEnvelope: prior
|
|
4037
|
-
});
|
|
4038
|
-
}
|
|
4039
|
-
await putDerivedOutput(outputCollection, run.runId, out.value, outCtx, { source: "derived" });
|
|
4040
|
-
}
|
|
4041
|
-
}
|
|
4042
|
-
}
|
|
3958
|
+
const { dispatchDerivations } = await import("./dispatch-PKQQFDBT.js");
|
|
3959
|
+
return dispatchDerivations({
|
|
3960
|
+
...this.#derivationDeleteCtx(this.derivationSource),
|
|
3961
|
+
via: this.via,
|
|
3962
|
+
recomputeRollup: (spec, parentId, source, w) => this.recomputeRollup(spec, parentId, source, w),
|
|
3963
|
+
dispatchCtx: (source) => this.#dispatchCtx(source),
|
|
3964
|
+
trackPut: (txCtx, collectionName, rid, prior) => this.#trackPut(txCtx, collectionName, rid, prior)
|
|
3965
|
+
}, id, record, version, wave);
|
|
4043
3966
|
}
|
|
4044
3967
|
/**
|
|
4045
3968
|
* Delete a record by ID. Runs inside the hub's write-queue tracker
|
|
@@ -4208,10 +4131,10 @@ var Collection = class {
|
|
|
4208
4131
|
if (existing && this.historyConfig.enabled !== false) {
|
|
4209
4132
|
const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
|
|
4210
4133
|
const prevForVdig = this.vdigFields !== null ? await this.adapter.get(this.vault, this.name, id) : null;
|
|
4211
|
-
await this.
|
|
4134
|
+
await this.strategies.history.saveHistory(this.adapter, this.vault, this.name, id, await this.codec.encryptRecord(existing.record, existing.version, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: prevForVdig } : void 0, id));
|
|
4212
4135
|
}
|
|
4213
4136
|
const previousEnvelope = await this.adapter.get(this.vault, this.name, id);
|
|
4214
|
-
const previousPayloadHash = await this.
|
|
4137
|
+
const previousPayloadHash = await this.strategies.history.envelopePayloadHash(previousEnvelope);
|
|
4215
4138
|
let markerVersion;
|
|
4216
4139
|
if (this.onDirty) {
|
|
4217
4140
|
const live = previousEnvelope;
|
|
@@ -4309,33 +4232,8 @@ var Collection = class {
|
|
|
4309
4232
|
*/
|
|
4310
4233
|
async dispatchArrayDerivationsOnDelete(id, eraseRecordShapeToo = false) {
|
|
4311
4234
|
if (this.derivationSource === void 0) return 0;
|
|
4312
|
-
const
|
|
4313
|
-
|
|
4314
|
-
if (strategies.length === 0) return 0;
|
|
4315
|
-
let helpers = null;
|
|
4316
|
-
const txCtx = this.derivationSource.getActiveTxContext();
|
|
4317
|
-
let erased = 0;
|
|
4318
|
-
for (const { spec } of strategies) {
|
|
4319
|
-
for (const [outputKey, outSpec] of Object.entries(spec.outputs)) {
|
|
4320
|
-
if (outSpec.shape === "record") {
|
|
4321
|
-
if (eraseRecordShapeToo && spec.source === this.name && outSpec.collection !== this.name) {
|
|
4322
|
-
if (await this.derivationSource.getCollection(outSpec.collection)._internalDelete(id, txCtx)) erased += 1;
|
|
4323
|
-
}
|
|
4324
|
-
continue;
|
|
4325
|
-
}
|
|
4326
|
-
if (helpers === null) {
|
|
4327
|
-
helpers = await import("./fanout-sidecar-HJV3A7PM.js");
|
|
4328
|
-
}
|
|
4329
|
-
const sidecar = await helpers.loadFanoutSidecar(this.adapter, this.vault, spec.source, id, outputKey, this.getDEK, this.storeCiphertext);
|
|
4330
|
-
if (!sidecar) continue;
|
|
4331
|
-
const outputCollection = this.derivationSource.getCollection(outSpec.collection);
|
|
4332
|
-
for (const derivedId of sidecar.keys) {
|
|
4333
|
-
if (await outputCollection._internalDelete(derivedId, txCtx)) erased += 1;
|
|
4334
|
-
}
|
|
4335
|
-
await helpers.deleteFanoutSidecar(this.adapter, this.vault, spec.source, id, outputKey);
|
|
4336
|
-
}
|
|
4337
|
-
}
|
|
4338
|
-
return erased;
|
|
4235
|
+
const { dispatchArrayDerivationsOnDelete } = await import("./dispatch-PKQQFDBT.js");
|
|
4236
|
+
return dispatchArrayDerivationsOnDelete(this.#derivationDeleteCtx(this.derivationSource), id, eraseRecordShapeToo);
|
|
4339
4237
|
}
|
|
4340
4238
|
/**
|
|
4341
4239
|
* Mirror of {@link dispatchMaterializedViews} for the delete/forget path — no `_materializedFrom`
|
|
@@ -4348,41 +4246,8 @@ var Collection = class {
|
|
|
4348
4246
|
*/
|
|
4349
4247
|
async dispatchMaterializedViewsOnDelete(id) {
|
|
4350
4248
|
if (this.materializedViewSource === void 0) return { deleted: 0, residueUndecodable: [], residueDeclined: [] };
|
|
4351
|
-
const
|
|
4352
|
-
|
|
4353
|
-
if (mvs.length === 0) return { deleted: 0, residueUndecodable: [], residueDeclined: [] };
|
|
4354
|
-
let executor = null;
|
|
4355
|
-
let staleHelpers = null;
|
|
4356
|
-
let deleted = 0;
|
|
4357
|
-
const residueUndecodable = [];
|
|
4358
|
-
const residueDeclined = [];
|
|
4359
|
-
for (const reg of mvs) {
|
|
4360
|
-
const mode = reg.spec.refresh;
|
|
4361
|
-
if (mode === "eager") {
|
|
4362
|
-
if (executor === null) {
|
|
4363
|
-
;
|
|
4364
|
-
({ MaterializedViewExecutor: executor } = await import("./executor-YORMIBWV.js"));
|
|
4365
|
-
}
|
|
4366
|
-
const rr = await executor.refresh(reg, {
|
|
4367
|
-
getCollection: (name) => this.materializedViewSource.getCollection(name),
|
|
4368
|
-
getActiveTxContext: () => this.materializedViewSource.getActiveTxContext(),
|
|
4369
|
-
getQueryContext: () => this.materializedViewSource.getQueryContext(),
|
|
4370
|
-
dispatchCtx: this.#dispatchCtx({ collection: this.name, id })
|
|
4371
|
-
});
|
|
4372
|
-
deleted += rr.deleted;
|
|
4373
|
-
residueUndecodable.push(...rr.residueUndecodable);
|
|
4374
|
-
residueDeclined.push(...rr.residueDeclined);
|
|
4375
|
-
} else {
|
|
4376
|
-
if (staleHelpers === null) {
|
|
4377
|
-
staleHelpers = await import("./stale-4UNPHWOU.js");
|
|
4378
|
-
}
|
|
4379
|
-
const inv = await staleHelpers.invalidateMVAtRest(this.materializedViewSource, reg, mode);
|
|
4380
|
-
deleted += inv.deleted;
|
|
4381
|
-
residueUndecodable.push(...inv.residueUndecodable.map((rid) => `${reg.outputCollection}:${rid}`));
|
|
4382
|
-
residueDeclined.push(...inv.residueDeclined.map((rid) => `${reg.outputCollection}:${rid}`));
|
|
4383
|
-
}
|
|
4384
|
-
}
|
|
4385
|
-
return { deleted, residueUndecodable, residueDeclined };
|
|
4249
|
+
const { dispatchMaterializedViewsOnDelete } = await import("./dispatch-SMXUO7W5.js");
|
|
4250
|
+
return dispatchMaterializedViewsOnDelete(this.#mvDispatchCtx(this.materializedViewSource), id);
|
|
4386
4251
|
}
|
|
4387
4252
|
/**
|
|
4388
4253
|
* List all records in the collection.
|
|
@@ -4401,7 +4266,7 @@ var Collection = class {
|
|
|
4401
4266
|
);
|
|
4402
4267
|
}
|
|
4403
4268
|
if (this.materializedViewSource !== void 0) {
|
|
4404
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
4269
|
+
const { resolveStaleMVOnRead } = await import("./stale-NBROTA66.js");
|
|
4405
4270
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: "resolve-on-read" }));
|
|
4406
4271
|
}
|
|
4407
4272
|
await this.ensureHydrated();
|
|
@@ -4422,28 +4287,28 @@ var Collection = class {
|
|
|
4422
4287
|
* see `src/search/tokenize.ts` for the Thai/CJK caveat.
|
|
4423
4288
|
*/
|
|
4424
4289
|
search(field, query, opts = {}) {
|
|
4425
|
-
return this.
|
|
4290
|
+
return this.strategies.search.search(this.searchContext(), field, query, opts);
|
|
4426
4291
|
}
|
|
4427
4292
|
/** Force-persist the lexical index now — gated behind `searchStrategy: withSearch()`. */
|
|
4428
4293
|
flushIndex() {
|
|
4429
|
-
return this.
|
|
4294
|
+
return this.strategies.search.flushIndex(this.searchContext());
|
|
4430
4295
|
}
|
|
4431
4296
|
/** Pre-build the lexical index — gated behind `searchStrategy: withSearch()`. */
|
|
4432
4297
|
warmIndex() {
|
|
4433
|
-
return this.
|
|
4298
|
+
return this.strategies.search.warmIndex(this.searchContext());
|
|
4434
4299
|
}
|
|
4435
4300
|
/** Retrieval (lexical | semantic | hybrid) — gated behind `searchStrategy: withSearch()`. */
|
|
4436
4301
|
retrieve(query, opts = {}) {
|
|
4437
|
-
return this.
|
|
4302
|
+
return this.strategies.search.retrieve(this.searchContext(), query, opts);
|
|
4438
4303
|
}
|
|
4439
4304
|
/** Raw-vector kNN — gated behind `searchStrategy: withSearch()`. */
|
|
4440
4305
|
similarTo(vector, opts = {}) {
|
|
4441
|
-
return this.
|
|
4306
|
+
return this.strategies.search.similarTo(this.searchContext(), vector, opts);
|
|
4442
4307
|
}
|
|
4443
4308
|
/** Opt-in bulk `_vec` re-derive (#788) — a plain collection has nothing to rebuild; gated behind `searchStrategy: withSearch()` otherwise. */
|
|
4444
4309
|
rebuildEmbeddings() {
|
|
4445
4310
|
if (!this.embeddings) return Promise.resolve({ rebuilt: 0, skipped: 0 });
|
|
4446
|
-
return this.
|
|
4311
|
+
return this.strategies.search.rebuildEmbeddings(this.searchContext());
|
|
4447
4312
|
}
|
|
4448
4313
|
/**
|
|
4449
4314
|
* Bind the {@link SearchContext} the search/retrieval surface needs. The
|
|
@@ -4653,7 +4518,7 @@ var Collection = class {
|
|
|
4653
4518
|
...this.defaultLocale !== void 0 ? { defaultLocale: this.defaultLocale } : {},
|
|
4654
4519
|
...resolver.resolveDictSource ? { resolveDictSource: (field) => resolver.resolveDictSource(leftCollection, field) } : {}
|
|
4655
4520
|
} : void 0;
|
|
4656
|
-
return new Query(source, void 0, joinContext, this.
|
|
4521
|
+
return new Query(source, void 0, joinContext, this.strategies.aggregate);
|
|
4657
4522
|
}
|
|
4658
4523
|
/**
|
|
4659
4524
|
* Subscribe to every put/delete on this collection. Returns an
|
|
@@ -4767,7 +4632,7 @@ var Collection = class {
|
|
|
4767
4632
|
// ─── History Methods ────────────────────────────────────────────
|
|
4768
4633
|
/** Get version history for a record, newest first. */
|
|
4769
4634
|
async history(id, options) {
|
|
4770
|
-
const envelopes = await this.
|
|
4635
|
+
const envelopes = await this.strategies.history.getHistoryEntries(
|
|
4771
4636
|
this.adapter,
|
|
4772
4637
|
this.vault,
|
|
4773
4638
|
this.name,
|
|
@@ -4799,7 +4664,7 @@ var Collection = class {
|
|
|
4799
4664
|
* and re-put the records through the normal `put()` path.
|
|
4800
4665
|
*/
|
|
4801
4666
|
async getVersion(id, version) {
|
|
4802
|
-
const envelope = await this.
|
|
4667
|
+
const envelope = await this.strategies.history.getVersionEnvelope(
|
|
4803
4668
|
this.adapter,
|
|
4804
4669
|
this.vault,
|
|
4805
4670
|
this.name,
|
|
@@ -4824,7 +4689,7 @@ var Collection = class {
|
|
|
4824
4689
|
*/
|
|
4825
4690
|
async diff(id, versionA, versionB) {
|
|
4826
4691
|
const recordA = versionA === 0 ? null : await this.resolveVersion(id, versionA);
|
|
4827
|
-
return this.
|
|
4692
|
+
return this.strategies.history.diff(recordA, versionB === void 0 || versionB === 0 ? versionB === 0 ? null : await this.resolveCurrentOrVersion(id) : await this.resolveVersion(id, versionB));
|
|
4828
4693
|
}
|
|
4829
4694
|
/** Resolve a version: try history first, then check if it's the current version. */
|
|
4830
4695
|
async resolveVersion(id, version) {
|
|
@@ -4841,7 +4706,7 @@ var Collection = class {
|
|
|
4841
4706
|
}
|
|
4842
4707
|
/** Prune history entries for a record (or all records if id is undefined). */
|
|
4843
4708
|
async pruneRecordHistory(id, options) {
|
|
4844
|
-
const pruned = await this.
|
|
4709
|
+
const pruned = await this.strategies.history.pruneHistory(
|
|
4845
4710
|
this.adapter,
|
|
4846
4711
|
this.vault,
|
|
4847
4712
|
this.name,
|
|
@@ -4860,7 +4725,7 @@ var Collection = class {
|
|
|
4860
4725
|
}
|
|
4861
4726
|
/** Clear all history for this collection (or a specific record). */
|
|
4862
4727
|
async clearHistory(id) {
|
|
4863
|
-
return this.
|
|
4728
|
+
return this.strategies.history.clearHistory(this.adapter, this.vault, this.name, id);
|
|
4864
4729
|
}
|
|
4865
4730
|
// ─── Core Methods ─────────────────────────────────────────────
|
|
4866
4731
|
/**
|
|
@@ -5282,7 +5147,7 @@ var Collection = class {
|
|
|
5282
5147
|
* vault-shared `_blob` DEK (enabling cross-collection deduplication).
|
|
5283
5148
|
*/
|
|
5284
5149
|
blob(id) {
|
|
5285
|
-
return this.
|
|
5150
|
+
return this.strategies.blob.openSlot({
|
|
5286
5151
|
store: this.adapter,
|
|
5287
5152
|
vault: this.vault,
|
|
5288
5153
|
collection: this.name,
|
|
@@ -5554,14 +5419,14 @@ var Collection = class {
|
|
|
5554
5419
|
/** C-A/R10: persist the classified marker once per classified handle (store I/O in config-drift.ts). */
|
|
5555
5420
|
async _ensureClassifiedMarker() {
|
|
5556
5421
|
if (this._markerPersisted || this.vdigFields === null) return;
|
|
5557
|
-
const { persistClassifiedMarkerForFields } = await import("./classified-marker-
|
|
5422
|
+
const { persistClassifiedMarkerForFields } = await import("./classified-marker-52P3D72W.js");
|
|
5558
5423
|
await persistClassifiedMarkerForFields(this.adapter, this.vault, this.name, this.vdigFields, await this.getDEK(this.name));
|
|
5559
5424
|
this._markerPersisted = true;
|
|
5560
5425
|
}
|
|
5561
5426
|
/** C-A/R10 drift signal — the marker's declared digest-only set, memoized to one store read per handle (see config-drift.ts). */
|
|
5562
5427
|
async _classifiedMarkerDigestOnly() {
|
|
5563
5428
|
if (this._markerDigestOnlyCache !== void 0) return this._markerDigestOnlyCache;
|
|
5564
|
-
const { readClassifiedMarkerDigestOnly } = await import("./classified-marker-
|
|
5429
|
+
const { readClassifiedMarkerDigestOnly } = await import("./classified-marker-52P3D72W.js");
|
|
5565
5430
|
this._markerDigestOnlyCache = await readClassifiedMarkerDigestOnly(this.adapter, this.vault, this.name, await this.getDEK(this.name));
|
|
5566
5431
|
return this._markerDigestOnlyCache;
|
|
5567
5432
|
}
|
|
@@ -5603,23 +5468,23 @@ var Collection = class {
|
|
|
5603
5468
|
// ─── Hierarchical Access ──────────────────────────
|
|
5604
5469
|
/** tier-aware put — gated behind `tiersStrategy: withTiers()`. `searchResidue: true` = stuck search compensation (#774, mirroring #764's elevate/demote posture); the write itself always completes. */
|
|
5605
5470
|
putAtTier(id, record, tier, opts) {
|
|
5606
|
-
return this.
|
|
5471
|
+
return this.strategies.tiers.putAtTier(this.tiersContext(), id, record, tier, opts);
|
|
5607
5472
|
}
|
|
5608
5473
|
/** tier-aware get — gated behind `tiersStrategy: withTiers()`. */
|
|
5609
5474
|
getAtTier(id) {
|
|
5610
|
-
return this.
|
|
5475
|
+
return this.strategies.tiers.getAtTier(this.tiersContext(), id);
|
|
5611
5476
|
}
|
|
5612
5477
|
/** list ids grouped by the caller's readability — gated behind `withTiers()`. */
|
|
5613
5478
|
listAtTier() {
|
|
5614
|
-
return this.
|
|
5479
|
+
return this.strategies.tiers.listAtTier(this.tiersContext());
|
|
5615
5480
|
}
|
|
5616
5481
|
/** elevate a record to a higher tier — gated behind `withTiers()`. `searchResidue: true` = stuck search compensation (#764); the move itself always completes. */
|
|
5617
5482
|
elevate(id, toTier) {
|
|
5618
|
-
return this.
|
|
5483
|
+
return this.strategies.tiers.elevate(this.tiersContext(), id, toTier);
|
|
5619
5484
|
}
|
|
5620
5485
|
/** demote a record to a lower tier — gated behind `withTiers()`. Same `searchResidue` posture as {@link elevate} (#764). */
|
|
5621
5486
|
demote(id, toTier) {
|
|
5622
|
-
return this.
|
|
5487
|
+
return this.strategies.tiers.demote(this.tiersContext(), id, toTier);
|
|
5623
5488
|
}
|
|
5624
5489
|
/**
|
|
5625
5490
|
* Emit a cross-tier access event. The subscriber sink stays collection-resident (it captures `onCrossTierAccess`); the tiers module reaches it via the {@link TiersContext.emitCrossTierEvent} callback.
|
|
@@ -5680,16 +5545,16 @@ var Collection = class {
|
|
|
5680
5545
|
},
|
|
5681
5546
|
syncIndexes: (id, rec, version, priorEnvelope) => syncTierIndexes(this.indexingContext(), id, rec, version, priorEnvelope),
|
|
5682
5547
|
syncSearch: (id, rec, version) => syncTierSearch(this.searchContext(), id, rec, version),
|
|
5683
|
-
syncHistory: async (id, fromDek, toDek) => this.
|
|
5548
|
+
syncHistory: async (id, fromDek, toDek) => this.strategies.history.rewrapHistory(this.adapter, this.vault, this.name, id, fromDek, toDek, await this.getDEK(this.name)),
|
|
5684
5549
|
saveHistorySnapshot: async (id, envelope) => {
|
|
5685
5550
|
if (this.historyConfig.enabled === false) return;
|
|
5686
|
-
await this.
|
|
5551
|
+
await this.strategies.history.saveHistory(this.adapter, this.vault, this.name, id, envelope);
|
|
5687
5552
|
this.emitter.emit("history:save", { vault: this.vault, collection: this.name, id, version: envelope._v });
|
|
5688
|
-
if (this.historyConfig.maxVersions) await this.
|
|
5553
|
+
if (this.historyConfig.maxVersions) await this.strategies.history.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions });
|
|
5689
5554
|
},
|
|
5690
|
-
historyEnabled: this.historyConfig.enabled !== false && this.
|
|
5555
|
+
historyEnabled: this.historyConfig.enabled !== false && this.strategies.history !== NO_HISTORY,
|
|
5691
5556
|
// #728/#737: lets putAtTier skip decrypting `existing` when no real history strategy is wired
|
|
5692
|
-
syncBlobs: (id, fromTier, toTier) => this.
|
|
5557
|
+
syncBlobs: (id, fromTier, toTier) => this.strategies.blob !== NO_BLOBS ? this.blob(id).syncTierMove(fromTier, toTier, this.blobTierPolicy) : Promise.resolve(),
|
|
5693
5558
|
// #724 I1: gate on blob storage enabled (not on declared blobFields) so undeclared-field blobs still rehome; #746: syncTierMove mints/resumes the rehome journal marker; self-no-ops on an empty slot map
|
|
5694
5559
|
syncLedger: async (id) => {
|
|
5695
5560
|
await this.ledger?.purgeRecordDeltas(this.name, id);
|
|
@@ -6017,46 +5882,6 @@ var DeferredNumberingStore = class {
|
|
|
6017
5882
|
}
|
|
6018
5883
|
};
|
|
6019
5884
|
|
|
6020
|
-
// src/with-fork/shadow/strategy.ts
|
|
6021
|
-
var NOT_ENABLED2 = new Error(
|
|
6022
|
-
'VaultFrame requires the shadow strategy. Import `{ withShadow }` from "@noy-db/hub/shadow" and pass it to `createNoydb({ shadowStrategy: withShadow() })`.'
|
|
6023
|
-
);
|
|
6024
|
-
var NO_SHADOW = {
|
|
6025
|
-
buildFrame() {
|
|
6026
|
-
throw NOT_ENABLED2;
|
|
6027
|
-
}
|
|
6028
|
-
};
|
|
6029
|
-
|
|
6030
|
-
// src/with-audit/consent/strategy.ts
|
|
6031
|
-
var NO_CONSENT = {
|
|
6032
|
-
async write() {
|
|
6033
|
-
},
|
|
6034
|
-
async read() {
|
|
6035
|
-
return [];
|
|
6036
|
-
}
|
|
6037
|
-
};
|
|
6038
|
-
|
|
6039
|
-
// src/with-audit/periods/strategy.ts
|
|
6040
|
-
var NOT_ENABLED3 = new Error(
|
|
6041
|
-
'Accounting periods require the periods strategy. Import `{ withPeriods }` from "@noy-db/hub/periods" and pass it to `createNoydb({ periodsStrategy: withPeriods() })`.'
|
|
6042
|
-
);
|
|
6043
|
-
var NO_PERIODS = {
|
|
6044
|
-
async loadPeriods() {
|
|
6045
|
-
return [];
|
|
6046
|
-
},
|
|
6047
|
-
async chainAnchor() {
|
|
6048
|
-
return { priorPeriodHash: "" };
|
|
6049
|
-
},
|
|
6050
|
-
assertTsWritable() {
|
|
6051
|
-
},
|
|
6052
|
-
validatePeriodName() {
|
|
6053
|
-
throw NOT_ENABLED3;
|
|
6054
|
-
},
|
|
6055
|
-
async appendPeriodLedgerEntry() {
|
|
6056
|
-
throw NOT_ENABLED3;
|
|
6057
|
-
}
|
|
6058
|
-
};
|
|
6059
|
-
|
|
6060
5885
|
// src/with-audit/periods/vault-facade.ts
|
|
6061
5886
|
var VaultPeriods = class {
|
|
6062
5887
|
constructor(deps) {
|
|
@@ -6986,7 +6811,7 @@ var VaultLinks = class {
|
|
|
6986
6811
|
// src/with-shape/links/lazy-handle.ts
|
|
6987
6812
|
function makeLazyLinkSetHandle(d) {
|
|
6988
6813
|
let engine = null;
|
|
6989
|
-
const load = () => engine ??= import("./link-set-
|
|
6814
|
+
const load = () => engine ??= import("./link-set-ZU4E5J5S.js").then(
|
|
6990
6815
|
({ LinkSet }) => new LinkSet(d.adapter, d.vault, d.name, d.spec, d.encrypted, d.getDEK, d.actor, d.emitter, d.endpointExists)
|
|
6991
6816
|
);
|
|
6992
6817
|
return {
|
|
@@ -7524,7 +7349,7 @@ function declareSatellite(ctx, collectionName, options, existingRegistry) {
|
|
|
7524
7349
|
ctx.forEachSyncEngine((e) => e.remirrorPairResolvers([spec.base, spec.satellite]));
|
|
7525
7350
|
const registry = reg;
|
|
7526
7351
|
const baseSchema = ctx.getBaseSchema(spec.base);
|
|
7527
|
-
void import("./post-register-
|
|
7352
|
+
void import("./post-register-XIAHB6KF.js").then((m) => m.postRegister(ctx.adapter, ctx.vaultName, spec, ctx.getDEK, baseSchema, registry)).catch(() => {
|
|
7528
7353
|
});
|
|
7529
7354
|
return reg;
|
|
7530
7355
|
}
|
|
@@ -8041,6 +7866,43 @@ var VaultAttestation = class {
|
|
|
8041
7866
|
};
|
|
8042
7867
|
|
|
8043
7868
|
// src/kernel/vault.ts
|
|
7869
|
+
var COLLECTION_PASSTHROUGH_KEYS = [
|
|
7870
|
+
"indexes",
|
|
7871
|
+
"reconcileOnOpen",
|
|
7872
|
+
"prefetch",
|
|
7873
|
+
"cache",
|
|
7874
|
+
"schema",
|
|
7875
|
+
"conflictPolicy",
|
|
7876
|
+
"crdt",
|
|
7877
|
+
"deterministicFields",
|
|
7878
|
+
"acknowledgeDeterministicRisk",
|
|
7879
|
+
"acknowledgeEquatableRisk",
|
|
7880
|
+
"sensitive",
|
|
7881
|
+
"perRecordKeys",
|
|
7882
|
+
"provenance",
|
|
7883
|
+
"ramCiphertext",
|
|
7884
|
+
"tiers",
|
|
7885
|
+
"tierMode",
|
|
7886
|
+
"blobTierPolicy",
|
|
7887
|
+
"i18nFields",
|
|
7888
|
+
"embeddings",
|
|
7889
|
+
"textIndexes",
|
|
7890
|
+
"warmIndexOnOpen",
|
|
7891
|
+
"textIndexPersist",
|
|
7892
|
+
"moneyFields",
|
|
7893
|
+
"viaFields",
|
|
7894
|
+
"computed",
|
|
7895
|
+
"classifiedFields",
|
|
7896
|
+
"fieldMeta",
|
|
7897
|
+
"meta"
|
|
7898
|
+
];
|
|
7899
|
+
function copyDefined(dst, src, keys) {
|
|
7900
|
+
if (src === void 0) return;
|
|
7901
|
+
for (const key of keys) {
|
|
7902
|
+
const value = src[key];
|
|
7903
|
+
if (value !== void 0) dst[key] = value;
|
|
7904
|
+
}
|
|
7905
|
+
}
|
|
8044
7906
|
var Vault = class {
|
|
8045
7907
|
adapter;
|
|
8046
7908
|
/** The vault's name as passed to `openVault()`. Stable for the instance lifetime. */
|
|
@@ -8058,36 +7920,22 @@ var Vault = class {
|
|
|
8058
7920
|
syncAdapter;
|
|
8059
7921
|
getPurgeableTargets;
|
|
8060
7922
|
historyConfig;
|
|
8061
|
-
/**
|
|
8062
|
-
*
|
|
8063
|
-
|
|
7923
|
+
/**
|
|
7924
|
+
* Every opt-in service, resolved once by `createNoydb` (#838). Shared by
|
|
7925
|
+
* reference with the owning `Noydb` and with every `Collection` this vault
|
|
7926
|
+
* opens, so all three always agree about which services are enabled.
|
|
7927
|
+
*/
|
|
7928
|
+
strategies;
|
|
8064
7929
|
objectStore;
|
|
8065
|
-
/** Cold-storage archival strategy (the archive target store). */
|
|
8066
|
-
archiveStrategy;
|
|
8067
7930
|
/** Per-collection record archival policies. Indexed by collection name. */
|
|
8068
7931
|
archiveRegistry = /* @__PURE__ */ new Map();
|
|
8069
|
-
indexStrategy;
|
|
8070
|
-
lazyStrategy;
|
|
8071
|
-
aggregateStrategy;
|
|
8072
|
-
crdtStrategy;
|
|
8073
|
-
tiersStrategy;
|
|
8074
|
-
searchStrategy;
|
|
8075
|
-
/** Cargo (partition extraction) strategy — `NO_CARGO` (throwing) unless `withCargo()` was passed.
|
|
8076
|
-
* Public so the `extractPartition` free function (which takes a `Vault`) routes through it. */
|
|
8077
|
-
cargoStrategy;
|
|
8078
|
-
brokerStrategy;
|
|
8079
|
-
sealedRecordStrategy;
|
|
8080
|
-
portabilityStrategy;
|
|
8081
|
-
sequenceStrategy;
|
|
8082
|
-
consentStrategy;
|
|
8083
7932
|
periods;
|
|
8084
7933
|
linksEnforcer;
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
classifiedStrategy;
|
|
7934
|
+
/** Cargo (partition extraction) strategy — `NO_CARGO` (throwing) unless `withCargo()` was passed.
|
|
7935
|
+
* Public so the `extractPartition` free function (which takes a `Vault`) routes through it. */
|
|
7936
|
+
get cargoStrategy() {
|
|
7937
|
+
return this.strategies.cargo;
|
|
7938
|
+
}
|
|
8091
7939
|
/** Per-vault guard registry; `null` until `_initGuards()` runs (or for vaults that never register
|
|
8092
7940
|
* one) — the runtime class is dynamic-imported on demand to keep it out of the floor bundle. */
|
|
8093
7941
|
guardRegistry = null;
|
|
@@ -8136,7 +7984,7 @@ var Vault = class {
|
|
|
8136
7984
|
* @see docs/superpowers/specs/2026-06-17-fr6-deed-custodian-liberate-design.md
|
|
8137
7985
|
*/
|
|
8138
7986
|
custody;
|
|
8139
|
-
/** Re-derives an UnlockedKeyring from the adapter using the active user's
|
|
7987
|
+
/** Re-derives an UnlockedKeyring from the adapter using the active user's secret; called by
|
|
8140
7988
|
* `load()` after the on-disk keyring file has been replaced. Provided by Noydb at openVault()
|
|
8141
7989
|
* time; `undefined` in tests that construct Vault directly (load() then skips the refresh). */
|
|
8142
7990
|
reloadKeyring;
|
|
@@ -8269,23 +8117,10 @@ var Vault = class {
|
|
|
8269
8117
|
this.onRegisterConflictResolver = opts.onRegisterConflictResolver;
|
|
8270
8118
|
this.syncAdapter = opts.syncAdapter;
|
|
8271
8119
|
this.getPurgeableTargets = opts.getPurgeableTargets ?? (() => []);
|
|
8272
|
-
this.
|
|
8120
|
+
this.strategies = opts.strategies;
|
|
8273
8121
|
this.objectStore = opts.objectStore;
|
|
8274
|
-
this.archiveStrategy = opts.archiveStrategy;
|
|
8275
|
-
this.indexStrategy = opts.indexStrategy;
|
|
8276
|
-
this.lazyStrategy = opts.lazyStrategy;
|
|
8277
|
-
this.aggregateStrategy = opts.aggregateStrategy;
|
|
8278
|
-
this.crdtStrategy = opts.crdtStrategy;
|
|
8279
|
-
this.tiersStrategy = opts.tiersStrategy;
|
|
8280
|
-
this.searchStrategy = opts.searchStrategy;
|
|
8281
|
-
this.cargoStrategy = opts.cargoStrategy ?? NO_CARGO;
|
|
8282
|
-
this.brokerStrategy = opts.brokerStrategy ?? NO_BROKER;
|
|
8283
|
-
this.sealedRecordStrategy = opts.sealedRecordStrategy ?? NO_SEALED_RECORD;
|
|
8284
|
-
this.portabilityStrategy = opts.portabilityStrategy ?? NO_PORTABILITY;
|
|
8285
|
-
this.sequenceStrategy = opts.sequenceStrategy ?? NO_SEQUENCE;
|
|
8286
|
-
this.consentStrategy = opts.consentStrategy ?? NO_CONSENT;
|
|
8287
8122
|
this.periods = new VaultPeriods({
|
|
8288
|
-
strategy:
|
|
8123
|
+
strategy: this.strategies.periods,
|
|
8289
8124
|
adapter: this.adapter,
|
|
8290
8125
|
vault: this.name,
|
|
8291
8126
|
encrypted: this.encrypted,
|
|
@@ -8310,12 +8145,6 @@ var Vault = class {
|
|
|
8310
8145
|
getActiveTxContext: () => this.noydb._activeTxContextOrNull,
|
|
8311
8146
|
emitter: this.emitter
|
|
8312
8147
|
});
|
|
8313
|
-
this.shadowStrategy = opts.shadowStrategy ?? NO_SHADOW;
|
|
8314
|
-
this.historyStrategy = opts.historyStrategy ?? NO_HISTORY;
|
|
8315
|
-
this.forgetStrategy = opts.forgetStrategy ?? NO_FORGET;
|
|
8316
|
-
this.i18nStrategy = opts.i18nStrategy ?? NO_I18N;
|
|
8317
|
-
this.syncStrategy = opts.syncStrategy ?? NO_SYNC;
|
|
8318
|
-
this.classifiedStrategy = opts.classifiedStrategy ?? NO_CLASSIFIED;
|
|
8319
8148
|
this.graph = new ViaGraph();
|
|
8320
8149
|
void opts.guardStrategies;
|
|
8321
8150
|
this.historyConfig = opts.historyConfig ?? { enabled: true };
|
|
@@ -8330,19 +8159,19 @@ var Vault = class {
|
|
|
8330
8159
|
getDEK: (collection) => this.getDEK(collection),
|
|
8331
8160
|
role: () => this.keyring.role,
|
|
8332
8161
|
getRawRecord: async (collection, recId) => await this.collection(collection).get(recId, { locale: "raw" })
|
|
8333
|
-
},
|
|
8162
|
+
}, this.strategies.attestation);
|
|
8334
8163
|
this.user = this.noydb.userApiFactory({
|
|
8335
8164
|
adapter: this.adapter,
|
|
8336
8165
|
vaultName: this.name,
|
|
8337
8166
|
writerKeyringId: this.keyring.userId,
|
|
8338
8167
|
getDek: () => this.getDEK(USER_ENVELOPE_COLLECTION),
|
|
8339
8168
|
checkGate: (gate, presented) => this.noydb.checkGate(this.name, gate, presented),
|
|
8340
|
-
exportAccessible: (opts2) => this.
|
|
8341
|
-
unilateralWithdraw: (opts2) => this.
|
|
8342
|
-
requestWithdraw: (opts2) => this.
|
|
8343
|
-
listWithdrawals: (opts2) => this.
|
|
8344
|
-
approveWithdraw: (requestId, opts2) => this.
|
|
8345
|
-
rejectWithdraw: (requestId, opts2) => this.
|
|
8169
|
+
exportAccessible: (opts2) => this.strategies.portability.exportAccessibleData(this, opts2),
|
|
8170
|
+
unilateralWithdraw: (opts2) => this.strategies.portability.withdrawAccessibleData(this, opts2),
|
|
8171
|
+
requestWithdraw: (opts2) => this.strategies.portability.requestWithdrawal(this, opts2),
|
|
8172
|
+
listWithdrawals: (opts2) => this.strategies.portability.listWithdrawalRequests(this, opts2),
|
|
8173
|
+
approveWithdraw: (requestId, opts2) => this.strategies.portability.approveWithdrawal(this, requestId, opts2),
|
|
8174
|
+
rejectWithdraw: (requestId, opts2) => this.strategies.portability.rejectWithdrawal(this, requestId, opts2)
|
|
8346
8175
|
});
|
|
8347
8176
|
this.custody = new CustodyApi(
|
|
8348
8177
|
(options, factors) => this.noydb.grantCustodian(this.name, options, factors),
|
|
@@ -8400,7 +8229,7 @@ var Vault = class {
|
|
|
8400
8229
|
* dispatch reads/writes — from this vault's OWN privates, rather than passing `this` itself. */
|
|
8401
8230
|
_viaReconcileCtx() {
|
|
8402
8231
|
return {
|
|
8403
|
-
i18nStrategy: this.
|
|
8232
|
+
i18nStrategy: this.strategies.i18n,
|
|
8404
8233
|
locale: this.locale,
|
|
8405
8234
|
translateText: this.translateText,
|
|
8406
8235
|
i18nFieldRegistry: this.i18nFieldRegistry,
|
|
@@ -8441,7 +8270,7 @@ var Vault = class {
|
|
|
8441
8270
|
this.satelliteRegistry = declareSatellite({
|
|
8442
8271
|
adapter: this.adapter,
|
|
8443
8272
|
vaultName: this.name,
|
|
8444
|
-
forgetSubjects: this.
|
|
8273
|
+
forgetSubjects: this.strategies.forget.subjects,
|
|
8445
8274
|
getDEK: this.getDEK,
|
|
8446
8275
|
getBaseSchema: (base) => this.collectionCache.get(base)?.getSchema(),
|
|
8447
8276
|
getBaseCrdt: (base) => this.collectionCache.get(base)?.getConfig()?.crdt,
|
|
@@ -8520,7 +8349,7 @@ var Vault = class {
|
|
|
8520
8349
|
const strategies = options.schemaUpdate ?? [];
|
|
8521
8350
|
const work = (async () => {
|
|
8522
8351
|
const dek = await this.getDEK(collectionName);
|
|
8523
|
-
const { persistSchemaIfNeeded } = await import("./register-
|
|
8352
|
+
const { persistSchemaIfNeeded } = await import("./register-HB4TQZSV.js");
|
|
8524
8353
|
const result = await persistSchemaIfNeeded({
|
|
8525
8354
|
store: this.adapter,
|
|
8526
8355
|
vault: this.name,
|
|
@@ -8561,22 +8390,9 @@ var Vault = class {
|
|
|
8561
8390
|
// #693: re-create gate fallback
|
|
8562
8391
|
historyConfig: effectiveHistoryConfig,
|
|
8563
8392
|
historyConfigExplicit: options?.historyConfig !== void 0,
|
|
8564
|
-
// thread the vault-wide blob strategy into every
|
|
8565
|
-
// collection. `undefined` is intentionally preserved so the
|
|
8566
|
-
// Collection constructor uses its NO_BLOBS default.
|
|
8567
|
-
...this.blobStrategy !== void 0 ? { blobStrategy: this.blobStrategy } : {},
|
|
8568
8393
|
...this.objectStore !== void 0 ? { objectStore: this.objectStore } : {},
|
|
8569
8394
|
...options?.blobFields !== void 0 ? { blobFields: options.blobFields } : {},
|
|
8570
|
-
|
|
8571
|
-
...this.lazyStrategy !== void 0 ? { lazyStrategy: this.lazyStrategy } : {},
|
|
8572
|
-
...this.aggregateStrategy !== void 0 ? { aggregateStrategy: this.aggregateStrategy } : {},
|
|
8573
|
-
...this.crdtStrategy !== void 0 ? { crdtStrategy: this.crdtStrategy } : {},
|
|
8574
|
-
...this.tiersStrategy !== void 0 ? { tiersStrategy: this.tiersStrategy } : {},
|
|
8575
|
-
...this.searchStrategy !== void 0 ? { searchStrategy: this.searchStrategy } : {},
|
|
8576
|
-
historyStrategy: this.historyStrategy,
|
|
8577
|
-
i18nStrategy: this.i18nStrategy,
|
|
8578
|
-
syncStrategy: this.syncStrategy,
|
|
8579
|
-
classifiedStrategy: this.classifiedStrategy,
|
|
8395
|
+
strategies: this.strategies,
|
|
8580
8396
|
// Per-collection ledger opt-out: when this collection sets
|
|
8581
8397
|
// `historyConfig.ledger: false`, withhold the ledger reference so all
|
|
8582
8398
|
// four `if (this.ledger)` append sites in Collection no-op. The chain
|
|
@@ -8614,27 +8430,8 @@ var Vault = class {
|
|
|
8614
8430
|
}
|
|
8615
8431
|
} : {}
|
|
8616
8432
|
};
|
|
8617
|
-
|
|
8618
|
-
|
|
8619
|
-
if (options?.prefetch !== void 0) collOpts.prefetch = options.prefetch;
|
|
8620
|
-
if (options?.cache !== void 0) collOpts.cache = options.cache;
|
|
8621
|
-
if (options?.schema !== void 0) collOpts.schema = options.schema;
|
|
8622
|
-
if (options?.conflictPolicy !== void 0) collOpts.conflictPolicy = options.conflictPolicy;
|
|
8623
|
-
if (options?.crdt !== void 0) collOpts.crdt = options.crdt;
|
|
8624
|
-
if (options?.deterministicFields !== void 0) {
|
|
8625
|
-
collOpts.deterministicFields = options.deterministicFields;
|
|
8626
|
-
}
|
|
8627
|
-
if (options?.acknowledgeDeterministicRisk !== void 0) {
|
|
8628
|
-
collOpts.acknowledgeDeterministicRisk = options.acknowledgeDeterministicRisk;
|
|
8629
|
-
}
|
|
8630
|
-
if (options?.acknowledgeEquatableRisk !== void 0) {
|
|
8631
|
-
collOpts.acknowledgeEquatableRisk = options.acknowledgeEquatableRisk;
|
|
8632
|
-
}
|
|
8633
|
-
if (options?.sensitive !== void 0) {
|
|
8634
|
-
collOpts.sensitive = options.sensitive;
|
|
8635
|
-
}
|
|
8636
|
-
if (options?.perRecordKeys !== void 0) collOpts.perRecordKeys = options.perRecordKeys;
|
|
8637
|
-
const subjectKey = this.forgetStrategy.subjects[collectionName];
|
|
8433
|
+
copyDefined(collOpts, options, COLLECTION_PASSTHROUGH_KEYS);
|
|
8434
|
+
const subjectKey = this.strategies.forget.subjects[collectionName];
|
|
8638
8435
|
if (subjectKey !== void 0) {
|
|
8639
8436
|
if (options?.perRecordKeys === false) {
|
|
8640
8437
|
console.warn(
|
|
@@ -8648,22 +8445,8 @@ var Vault = class {
|
|
|
8648
8445
|
if (value !== void 0 && value !== null) await this._addSubjectRef(coerceSubjectId(value), { collection: collectionName, id });
|
|
8649
8446
|
};
|
|
8650
8447
|
}
|
|
8651
|
-
if (options?.provenance !== void 0) collOpts.provenance = options.provenance;
|
|
8652
|
-
if (options?.ramCiphertext !== void 0) collOpts.ramCiphertext = options.ramCiphertext;
|
|
8653
|
-
if (options?.tiers !== void 0) collOpts.tiers = options.tiers;
|
|
8654
|
-
if (options?.tierMode !== void 0) collOpts.tierMode = options.tierMode;
|
|
8655
|
-
if (options?.blobTierPolicy !== void 0) collOpts.blobTierPolicy = options.blobTierPolicy;
|
|
8656
8448
|
collOpts.onCrossTierAccess = (event) => this.emitCrossTier(event);
|
|
8657
8449
|
if (this.syncAdapter !== void 0) collOpts.syncAdapter = this.syncAdapter;
|
|
8658
|
-
if (options?.i18nFields !== void 0) collOpts.i18nFields = options.i18nFields;
|
|
8659
|
-
if (options?.embeddings !== void 0) collOpts.embeddings = options.embeddings;
|
|
8660
|
-
if (options?.textIndexes !== void 0) collOpts.textIndexes = options.textIndexes;
|
|
8661
|
-
if (options?.warmIndexOnOpen !== void 0) collOpts.warmIndexOnOpen = options.warmIndexOnOpen;
|
|
8662
|
-
if (options?.textIndexPersist !== void 0) collOpts.textIndexPersist = options.textIndexPersist;
|
|
8663
|
-
if (options?.moneyFields !== void 0) collOpts.moneyFields = options.moneyFields;
|
|
8664
|
-
if (options?.viaFields !== void 0) collOpts.viaFields = options.viaFields;
|
|
8665
|
-
if (options?.computed !== void 0) collOpts.computed = options.computed;
|
|
8666
|
-
if (options?.classifiedFields !== void 0) collOpts.classifiedFields = options.classifiedFields;
|
|
8667
8450
|
if (effectiveViaFields.dictKeyFields !== void 0 || effectiveViaFields.lookupFields !== void 0) {
|
|
8668
8451
|
collOpts.dictLabelResolver = async (dictName, key, locale, fallback) => {
|
|
8669
8452
|
const stat = this.staticByName.get(dictName);
|
|
@@ -8697,10 +8480,6 @@ var Vault = class {
|
|
|
8697
8480
|
if (effectiveViaFields.i18nFields !== void 0 && this.translateText) {
|
|
8698
8481
|
collOpts.autoTranslateHook = this.translateText;
|
|
8699
8482
|
}
|
|
8700
|
-
if (options?.fieldMeta !== void 0) {
|
|
8701
|
-
collOpts.fieldMeta = options.fieldMeta;
|
|
8702
|
-
}
|
|
8703
|
-
if (options?.meta !== void 0) collOpts.meta = options.meta;
|
|
8704
8483
|
if (options?.refs !== void 0) {
|
|
8705
8484
|
collOpts.declaredRefs = this.refRegistry.getOutbound(collectionName);
|
|
8706
8485
|
}
|
|
@@ -8719,7 +8498,7 @@ var Vault = class {
|
|
|
8719
8498
|
const work = (async () => {
|
|
8720
8499
|
try {
|
|
8721
8500
|
const dek = await this.getDEK(collectionName);
|
|
8722
|
-
await (await import("./register-
|
|
8501
|
+
await (await import("./register-HB4TQZSV.js")).persistSchemaIfNeeded({
|
|
8723
8502
|
store: this.adapter,
|
|
8724
8503
|
vault: this.name,
|
|
8725
8504
|
collectionName,
|
|
@@ -9015,7 +8794,7 @@ var Vault = class {
|
|
|
9015
8794
|
const values = getAtPath(obj, field);
|
|
9016
8795
|
for (const value of values) {
|
|
9017
8796
|
if (value === void 0 || value === null) continue;
|
|
9018
|
-
this.
|
|
8797
|
+
this.strategies.i18n.validateI18nTextValue(value, field, descriptor);
|
|
9019
8798
|
}
|
|
9020
8799
|
}
|
|
9021
8800
|
}
|
|
@@ -9056,7 +8835,7 @@ var Vault = class {
|
|
|
9056
8835
|
this.reservedLookupCollections.set(dictCollectionName(name), name);
|
|
9057
8836
|
let handle = this.dictionaryCache.get(name);
|
|
9058
8837
|
if (!handle) {
|
|
9059
|
-
handle = this.
|
|
8838
|
+
handle = this.strategies.i18n.buildDictionaryHandle({
|
|
9060
8839
|
adapter: this.adapter,
|
|
9061
8840
|
compartmentName: this.name,
|
|
9062
8841
|
dictionaryName: name,
|
|
@@ -9217,7 +8996,7 @@ var Vault = class {
|
|
|
9217
8996
|
* is re-keyed for distinct recipients.
|
|
9218
8997
|
*
|
|
9219
8998
|
* Each recipient becomes its own `KeyringFile` sealed with that
|
|
9220
|
-
* recipient's
|
|
8999
|
+
* recipient's secret. The DEKs wrapped into each slot are
|
|
9221
9000
|
* exactly those the recipient's role + permissions justify, and
|
|
9222
9001
|
* never wider than the source keyring's own DEK set
|
|
9223
9002
|
* (privilege-escalation check).
|
|
@@ -9269,7 +9048,7 @@ var Vault = class {
|
|
|
9269
9048
|
};
|
|
9270
9049
|
}
|
|
9271
9050
|
if (!this.sequenceStore) {
|
|
9272
|
-
this.sequenceStore = this.
|
|
9051
|
+
this.sequenceStore = this.strategies.sequence.createStore({
|
|
9273
9052
|
adapter: this.adapter,
|
|
9274
9053
|
vault: this.name,
|
|
9275
9054
|
encrypted: this.encrypted,
|
|
@@ -9367,7 +9146,7 @@ var Vault = class {
|
|
|
9367
9146
|
return runListArchived(this._archiveContext(), collection);
|
|
9368
9147
|
}
|
|
9369
9148
|
_archiveContext() {
|
|
9370
|
-
const strategy = this.
|
|
9149
|
+
const strategy = this.strategies.archive;
|
|
9371
9150
|
if (!strategy) {
|
|
9372
9151
|
throw new Error(
|
|
9373
9152
|
"vault.archive/restore/listArchived require `archiveStrategy: withArchive({ store })` in createNoydb"
|
|
@@ -9534,7 +9313,7 @@ var Vault = class {
|
|
|
9534
9313
|
*/
|
|
9535
9314
|
getLedgerOrNull() {
|
|
9536
9315
|
if (!this.ledgerStore) {
|
|
9537
|
-
this.ledgerStore = this.
|
|
9316
|
+
this.ledgerStore = this.strategies.history.buildLedger({
|
|
9538
9317
|
adapter: this.adapter,
|
|
9539
9318
|
vault: this.name,
|
|
9540
9319
|
encrypted: this.encrypted,
|
|
@@ -9559,7 +9338,7 @@ var Vault = class {
|
|
|
9559
9338
|
* number of distinct subjects re-indexed.
|
|
9560
9339
|
*/
|
|
9561
9340
|
async rebuildSubjectIndex() {
|
|
9562
|
-
if (Object.keys(this.
|
|
9341
|
+
if (Object.keys(this.strategies.forget.subjects).length === 0) {
|
|
9563
9342
|
throw new ForgetStrategyNotConfiguredError();
|
|
9564
9343
|
}
|
|
9565
9344
|
return rebuildSubjectIndex(
|
|
@@ -9567,7 +9346,7 @@ var Vault = class {
|
|
|
9567
9346
|
this.name,
|
|
9568
9347
|
this.getDEK,
|
|
9569
9348
|
this.encrypted,
|
|
9570
|
-
this.
|
|
9349
|
+
this.strategies.forget.subjects,
|
|
9571
9350
|
async (collectionName, id, env) => {
|
|
9572
9351
|
const coll = this.collection(collectionName);
|
|
9573
9352
|
return coll._decodeEnvelope(env, id);
|
|
@@ -9592,7 +9371,7 @@ var Vault = class {
|
|
|
9592
9371
|
* @throws ForgetStrategyNotConfiguredError when no `withForgetCascade` was set.
|
|
9593
9372
|
*/
|
|
9594
9373
|
async forget(subjectId) {
|
|
9595
|
-
if (Object.keys(this.
|
|
9374
|
+
if (Object.keys(this.strategies.forget.subjects).length === 0) {
|
|
9596
9375
|
throw new ForgetStrategyNotConfiguredError();
|
|
9597
9376
|
}
|
|
9598
9377
|
const ledger = this.getLedgerOrNull();
|
|
@@ -9614,17 +9393,17 @@ var Vault = class {
|
|
|
9614
9393
|
const sealedResidue = [];
|
|
9615
9394
|
const indexResidue = [];
|
|
9616
9395
|
const ledgerDeltaResidue = [];
|
|
9617
|
-
const blobsEnabled = this.
|
|
9396
|
+
const blobsEnabled = this.strategies.blob !== NO_BLOBS;
|
|
9618
9397
|
const actor = this.keyring.userId;
|
|
9619
9398
|
const fanoutStats = { recordsErased: 0, aggregatesRecomputed: 0, residueFrozen: [], lookupReferencesCascaded: 0, lookupReferencesNullified: 0, lookupReferencesResidue: [], derivedResidueUndecodable: [], derivedResidueDeclined: [] };
|
|
9620
9399
|
const { partitionSealedCekKeys, shouldSkipBlobScan, bumpResidueCount, residueNoticesFromMap } = await import("./purge-scope-FGNNLWHD.js");
|
|
9621
|
-
const scopedPurge = this.
|
|
9400
|
+
const scopedPurge = this.strategies.forget.scopedPurge === true;
|
|
9622
9401
|
const sealedCekScopedSkipped = /* @__PURE__ */ new Map();
|
|
9623
9402
|
const blobScopedSkipped = /* @__PURE__ */ new Map();
|
|
9624
9403
|
for (const ref2 of allRefs) {
|
|
9625
9404
|
const coll = this.collection(ref2.collection);
|
|
9626
9405
|
const satelliteOf = ref2.satelliteOf;
|
|
9627
|
-
const perRecordKeys = this.
|
|
9406
|
+
const perRecordKeys = this.strategies.forget.subjects[satelliteOf ?? ref2.collection] !== void 0;
|
|
9628
9407
|
const lookupCompareKeys = await this.linksEnforcer.checkLookupRefsRestrict(this.graph, ref2.collection, ref2.collection, ref2.id);
|
|
9629
9408
|
const live = await this.adapter.get(this.name, ref2.collection, ref2.id);
|
|
9630
9409
|
if (perRecordKeys && live && live._data && !hasPerRecordKey(live)) {
|
|
@@ -9684,7 +9463,7 @@ var Vault = class {
|
|
|
9684
9463
|
collections.add(ref2.collection);
|
|
9685
9464
|
await forgetDerivedFanout(this, { collection: ref2.collection, id: ref2.id }, live, fanoutStats, lookupCompareKeys);
|
|
9686
9465
|
}
|
|
9687
|
-
historyVersionsShredded += await this.
|
|
9466
|
+
historyVersionsShredded += await this.strategies.history.tombstoneHistory(
|
|
9688
9467
|
this.adapter,
|
|
9689
9468
|
this.name,
|
|
9690
9469
|
ref2.collection,
|
|
@@ -9814,7 +9593,7 @@ var Vault = class {
|
|
|
9814
9593
|
* `<collection>/<id>/<pid>` key the delivery envelope was written under.
|
|
9815
9594
|
*/
|
|
9816
9595
|
async sealRecordToHost(collection, id, hostSealer, opts) {
|
|
9817
|
-
return this.
|
|
9596
|
+
return this.strategies.sealedRecord.sealRecordToHost(this._sealingContext(), collection, id, hostSealer, opts);
|
|
9818
9597
|
}
|
|
9819
9598
|
/**
|
|
9820
9599
|
* Revoke a sealed-CEK grant. **Default is SOFT**: deletes the `pid` delivery
|
|
@@ -9824,7 +9603,7 @@ var Vault = class {
|
|
|
9824
9603
|
* longer open the record. See `revokeSealedRecord` in `record-keys/sealing.ts`.
|
|
9825
9604
|
*/
|
|
9826
9605
|
async revokeSealedRecord(collection, id, pid, opts) {
|
|
9827
|
-
return this.
|
|
9606
|
+
return this.strategies.sealedRecord.revokeSealedRecord(this._sealingContext(), collection, id, pid, opts);
|
|
9828
9607
|
}
|
|
9829
9608
|
/**
|
|
9830
9609
|
* HARD-rotate a record's CEK: decrypt the live body under the old CEK,
|
|
@@ -9844,7 +9623,7 @@ var Vault = class {
|
|
|
9844
9623
|
* @throws {@link RecordCekNotFoundError} if the record is missing or has no `_cek`.
|
|
9845
9624
|
*/
|
|
9846
9625
|
async rotateRecordCek(collection, id) {
|
|
9847
|
-
return this.
|
|
9626
|
+
return this.strategies.sealedRecord.rotateRecordCek(this._sealingContext(), collection, id);
|
|
9848
9627
|
}
|
|
9849
9628
|
/**
|
|
9850
9629
|
* Build the {@link SealingContext} the record-keys grantor functions need:
|
|
@@ -9906,7 +9685,7 @@ var Vault = class {
|
|
|
9906
9685
|
async _initDerivations(handles) {
|
|
9907
9686
|
if (handles.length === 0) return;
|
|
9908
9687
|
const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
|
|
9909
|
-
import("./registry-
|
|
9688
|
+
import("./registry-JOFO7RAH.js"),
|
|
9910
9689
|
import("./read-only-facade-CHCKSEPD.js")
|
|
9911
9690
|
]);
|
|
9912
9691
|
const registry = new DerivationRegistry();
|
|
@@ -9938,7 +9717,7 @@ var Vault = class {
|
|
|
9938
9717
|
*/
|
|
9939
9718
|
async _initMaterializedViews(handles) {
|
|
9940
9719
|
if (handles.length === 0) return;
|
|
9941
|
-
const { MaterializedViewRegistry } = await import("./registry-
|
|
9720
|
+
const { MaterializedViewRegistry } = await import("./registry-6BMBFEXT.js");
|
|
9942
9721
|
const registry = new MaterializedViewRegistry();
|
|
9943
9722
|
this.materializedViewRegistry = registry;
|
|
9944
9723
|
const db = this;
|
|
@@ -9963,7 +9742,7 @@ var Vault = class {
|
|
|
9963
9742
|
*/
|
|
9964
9743
|
async _initOverlayedViews(handles) {
|
|
9965
9744
|
if (handles.length === 0) return;
|
|
9966
|
-
const { OverlayedViewRegistry } = await import("./registry-
|
|
9745
|
+
const { OverlayedViewRegistry } = await import("./registry-7CZWF3EQ.js");
|
|
9967
9746
|
const registry = new OverlayedViewRegistry();
|
|
9968
9747
|
const mvRegistry = this.materializedViewRegistry;
|
|
9969
9748
|
const overlayNames = /* @__PURE__ */ new Set();
|
|
@@ -10010,14 +9789,14 @@ var Vault = class {
|
|
|
10010
9789
|
if (!reg) {
|
|
10011
9790
|
throw new Error(`refreshView: no MV registered with name "${name}"`);
|
|
10012
9791
|
}
|
|
10013
|
-
const { MaterializedViewExecutor } = await import("./executor-
|
|
9792
|
+
const { MaterializedViewExecutor } = await import("./executor-SHYLIBOM.js");
|
|
10014
9793
|
const result = await MaterializedViewExecutor.refresh(reg, {
|
|
10015
9794
|
getCollection: (n) => this.collection(n),
|
|
10016
9795
|
getActiveTxContext: () => this.noydb._activeTxContextOrNull,
|
|
10017
9796
|
getQueryContext: () => this,
|
|
10018
9797
|
dispatchCtx: this._dispatchCtx({ collection: name, id: "refreshView" })
|
|
10019
9798
|
});
|
|
10020
|
-
const { clearMVStaleFully } = await import("./stale-
|
|
9799
|
+
const { clearMVStaleFully } = await import("./stale-NBROTA66.js");
|
|
10021
9800
|
await clearMVStaleFully(this.adapter, this.name, registry, name);
|
|
10022
9801
|
return result;
|
|
10023
9802
|
}
|
|
@@ -10030,7 +9809,7 @@ var Vault = class {
|
|
|
10030
9809
|
if (registry === null) return { derived: 0, failed: 0, skippedFrozen: 0 };
|
|
10031
9810
|
const strategies = registry.strategiesForSource(sourceCollection);
|
|
10032
9811
|
if (strategies.length === 0) return { derived: 0, failed: 0, skippedFrozen: 0 };
|
|
10033
|
-
const { DerivationExecutor } = await import("./executor-
|
|
9812
|
+
const { DerivationExecutor } = await import("./executor-FCJEH3FU.js");
|
|
10034
9813
|
const sourceColl = this.collection(sourceCollection);
|
|
10035
9814
|
const records = await sourceColl.list();
|
|
10036
9815
|
const ctx = { vault: this.derivationFacade ?? new (await import("./read-only-facade-CHCKSEPD.js")).ReadOnlyVaultFacade(this, "derivation") };
|
|
@@ -10057,7 +9836,7 @@ var Vault = class {
|
|
|
10057
9836
|
if (!outSpec) continue;
|
|
10058
9837
|
const outputColl = this.collection(outSpec.collection);
|
|
10059
9838
|
if (out.kind === "array") {
|
|
10060
|
-
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-
|
|
9839
|
+
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-WWXVHHUH.js");
|
|
10061
9840
|
const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key, this.getDEK, this.encrypted);
|
|
10062
9841
|
const prevKeys = new Set(prior?.keys ?? []);
|
|
10063
9842
|
const newKeysList = out.entries.map((e) => e.key);
|
|
@@ -10151,7 +9930,7 @@ var Vault = class {
|
|
|
10151
9930
|
*/
|
|
10152
9931
|
at(timestamp) {
|
|
10153
9932
|
const iso = timestamp instanceof Date ? timestamp.toISOString() : timestamp;
|
|
10154
|
-
return this.
|
|
9933
|
+
return this.strategies.history.buildVaultInstant(
|
|
10155
9934
|
{
|
|
10156
9935
|
adapter: this.adapter,
|
|
10157
9936
|
name: this.name,
|
|
@@ -10183,11 +9962,11 @@ var Vault = class {
|
|
|
10183
9962
|
*.
|
|
10184
9963
|
*/
|
|
10185
9964
|
frame() {
|
|
10186
|
-
return this.
|
|
9965
|
+
return this.strategies.shadow.buildFrame(this);
|
|
10187
9966
|
}
|
|
10188
9967
|
/** Credential-broker handle (#479); `NO_BROKER` throws unless `brokerStrategy: withBroker(config)` was passed to createNoydb(). */
|
|
10189
9968
|
broker() {
|
|
10190
|
-
return buildCredentialBrokerHandle(this.
|
|
9969
|
+
return buildCredentialBrokerHandle(this.strategies.broker, this.adapter, this.name, () => this.keyring);
|
|
10191
9970
|
}
|
|
10192
9971
|
/**
|
|
10193
9972
|
* Run `fn` under a consent scope. Every `get` / `put` / `delete`
|
|
@@ -10229,7 +10008,7 @@ var Vault = class {
|
|
|
10229
10008
|
*.
|
|
10230
10009
|
*/
|
|
10231
10010
|
async consentAudit(filter = {}) {
|
|
10232
|
-
return this.
|
|
10011
|
+
return this.strategies.consent.read(this.adapter, this.name, this.encrypted, this.getDEK, filter);
|
|
10233
10012
|
}
|
|
10234
10013
|
/**
|
|
10235
10014
|
* Called by Collection after every access when a consent scope is
|
|
@@ -10240,7 +10019,7 @@ var Vault = class {
|
|
|
10240
10019
|
async _logConsent(op, collection, recordId) {
|
|
10241
10020
|
const ctx = this.consentContext;
|
|
10242
10021
|
if (!ctx) return;
|
|
10243
|
-
await this.
|
|
10022
|
+
await this.strategies.consent.write(
|
|
10244
10023
|
this.adapter,
|
|
10245
10024
|
this.name,
|
|
10246
10025
|
this.encrypted,
|
|
@@ -10284,10 +10063,10 @@ var Vault = class {
|
|
|
10284
10063
|
* collection.
|
|
10285
10064
|
*/
|
|
10286
10065
|
async delegate(opts) {
|
|
10287
|
-
const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-
|
|
10066
|
+
const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-WWZPEDK2.js");
|
|
10288
10067
|
if (!this.keyring.kek) {
|
|
10289
10068
|
throw new ValidationError(
|
|
10290
|
-
"issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (
|
|
10069
|
+
"issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (secret) first."
|
|
10291
10070
|
);
|
|
10292
10071
|
}
|
|
10293
10072
|
const targetKek = this.keyring.kek;
|
|
@@ -10306,7 +10085,7 @@ var Vault = class {
|
|
|
10306
10085
|
* if the id does not exist.
|
|
10307
10086
|
*/
|
|
10308
10087
|
async revokeDelegation(id) {
|
|
10309
|
-
const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-
|
|
10088
|
+
const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-WWZPEDK2.js");
|
|
10310
10089
|
await revokeDelegation(this.adapter, this.name, id);
|
|
10311
10090
|
void DELEGATIONS_COLLECTION;
|
|
10312
10091
|
}
|
|
@@ -10554,7 +10333,7 @@ var Vault = class {
|
|
|
10554
10333
|
* @see docs/superpowers/specs/2026-05-22-schema-dump-design.md
|
|
10555
10334
|
*/
|
|
10556
10335
|
async dumpSchema(opts = {}) {
|
|
10557
|
-
const { dumpVaultSchema } = await import("./walk-
|
|
10336
|
+
const { dumpVaultSchema } = await import("./walk-E3OVLBFR.js");
|
|
10558
10337
|
return dumpVaultSchema(this, opts);
|
|
10559
10338
|
}
|
|
10560
10339
|
/**
|
|
@@ -10689,7 +10468,7 @@ var Vault = class {
|
|
|
10689
10468
|
* @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md
|
|
10690
10469
|
*/
|
|
10691
10470
|
async getCover(opts = {}) {
|
|
10692
|
-
const { readCover } = await import("./cover-
|
|
10471
|
+
const { readCover } = await import("./cover-5BSNJREH.js");
|
|
10693
10472
|
return readCover(this.adapter, this.name, opts);
|
|
10694
10473
|
}
|
|
10695
10474
|
/**
|
|
@@ -10704,7 +10483,7 @@ var Vault = class {
|
|
|
10704
10483
|
* both modes round-trip cleanly.
|
|
10705
10484
|
*/
|
|
10706
10485
|
async dump() {
|
|
10707
|
-
const { dumpVault } = await import("./backup-
|
|
10486
|
+
const { dumpVault } = await import("./backup-YCHAC575.js");
|
|
10708
10487
|
return dumpVault(this.backupContext());
|
|
10709
10488
|
}
|
|
10710
10489
|
/**
|
|
@@ -10719,7 +10498,7 @@ var Vault = class {
|
|
|
10719
10498
|
vault: this.name,
|
|
10720
10499
|
userId: () => this.keyring.userId,
|
|
10721
10500
|
getLedgerOrNull: () => this.getLedgerOrNull(),
|
|
10722
|
-
envelopePayloadHash: (envelope) => this.
|
|
10501
|
+
envelopePayloadHash: (envelope) => this.strategies.history.envelopePayloadHash(envelope),
|
|
10723
10502
|
reloadKeyringAndRebuildDEK: async () => {
|
|
10724
10503
|
if (this.reloadKeyring) {
|
|
10725
10504
|
this.keyring = await this.reloadKeyring();
|
|
@@ -10756,7 +10535,7 @@ var Vault = class {
|
|
|
10756
10535
|
* — there's no chain to verify against.
|
|
10757
10536
|
*/
|
|
10758
10537
|
async load(backupJson) {
|
|
10759
|
-
const { loadVault } = await import("./backup-
|
|
10538
|
+
const { loadVault } = await import("./backup-YCHAC575.js");
|
|
10760
10539
|
return loadVault(this.backupContext(), backupJson);
|
|
10761
10540
|
}
|
|
10762
10541
|
/**
|
|
@@ -10788,7 +10567,7 @@ var Vault = class {
|
|
|
10788
10567
|
* way to detect tampering of an in-place vault.
|
|
10789
10568
|
*/
|
|
10790
10569
|
async verifyBackupIntegrity() {
|
|
10791
|
-
const { verifyBackupIntegrity } = await import("./backup-
|
|
10570
|
+
const { verifyBackupIntegrity } = await import("./backup-YCHAC575.js");
|
|
10792
10571
|
return verifyBackupIntegrity(this.backupContext());
|
|
10793
10572
|
}
|
|
10794
10573
|
/**
|
|
@@ -11006,7 +10785,7 @@ var Vault = class {
|
|
|
11006
10785
|
* is the live validator object, not a serialization of it).
|
|
11007
10786
|
*/
|
|
11008
10787
|
async exportJSON(opts = {}) {
|
|
11009
|
-
const { exportVaultJSON } = await import("./backup-
|
|
10788
|
+
const { exportVaultJSON } = await import("./backup-YCHAC575.js");
|
|
11010
10789
|
return exportVaultJSON(this.backupContext(), opts);
|
|
11011
10790
|
}
|
|
11012
10791
|
};
|
|
@@ -11404,25 +11183,6 @@ var QuickUnlockStore = class {
|
|
|
11404
11183
|
}
|
|
11405
11184
|
};
|
|
11406
11185
|
|
|
11407
|
-
// src/with-fork/snapshots/strategy.ts
|
|
11408
|
-
var NOT_ENABLED4 = new Error(
|
|
11409
|
-
'Snapshots require the snapshot strategy. Import `{ withSnapshots }` from "@noy-db/hub/snapshots" and pass it to `createNoydb({ snapshotStrategy: withSnapshots({ store }) })`.'
|
|
11410
|
-
);
|
|
11411
|
-
var NO_SNAPSHOTS = {
|
|
11412
|
-
async snapshot() {
|
|
11413
|
-
throw NOT_ENABLED4;
|
|
11414
|
-
},
|
|
11415
|
-
async listSnapshots() {
|
|
11416
|
-
throw NOT_ENABLED4;
|
|
11417
|
-
},
|
|
11418
|
-
async restoreSnapshot() {
|
|
11419
|
-
throw NOT_ENABLED4;
|
|
11420
|
-
},
|
|
11421
|
-
async autoSnapshot() {
|
|
11422
|
-
throw NOT_ENABLED4;
|
|
11423
|
-
}
|
|
11424
|
-
};
|
|
11425
|
-
|
|
11426
11186
|
// src/with-fork/snapshots/scheduler.ts
|
|
11427
11187
|
var SnapshotScheduler = class {
|
|
11428
11188
|
policy;
|
|
@@ -11623,19 +11383,6 @@ var NoydbSnapshots = class {
|
|
|
11623
11383
|
}
|
|
11624
11384
|
};
|
|
11625
11385
|
|
|
11626
|
-
// src/with-commit/tx/strategy.ts
|
|
11627
|
-
var NOT_ENABLED5 = new Error(
|
|
11628
|
-
'Multi-record transactions require the tx strategy. Import `{ withTransactions }` from "@noy-db/hub/tx" and pass it to `createNoydb({ txStrategy: withTransactions() })`.'
|
|
11629
|
-
);
|
|
11630
|
-
var NO_TX = {
|
|
11631
|
-
async runTransaction(_db, _fn, _options, _txInvariants) {
|
|
11632
|
-
throw NOT_ENABLED5;
|
|
11633
|
-
},
|
|
11634
|
-
async runDryRun() {
|
|
11635
|
-
throw NOT_ENABLED5;
|
|
11636
|
-
}
|
|
11637
|
-
};
|
|
11638
|
-
|
|
11639
11386
|
// src/kernel/memory-store.ts
|
|
11640
11387
|
function memoryStore() {
|
|
11641
11388
|
const store = /* @__PURE__ */ new Map();
|
|
@@ -11719,23 +11466,6 @@ function memoryStore() {
|
|
|
11719
11466
|
};
|
|
11720
11467
|
}
|
|
11721
11468
|
|
|
11722
|
-
// src/with-party/session/strategy.ts
|
|
11723
|
-
function notEnabled3(op) {
|
|
11724
|
-
return new Error(
|
|
11725
|
-
`${op} requires the session strategy. Import \`{ withSession }\` from "@noy-db/hub/session" and pass it to \`createNoydb({ sessionStrategy: withSession() })\`.`
|
|
11726
|
-
);
|
|
11727
|
-
}
|
|
11728
|
-
var NO_SESSION = {
|
|
11729
|
-
validateSessionPolicy() {
|
|
11730
|
-
throw notEnabled3("sessionPolicy");
|
|
11731
|
-
},
|
|
11732
|
-
createEnforcer() {
|
|
11733
|
-
throw notEnabled3("session policy enforcement");
|
|
11734
|
-
},
|
|
11735
|
-
revokeAllSessions() {
|
|
11736
|
-
}
|
|
11737
|
-
};
|
|
11738
|
-
|
|
11739
11469
|
// src/with-party/auth-introspection/index.ts
|
|
11740
11470
|
async function describeAuthConfig(store, vault) {
|
|
11741
11471
|
const policy = await loadVaultPolicy(store, vault) ?? defaultPolicySnapshot();
|
|
@@ -11743,8 +11473,8 @@ async function describeAuthConfig(store, vault) {
|
|
|
11743
11473
|
const lines = [];
|
|
11744
11474
|
lines.push(`Vault "${vault}" \u2014 three-tier authentication`);
|
|
11745
11475
|
lines.push("");
|
|
11746
|
-
lines.push("Tier 1 \u2014
|
|
11747
|
-
lines.push(` Phrase format: ${policy.
|
|
11476
|
+
lines.push("Tier 1 \u2014 Secret (master)");
|
|
11477
|
+
lines.push(` Phrase format: ${policy.secret?.minWords ?? 6}+ words, lowercase letters, \u2265${policy.secret?.minWordLength ?? 3} chars/word`);
|
|
11748
11478
|
lines.push(" Strength validator: enforced (override available for tests only)");
|
|
11749
11479
|
lines.push("");
|
|
11750
11480
|
lines.push("Tier 2 \u2014 Authenticate (routine login)");
|
|
@@ -11755,7 +11485,7 @@ async function describeAuthConfig(store, vault) {
|
|
|
11755
11485
|
lines.push(" Method: PIN (per-app configurable)");
|
|
11756
11486
|
lines.push("");
|
|
11757
11487
|
lines.push(`Recovery profiles enrolled: ${recoveryProfiles.length === 0 ? "none" : recoveryProfiles.join(", ")}`);
|
|
11758
|
-
lines.push("Managed-
|
|
11488
|
+
lines.push("Managed-secret mode: off (post-1.0)");
|
|
11759
11489
|
lines.push("");
|
|
11760
11490
|
lines.push("Sensitive-action gates:");
|
|
11761
11491
|
for (const [gate, gp] of Object.entries(policy.gates)) {
|
|
@@ -11768,7 +11498,7 @@ async function diagramAuthConfig(store, vault) {
|
|
|
11768
11498
|
const lines = [];
|
|
11769
11499
|
lines.push("flowchart TB");
|
|
11770
11500
|
lines.push(` vault["Vault: ${escapeMermaid(vault)}"]`);
|
|
11771
|
-
lines.push(' tier1["Tier 1<br/>
|
|
11501
|
+
lines.push(' tier1["Tier 1<br/>Secret"]');
|
|
11772
11502
|
lines.push(' tier2["Tier 2<br/>Multi-slot Authenticate"]');
|
|
11773
11503
|
lines.push(' tier3["Tier 3<br/>PIN / Quick-resume"]');
|
|
11774
11504
|
lines.push(" vault --> tier1");
|
|
@@ -11842,7 +11572,7 @@ function describeGatePolicy(gp) {
|
|
|
11842
11572
|
}
|
|
11843
11573
|
function defaultPolicySnapshot() {
|
|
11844
11574
|
return {
|
|
11845
|
-
|
|
11575
|
+
secret: { minWords: 6, minWordLength: 3, rejectRepeatedAdjacent: true },
|
|
11846
11576
|
gates: {}
|
|
11847
11577
|
};
|
|
11848
11578
|
}
|
|
@@ -11992,7 +11722,7 @@ var TeamFacade = class {
|
|
|
11992
11722
|
* ```ts
|
|
11993
11723
|
* import { enrollWebAuthn } from '@noy-db/on-webauthn'
|
|
11994
11724
|
*
|
|
11995
|
-
* await db.enrollWebAuthn('demo', async (keyring) => {
|
|
11725
|
+
* await db.team.enrollWebAuthn('demo', async (keyring) => {
|
|
11996
11726
|
* const e = await enrollWebAuthn(keyring, 'demo', { rp: {...} })
|
|
11997
11727
|
* return {
|
|
11998
11728
|
* id: `webauthn-${e.credentialId.slice(0, 8)}`,
|
|
@@ -12021,7 +11751,7 @@ var TeamFacade = class {
|
|
|
12021
11751
|
const slotOptions = await ceremony(keyring);
|
|
12022
11752
|
if (slotOptions.method !== "webauthn") {
|
|
12023
11753
|
throw new ValidationError(
|
|
12024
|
-
`enrollWebAuthn: ceremony returned method "${slotOptions.method}"; expected "webauthn". Use db.enrollAuthenticator() for non-webauthn methods.`
|
|
11754
|
+
`enrollWebAuthn: ceremony returned method "${slotOptions.method}"; expected "webauthn". Use db.team.enrollAuthenticator() for non-webauthn methods.`
|
|
12025
11755
|
);
|
|
12026
11756
|
}
|
|
12027
11757
|
const credentialId = slotOptions.meta.credentialId;
|
|
@@ -12099,44 +11829,44 @@ var TeamFacade = class {
|
|
|
12099
11829
|
}
|
|
12100
11830
|
// ─── Tier-1 change flows ────────────────────────────────────────
|
|
12101
11831
|
/**
|
|
12102
|
-
* Rotate the user's
|
|
12103
|
-
* new phrase against the configured `
|
|
12104
|
-
* `rotate-
|
|
11832
|
+
* Rotate the user's secret (user remembers old). Validates the
|
|
11833
|
+
* new phrase against the configured `secret` policy, runs the
|
|
11834
|
+
* `rotate-secret` gate, then re-derives + re-wraps every DEK.
|
|
12105
11835
|
*
|
|
12106
11836
|
* Tier-2 authenticator slots are dropped — each slot wraps the old
|
|
12107
11837
|
* KEK and would need its derivation key to be re-presented. Re-enrol
|
|
12108
11838
|
* via `db.enrollAuthenticator` after rotation.
|
|
12109
11839
|
*
|
|
12110
|
-
* @throws `
|
|
11840
|
+
* @throws `WeakSecretError` on a weak new phrase.
|
|
12111
11841
|
* @throws `PolicyDeniedError` when the gate denies (missing factor, …).
|
|
12112
|
-
* @throws `InvalidKeyError` when `
|
|
11842
|
+
* @throws `InvalidKeyError` when `oldSecret` is wrong.
|
|
12113
11843
|
*/
|
|
12114
|
-
async
|
|
12115
|
-
if (this.deps.options.
|
|
11844
|
+
async rotateSecret(vault, input, factors) {
|
|
11845
|
+
if (this.deps.options.secretMode === "managed") {
|
|
12116
11846
|
throw new PolicyDeniedError(
|
|
12117
|
-
"rotate-
|
|
11847
|
+
"rotate-secret",
|
|
12118
11848
|
"disabled",
|
|
12119
11849
|
{ minTier: 1, enabled: false },
|
|
12120
|
-
"Managed-
|
|
11850
|
+
"Managed-secret mode (#14): the secret is hub-generated and sealed under the SealingKeyProvider \u2014 there is no plaintext to rotate. Use the recovery flow (follow-up issue) to mint a fresh sealed secret."
|
|
12121
11851
|
);
|
|
12122
11852
|
}
|
|
12123
|
-
await this.deps.checkGate(vault, "rotate-
|
|
11853
|
+
await this.deps.checkGate(vault, "rotate-secret", factors);
|
|
12124
11854
|
const userId = this.deps.options.user;
|
|
12125
|
-
const next = await
|
|
11855
|
+
const next = await rotateSecret(this.deps.options.store, vault, userId, input);
|
|
12126
11856
|
this.deps.keyringCache.set(vault, next);
|
|
12127
11857
|
}
|
|
12128
11858
|
/**
|
|
12129
|
-
* Reset the
|
|
11859
|
+
* Reset the secret using a recovery proof (user forgot the old).
|
|
12130
11860
|
* Currently supports the `'paper'` profile end-to-end; the
|
|
12131
11861
|
* other profiles throw {@link RecoveryProfileNotImplementedError}.
|
|
12132
11862
|
*
|
|
12133
11863
|
* Burns the used recovery entry on success.
|
|
12134
11864
|
*/
|
|
12135
|
-
async
|
|
12136
|
-
await this.deps.checkGate(vault, "recover-
|
|
11865
|
+
async recoverSecret(vault, input, factors) {
|
|
11866
|
+
await this.deps.checkGate(vault, "recover-secret", factors);
|
|
12137
11867
|
const userId = this.deps.options.user;
|
|
12138
11868
|
const entriesBeforeRecovery = await loadPaperRecoveryEntries(this.deps.options.store, vault);
|
|
12139
|
-
const next = await
|
|
11869
|
+
const next = await recoverSecret(this.deps.options.shamirRecovery, this.deps.options.store, vault, userId, input);
|
|
12140
11870
|
this.deps.keyringCache.set(vault, next);
|
|
12141
11871
|
const rotateRemaining = input.rotateRemainingCodes ?? true;
|
|
12142
11872
|
const remainingAfterBurn = Math.max(0, entriesBeforeRecovery.length - 1);
|
|
@@ -12158,15 +11888,15 @@ var TeamFacade = class {
|
|
|
12158
11888
|
}
|
|
12159
11889
|
/**
|
|
12160
11890
|
* Deliberate paper-recovery-code regeneration. User knows their
|
|
12161
|
-
*
|
|
11891
|
+
* secret but wants a fresh sheet — they lost the printout or
|
|
12162
11892
|
* suspect compromise of the off-site copy.
|
|
12163
11893
|
*
|
|
12164
|
-
* Symmetric to {@link
|
|
11894
|
+
* Symmetric to {@link rotateSecret} for the recovery profile:
|
|
12165
11895
|
* gated, audit-trackable, ergonomic. Replaces (not appends) the
|
|
12166
11896
|
* paper sheet under `_meta/recovery-paper` in a single envelope `put`.
|
|
12167
11897
|
*
|
|
12168
11898
|
* Gated by the `rotate-recovery` policy gate:
|
|
12169
|
-
* - PERSONAL_POLICY: `{ minTier: 1 }` — knowing the
|
|
11899
|
+
* - PERSONAL_POLICY: `{ minTier: 1 }` — knowing the secret
|
|
12170
11900
|
* suffices, matching the lower-level flow's bar.
|
|
12171
11901
|
* - STRICT_POLICY: `{ minTier: 1, factors: [{ anyOf: ['totp',
|
|
12172
11902
|
* 'email-otp', 'webauthn-roaming'] }] }` — rotation is an
|
|
@@ -12186,13 +11916,13 @@ var TeamFacade = class {
|
|
|
12186
11916
|
*
|
|
12187
11917
|
* @example Default count + show-once UI
|
|
12188
11918
|
* ```ts
|
|
12189
|
-
* const { newCodes } = await db.rotateRecovery('acme', { profile: 'paper' })
|
|
11919
|
+
* const { newCodes } = await db.team.rotateRecovery('acme', { profile: 'paper' })
|
|
12190
11920
|
* showCodesToUser(newCodes)
|
|
12191
11921
|
* ```
|
|
12192
11922
|
*
|
|
12193
11923
|
* @example STRICT-policy site with TOTP factor proof
|
|
12194
11924
|
* ```ts
|
|
12195
|
-
* await db.rotateRecovery(
|
|
11925
|
+
* await db.team.rotateRecovery(
|
|
12196
11926
|
* 'acme',
|
|
12197
11927
|
* { profile: 'paper', count: 10 },
|
|
12198
11928
|
* { factors: [{ kind: 'totp', proof: '123456' }] },
|
|
@@ -12216,7 +11946,7 @@ var TeamFacade = class {
|
|
|
12216
11946
|
const existing = await loadPaperRecoveryEntries(this.deps.options.store, vault);
|
|
12217
11947
|
if (existing.length === 0) {
|
|
12218
11948
|
throw new Error(
|
|
12219
|
-
`db.rotateRecovery: no recovery codes are enrolled for vault "${vault}". Call db.enrollRecovery({ profile: 'paper', entries }) first; rotateRecovery replaces an existing sheet rather than minting one from scratch.`
|
|
11949
|
+
`db.rotateRecovery: no recovery codes are enrolled for vault "${vault}". Call db.team.enrollRecovery({ profile: 'paper', entries }) first; rotateRecovery replaces an existing sheet rather than minting one from scratch.`
|
|
12220
11950
|
);
|
|
12221
11951
|
}
|
|
12222
11952
|
const keyring = await this.getKeyring(vault);
|
|
@@ -12238,7 +11968,7 @@ var TeamFacade = class {
|
|
|
12238
11968
|
const existing = await loadShamirRecoveryEntries(this.deps.options.store, vault);
|
|
12239
11969
|
if (existing.length === 0) {
|
|
12240
11970
|
throw new Error(
|
|
12241
|
-
`db.rotateRecovery: no Shamir recovery entry is enrolled for vault "${vault}". Call db.enrollRecovery({ profile: 'shamir', k, n }) first; rotateRecovery replaces an existing entry rather than minting one from scratch.`
|
|
11971
|
+
`db.rotateRecovery: no Shamir recovery entry is enrolled for vault "${vault}". Call db.team.enrollRecovery({ profile: 'shamir', k, n }) first; rotateRecovery replaces an existing entry rather than minting one from scratch.`
|
|
12242
11972
|
);
|
|
12243
11973
|
}
|
|
12244
11974
|
let targetEntryId;
|
|
@@ -12275,7 +12005,7 @@ var TeamFacade = class {
|
|
|
12275
12005
|
* **Atomic create-and-enroll for managed-mode vaults.**
|
|
12276
12006
|
*
|
|
12277
12007
|
* Bootstraps a managed-mode vault and enrolls strong recovery in
|
|
12278
|
-
* a single ceremony. Under `
|
|
12008
|
+
* a single ceremony. Under `secretMode: 'managed'`, every
|
|
12279
12009
|
* `openVault` call requires a strong recovery profile (Shamir
|
|
12280
12010
|
* today) to be enrolled — otherwise it throws
|
|
12281
12011
|
* {@link ManagedRecoveryNotEnrolledError}. This method bypasses
|
|
@@ -12294,11 +12024,11 @@ var TeamFacade = class {
|
|
|
12294
12024
|
* ```ts
|
|
12295
12025
|
* const db = await createNoydb({
|
|
12296
12026
|
* store, user: 'alice',
|
|
12297
|
-
*
|
|
12027
|
+
* secretMode: 'managed',
|
|
12298
12028
|
* sealingKey: macosKeychainSealingProvider({ ... }),
|
|
12299
12029
|
* })
|
|
12300
12030
|
*
|
|
12301
|
-
* const { vault, recoveryEnrollments } = await db.openVaultAndEnrollRecovery('acme', {
|
|
12031
|
+
* const { vault, recoveryEnrollments } = await db.team.openVaultAndEnrollRecovery('acme', {
|
|
12302
12032
|
* recovery: [{ profile: 'shamir', k: 2, n: 3 }],
|
|
12303
12033
|
* })
|
|
12304
12034
|
* for (const r of recoveryEnrollments) {
|
|
@@ -12315,11 +12045,11 @@ var TeamFacade = class {
|
|
|
12315
12045
|
"openVaultAndEnrollRecovery: at least one recovery enrollment is required."
|
|
12316
12046
|
);
|
|
12317
12047
|
}
|
|
12318
|
-
if (this.deps.options.
|
|
12048
|
+
if (this.deps.options.secretMode === "managed") {
|
|
12319
12049
|
const hasStrong = opts.recovery.some((r) => r.profile === "shamir");
|
|
12320
12050
|
if (!hasStrong) {
|
|
12321
12051
|
throw new ValidationError(
|
|
12322
|
-
'openVaultAndEnrollRecovery: managed-mode vaults require at least one strong recovery profile in the `recovery` array. Paper alone is not strong under managed mode (no user
|
|
12052
|
+
'openVaultAndEnrollRecovery: managed-mode vaults require at least one strong recovery profile in the `recovery` array. Paper alone is not strong under managed mode (no user secret to fall back on). Include { profile: "shamir", k, n } in `recovery`.'
|
|
12323
12053
|
);
|
|
12324
12054
|
}
|
|
12325
12055
|
}
|
|
@@ -12334,7 +12064,7 @@ var TeamFacade = class {
|
|
|
12334
12064
|
for (const enrollment of opts.recovery) {
|
|
12335
12065
|
recoveryEnrollments.push(await this.enrollRecovery(vault, enrollment));
|
|
12336
12066
|
}
|
|
12337
|
-
if (this.deps.options.
|
|
12067
|
+
if (this.deps.options.secretMode === "managed") {
|
|
12338
12068
|
const policy = this.deps.policyCache.get(vault);
|
|
12339
12069
|
if (policy) {
|
|
12340
12070
|
await this.deps.assertRecoveryEnrolled(vault, policy);
|
|
@@ -12343,20 +12073,20 @@ var TeamFacade = class {
|
|
|
12343
12073
|
return { vault: vaultHandle, recoveryEnrollments };
|
|
12344
12074
|
}
|
|
12345
12075
|
/**
|
|
12346
|
-
* **Recovery flow under managed-
|
|
12076
|
+
* **Recovery flow under managed-secret mode.**
|
|
12347
12077
|
*
|
|
12348
|
-
* Replaces the sealed
|
|
12078
|
+
* Replaces the sealed secret of a managed-mode vault with a
|
|
12349
12079
|
* fresh 256-bit random, sealed under the configured
|
|
12350
|
-
* `SealingKeyProvider`. The user never sees the new
|
|
12080
|
+
* `SealingKeyProvider`. The user never sees the new secret.
|
|
12351
12081
|
*
|
|
12352
12082
|
* Internally:
|
|
12353
12083
|
* 1. Verify the recovery proof (Shamir today) and unwrap the
|
|
12354
12084
|
* DEK set.
|
|
12355
|
-
* 2. Mint a fresh 256-bit random as the new effective
|
|
12085
|
+
* 2. Mint a fresh 256-bit random as the new effective secret.
|
|
12356
12086
|
* 3. Rewrap the DEK set under a fresh KEK derived from the new
|
|
12357
|
-
*
|
|
12087
|
+
* secret (via the existing `recoverSecret` path).
|
|
12358
12088
|
* 4. Seal the random bytes under the provider and overwrite
|
|
12359
|
-
* `_meta/sealed-
|
|
12089
|
+
* `_meta/sealed-secret`.
|
|
12360
12090
|
* 5. Drop the keyring cache so the next operation re-derives.
|
|
12361
12091
|
*
|
|
12362
12092
|
* The vault's strong-recovery enrollment is preserved across
|
|
@@ -12364,40 +12094,40 @@ var TeamFacade = class {
|
|
|
12364
12094
|
*
|
|
12365
12095
|
* @throws ValidationError if the Noydb instance is not in managed mode.
|
|
12366
12096
|
*/
|
|
12367
|
-
async
|
|
12368
|
-
if (this.deps.options.
|
|
12097
|
+
async recoverManagedSecret(vault, options) {
|
|
12098
|
+
if (this.deps.options.secretMode !== "managed") {
|
|
12369
12099
|
throw new ValidationError(
|
|
12370
|
-
"
|
|
12100
|
+
"recoverManagedSecret: this method only applies to vaults opened in managed-secret mode. For standard mode, use db.recoverSecret."
|
|
12371
12101
|
);
|
|
12372
12102
|
}
|
|
12373
12103
|
const provider = this.deps.options.sealingKey;
|
|
12374
12104
|
if (!provider) {
|
|
12375
12105
|
throw new ValidationError(
|
|
12376
|
-
'
|
|
12106
|
+
'recoverManagedSecret: createNoydb({ secretMode: "managed" }) requires `sealingKey` to be supplied; without it the new sealed secret cannot be persisted.'
|
|
12377
12107
|
);
|
|
12378
12108
|
}
|
|
12379
12109
|
const randomBytes = new Uint8Array(32);
|
|
12380
12110
|
globalThis.crypto.getRandomValues(randomBytes);
|
|
12381
12111
|
let binary = "";
|
|
12382
12112
|
for (let i = 0; i < randomBytes.length; i++) binary += String.fromCharCode(randomBytes[i]);
|
|
12383
|
-
const
|
|
12113
|
+
const newSecret = btoa(binary);
|
|
12384
12114
|
try {
|
|
12385
12115
|
const sealed = await provider.seal(randomBytes);
|
|
12386
|
-
await
|
|
12116
|
+
await recoverSecret(
|
|
12387
12117
|
this.deps.options.shamirRecovery,
|
|
12388
12118
|
this.deps.options.store,
|
|
12389
12119
|
vault,
|
|
12390
12120
|
this.deps.options.user,
|
|
12391
12121
|
{
|
|
12392
|
-
|
|
12122
|
+
newSecret,
|
|
12393
12123
|
recoveryProof: options.recoveryProof,
|
|
12394
|
-
// The new
|
|
12124
|
+
// The new secret IS 256 bits of random; policy gates on
|
|
12395
12125
|
// length/entropy don't apply.
|
|
12396
|
-
|
|
12397
|
-
...options.
|
|
12126
|
+
allowWeakSecret: true,
|
|
12127
|
+
...options.secretPolicy !== void 0 ? { secretPolicy: options.secretPolicy } : {}
|
|
12398
12128
|
}
|
|
12399
12129
|
);
|
|
12400
|
-
await
|
|
12130
|
+
await saveSealedSecret(this.deps.options.store, vault, {
|
|
12401
12131
|
providerId: provider.id,
|
|
12402
12132
|
sealed
|
|
12403
12133
|
});
|
|
@@ -12408,7 +12138,7 @@ var TeamFacade = class {
|
|
|
12408
12138
|
}
|
|
12409
12139
|
/**
|
|
12410
12140
|
* Atomic peer-recovery — re-wraps an EXISTING user's keyring under
|
|
12411
|
-
* a fresh temp
|
|
12141
|
+
* a fresh temp secret in a single store write. Closes the
|
|
12412
12142
|
* partial-failure window (the previous compose-from-primitives
|
|
12413
12143
|
* pattern was `db.revoke + db.grant`, two writes — if the issuer
|
|
12414
12144
|
* cancelled between them the target was locked out entirely).
|
|
@@ -12427,17 +12157,17 @@ var TeamFacade = class {
|
|
|
12427
12157
|
* recovery / TOTP / email-OTP factor proof at the moment of
|
|
12428
12158
|
* recovery, so the issuer affirmatively re-asserts identity.
|
|
12429
12159
|
*
|
|
12430
|
-
* The recipient should call `db.
|
|
12160
|
+
* The recipient should call `db.rotateSecret` on first session
|
|
12431
12161
|
* to choose their own phrase — the temp acts as a single-use
|
|
12432
12162
|
* bridge.
|
|
12433
12163
|
*
|
|
12434
12164
|
* ```ts
|
|
12435
|
-
* await db.recoverUser('acme', {
|
|
12165
|
+
* await db.team.recoverUser('acme', {
|
|
12436
12166
|
* userId: 'bob',
|
|
12437
|
-
*
|
|
12167
|
+
* secret: 'temporary-correct-horse-battery-staple-printer',
|
|
12438
12168
|
* }, { factors: [{ kind: 'recovery' }] })
|
|
12439
12169
|
* // Bob opens createNoydb({ user: 'bob', secret: tempPhrase })
|
|
12440
|
-
* // and immediately calls db.
|
|
12170
|
+
* // and immediately calls db.rotateSecret to set his own.
|
|
12441
12171
|
* ```
|
|
12442
12172
|
*
|
|
12443
12173
|
* @throws `NoAccessError` when no keyring exists for the target.
|
|
@@ -12463,17 +12193,17 @@ var TeamFacade = class {
|
|
|
12463
12193
|
* The hub wraps the user's DEK set (not the KEK) under a code-derived
|
|
12464
12194
|
* AES-GCM key — see `team/recovery.ts` for the rationale. The mint
|
|
12465
12195
|
* helper {@link mintPaperRecoveryEntry} is the canonical primitive;
|
|
12466
|
-
* pair it with `db.getKeyring(vault)` to obtain the live DEK set:
|
|
12196
|
+
* pair it with `db.team.getKeyring(vault)` to obtain the live DEK set:
|
|
12467
12197
|
*
|
|
12468
12198
|
* ```ts
|
|
12469
12199
|
* import { mintPaperRecoveryEntry } from '@noy-db/hub'
|
|
12470
12200
|
*
|
|
12471
|
-
* const keyring = await db.getKeyring('acme')
|
|
12201
|
+
* const keyring = await db.team.getKeyring('acme')
|
|
12472
12202
|
* const codes: string[] = ['CORRECT-HORSE-1', 'BATTERY-STAPLE-2', ...]
|
|
12473
12203
|
* const entries = await Promise.all(
|
|
12474
12204
|
* codes.map((code, i) => mintPaperRecoveryEntry(keyring.deks, code, `code-${i}`)),
|
|
12475
12205
|
* )
|
|
12476
|
-
* await db.enrollRecovery('acme', { profile: 'paper', entries })
|
|
12206
|
+
* await db.team.enrollRecovery('acme', { profile: 'paper', entries })
|
|
12477
12207
|
* showCodesToUser(codes)
|
|
12478
12208
|
* ```
|
|
12479
12209
|
*
|
|
@@ -12484,7 +12214,7 @@ var TeamFacade = class {
|
|
|
12484
12214
|
* ```ts
|
|
12485
12215
|
* import { generateRecoveryCodeSet } from '@noy-db/on-recovery'
|
|
12486
12216
|
* const { codes, entries } = await generateRecoveryCodeSet({ deks: keyring.deks, count: 8 })
|
|
12487
|
-
* await db.enrollRecovery('acme', { profile: 'paper', entries })
|
|
12217
|
+
* await db.team.enrollRecovery('acme', { profile: 'paper', entries })
|
|
12488
12218
|
* ```
|
|
12489
12219
|
*/
|
|
12490
12220
|
async enrollRecovery(vault, enrollment) {
|
|
@@ -12584,7 +12314,7 @@ var TeamFacade = class {
|
|
|
12584
12314
|
* and no `secret` / `getKeyring` is configured.
|
|
12585
12315
|
*
|
|
12586
12316
|
* ```ts
|
|
12587
|
-
* const keyring = await db.getKeyring('acme')
|
|
12317
|
+
* const keyring = await db.team.getKeyring('acme')
|
|
12588
12318
|
* // keyring.deks: Map<collection, CryptoKey>
|
|
12589
12319
|
* // keyring.kek: CryptoKey | null (null for tier-3 / wrap-DEKs sessions)
|
|
12590
12320
|
* // keyring.role / .permissions / .authenticators
|
|
@@ -12661,7 +12391,7 @@ var Noydb = class {
|
|
|
12661
12391
|
keyringCache = /* @__PURE__ */ new Map();
|
|
12662
12392
|
syncEngines = /* @__PURE__ */ new Map();
|
|
12663
12393
|
/**
|
|
12664
|
-
* Per-vault active session tier — defaults to `1` after a
|
|
12394
|
+
* Per-vault active session tier — defaults to `1` after a secret
|
|
12665
12395
|
* unlock; tier-2 / tier-3 unlocks downgrade it. Used by
|
|
12666
12396
|
* {@link checkGate} to evaluate `gate.minTier`.
|
|
12667
12397
|
*/
|
|
@@ -12689,26 +12419,43 @@ var Noydb = class {
|
|
|
12689
12419
|
writeRelay;
|
|
12690
12420
|
/** Per-vault policy enforcers. */
|
|
12691
12421
|
policyEnforcers = /* @__PURE__ */ new Map();
|
|
12692
|
-
txStrategy;
|
|
12693
|
-
forgetStrategy;
|
|
12694
12422
|
/**
|
|
12695
|
-
*
|
|
12696
|
-
* `
|
|
12697
|
-
*
|
|
12423
|
+
* Every opt-in service, resolved once (#838). Shared by reference with each
|
|
12424
|
+
* `Vault` this instance opens and, through them, every `Collection` — so
|
|
12425
|
+
* there is exactly one resolution and no construction path can disagree
|
|
12426
|
+
* about which services are enabled (the #834 bug class).
|
|
12698
12427
|
*/
|
|
12699
|
-
|
|
12428
|
+
strategies;
|
|
12700
12429
|
/**
|
|
12701
|
-
* Opt-in
|
|
12702
|
-
* `
|
|
12703
|
-
*
|
|
12704
|
-
|
|
12705
|
-
|
|
12706
|
-
|
|
12430
|
+
* Opt-in sovereign-custody (FR-6) strategy — `NO_CUSTODY` (throwing) unless
|
|
12431
|
+
* `withCustody()` was passed. Kept as a public accessor because `Vault`
|
|
12432
|
+
* routes `vault.custody.liberate` through `this.noydb.custodyStrategy`.
|
|
12433
|
+
* @internal
|
|
12434
|
+
*/
|
|
12435
|
+
get custodyStrategy() {
|
|
12436
|
+
return this.strategies.custody;
|
|
12437
|
+
}
|
|
12707
12438
|
snapshots;
|
|
12708
12439
|
policyManager;
|
|
12709
12440
|
/** Pre-resolved policy-gate engine function (mirrors `coordinationProvider`/`userApiFactory` above). */
|
|
12710
12441
|
policyCheckGate;
|
|
12711
|
-
|
|
12442
|
+
/**
|
|
12443
|
+
* Credential and multi-user operations — enrolment, secret rotation,
|
|
12444
|
+
* recovery, quick-unlock (#846).
|
|
12445
|
+
*
|
|
12446
|
+
* Public because 23 methods on this class did nothing but restate a
|
|
12447
|
+
* TeamFacade signature and forward to it, so every signature had to be
|
|
12448
|
+
* hand-kept in sync with its counterpart. `db.team.rotateSecret(…)`
|
|
12449
|
+
* reads the same and has one source of truth.
|
|
12450
|
+
*
|
|
12451
|
+
* A getter, not a field, so it appears in the prototype-based kernel API
|
|
12452
|
+
* manifest — an instance field is invisible to it (the same reason
|
|
12453
|
+
* `custodyStrategy` became one in #838).
|
|
12454
|
+
*/
|
|
12455
|
+
get team() {
|
|
12456
|
+
return this.#team;
|
|
12457
|
+
}
|
|
12458
|
+
#team;
|
|
12712
12459
|
/**
|
|
12713
12460
|
* Currently-running multi-record transaction, set by
|
|
12714
12461
|
* `runTransaction` at the start of Phase 2 (commit) and cleared in
|
|
@@ -12747,14 +12494,9 @@ var Noydb = class {
|
|
|
12747
12494
|
this.userApiFactory = options.userApiFactory;
|
|
12748
12495
|
if (!options.policyFactory || !options.policyCheckGateFn) throw new ValidationError("Noydb must be constructed via createNoydb(), which resolves the default policy service.");
|
|
12749
12496
|
this.policyCheckGate = options.policyCheckGateFn;
|
|
12750
|
-
this.
|
|
12751
|
-
this.forgetStrategy = options.forgetStrategy ?? NO_FORGET;
|
|
12752
|
-
this.custodyStrategy = options.custodyStrategy ?? NO_CUSTODY;
|
|
12753
|
-
this.teamStrategy = options.teamStrategy ?? NO_TEAM;
|
|
12754
|
-
this.sessionStrategy = options.sessionStrategy ?? NO_SESSION;
|
|
12755
|
-
this.syncStrategy = options.syncStrategy ?? NO_SYNC;
|
|
12497
|
+
this.strategies = resolveStrategies(options);
|
|
12756
12498
|
this.snapshots = new NoydbSnapshots({
|
|
12757
|
-
strategy:
|
|
12499
|
+
strategy: this.strategies.snapshot,
|
|
12758
12500
|
user: options.user,
|
|
12759
12501
|
isClosed: () => this.closed,
|
|
12760
12502
|
getVault: (name) => this.vaultCache.get(name),
|
|
@@ -12775,7 +12517,7 @@ var Noydb = class {
|
|
|
12775
12517
|
this.vaultCache.delete(vault);
|
|
12776
12518
|
}
|
|
12777
12519
|
});
|
|
12778
|
-
this
|
|
12520
|
+
this.#team = new TeamFacade({
|
|
12779
12521
|
options: this.options,
|
|
12780
12522
|
keyringCache: this.keyringCache,
|
|
12781
12523
|
activeTier: this.activeTier,
|
|
@@ -12791,7 +12533,7 @@ var Noydb = class {
|
|
|
12791
12533
|
}
|
|
12792
12534
|
});
|
|
12793
12535
|
if (options.sessionPolicy) {
|
|
12794
|
-
this.
|
|
12536
|
+
this.strategies.session.validateSessionPolicy(options.sessionPolicy);
|
|
12795
12537
|
}
|
|
12796
12538
|
this.#registerGuardGate();
|
|
12797
12539
|
this.#registerPeriodGate();
|
|
@@ -12800,7 +12542,7 @@ var Noydb = class {
|
|
|
12800
12542
|
}
|
|
12801
12543
|
/** @internal — resolved forget strategy (NO_FORGET when not configured). */
|
|
12802
12544
|
get _forgetStrategy() {
|
|
12803
|
-
return this.
|
|
12545
|
+
return this.strategies.forget;
|
|
12804
12546
|
}
|
|
12805
12547
|
// GDPR subject-index maintenance. When `withForgetCascade` declares
|
|
12806
12548
|
// any subject fields, keep the encrypted `_subject_index` in lock-step with
|
|
@@ -12813,7 +12555,7 @@ var Noydb = class {
|
|
|
12813
12555
|
// does NOT) — drop the ref so a deleted record never lingers in the
|
|
12814
12556
|
// index (RISK #2). Without it, forget() would try to shred a ghost.
|
|
12815
12557
|
#registerForgetHooks() {
|
|
12816
|
-
const subjects = this.
|
|
12558
|
+
const subjects = this.strategies.forget.subjects;
|
|
12817
12559
|
if (Object.keys(subjects).length === 0) return;
|
|
12818
12560
|
const subjectFieldFor = (collection) => subjects[collection];
|
|
12819
12561
|
this.writeHooks.onAfterWrite(async (event) => {
|
|
@@ -12877,7 +12619,7 @@ var Noydb = class {
|
|
|
12877
12619
|
if (!facade) return;
|
|
12878
12620
|
const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
|
|
12879
12621
|
await registry.runChecks(e.collection, incoming, ctx);
|
|
12880
|
-
const { GuardExecutor } = await import("./executor-
|
|
12622
|
+
const { GuardExecutor } = await import("./executor-OHET7TF7.js");
|
|
12881
12623
|
for (const g of guards) {
|
|
12882
12624
|
await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming, e.computedFieldNames);
|
|
12883
12625
|
}
|
|
@@ -13002,7 +12744,7 @@ var Noydb = class {
|
|
|
13002
12744
|
if (targets.length > 0) {
|
|
13003
12745
|
const primary = targets.find((t) => t.role === "sync-peer") ?? targets[0];
|
|
13004
12746
|
const effectivePolicy = this.options.syncPolicy ?? primary.policy ?? INDEXED_STORE_POLICY;
|
|
13005
|
-
syncEngine = this.
|
|
12747
|
+
syncEngine = this.strategies.sync.buildSyncEngine({
|
|
13006
12748
|
local: this.options.store,
|
|
13007
12749
|
remote: primary.store,
|
|
13008
12750
|
vault: name,
|
|
@@ -13016,7 +12758,7 @@ var Noydb = class {
|
|
|
13016
12758
|
for (const target of targets) {
|
|
13017
12759
|
if (target === primary) continue;
|
|
13018
12760
|
const targetPolicy = target.policy ?? this.options.syncPolicy ?? INDEXED_STORE_POLICY;
|
|
13019
|
-
const engine = this.
|
|
12761
|
+
const engine = this.strategies.sync.buildSyncEngine({
|
|
13020
12762
|
local: this.options.store,
|
|
13021
12763
|
remote: target.store,
|
|
13022
12764
|
vault: name,
|
|
@@ -13049,31 +12791,14 @@ var Noydb = class {
|
|
|
13049
12791
|
syncAdapter: targets.length > 0 ? targets[0].store : void 0,
|
|
13050
12792
|
getPurgeableTargets: () => targets.filter((t) => t.role === "backup" || t.role === "archive").map((t) => ({ store: t.store, role: t.role, ...t.label !== void 0 ? { label: t.label } : {} })),
|
|
13051
12793
|
historyConfig: this.options.history,
|
|
13052
|
-
|
|
12794
|
+
// #838 — the 21 conditional strategy spreads that used to live here are
|
|
12795
|
+
// one shared reference. This block is where #834's drift happened: a
|
|
12796
|
+
// copy of it silently omitted six strategies, and there was nothing to
|
|
12797
|
+
// catch that. There is no longer a per-service line to omit.
|
|
12798
|
+
strategies: this.strategies,
|
|
13053
12799
|
...this.options.objectStore !== void 0 ? { objectStore: this.options.objectStore } : {},
|
|
13054
|
-
...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
|
|
13055
|
-
...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
|
|
13056
|
-
...this.options.lazyStrategy !== void 0 ? { lazyStrategy: this.options.lazyStrategy } : {},
|
|
13057
|
-
...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
|
|
13058
|
-
...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
|
|
13059
|
-
...this.options.tiersStrategy !== void 0 ? { tiersStrategy: this.options.tiersStrategy } : {},
|
|
13060
|
-
...this.options.searchStrategy !== void 0 ? { searchStrategy: this.options.searchStrategy } : {},
|
|
13061
|
-
...this.options.cargoStrategy !== void 0 ? { cargoStrategy: this.options.cargoStrategy } : {},
|
|
13062
|
-
...this.options.brokerStrategy !== void 0 ? { brokerStrategy: this.options.brokerStrategy } : {},
|
|
13063
|
-
...this.options.consentStrategy !== void 0 ? { consentStrategy: this.options.consentStrategy } : {},
|
|
13064
|
-
...this.options.periodsStrategy !== void 0 ? { periodsStrategy: this.options.periodsStrategy } : {},
|
|
13065
|
-
...this.options.shadowStrategy !== void 0 ? { shadowStrategy: this.options.shadowStrategy } : {},
|
|
13066
|
-
...this.options.historyStrategy !== void 0 ? { historyStrategy: this.options.historyStrategy } : {},
|
|
13067
|
-
...this.options.i18nStrategy !== void 0 ? { i18nStrategy: this.options.i18nStrategy } : {},
|
|
13068
|
-
...this.options.syncStrategy !== void 0 ? { syncStrategy: this.options.syncStrategy } : {},
|
|
13069
12800
|
...this.options.guardStrategies !== void 0 ? { guardStrategies: this.options.guardStrategies } : {},
|
|
13070
12801
|
...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
|
|
13071
|
-
forgetStrategy: this.forgetStrategy,
|
|
13072
|
-
...this.options.attestationStrategy !== void 0 ? { attestationStrategy: this.options.attestationStrategy } : {},
|
|
13073
|
-
...this.options.classifiedStrategy !== void 0 ? { classifiedStrategy: this.options.classifiedStrategy } : {},
|
|
13074
|
-
...this.options.sealedRecordStrategy !== void 0 ? { sealedRecordStrategy: this.options.sealedRecordStrategy } : {},
|
|
13075
|
-
...this.options.portabilityStrategy !== void 0 ? { portabilityStrategy: this.options.portabilityStrategy } : {},
|
|
13076
|
-
...this.options.sequenceStrategy !== void 0 ? { sequenceStrategy: this.options.sequenceStrategy } : {},
|
|
13077
12802
|
locale: opts?.locale,
|
|
13078
12803
|
...opts?.meta !== void 0 ? { meta: opts.meta } : {},
|
|
13079
12804
|
// Thread the translator hook so Collection.put() can invoke it
|
|
@@ -13142,7 +12867,7 @@ var Noydb = class {
|
|
|
13142
12867
|
* Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
|
|
13143
12868
|
*/
|
|
13144
12869
|
async grant(vault, options, factors) {
|
|
13145
|
-
return this.
|
|
12870
|
+
return this.strategies.team.grant(this.team, vault, options, factors);
|
|
13146
12871
|
}
|
|
13147
12872
|
/**
|
|
13148
12873
|
* Revoke a user's access to a vault.
|
|
@@ -13155,7 +12880,7 @@ var Noydb = class {
|
|
|
13155
12880
|
* Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
|
|
13156
12881
|
*/
|
|
13157
12882
|
async revoke(vault, options, factors) {
|
|
13158
|
-
return this.
|
|
12883
|
+
return this.strategies.team.revoke(this.team, vault, options, factors);
|
|
13159
12884
|
}
|
|
13160
12885
|
/**
|
|
13161
12886
|
* Grant the FR-6 `custodian` role to a user (owner-only custody API).
|
|
@@ -13168,7 +12893,7 @@ var Noydb = class {
|
|
|
13168
12893
|
* owner-only invariant even if a host mis-configures the gate.
|
|
13169
12894
|
*/
|
|
13170
12895
|
async grantCustodian(vault, options, factors) {
|
|
13171
|
-
return this.
|
|
12896
|
+
return this.strategies.custody.grantCustodian(this, vault, options, factors);
|
|
13172
12897
|
}
|
|
13173
12898
|
/** @internal — grant-custodian engine, reached only via withCustody(); the
|
|
13174
12899
|
* keyring engine arrives as an argument so the floor never carries it (#267). */
|
|
@@ -13187,7 +12912,7 @@ var Noydb = class {
|
|
|
13187
12912
|
* 'owner'` check, so an admin cannot unwind a custodianship.
|
|
13188
12913
|
*/
|
|
13189
12914
|
async revokeCustodian(vault, options, factors) {
|
|
13190
|
-
return this.
|
|
12915
|
+
return this.strategies.custody.revokeCustodian(this, vault, options, factors);
|
|
13191
12916
|
}
|
|
13192
12917
|
/** @internal — revoke-custodian engine, reached only via withCustody().
|
|
13193
12918
|
* Mirrors `_grantCustodianImpl` (#267: engine passed in). */
|
|
@@ -13266,7 +12991,7 @@ var Noydb = class {
|
|
|
13266
12991
|
* Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
|
|
13267
12992
|
*/
|
|
13268
12993
|
async rotate(vault, collections) {
|
|
13269
|
-
return this.
|
|
12994
|
+
return this.strategies.team.rotate(this.team, vault, collections);
|
|
13270
12995
|
}
|
|
13271
12996
|
/** List all users with access to a vault. */
|
|
13272
12997
|
async listUsers(vault) {
|
|
@@ -13279,9 +13004,9 @@ var Noydb = class {
|
|
|
13279
13004
|
*
|
|
13280
13005
|
* The walk is a two-step pipeline: first ask the adapter for the
|
|
13281
13006
|
* universe of compartments it stores, then for each one attempt to
|
|
13282
|
-
* load the calling user's keyring with the in-memory
|
|
13007
|
+
* load the calling user's keyring with the in-memory secret.
|
|
13283
13008
|
* Compartments where the user has no keyring file (`NoAccessError`)
|
|
13284
|
-
* or where the
|
|
13009
|
+
* or where the secret doesn't unwrap (`InvalidKeyError`) are
|
|
13285
13010
|
* silently dropped from the result — the existence of those
|
|
13286
13011
|
* compartments is **not** confirmed in the return value.
|
|
13287
13012
|
*
|
|
@@ -13302,15 +13027,15 @@ var Noydb = class {
|
|
|
13302
13027
|
* **Known edge case.** A vault whose keyring file
|
|
13303
13028
|
* happens to have an empty wrapped-DEKs map (because the owner
|
|
13304
13029
|
* granted access before any collection was created) will pass the
|
|
13305
|
-
* `loadKeyring` probe with *any*
|
|
13030
|
+
* `loadKeyring` probe with *any* secret — there are no DEKs to
|
|
13306
13031
|
* unwrap, so the integrity-checked unwrap that normally rejects
|
|
13307
|
-
* wrong
|
|
13032
|
+
* wrong secrets never runs. The result is that an unrelated
|
|
13308
13033
|
* principal who happens to know the user-id and the vault
|
|
13309
13034
|
* name can show up in `listAccessibleVaults()` as having
|
|
13310
13035
|
* access to that empty vault. They cannot read any actual
|
|
13311
13036
|
* data (their DEK set is empty), so this is a metadata leak
|
|
13312
13037
|
* (vault name + user-id), not a content leak. Hardening this
|
|
13313
|
-
* via a
|
|
13038
|
+
* via a secret canary in the keyring file is a deferred
|
|
13314
13039
|
* follow-up.
|
|
13315
13040
|
*
|
|
13316
13041
|
* **Cost.** O(compartments × keyring-load) — one `loadKeyring`
|
|
@@ -13351,7 +13076,7 @@ var Noydb = class {
|
|
|
13351
13076
|
}
|
|
13352
13077
|
if (!this.options.secret) {
|
|
13353
13078
|
throw new ValidationError(
|
|
13354
|
-
"Noydb.listAccessibleVaults(): a secret (
|
|
13079
|
+
"Noydb.listAccessibleVaults(): a secret (secret) is required when encryption is enabled."
|
|
13355
13080
|
);
|
|
13356
13081
|
}
|
|
13357
13082
|
const minRank = ROLE_RANK[options.minRole ?? "client"];
|
|
@@ -13490,21 +13215,21 @@ var Noydb = class {
|
|
|
13490
13215
|
return store.resolveBackend ? store.resolveBackend(vaultId) : this.options.store;
|
|
13491
13216
|
}
|
|
13492
13217
|
/**
|
|
13493
|
-
* Change the current user's
|
|
13218
|
+
* Change the current user's secret for a vault.
|
|
13494
13219
|
*
|
|
13495
|
-
* Validates the new
|
|
13496
|
-
* `{
|
|
13497
|
-
* fixtures and migrations. Pass a `
|
|
13220
|
+
* Validates the new secret against the strength rules. Pass
|
|
13221
|
+
* `{ allowWeakSecret: true }` to skip — typically only useful for
|
|
13222
|
+
* fixtures and migrations. Pass a `SecretPolicy` to override the
|
|
13498
13223
|
* default rules (e.g. consumer-tunable `pattern` / `customValidator`).
|
|
13499
13224
|
*/
|
|
13500
|
-
async changeSecret(vault,
|
|
13225
|
+
async changeSecret(vault, newSecret, options) {
|
|
13501
13226
|
this.checkPolicyOperation(vault, "changeSecret");
|
|
13502
13227
|
const keyring = await this._getKeyringInternal(vault);
|
|
13503
13228
|
const updated = await changeSecret(
|
|
13504
13229
|
this.options.store,
|
|
13505
13230
|
vault,
|
|
13506
13231
|
keyring,
|
|
13507
|
-
|
|
13232
|
+
newSecret,
|
|
13508
13233
|
options
|
|
13509
13234
|
);
|
|
13510
13235
|
this.keyringCache.set(vault, updated);
|
|
@@ -13556,7 +13281,7 @@ var Noydb = class {
|
|
|
13556
13281
|
}
|
|
13557
13282
|
transaction(arg, maybeFn) {
|
|
13558
13283
|
if (typeof arg === "function") {
|
|
13559
|
-
return this.
|
|
13284
|
+
return this.strategies.tx.runTransaction(this, arg);
|
|
13560
13285
|
}
|
|
13561
13286
|
if (typeof arg === "object" && arg !== null && arg.dryRun === true) {
|
|
13562
13287
|
if (typeof maybeFn !== "function") {
|
|
@@ -13564,7 +13289,7 @@ var Noydb = class {
|
|
|
13564
13289
|
"db.transaction({ dryRun: true }, fn) requires the callback as the second argument."
|
|
13565
13290
|
);
|
|
13566
13291
|
}
|
|
13567
|
-
return this.
|
|
13292
|
+
return this.strategies.tx.runDryRun(this, maybeFn);
|
|
13568
13293
|
}
|
|
13569
13294
|
if (typeof arg === "object" && arg !== null && arg.amendment === true) {
|
|
13570
13295
|
if (typeof maybeFn !== "function") {
|
|
@@ -13572,7 +13297,7 @@ var Noydb = class {
|
|
|
13572
13297
|
"db.transaction({ amendment: true }, fn) requires the callback as the second argument."
|
|
13573
13298
|
);
|
|
13574
13299
|
}
|
|
13575
|
-
return this.
|
|
13300
|
+
return this.strategies.tx.runTransaction(this, maybeFn, arg);
|
|
13576
13301
|
}
|
|
13577
13302
|
const vault = arg;
|
|
13578
13303
|
const comp = this.vaultCache.get(vault);
|
|
@@ -13582,7 +13307,7 @@ var Noydb = class {
|
|
|
13582
13307
|
);
|
|
13583
13308
|
}
|
|
13584
13309
|
const engine = this.getSyncEngine(vault);
|
|
13585
|
-
return this.
|
|
13310
|
+
return this.strategies.sync.buildSyncTransaction(comp, engine);
|
|
13586
13311
|
}
|
|
13587
13312
|
/**
|
|
13588
13313
|
* Internal accessor for the primary store — used by the tx
|
|
@@ -13863,7 +13588,7 @@ var Noydb = class {
|
|
|
13863
13588
|
enforcer.destroy();
|
|
13864
13589
|
}
|
|
13865
13590
|
this.policyEnforcers.clear();
|
|
13866
|
-
this.
|
|
13591
|
+
this.strategies.session.revokeAllSessions();
|
|
13867
13592
|
for (const engine of this.syncEngines.values()) {
|
|
13868
13593
|
engine.stopAutoSync();
|
|
13869
13594
|
}
|
|
@@ -13985,7 +13710,7 @@ var Noydb = class {
|
|
|
13985
13710
|
* denial; resolves with `void` on success.
|
|
13986
13711
|
*
|
|
13987
13712
|
* @param vault The vault whose policy applies.
|
|
13988
|
-
* @param gate Gate name — built-in (e.g. `'rotate-
|
|
13713
|
+
* @param gate Gate name — built-in (e.g. `'rotate-secret'`)
|
|
13989
13714
|
* or app-defined (`app:*`).
|
|
13990
13715
|
* @param presented Caller-supplied factor proofs.
|
|
13991
13716
|
*/
|
|
@@ -14010,12 +13735,12 @@ var Noydb = class {
|
|
|
14010
13735
|
* Two enforcement modes:
|
|
14011
13736
|
*
|
|
14012
13737
|
* 1. **Managed-mode mandatory strong-recovery.** When
|
|
14013
|
-
* `
|
|
13738
|
+
* `secretMode === 'managed'`, the vault MUST have at least
|
|
14014
13739
|
* one **strong** recovery profile (Shamir today). Paper alone is
|
|
14015
13740
|
* rejected because under managed mode the user has no memorized
|
|
14016
|
-
*
|
|
13741
|
+
* secret, so losing the paper sheet = losing every record.
|
|
14017
13742
|
* This check is unconditional — independent of `requireRecovery`
|
|
14018
|
-
* and the `recover-
|
|
13743
|
+
* and the `recover-secret` gate.
|
|
14019
13744
|
*
|
|
14020
13745
|
* 2. **Opt-in strict mandatory-recovery.** When
|
|
14021
13746
|
* `requireRecovery: true` is set on createNoydb (and the gate is
|
|
@@ -14029,14 +13754,14 @@ var Noydb = class {
|
|
|
14029
13754
|
*/
|
|
14030
13755
|
async assertRecoveryEnrolled(vault, policy, opts) {
|
|
14031
13756
|
const skipManaged = (opts?.skipManagedCheck ?? false) || this._skipNextManagedRecoveryCheck;
|
|
14032
|
-
if (this.options.
|
|
13757
|
+
if (this.options.secretMode === "managed" && !skipManaged) {
|
|
14033
13758
|
const enrolled2 = await hasStrongRecoveryEnrolled(this.options.store, vault);
|
|
14034
13759
|
if (!enrolled2) {
|
|
14035
13760
|
throw new ManagedRecoveryNotEnrolledError(vault);
|
|
14036
13761
|
}
|
|
14037
13762
|
}
|
|
14038
13763
|
if (this.options.requireRecovery !== true) return;
|
|
14039
|
-
const gate = policy.gates["recover-
|
|
13764
|
+
const gate = policy.gates["recover-secret"];
|
|
14040
13765
|
if (gate?.enabled === false) return;
|
|
14041
13766
|
const enrolled = await hasRecoveryEnrolled(this.options.store, vault);
|
|
14042
13767
|
if (enrolled) return;
|
|
@@ -14051,34 +13776,6 @@ var Noydb = class {
|
|
|
14051
13776
|
this.activeTier.set(vault, tier);
|
|
14052
13777
|
}
|
|
14053
13778
|
// ─── Tier-2 enroll / remove ─────────────────────────────────────
|
|
14054
|
-
/** Add a tier-2 authenticator slot — see {@link TeamFacade.enrollAuthenticator}. */
|
|
14055
|
-
async enrollAuthenticator(vault, options, factors) {
|
|
14056
|
-
return this.team.enrollAuthenticator(vault, options, factors);
|
|
14057
|
-
}
|
|
14058
|
-
/** Remove a tier-2 authenticator slot — see {@link TeamFacade.removeAuthenticator}. */
|
|
14059
|
-
async removeAuthenticator(vault, slotId, factors) {
|
|
14060
|
-
return this.team.removeAuthenticator(vault, slotId, factors);
|
|
14061
|
-
}
|
|
14062
|
-
/** Read the slot list for a vault — see {@link TeamFacade.listAuthenticators}. */
|
|
14063
|
-
async listAuthenticators(vault) {
|
|
14064
|
-
return this.team.listAuthenticators(vault);
|
|
14065
|
-
}
|
|
14066
|
-
/** Mutate an authenticator slot's `meta` — see {@link TeamFacade.updateAuthenticator}. */
|
|
14067
|
-
async updateAuthenticator(vault, slotId, options, factors) {
|
|
14068
|
-
return this.team.updateAuthenticator(vault, slotId, options, factors);
|
|
14069
|
-
}
|
|
14070
|
-
/** Native WebAuthn enrollment — see {@link TeamFacade.enrollWebAuthn}. */
|
|
14071
|
-
async enrollWebAuthn(vault, ceremony, factors) {
|
|
14072
|
-
return this.team.enrollWebAuthn(vault, ceremony, factors);
|
|
14073
|
-
}
|
|
14074
|
-
/** List webauthn-method slots — see {@link TeamFacade.listWebAuthnSlots}. */
|
|
14075
|
-
async listWebAuthnSlots(vault) {
|
|
14076
|
-
return this.team.listWebAuthnSlots(vault);
|
|
14077
|
-
}
|
|
14078
|
-
/** Unlock via a tier-2 authenticator slot — see {@link TeamFacade.unlockViaAuthenticator}. */
|
|
14079
|
-
async unlockViaAuthenticator(vault, slotId, verify) {
|
|
14080
|
-
return this.team.unlockViaAuthenticator(vault, slotId, verify);
|
|
14081
|
-
}
|
|
14082
13779
|
// ─── Cover (https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md) ──────
|
|
14083
13780
|
/**
|
|
14084
13781
|
* Set the owner-curated cover for a vault. Throws
|
|
@@ -14102,7 +13799,7 @@ var Noydb = class {
|
|
|
14102
13799
|
"setCover: the cover feature is not enabled. Pass `cover: true` (or a schema object) to `createNoydb`."
|
|
14103
13800
|
);
|
|
14104
13801
|
}
|
|
14105
|
-
const { loadCover, saveCover, resolveSchema, validateCoverInput, mergeCustom, validateCoverSize } = await import("./cover-
|
|
13802
|
+
const { loadCover, saveCover, resolveSchema, validateCoverInput, mergeCustom, validateCoverSize } = await import("./cover-5BSNJREH.js");
|
|
14106
13803
|
const schema = resolveSchema(coverOption);
|
|
14107
13804
|
validateCoverInput(input, schema);
|
|
14108
13805
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -14134,76 +13831,12 @@ var Noydb = class {
|
|
|
14134
13831
|
* regardless).
|
|
14135
13832
|
*/
|
|
14136
13833
|
async getCover(vault, opts = {}) {
|
|
14137
|
-
const { readCover } = await import("./cover-
|
|
13834
|
+
const { readCover } = await import("./cover-5BSNJREH.js");
|
|
14138
13835
|
return readCover(this.options.store, vault, opts);
|
|
14139
13836
|
}
|
|
14140
13837
|
// ─── Auth introspection ─────────────────────────────────────────
|
|
14141
|
-
/** English summary of the configured auth model — see {@link TeamFacade.describeAuthConfig}. */
|
|
14142
|
-
async describeAuthConfig(vault) {
|
|
14143
|
-
return this.team.describeAuthConfig(vault);
|
|
14144
|
-
}
|
|
14145
|
-
/** Mermaid `flowchart TB` source for the auth graph — see {@link TeamFacade.diagramAuthConfig}. */
|
|
14146
|
-
async diagramAuthConfig(vault) {
|
|
14147
|
-
return this.team.diagramAuthConfig(vault);
|
|
14148
|
-
}
|
|
14149
|
-
/** Per-user enrollment summary — see {@link TeamFacade.describeUserAuth}. */
|
|
14150
|
-
async describeUserAuth(vault, userId, factors) {
|
|
14151
|
-
return this.team.describeUserAuth(vault, userId, factors);
|
|
14152
|
-
}
|
|
14153
|
-
/** Bulk per-user enrollment summary — see {@link TeamFacade.describeAllUsersAuth}. */
|
|
14154
|
-
async describeAllUsersAuth(vault, factors) {
|
|
14155
|
-
return this.team.describeAllUsersAuth(vault, factors);
|
|
14156
|
-
}
|
|
14157
13838
|
// ─── Tier-1 change flows ────────────────────────────────────────
|
|
14158
|
-
/** Rotate the user's passphrase (user remembers old) — see {@link TeamFacade.rotatePassphrase}. */
|
|
14159
|
-
async rotatePassphrase(vault, input, factors) {
|
|
14160
|
-
return this.team.rotatePassphrase(vault, input, factors);
|
|
14161
|
-
}
|
|
14162
|
-
/** Reset the passphrase using a recovery proof — see {@link TeamFacade.recoverPassphrase}. */
|
|
14163
|
-
async recoverPassphrase(vault, input, factors) {
|
|
14164
|
-
return this.team.recoverPassphrase(vault, input, factors);
|
|
14165
|
-
}
|
|
14166
|
-
/** Deliberate paper/Shamir recovery-code regeneration — see {@link TeamFacade.rotateRecovery}. */
|
|
14167
|
-
async rotateRecovery(vault, options, factors) {
|
|
14168
|
-
return this.team.rotateRecovery(vault, options, factors);
|
|
14169
|
-
}
|
|
14170
|
-
/** Atomic create-and-enroll for managed-mode vaults — see {@link TeamFacade.openVaultAndEnrollRecovery}. */
|
|
14171
|
-
async openVaultAndEnrollRecovery(vault, opts) {
|
|
14172
|
-
return this.team.openVaultAndEnrollRecovery(vault, opts);
|
|
14173
|
-
}
|
|
14174
|
-
/** Recovery flow under managed-passphrase mode — see {@link TeamFacade.recoverManagedPassphrase}. */
|
|
14175
|
-
async recoverManagedPassphrase(vault, options) {
|
|
14176
|
-
return this.team.recoverManagedPassphrase(vault, options);
|
|
14177
|
-
}
|
|
14178
|
-
/** Atomic peer-recovery of an existing user's keyring — see {@link TeamFacade.recoverUser}. */
|
|
14179
|
-
async recoverUser(vault, options, factors) {
|
|
14180
|
-
return this.team.recoverUser(vault, options, factors);
|
|
14181
|
-
}
|
|
14182
|
-
/** Persist a recovery enrollment (paper or Shamir) — see {@link TeamFacade.enrollRecovery}. */
|
|
14183
|
-
async enrollRecovery(vault, enrollment) {
|
|
14184
|
-
return this.team.enrollRecovery(vault, enrollment);
|
|
14185
|
-
}
|
|
14186
|
-
/** Read the persisted recovery entries (paper + Shamir) — see {@link TeamFacade.listRecoveryEntries}. */
|
|
14187
|
-
async listRecoveryEntries(vault) {
|
|
14188
|
-
return this.team.listRecoveryEntries(vault);
|
|
14189
|
-
}
|
|
14190
13839
|
// ─── Tier-3 enroll / unlock ─────────────────────────────────────
|
|
14191
|
-
/** Register a tier-3 quick-unlock state — see {@link TeamFacade.enrollUnlock}. */
|
|
14192
|
-
async enrollUnlock(vault, state, factors) {
|
|
14193
|
-
return this.team.enrollUnlock(vault, state, factors);
|
|
14194
|
-
}
|
|
14195
|
-
/** Resume a session via the registered tier-3 state — see {@link TeamFacade.unlockViaPin}. */
|
|
14196
|
-
async unlockViaPin(vault, resume) {
|
|
14197
|
-
return this.team.unlockViaPin(vault, resume);
|
|
14198
|
-
}
|
|
14199
|
-
/** Drop the tier-3 state for a vault — see {@link TeamFacade.clearQuickUnlock}. */
|
|
14200
|
-
clearQuickUnlock(vault) {
|
|
14201
|
-
this.team.clearQuickUnlock(vault);
|
|
14202
|
-
}
|
|
14203
|
-
/** Public defensive-copy accessor for the unlocked keyring — see {@link TeamFacade.getKeyring}. */
|
|
14204
|
-
async getKeyring(vault) {
|
|
14205
|
-
return this.team.getKeyring(vault);
|
|
14206
|
-
}
|
|
14207
13840
|
/**
|
|
14208
13841
|
* Live-reference variant used by the hub's own code paths. Internal
|
|
14209
13842
|
* mutations on `deks` (e.g. {@link ensureCollectionDEK} adding a
|
|
@@ -14224,7 +13857,7 @@ var Noydb = class {
|
|
|
14224
13857
|
}
|
|
14225
13858
|
await assertKeyringOpenAllowed(this.options.store, vault, this.options.user, opts.create);
|
|
14226
13859
|
let effectiveSecret;
|
|
14227
|
-
if (this.options.
|
|
13860
|
+
if (this.options.secretMode === "managed") {
|
|
14228
13861
|
effectiveSecret = await resolveManagedSecret(
|
|
14229
13862
|
this.options.store,
|
|
14230
13863
|
vault,
|
|
@@ -14234,7 +13867,7 @@ var Noydb = class {
|
|
|
14234
13867
|
effectiveSecret = this.options.secret;
|
|
14235
13868
|
}
|
|
14236
13869
|
if (!effectiveSecret) {
|
|
14237
|
-
throw new ValidationError("A secret (
|
|
13870
|
+
throw new ValidationError("A secret (secret) or getKeyring callback is required when encryption is enabled");
|
|
14238
13871
|
}
|
|
14239
13872
|
let keyring;
|
|
14240
13873
|
try {
|
|
@@ -14248,10 +13881,10 @@ var Noydb = class {
|
|
|
14248
13881
|
effectiveSecret,
|
|
14249
13882
|
{
|
|
14250
13883
|
// Managed mode generates 256-bit base64 strings that don't satisfy
|
|
14251
|
-
// the human-
|
|
13884
|
+
// the human-secret strength rules (no spaces, no "words").
|
|
14252
13885
|
// Skip validation in managed mode — the entropy floor is already
|
|
14253
13886
|
// 256 bits by construction.
|
|
14254
|
-
validate: this.options.
|
|
13887
|
+
validate: this.options.secretMode === "managed" ? false : this.options.validateSecret === true
|
|
14255
13888
|
}
|
|
14256
13889
|
);
|
|
14257
13890
|
} else if (err instanceof InvalidKeyError && this.options.onInvalidKey === "reset") {
|
|
@@ -14262,7 +13895,7 @@ var Noydb = class {
|
|
|
14262
13895
|
this.options.user,
|
|
14263
13896
|
effectiveSecret,
|
|
14264
13897
|
{
|
|
14265
|
-
validate: this.options.
|
|
13898
|
+
validate: this.options.secretMode === "managed" ? false : this.options.validateSecret === true
|
|
14266
13899
|
}
|
|
14267
13900
|
);
|
|
14268
13901
|
} else {
|
|
@@ -14300,34 +13933,34 @@ var Noydb = class {
|
|
|
14300
13933
|
async function createNoydb(options) {
|
|
14301
13934
|
if (!options.store) options = { ...options, store: memoryStore() };
|
|
14302
13935
|
const encrypted = options.encrypt !== false;
|
|
14303
|
-
const managed = options.
|
|
13936
|
+
const managed = options.secretMode === "managed";
|
|
14304
13937
|
if (options.secret && options.getKeyring) {
|
|
14305
13938
|
throw new ValidationError("Provide either `secret` or `getKeyring`, not both");
|
|
14306
13939
|
}
|
|
14307
13940
|
if (managed) {
|
|
14308
13941
|
if (options.secret) {
|
|
14309
13942
|
throw new ValidationError(
|
|
14310
|
-
'`
|
|
13943
|
+
'`secretMode: "managed"` is mutually exclusive with `secret` \u2014 managed mode generates the secret itself. Drop `secret`.'
|
|
14311
13944
|
);
|
|
14312
13945
|
}
|
|
14313
13946
|
if (options.getKeyring) {
|
|
14314
13947
|
throw new ValidationError(
|
|
14315
|
-
'`
|
|
13948
|
+
'`secretMode: "managed"` is mutually exclusive with `getKeyring` \u2014 a custom unlock callback would bypass the sealing flow. Drop `getKeyring`.'
|
|
14316
13949
|
);
|
|
14317
13950
|
}
|
|
14318
13951
|
if (!options.sealingKey) {
|
|
14319
13952
|
throw new ValidationError(
|
|
14320
|
-
'`
|
|
13953
|
+
'`secretMode: "managed"` requires `sealingKey: SealingKeyProvider` (see @noy-db/seal-macos-keychain / @noy-db/seal-aws-kms / etc.).'
|
|
14321
13954
|
);
|
|
14322
13955
|
}
|
|
14323
13956
|
}
|
|
14324
13957
|
if (encrypted && !managed && !options.secret && !options.getKeyring) {
|
|
14325
|
-
throw new ValidationError("A secret (
|
|
13958
|
+
throw new ValidationError("A secret (secret) or getKeyring callback is required when encryption is enabled");
|
|
14326
13959
|
}
|
|
14327
13960
|
if (!options.coordinationStrategy) options = { ...options, coordinationStrategy: await createDefaultCoordinationProvider(options.store) };
|
|
14328
|
-
if (!options.userApiFactory) options = { ...options, userApiFactory: (await import("./api-
|
|
13961
|
+
if (!options.userApiFactory) options = { ...options, userApiFactory: (await import("./api-22ES33N3.js")).createUserApi };
|
|
14329
13962
|
if (!options.policyFactory) {
|
|
14330
|
-
const policyModule = await import("./policy-
|
|
13963
|
+
const policyModule = await import("./policy-IY2YEA3A.js");
|
|
14331
13964
|
options = { ...options, policyFactory: policyModule.createNoydbPolicy, policyCheckGateFn: policyModule.checkGate };
|
|
14332
13965
|
}
|
|
14333
13966
|
return new Noydb(options);
|
|
@@ -14364,4 +13997,4 @@ export {
|
|
|
14364
13997
|
Noydb,
|
|
14365
13998
|
createNoydb
|
|
14366
13999
|
};
|
|
14367
|
-
//# sourceMappingURL=chunk-
|
|
14000
|
+
//# sourceMappingURL=chunk-EEZCB74X.js.map
|