@noy-db/hub 0.9.0-pre.0 → 0.9.0-pre.2
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/CHANGELOG.md +39 -0
- package/dist/api-H4B7ZQXP.js +18 -0
- package/dist/as/index.js +10 -10
- package/dist/at/index.js +8 -8
- package/dist/attestation/index.js +18 -18
- package/dist/{backup-7RKNZMQO.js → backup-E3GBMNDA.js} +92 -31
- package/dist/backup-E3GBMNDA.js.map +1 -0
- package/dist/blobs/index.js +12 -12
- package/dist/broker/index.js +13 -13
- package/dist/by/index.js +2 -2
- package/dist/capsule/contract.js +6 -6
- package/dist/capsule/enclave-aes/crypto.d.ts +18 -0
- package/dist/capsule/enclave-aes/index.d.ts +2 -2
- package/dist/capsule/enclave-aes/index.js +14 -8
- package/dist/capsule/enclave-aes/index.js.map +1 -1
- package/dist/capsule/index.d.ts +1 -1
- package/dist/{capsule-57BDK7LG.js → capsule-YQKQZPH7.js} +14 -8
- package/dist/cargo/index.js +35 -35
- package/dist/{chunk-AJFPAHMW.js → chunk-27NCEPKM.js} +3 -3
- package/dist/{chunk-PGC35KXE.js → chunk-2IASHJPS.js} +2 -2
- package/dist/{chunk-NYJBYVBG.js → chunk-2ODEFG6K.js} +4 -4
- package/dist/{chunk-7BMOS4JQ.js → chunk-2QH3I7QC.js} +11 -11
- package/dist/{chunk-VSUQI5Q6.js → chunk-2RH5SEY7.js} +16 -2
- package/dist/chunk-2RH5SEY7.js.map +1 -0
- package/dist/{chunk-IVMFIKNA.js → chunk-2T2TGRWE.js} +6 -6
- package/dist/{chunk-G66YXUTY.js → chunk-35CNOVQE.js} +3 -3
- package/dist/{chunk-OJU67C23.js → chunk-3EXQXOQ2.js} +4 -4
- package/dist/{chunk-BJH77UY2.js → chunk-4KYKRYRT.js} +2 -2
- package/dist/{chunk-RDOEOPOI.js → chunk-4N4OIVK3.js} +5 -5
- package/dist/{chunk-WHOKGHJ3.js → chunk-4WLI37WK.js} +7 -7
- package/dist/{chunk-RNACRT5H.js → chunk-52ZFNK46.js} +2 -2
- package/dist/{chunk-CB4467G3.js → chunk-5A3HOTP5.js} +33 -7
- package/dist/chunk-5A3HOTP5.js.map +1 -0
- package/dist/{chunk-QDHHHI5Q.js → chunk-5SMCBPJ2.js} +5 -5
- package/dist/{chunk-EMAWOGVH.js → chunk-654RE5YC.js} +3 -3
- package/dist/{chunk-FZXRLNJO.js → chunk-6BEBWHNL.js} +3 -3
- package/dist/{chunk-EUD3HQM4.js → chunk-6WEPFEMJ.js} +4 -4
- package/dist/{chunk-YFFMPZPY.js → chunk-6WIFF46H.js} +2 -2
- package/dist/{chunk-ZVSKSUGI.js → chunk-7C7OF26T.js} +5 -5
- package/dist/{chunk-QXJXG7DN.js → chunk-7IV7GVOS.js} +5 -5
- package/dist/{chunk-MQ7YWBQ5.js → chunk-7JRLCP2J.js} +2 -2
- package/dist/{chunk-QSHATAXJ.js → chunk-7ONMS7QI.js} +2 -2
- package/dist/{chunk-JBMMWYOH.js → chunk-7UHLO4ZN.js} +35 -2
- package/dist/chunk-7UHLO4ZN.js.map +1 -0
- package/dist/{chunk-6WS35E6X.js → chunk-A52BK5AY.js} +2 -2
- package/dist/{chunk-GOJQ5DZA.js → chunk-AI35LNWQ.js} +4 -4
- package/dist/chunk-AI35LNWQ.js.map +1 -0
- package/dist/{chunk-XXQ5XIYY.js → chunk-AMSSAOOB.js} +2 -2
- package/dist/{chunk-3V6LZHUO.js → chunk-AYOQZJDB.js} +2 -2
- package/dist/{chunk-DL6BZKP3.js → chunk-B3B6HV5S.js} +2 -2
- package/dist/{chunk-5XONHAFD.js → chunk-B6EWMGFX.js} +2 -2
- package/dist/{chunk-6Y5E4SJU.js → chunk-BMAXBTYH.js} +5 -5
- package/dist/{chunk-LGGIFKJP.js → chunk-BNYDOF2Q.js} +4 -4
- package/dist/{chunk-XXNWU5QZ.js → chunk-BQJ5ORU5.js} +2 -2
- package/dist/{chunk-Z3ZXVB2Y.js → chunk-BSEPI3HD.js} +12 -12
- package/dist/chunk-BSEPI3HD.js.map +1 -0
- package/dist/{chunk-BYHCKX73.js → chunk-CLOSXHR4.js} +3 -3
- package/dist/{chunk-5HNW4ZTA.js → chunk-CSAN22QG.js} +6 -6
- package/dist/{chunk-TZYTMZZY.js → chunk-DL4GCSTS.js} +10 -10
- package/dist/{chunk-EA4VDI5D.js → chunk-DYIR6RC3.js} +4 -4
- package/dist/{chunk-PUBI455O.js → chunk-EPPAEGH5.js} +2 -2
- package/dist/{chunk-2A56DSRI.js → chunk-EQ6C2ZPT.js} +17 -51
- package/dist/chunk-EQ6C2ZPT.js.map +1 -0
- package/dist/{chunk-BNFNQNEP.js → chunk-F7X7MPK4.js} +2 -2
- package/dist/{chunk-SNM7LSYG.js → chunk-FUHUGKDN.js} +4 -4
- package/dist/{chunk-72XBVN4J.js → chunk-FVKQ5QUC.js} +2 -2
- package/dist/chunk-FVKQ5QUC.js.map +1 -0
- package/dist/{chunk-D4V5JJAK.js → chunk-GHMINSER.js} +4 -4
- package/dist/{chunk-APFFJN5T.js → chunk-GLSCL74M.js} +31 -34
- package/dist/chunk-GLSCL74M.js.map +1 -0
- package/dist/{chunk-XKBTJGFP.js → chunk-GU6QXHPZ.js} +3 -3
- package/dist/chunk-GU6QXHPZ.js.map +1 -0
- package/dist/{chunk-QGFEBNHO.js → chunk-GZISWBCJ.js} +4 -4
- package/dist/{chunk-OM3SEDI4.js → chunk-HTRLQ4ZZ.js} +4 -4
- package/dist/{chunk-SWXLZ4HX.js → chunk-ICHHNI5E.js} +8 -8
- package/dist/{chunk-K673OO6B.js → chunk-ID4ZBC3X.js} +4 -4
- package/dist/{chunk-H3YM66EI.js → chunk-IF2M43G4.js} +2 -2
- package/dist/{chunk-QGSNJD3B.js → chunk-IFUYLIEY.js} +2 -2
- package/dist/{chunk-D5A3GCZ4.js → chunk-IPF5ORDI.js} +3 -3
- package/dist/{delegation-ONLM4JFI.js → chunk-JQMEXCUZ.js} +59 -16
- package/dist/chunk-JQMEXCUZ.js.map +1 -0
- package/dist/{chunk-TFWFPZRU.js → chunk-K5JNK63R.js} +11 -11
- package/dist/{chunk-TFWFPZRU.js.map → chunk-K5JNK63R.js.map} +1 -1
- package/dist/{chunk-BVF3SXD7.js → chunk-KBIS64X4.js} +5 -5
- package/dist/chunk-L4UL4IAR.js +55 -0
- package/dist/chunk-L4UL4IAR.js.map +1 -0
- package/dist/{chunk-RIZTZJX6.js → chunk-LJ744WXU.js} +2 -2
- package/dist/{chunk-XITHENBI.js → chunk-LMC5L3MM.js} +7 -7
- package/dist/{chunk-XITHENBI.js.map → chunk-LMC5L3MM.js.map} +1 -1
- package/dist/{chunk-L5A3KR7R.js → chunk-LUQBG637.js} +3 -3
- package/dist/{chunk-6QLCS7ET.js → chunk-LZN6DTFI.js} +2 -2
- package/dist/{chunk-NIXRB5BP.js → chunk-MMWX5OT5.js} +2 -2
- package/dist/{chunk-JA25QG5M.js → chunk-N6EWQ5VB.js} +622 -119
- package/dist/chunk-N6EWQ5VB.js.map +1 -0
- package/dist/{chunk-UOZOWN73.js → chunk-ND6S2DKC.js} +2 -2
- package/dist/{chunk-WFWFXDNS.js → chunk-NHEKQWFI.js} +2 -2
- package/dist/{chunk-2ZFD2UJC.js → chunk-NIUHKKMM.js} +9 -9
- package/dist/{chunk-XA34THLF.js → chunk-NK4LGBGQ.js} +4 -4
- package/dist/{chunk-JSWKVZCR.js → chunk-NUZ7ROUZ.js} +2 -2
- package/dist/{chunk-DHU2AQ6T.js → chunk-O3NGOHXQ.js} +2 -2
- package/dist/{chunk-ZBUAX4EF.js → chunk-O6VOR4NH.js} +2 -2
- package/dist/{chunk-JZ4EDEIP.js → chunk-ODBOHPZU.js} +3 -3
- package/dist/{chunk-5UUJE4FP.js → chunk-OK44MD3C.js} +2 -2
- package/dist/{chunk-ECGXA4LT.js → chunk-OR3OHKU6.js} +2 -2
- package/dist/{chunk-ZWF3EWZA.js → chunk-P6FATPXQ.js} +2 -2
- package/dist/{chunk-PCYPXLEX.js → chunk-PBEHTFUG.js} +6 -6
- package/dist/{chunk-7CT6SX4M.js → chunk-PFHDQY5L.js} +3 -3
- package/dist/{chunk-PTJY5R3O.js → chunk-PIO6NW7O.js} +2 -2
- package/dist/{chunk-TMIJAR2X.js → chunk-PREYKC76.js} +3 -3
- package/dist/{chunk-ZHQJAV6D.js → chunk-PU5ZEV65.js} +2 -2
- package/dist/{chunk-UNSQZSZP.js → chunk-PWAMX5KU.js} +2 -2
- package/dist/{chunk-GETUTTZU.js → chunk-PZN76MMV.js} +4 -4
- package/dist/{chunk-ABU6A4Z5.js → chunk-Q4DBU5RM.js} +2 -2
- package/dist/{chunk-2WJKJZSO.js → chunk-QHG7GQKM.js} +2 -2
- package/dist/{chunk-UAKY6E4N.js → chunk-QNOWNCZS.js} +2 -2
- package/dist/{chunk-JPSL5GIZ.js → chunk-QQLXKDGC.js} +3 -3
- package/dist/{chunk-45VHWE4C.js → chunk-QVUMKG3Z.js} +271 -69
- package/dist/chunk-QVUMKG3Z.js.map +1 -0
- package/dist/{chunk-OK57EATL.js → chunk-R4GLRJ55.js} +2 -2
- package/dist/{chunk-B65CC6Z6.js → chunk-RF5WDM25.js} +2 -2
- package/dist/{chunk-G46JSSVX.js → chunk-RKBCUP5D.js} +7 -7
- package/dist/{chunk-GCUMOKTN.js → chunk-S2ORTQGS.js} +3 -3
- package/dist/{chunk-MRJDLXI3.js → chunk-SVXFCCSX.js} +8 -8
- package/dist/{chunk-BUE7R3B5.js → chunk-SXPLIRQH.js} +2 -2
- package/dist/{chunk-5LMCVBMY.js → chunk-T5EXREMW.js} +5 -5
- package/dist/{chunk-PT2YCQVK.js → chunk-TBVDI3LY.js} +4 -4
- package/dist/{chunk-BMHQHH7Q.js → chunk-TLIFNRU5.js} +2 -2
- package/dist/{chunk-YKGJ44Z7.js → chunk-TU6ZJTYT.js} +3 -3
- package/dist/{chunk-FSQNGPHH.js → chunk-U277K5GR.js} +612 -175
- package/dist/chunk-U277K5GR.js.map +1 -0
- package/dist/{chunk-55P6OBB7.js → chunk-U43RSPPX.js} +2 -2
- package/dist/{chunk-K7RW7FI4.js → chunk-UADW5NOU.js} +5 -5
- package/dist/{chunk-GRS2HIV6.js → chunk-UMV5GBTJ.js} +2 -2
- package/dist/{chunk-4UIP3QNW.js → chunk-UNAMWK2Q.js} +2 -2
- package/dist/{chunk-J4KAPKBJ.js → chunk-UORWAG7K.js} +2 -2
- package/dist/{chunk-V55JASXO.js → chunk-UQRKAM2R.js} +3 -3
- package/dist/{chunk-2ELOCEXE.js → chunk-URGHKZPL.js} +1 -1
- package/dist/chunk-URGHKZPL.js.map +1 -0
- package/dist/{chunk-ZMVSKYTJ.js → chunk-VLRY2UH4.js} +10 -10
- package/dist/{chunk-SPPOUJLN.js → chunk-VZFTON37.js} +2 -2
- package/dist/{chunk-CAD7N6HQ.js → chunk-WIUH6EJ7.js} +10 -10
- package/dist/chunk-WIUH6EJ7.js.map +1 -0
- package/dist/{chunk-YQFBH5ZJ.js → chunk-WQUIJPN4.js} +3 -3
- package/dist/{chunk-4J3MNVVX.js → chunk-WRLWEYHY.js} +7 -1
- package/dist/{chunk-4J3MNVVX.js.map → chunk-WRLWEYHY.js.map} +1 -1
- package/dist/{chunk-NZULV7LK.js → chunk-WVQDY3UM.js} +4 -4
- package/dist/{chunk-3Y5JLSXS.js → chunk-X5RGG3ZW.js} +2 -2
- package/dist/{chunk-PFCTSXHU.js → chunk-X6Z2SIRF.js} +2 -2
- package/dist/{chunk-UHFGK6YA.js → chunk-XQGKS4OW.js} +3 -3
- package/dist/{chunk-L2F3CFCH.js → chunk-Y22JWHCP.js} +4 -4
- package/dist/{chunk-C53ER7AG.js → chunk-YVA6UPRN.js} +2 -2
- package/dist/{chunk-226V6XXJ.js → chunk-Z2KP6PNF.js} +6 -6
- package/dist/{chunk-G5EDYVSE.js → chunk-ZK2WT532.js} +5 -5
- package/dist/{chunk-SFCD6OU7.js → chunk-ZNVBCKMV.js} +2 -2
- package/dist/{chunk-BU2ABHFW.js → chunk-ZOFNZLAA.js} +4 -4
- package/dist/{chunk-X2RP4TO5.js → chunk-ZVJKHGE5.js} +7 -7
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-KHDOYIJB.js → classified-marker-7HXDMYHI.js} +3 -3
- package/dist/collection-facade-V63BEBGU.js +41 -0
- package/dist/{computed-XMFTHAXV.js → computed-LZLSYOPG.js} +3 -3
- package/dist/consent/index.js +8 -8
- package/dist/cover/index.js +8 -8
- package/dist/custody/index.js +12 -12
- package/dist/{dead-filter-CXV5NS67.js → dead-filter-PZIJ4F4G.js} +10 -10
- package/dist/debug/index.js +7 -7
- package/dist/delegation-7SSGIETH.js +26 -0
- package/dist/derivations/index.js +22 -22
- package/dist/derive-IMI3BMDS.js +20 -0
- package/dist/directory/index.js +9 -9
- package/dist/{dispatch-2MQFMEGY.js → dispatch-4BUYPWMJ.js} +19 -19
- package/dist/{dispatch-OFDA4WQV.js → dispatch-KOPDDPEQ.js} +5 -5
- package/dist/executor-7SY3M6TZ.js +8 -0
- package/dist/executor-SNHW4ELF.js +35 -0
- package/dist/executor-Z3IKK7G3.js +8 -0
- package/dist/export-accessible-O7DIVFUO.js +22 -0
- package/dist/extract-partition-ELZEJKXM.js +35 -0
- package/dist/{fanout-sidecar-BO67PCPO.js → fanout-sidecar-FYDRL7F3.js} +8 -8
- package/dist/find-KWB2RYWJ.js +10 -0
- package/dist/forget/index.js +8 -8
- package/dist/guards/index.js +4 -4
- package/dist/history/index.js +15 -13
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.js +13 -13
- package/dist/index.d.ts +3 -2
- package/dist/index.js +111 -107
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +5 -5
- package/dist/introspection/index.js +10 -10
- package/dist/issue-5ZHXK4HJ.js +19 -0
- package/dist/kernel/collection.d.ts +85 -6
- package/dist/kernel/constants.d.ts +7 -0
- package/dist/kernel/errors.d.ts +9 -0
- package/dist/kernel/merge-authority.d.ts +5 -1
- package/dist/kernel/noydb.d.ts +116 -21
- package/dist/kernel/rejection-seal.d.ts +13 -0
- package/dist/kernel/sync-wiring.d.ts +55 -0
- package/dist/kernel/types.d.ts +366 -8
- package/dist/kernel/vault.d.ts +39 -5
- package/dist/{ledger-MSJGWKGW.js → ledger-UFJCB6T5.js} +10 -10
- package/dist/liberate-OEOSNNFH.js +25 -0
- package/dist/{link-set-QXXSPPHL.js → link-set-KMUBFN2L.js} +10 -10
- package/dist/{managed-secret-VSK7ANQI.js → managed-secret-H5WYSJ46.js} +9 -9
- package/dist/materialized-views/index.js +25 -25
- package/dist/{migrate-cek-GEBFYBDC.js → migrate-cek-SPESQAAO.js} +2 -2
- package/dist/money/index.js +5 -5
- package/dist/noydb-QDZ4QIKO.js +100 -0
- package/dist/on/index.js +12 -12
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +11 -11
- package/dist/pod/index.js +66 -64
- package/dist/{pod-handle-YE7CT66T.js → pod-handle-GJLCOUGK.js} +8 -8
- package/dist/policy/index.js +9 -9
- package/dist/port/at/index.d.ts +1 -1
- package/dist/port/by/index.d.ts +1 -1
- package/dist/port/on/index.d.ts +1 -1
- package/dist/port/with/admission-authority.d.ts +34 -0
- package/dist/port/with/broker-strategy.d.ts +10 -0
- package/dist/port/with/rejection-courier.d.ts +37 -0
- package/dist/port/with/restore-host.d.ts +33 -0
- package/dist/port/with/service-bus.d.ts +18 -0
- package/dist/port/with/team-strategy.d.ts +2 -2
- package/dist/port/with/write-hooks.d.ts +2 -0
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-QC5TEAW3.js → post-register-2AC2STHC.js} +6 -6
- package/dist/query/all/index.js +15 -15
- package/dist/query/index.js +7 -7
- package/dist/query/live/index.js +7 -7
- package/dist/query/reduce/index.js +10 -10
- package/dist/query/relate/index.js +9 -9
- package/dist/reduce/index.js +8 -8
- package/dist/register-PIORIMMR.js +30 -0
- package/dist/registry-BIMICFUH.js +23 -0
- package/dist/registry-JGWLW53D.js +35 -0
- package/dist/registry-SELCBYEQ.js +8 -0
- package/dist/registry-W327UNYH.js +8 -0
- package/dist/request-withdrawal-K3SXXODI.js +28 -0
- package/dist/restore-to-OOPKLAPU.js +66 -0
- package/dist/restore-to-OOPKLAPU.js.map +1 -0
- package/dist/{reveal-YQTRNQFH.js → reveal-UAPBG743.js} +7 -7
- package/dist/revoke-6AFVXTWF.js +24 -0
- package/dist/satellites/index.js +1 -1
- package/dist/schema-update/index.js +2 -2
- package/dist/sealed-record/index.js +11 -11
- package/dist/search/index.js +4 -4
- package/dist/{seed-JMQTRKRE.js → seed-BVYDPVIW.js} +33 -18
- package/dist/seed-BVYDPVIW.js.map +1 -0
- package/dist/sequence/index.js +8 -8
- package/dist/session/index.js +8 -8
- package/dist/shadow/index.js +2 -2
- package/dist/signer-TW5MAQJP.js +23 -0
- package/dist/snapshots/index.js +9 -9
- package/dist/{stale-SKV33PBU.js → stale-CROGJBIJ.js} +9 -9
- package/dist/storage-SO2L2Z5J.js +21 -0
- package/dist/{store-coordination-provider-Z6HKPOGM.js → store-coordination-provider-2YD2PTTP.js} +9 -9
- package/dist/sync/index.js +16 -16
- package/dist/sync/index.js.map +1 -1
- package/dist/team/index.js +15 -15
- package/dist/tiers/index.js +10 -10
- package/dist/to/index.js +2 -2
- package/dist/transactions/index.js +3 -3
- package/dist/util/index.js +1 -1
- package/dist/vault-head/index.js +7 -7
- package/dist/{verify-KWQIWLGH.js → verify-QWO5UKD6.js} +7 -7
- package/dist/walk-3KEOL7BY.js +20 -0
- package/dist/with-audit/guards/types.d.ts +2 -0
- package/dist/with-audit/tiers/index.d.ts +5 -5
- package/dist/with-commit/history/history.d.ts +16 -0
- package/dist/with-commit/history/restore-to.d.ts +40 -0
- package/dist/with-party/broker/seed.d.ts +4 -0
- package/dist/with-party/custody/strategy.d.ts +2 -2
- package/dist/with-party/team/delegation.d.ts +41 -11
- package/dist/with-party/team/index.d.ts +2 -0
- package/dist/with-party/team/keyring.d.ts +133 -3
- package/dist/with-party/team/managed-secret.d.ts +1 -1
- package/dist/with-party/team/noydb-facade.d.ts +14 -2
- package/dist/with-party/team/roster-tag.d.ts +1 -1
- package/dist/with-pod/backup.d.ts +9 -17
- package/dist/with-sync/active.d.ts +28 -1
- package/dist/with-sync/engine.d.ts +59 -2
- package/dist/with-sync/index.d.ts +1 -0
- package/dist/with-sync/reserved-mirror.d.ts +27 -4
- package/dist/with-sync/strategy.d.ts +2 -0
- package/dist/withdraw-accessible-OZU525ND.js +25 -0
- package/dist/withdraw-accessible-OZU525ND.js.map +1 -0
- package/package.json +3 -3
- package/dist/api-MSJXVYQG.js +0 -18
- package/dist/backup-7RKNZMQO.js.map +0 -1
- package/dist/chunk-2A56DSRI.js.map +0 -1
- package/dist/chunk-2ELOCEXE.js.map +0 -1
- package/dist/chunk-45VHWE4C.js.map +0 -1
- package/dist/chunk-72XBVN4J.js.map +0 -1
- package/dist/chunk-APFFJN5T.js.map +0 -1
- package/dist/chunk-CAD7N6HQ.js.map +0 -1
- package/dist/chunk-CB4467G3.js.map +0 -1
- package/dist/chunk-FSQNGPHH.js.map +0 -1
- package/dist/chunk-GOJQ5DZA.js.map +0 -1
- package/dist/chunk-JA25QG5M.js.map +0 -1
- package/dist/chunk-JBMMWYOH.js.map +0 -1
- package/dist/chunk-VSUQI5Q6.js.map +0 -1
- package/dist/chunk-XKBTJGFP.js.map +0 -1
- package/dist/chunk-Z3ZXVB2Y.js.map +0 -1
- package/dist/collection-facade-LZIF7GWD.js +0 -41
- package/dist/delegation-ONLM4JFI.js.map +0 -1
- package/dist/derive-3YSIS36W.js +0 -20
- package/dist/executor-E6YDJ7YA.js +0 -8
- package/dist/executor-NJX3YQQ4.js +0 -35
- package/dist/executor-WWM3DD4P.js +0 -8
- package/dist/export-accessible-RLHU5G4W.js +0 -22
- package/dist/extract-partition-QII2EDCS.js +0 -35
- package/dist/find-6M7GYDUZ.js +0 -10
- package/dist/issue-LPEEEMPP.js +0 -19
- package/dist/liberate-LEKDYKTC.js +0 -25
- package/dist/noydb-F2AUF6KL.js +0 -98
- package/dist/register-SN72QALV.js +0 -30
- package/dist/registry-253FF7C6.js +0 -35
- package/dist/registry-3AZWQTDT.js +0 -23
- package/dist/registry-7UEBTHWG.js +0 -8
- package/dist/registry-IVJ67NFQ.js +0 -8
- package/dist/request-withdrawal-UKVJZKX2.js +0 -28
- package/dist/revoke-G2KXJQA5.js +0 -24
- package/dist/seed-JMQTRKRE.js.map +0 -1
- package/dist/signer-IUIYR3CX.js +0 -23
- package/dist/storage-NPBYP2SM.js +0 -21
- package/dist/walk-F4OLXI5H.js +0 -20
- package/dist/withdraw-accessible-ZKPLZ66E.js +0 -25
- /package/dist/{api-MSJXVYQG.js.map → api-H4B7ZQXP.js.map} +0 -0
- /package/dist/{capsule-57BDK7LG.js.map → capsule-YQKQZPH7.js.map} +0 -0
- /package/dist/{chunk-AJFPAHMW.js.map → chunk-27NCEPKM.js.map} +0 -0
- /package/dist/{chunk-PGC35KXE.js.map → chunk-2IASHJPS.js.map} +0 -0
- /package/dist/{chunk-NYJBYVBG.js.map → chunk-2ODEFG6K.js.map} +0 -0
- /package/dist/{chunk-7BMOS4JQ.js.map → chunk-2QH3I7QC.js.map} +0 -0
- /package/dist/{chunk-IVMFIKNA.js.map → chunk-2T2TGRWE.js.map} +0 -0
- /package/dist/{chunk-G66YXUTY.js.map → chunk-35CNOVQE.js.map} +0 -0
- /package/dist/{chunk-OJU67C23.js.map → chunk-3EXQXOQ2.js.map} +0 -0
- /package/dist/{chunk-BJH77UY2.js.map → chunk-4KYKRYRT.js.map} +0 -0
- /package/dist/{chunk-RDOEOPOI.js.map → chunk-4N4OIVK3.js.map} +0 -0
- /package/dist/{chunk-WHOKGHJ3.js.map → chunk-4WLI37WK.js.map} +0 -0
- /package/dist/{chunk-RNACRT5H.js.map → chunk-52ZFNK46.js.map} +0 -0
- /package/dist/{chunk-QDHHHI5Q.js.map → chunk-5SMCBPJ2.js.map} +0 -0
- /package/dist/{chunk-EMAWOGVH.js.map → chunk-654RE5YC.js.map} +0 -0
- /package/dist/{chunk-FZXRLNJO.js.map → chunk-6BEBWHNL.js.map} +0 -0
- /package/dist/{chunk-EUD3HQM4.js.map → chunk-6WEPFEMJ.js.map} +0 -0
- /package/dist/{chunk-YFFMPZPY.js.map → chunk-6WIFF46H.js.map} +0 -0
- /package/dist/{chunk-ZVSKSUGI.js.map → chunk-7C7OF26T.js.map} +0 -0
- /package/dist/{chunk-QXJXG7DN.js.map → chunk-7IV7GVOS.js.map} +0 -0
- /package/dist/{chunk-MQ7YWBQ5.js.map → chunk-7JRLCP2J.js.map} +0 -0
- /package/dist/{chunk-QSHATAXJ.js.map → chunk-7ONMS7QI.js.map} +0 -0
- /package/dist/{chunk-6WS35E6X.js.map → chunk-A52BK5AY.js.map} +0 -0
- /package/dist/{chunk-XXQ5XIYY.js.map → chunk-AMSSAOOB.js.map} +0 -0
- /package/dist/{chunk-3V6LZHUO.js.map → chunk-AYOQZJDB.js.map} +0 -0
- /package/dist/{chunk-DL6BZKP3.js.map → chunk-B3B6HV5S.js.map} +0 -0
- /package/dist/{chunk-5XONHAFD.js.map → chunk-B6EWMGFX.js.map} +0 -0
- /package/dist/{chunk-6Y5E4SJU.js.map → chunk-BMAXBTYH.js.map} +0 -0
- /package/dist/{chunk-LGGIFKJP.js.map → chunk-BNYDOF2Q.js.map} +0 -0
- /package/dist/{chunk-XXNWU5QZ.js.map → chunk-BQJ5ORU5.js.map} +0 -0
- /package/dist/{chunk-BYHCKX73.js.map → chunk-CLOSXHR4.js.map} +0 -0
- /package/dist/{chunk-5HNW4ZTA.js.map → chunk-CSAN22QG.js.map} +0 -0
- /package/dist/{chunk-TZYTMZZY.js.map → chunk-DL4GCSTS.js.map} +0 -0
- /package/dist/{chunk-EA4VDI5D.js.map → chunk-DYIR6RC3.js.map} +0 -0
- /package/dist/{chunk-PUBI455O.js.map → chunk-EPPAEGH5.js.map} +0 -0
- /package/dist/{chunk-BNFNQNEP.js.map → chunk-F7X7MPK4.js.map} +0 -0
- /package/dist/{chunk-SNM7LSYG.js.map → chunk-FUHUGKDN.js.map} +0 -0
- /package/dist/{chunk-D4V5JJAK.js.map → chunk-GHMINSER.js.map} +0 -0
- /package/dist/{chunk-QGFEBNHO.js.map → chunk-GZISWBCJ.js.map} +0 -0
- /package/dist/{chunk-OM3SEDI4.js.map → chunk-HTRLQ4ZZ.js.map} +0 -0
- /package/dist/{chunk-SWXLZ4HX.js.map → chunk-ICHHNI5E.js.map} +0 -0
- /package/dist/{chunk-K673OO6B.js.map → chunk-ID4ZBC3X.js.map} +0 -0
- /package/dist/{chunk-H3YM66EI.js.map → chunk-IF2M43G4.js.map} +0 -0
- /package/dist/{chunk-QGSNJD3B.js.map → chunk-IFUYLIEY.js.map} +0 -0
- /package/dist/{chunk-D5A3GCZ4.js.map → chunk-IPF5ORDI.js.map} +0 -0
- /package/dist/{chunk-BVF3SXD7.js.map → chunk-KBIS64X4.js.map} +0 -0
- /package/dist/{chunk-RIZTZJX6.js.map → chunk-LJ744WXU.js.map} +0 -0
- /package/dist/{chunk-L5A3KR7R.js.map → chunk-LUQBG637.js.map} +0 -0
- /package/dist/{chunk-6QLCS7ET.js.map → chunk-LZN6DTFI.js.map} +0 -0
- /package/dist/{chunk-NIXRB5BP.js.map → chunk-MMWX5OT5.js.map} +0 -0
- /package/dist/{chunk-UOZOWN73.js.map → chunk-ND6S2DKC.js.map} +0 -0
- /package/dist/{chunk-WFWFXDNS.js.map → chunk-NHEKQWFI.js.map} +0 -0
- /package/dist/{chunk-2ZFD2UJC.js.map → chunk-NIUHKKMM.js.map} +0 -0
- /package/dist/{chunk-XA34THLF.js.map → chunk-NK4LGBGQ.js.map} +0 -0
- /package/dist/{chunk-JSWKVZCR.js.map → chunk-NUZ7ROUZ.js.map} +0 -0
- /package/dist/{chunk-DHU2AQ6T.js.map → chunk-O3NGOHXQ.js.map} +0 -0
- /package/dist/{chunk-ZBUAX4EF.js.map → chunk-O6VOR4NH.js.map} +0 -0
- /package/dist/{chunk-JZ4EDEIP.js.map → chunk-ODBOHPZU.js.map} +0 -0
- /package/dist/{chunk-5UUJE4FP.js.map → chunk-OK44MD3C.js.map} +0 -0
- /package/dist/{chunk-ECGXA4LT.js.map → chunk-OR3OHKU6.js.map} +0 -0
- /package/dist/{chunk-ZWF3EWZA.js.map → chunk-P6FATPXQ.js.map} +0 -0
- /package/dist/{chunk-PCYPXLEX.js.map → chunk-PBEHTFUG.js.map} +0 -0
- /package/dist/{chunk-7CT6SX4M.js.map → chunk-PFHDQY5L.js.map} +0 -0
- /package/dist/{chunk-PTJY5R3O.js.map → chunk-PIO6NW7O.js.map} +0 -0
- /package/dist/{chunk-TMIJAR2X.js.map → chunk-PREYKC76.js.map} +0 -0
- /package/dist/{chunk-ZHQJAV6D.js.map → chunk-PU5ZEV65.js.map} +0 -0
- /package/dist/{chunk-UNSQZSZP.js.map → chunk-PWAMX5KU.js.map} +0 -0
- /package/dist/{chunk-GETUTTZU.js.map → chunk-PZN76MMV.js.map} +0 -0
- /package/dist/{chunk-ABU6A4Z5.js.map → chunk-Q4DBU5RM.js.map} +0 -0
- /package/dist/{chunk-2WJKJZSO.js.map → chunk-QHG7GQKM.js.map} +0 -0
- /package/dist/{chunk-UAKY6E4N.js.map → chunk-QNOWNCZS.js.map} +0 -0
- /package/dist/{chunk-JPSL5GIZ.js.map → chunk-QQLXKDGC.js.map} +0 -0
- /package/dist/{chunk-OK57EATL.js.map → chunk-R4GLRJ55.js.map} +0 -0
- /package/dist/{chunk-B65CC6Z6.js.map → chunk-RF5WDM25.js.map} +0 -0
- /package/dist/{chunk-G46JSSVX.js.map → chunk-RKBCUP5D.js.map} +0 -0
- /package/dist/{chunk-GCUMOKTN.js.map → chunk-S2ORTQGS.js.map} +0 -0
- /package/dist/{chunk-MRJDLXI3.js.map → chunk-SVXFCCSX.js.map} +0 -0
- /package/dist/{chunk-BUE7R3B5.js.map → chunk-SXPLIRQH.js.map} +0 -0
- /package/dist/{chunk-5LMCVBMY.js.map → chunk-T5EXREMW.js.map} +0 -0
- /package/dist/{chunk-PT2YCQVK.js.map → chunk-TBVDI3LY.js.map} +0 -0
- /package/dist/{chunk-BMHQHH7Q.js.map → chunk-TLIFNRU5.js.map} +0 -0
- /package/dist/{chunk-YKGJ44Z7.js.map → chunk-TU6ZJTYT.js.map} +0 -0
- /package/dist/{chunk-55P6OBB7.js.map → chunk-U43RSPPX.js.map} +0 -0
- /package/dist/{chunk-K7RW7FI4.js.map → chunk-UADW5NOU.js.map} +0 -0
- /package/dist/{chunk-GRS2HIV6.js.map → chunk-UMV5GBTJ.js.map} +0 -0
- /package/dist/{chunk-4UIP3QNW.js.map → chunk-UNAMWK2Q.js.map} +0 -0
- /package/dist/{chunk-J4KAPKBJ.js.map → chunk-UORWAG7K.js.map} +0 -0
- /package/dist/{chunk-V55JASXO.js.map → chunk-UQRKAM2R.js.map} +0 -0
- /package/dist/{chunk-ZMVSKYTJ.js.map → chunk-VLRY2UH4.js.map} +0 -0
- /package/dist/{chunk-SPPOUJLN.js.map → chunk-VZFTON37.js.map} +0 -0
- /package/dist/{chunk-YQFBH5ZJ.js.map → chunk-WQUIJPN4.js.map} +0 -0
- /package/dist/{chunk-NZULV7LK.js.map → chunk-WVQDY3UM.js.map} +0 -0
- /package/dist/{chunk-3Y5JLSXS.js.map → chunk-X5RGG3ZW.js.map} +0 -0
- /package/dist/{chunk-PFCTSXHU.js.map → chunk-X6Z2SIRF.js.map} +0 -0
- /package/dist/{chunk-UHFGK6YA.js.map → chunk-XQGKS4OW.js.map} +0 -0
- /package/dist/{chunk-L2F3CFCH.js.map → chunk-Y22JWHCP.js.map} +0 -0
- /package/dist/{chunk-C53ER7AG.js.map → chunk-YVA6UPRN.js.map} +0 -0
- /package/dist/{chunk-226V6XXJ.js.map → chunk-Z2KP6PNF.js.map} +0 -0
- /package/dist/{chunk-G5EDYVSE.js.map → chunk-ZK2WT532.js.map} +0 -0
- /package/dist/{chunk-SFCD6OU7.js.map → chunk-ZNVBCKMV.js.map} +0 -0
- /package/dist/{chunk-BU2ABHFW.js.map → chunk-ZOFNZLAA.js.map} +0 -0
- /package/dist/{chunk-X2RP4TO5.js.map → chunk-ZVJKHGE5.js.map} +0 -0
- /package/dist/{classified-marker-KHDOYIJB.js.map → classified-marker-7HXDMYHI.js.map} +0 -0
- /package/dist/{collection-facade-LZIF7GWD.js.map → collection-facade-V63BEBGU.js.map} +0 -0
- /package/dist/{computed-XMFTHAXV.js.map → computed-LZLSYOPG.js.map} +0 -0
- /package/dist/{dead-filter-CXV5NS67.js.map → dead-filter-PZIJ4F4G.js.map} +0 -0
- /package/dist/{derive-3YSIS36W.js.map → delegation-7SSGIETH.js.map} +0 -0
- /package/dist/{executor-E6YDJ7YA.js.map → derive-IMI3BMDS.js.map} +0 -0
- /package/dist/{dispatch-2MQFMEGY.js.map → dispatch-4BUYPWMJ.js.map} +0 -0
- /package/dist/{dispatch-OFDA4WQV.js.map → dispatch-KOPDDPEQ.js.map} +0 -0
- /package/dist/{executor-NJX3YQQ4.js.map → executor-7SY3M6TZ.js.map} +0 -0
- /package/dist/{executor-WWM3DD4P.js.map → executor-SNHW4ELF.js.map} +0 -0
- /package/dist/{export-accessible-RLHU5G4W.js.map → executor-Z3IKK7G3.js.map} +0 -0
- /package/dist/{extract-partition-QII2EDCS.js.map → export-accessible-O7DIVFUO.js.map} +0 -0
- /package/dist/{find-6M7GYDUZ.js.map → extract-partition-ELZEJKXM.js.map} +0 -0
- /package/dist/{fanout-sidecar-BO67PCPO.js.map → fanout-sidecar-FYDRL7F3.js.map} +0 -0
- /package/dist/{issue-LPEEEMPP.js.map → find-KWB2RYWJ.js.map} +0 -0
- /package/dist/{ledger-MSJGWKGW.js.map → issue-5ZHXK4HJ.js.map} +0 -0
- /package/dist/{liberate-LEKDYKTC.js.map → ledger-UFJCB6T5.js.map} +0 -0
- /package/dist/{link-set-QXXSPPHL.js.map → liberate-OEOSNNFH.js.map} +0 -0
- /package/dist/{managed-secret-VSK7ANQI.js.map → link-set-KMUBFN2L.js.map} +0 -0
- /package/dist/{noydb-F2AUF6KL.js.map → managed-secret-H5WYSJ46.js.map} +0 -0
- /package/dist/{migrate-cek-GEBFYBDC.js.map → migrate-cek-SPESQAAO.js.map} +0 -0
- /package/dist/{register-SN72QALV.js.map → noydb-QDZ4QIKO.js.map} +0 -0
- /package/dist/{pod-handle-YE7CT66T.js.map → pod-handle-GJLCOUGK.js.map} +0 -0
- /package/dist/{post-register-QC5TEAW3.js.map → post-register-2AC2STHC.js.map} +0 -0
- /package/dist/{registry-253FF7C6.js.map → register-PIORIMMR.js.map} +0 -0
- /package/dist/{registry-3AZWQTDT.js.map → registry-BIMICFUH.js.map} +0 -0
- /package/dist/{registry-7UEBTHWG.js.map → registry-JGWLW53D.js.map} +0 -0
- /package/dist/{registry-IVJ67NFQ.js.map → registry-SELCBYEQ.js.map} +0 -0
- /package/dist/{request-withdrawal-UKVJZKX2.js.map → registry-W327UNYH.js.map} +0 -0
- /package/dist/{revoke-G2KXJQA5.js.map → request-withdrawal-K3SXXODI.js.map} +0 -0
- /package/dist/{reveal-YQTRNQFH.js.map → reveal-UAPBG743.js.map} +0 -0
- /package/dist/{signer-IUIYR3CX.js.map → revoke-6AFVXTWF.js.map} +0 -0
- /package/dist/{stale-SKV33PBU.js.map → signer-TW5MAQJP.js.map} +0 -0
- /package/dist/{storage-NPBYP2SM.js.map → stale-CROGJBIJ.js.map} +0 -0
- /package/dist/{walk-F4OLXI5H.js.map → storage-SO2L2Z5J.js.map} +0 -0
- /package/dist/{store-coordination-provider-Z6HKPOGM.js.map → store-coordination-provider-2YD2PTTP.js.map} +0 -0
- /package/dist/{verify-KWQIWLGH.js.map → verify-QWO5UKD6.js.map} +0 -0
- /package/dist/{withdraw-accessible-ZKPLZ66E.js.map → walk-3KEOL7BY.js.map} +0 -0
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
readDirectoryConfig,
|
|
6
6
|
readUserVisibility,
|
|
7
7
|
saveUserEnvelope
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-6BEBWHNL.js";
|
|
9
9
|
import {
|
|
10
10
|
keyringClearance
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-XQGKS4OW.js";
|
|
12
12
|
import {
|
|
13
13
|
parseDekKey
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-LJ744WXU.js";
|
|
15
15
|
import {
|
|
16
16
|
base64ToBuffer,
|
|
17
17
|
bufferToBase64,
|
|
@@ -26,26 +26,38 @@ import {
|
|
|
26
26
|
encrypt,
|
|
27
27
|
encryptBytes,
|
|
28
28
|
envelopeOpensUnderAny,
|
|
29
|
+
exportDekSet,
|
|
30
|
+
exportRecipientPrivateKeyPkcs8,
|
|
31
|
+
exportRecipientPublicKeySpki,
|
|
29
32
|
generateDEK,
|
|
33
|
+
generateRecipientKeyPair,
|
|
30
34
|
generateSalt,
|
|
31
35
|
hasSealedBody,
|
|
36
|
+
importDekSet,
|
|
37
|
+
importRecipientKeyPair,
|
|
38
|
+
importRecipientPublicKeySpki,
|
|
39
|
+
importTransferKey,
|
|
32
40
|
mintCanary,
|
|
41
|
+
recipientUnwrap,
|
|
42
|
+
recipientWrap,
|
|
33
43
|
rekeyBlobSet,
|
|
34
44
|
rekeyEnvelopeIfNeeded,
|
|
35
45
|
unwrapKey,
|
|
36
46
|
wrapKey
|
|
37
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-WRLWEYHY.js";
|
|
38
48
|
import {
|
|
39
49
|
NOYDB_KEYRING_VERSION
|
|
40
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-URGHKZPL.js";
|
|
41
51
|
import {
|
|
42
52
|
BLOB_ADDRESS_KEY_ID,
|
|
43
53
|
DirectoryDisabledError,
|
|
44
54
|
EchoCeremonyRequiredError,
|
|
55
|
+
INBOX_KEY_ID,
|
|
45
56
|
InvalidKeyError,
|
|
46
57
|
KeyringCorruptError,
|
|
47
58
|
KeyringExpiredError,
|
|
48
59
|
KeyringTamperedError,
|
|
60
|
+
MemberInboxMissingError,
|
|
49
61
|
NoAccessError,
|
|
50
62
|
NoydbError,
|
|
51
63
|
PermissionDeniedError,
|
|
@@ -54,8 +66,9 @@ import {
|
|
|
54
66
|
TamperedError,
|
|
55
67
|
USER_ENVELOPE_COLLECTION,
|
|
56
68
|
ValidationError,
|
|
57
|
-
WrongPromptError
|
|
58
|
-
|
|
69
|
+
WrongPromptError,
|
|
70
|
+
isConflictError
|
|
71
|
+
} from "./chunk-2RH5SEY7.js";
|
|
59
72
|
|
|
60
73
|
// src/with-party/team/roster-epoch.ts
|
|
61
74
|
function assertRosterEpochCurrent(found, expected, userId) {
|
|
@@ -141,7 +154,19 @@ function rosterCanonical(file) {
|
|
|
141
154
|
// which is the difference between a caught tamper and a silent one, for a
|
|
142
155
|
// reader who trusted the cheap number. It is defence in depth for a field
|
|
143
156
|
// whose whole risk is being read instead of the DEK map.
|
|
144
|
-
...file.clearance !== void 0 ? { clearance: file.clearance } : {}
|
|
157
|
+
...file.clearance !== void 0 ? { clearance: file.clearance } : {},
|
|
158
|
+
// core#96 — the inbox PUBLIC KEY and the PENDING SLOT NAMES, bound ONLY
|
|
159
|
+
// WHEN PRESENT (same conditional spread, same reason as the two above).
|
|
160
|
+
//
|
|
161
|
+
// `inbox_pub`: an amend seals DEKs to this key, so a store that could swap
|
|
162
|
+
// it for its own would read every DEK delivered afterwards. Bound, a swap
|
|
163
|
+
// fails the tag before anything is sealed to it.
|
|
164
|
+
// `inbox_slots`: `revoke` rotates what the target's file NAMES; a pending
|
|
165
|
+
// delivery is a DEK the target may hold, so its names must be as
|
|
166
|
+
// unstrippable as `dek_slots`. Contents are self-authenticating (AES-GCM
|
|
167
|
+
// under a CEK only the private half unwraps) and stay out.
|
|
168
|
+
...file.inbox_key !== void 0 ? { inbox_pub: file.inbox_key.pub } : {},
|
|
169
|
+
...file.inbox !== void 0 ? { inbox_slots: [...new Set(file.inbox.flatMap((box) => box.slots))].sort() } : {}
|
|
145
170
|
});
|
|
146
171
|
}
|
|
147
172
|
async function mintRosterTag(file, rosterKey) {
|
|
@@ -481,7 +506,10 @@ async function loadKeyring(store, vault, opts) {
|
|
|
481
506
|
}
|
|
482
507
|
const { file: keyringFile } = found;
|
|
483
508
|
const salt = base64ToBuffer(keyringFile.salt);
|
|
484
|
-
|
|
509
|
+
if (opts.kek === void 0 && secret === void 0) {
|
|
510
|
+
throw new ValidationError(`loadKeyring: one of \`secret\` / \`kek\` is required (user "${userId}").`);
|
|
511
|
+
}
|
|
512
|
+
const kek = opts.kek ?? await deriveKekForKeyring(keyringFile, secret, salt);
|
|
485
513
|
if (keyringFile.canary === void 0) {
|
|
486
514
|
throw new KeyringTamperedError({ userId, reason: "canary-missing" });
|
|
487
515
|
}
|
|
@@ -520,7 +548,13 @@ async function loadKeyring(store, vault, opts) {
|
|
|
520
548
|
}
|
|
521
549
|
await assertRosterAuthenticated(keyringFile, deks, userId);
|
|
522
550
|
assertKeyringNotExpired(keyringFile);
|
|
523
|
-
|
|
551
|
+
let drained = false;
|
|
552
|
+
const inboxKeyAes = deks.get(INBOX_KEY_ID);
|
|
553
|
+
if (keyringFile.inbox !== void 0 && keyringFile.inbox.length > 0 && inboxKeyAes !== void 0) {
|
|
554
|
+
for (const [name, dek] of await openInbox(keyringFile, inboxKeyAes)) deks.set(name, dek);
|
|
555
|
+
drained = true;
|
|
556
|
+
}
|
|
557
|
+
const unlocked = {
|
|
524
558
|
userId: keyringFile.user_id,
|
|
525
559
|
displayName: keyringFile.display_name,
|
|
526
560
|
role: keyringFile.role,
|
|
@@ -534,6 +568,8 @@ async function loadKeyring(store, vault, opts) {
|
|
|
534
568
|
...keyringFile.import_capability !== void 0 && { importCapability: keyringFile.import_capability },
|
|
535
569
|
...keyringFile.policy !== void 0 && { policy: keyringFile.policy }
|
|
536
570
|
};
|
|
571
|
+
if (drained) await persistKeyring(store, vault, unlocked);
|
|
572
|
+
return unlocked;
|
|
537
573
|
}
|
|
538
574
|
async function assertKeyringOpenAllowed(store, vault, userId, create) {
|
|
539
575
|
const keyringUsers = await store.list(vault, "_keyring");
|
|
@@ -566,6 +602,7 @@ async function createOwnerKeyring(store, vault, opts) {
|
|
|
566
602
|
const wrappedRosterKey = await wrapKey(rosterKey, kek);
|
|
567
603
|
const blobAddressKey = await generateDEK();
|
|
568
604
|
const wrappedBlobAddressKey = await wrapKey(blobAddressKey, kek);
|
|
605
|
+
const inbox = await mintInboxKey(kek);
|
|
569
606
|
const canary = await mintKeyringCanary(kek);
|
|
570
607
|
const authority = {
|
|
571
608
|
user_id: userId,
|
|
@@ -579,8 +616,11 @@ async function createOwnerKeyring(store, vault, opts) {
|
|
|
579
616
|
deks: {
|
|
580
617
|
[USER_ENVELOPE_COLLECTION]: wrappedUserEnvelopeDek,
|
|
581
618
|
[ROSTER_KEY_ID]: wrappedRosterKey,
|
|
582
|
-
[BLOB_ADDRESS_KEY_ID]: wrappedBlobAddressKey
|
|
583
|
-
|
|
619
|
+
[BLOB_ADDRESS_KEY_ID]: wrappedBlobAddressKey,
|
|
620
|
+
[INBOX_KEY_ID]: inbox.wrappedInboxKey
|
|
621
|
+
},
|
|
622
|
+
inbox_key: inbox.inboxKey
|
|
623
|
+
// core#65 — tag-bound, like every other keyring's
|
|
584
624
|
};
|
|
585
625
|
const withEpoch = stampAuthority(authorityWithDeks, void 0);
|
|
586
626
|
const keyringFile = {
|
|
@@ -600,7 +640,7 @@ async function createOwnerKeyring(store, vault, opts) {
|
|
|
600
640
|
)
|
|
601
641
|
} : {}
|
|
602
642
|
};
|
|
603
|
-
await writeKeyringFile(store, vault, userId, keyringFile);
|
|
643
|
+
await writeKeyringFile(store, vault, userId, keyringFile, "create");
|
|
604
644
|
return {
|
|
605
645
|
userId,
|
|
606
646
|
displayName: userId,
|
|
@@ -608,13 +648,41 @@ async function createOwnerKeyring(store, vault, opts) {
|
|
|
608
648
|
permissions: {},
|
|
609
649
|
deks: /* @__PURE__ */ new Map([
|
|
610
650
|
[USER_ENVELOPE_COLLECTION, userEnvelopeDek],
|
|
611
|
-
[ROSTER_KEY_ID, rosterKey]
|
|
651
|
+
[ROSTER_KEY_ID, rosterKey],
|
|
652
|
+
[INBOX_KEY_ID, inbox.inboxKeyAes]
|
|
653
|
+
// core#65 — in the SESSION too, not only the file: it opens this owner's own inbox
|
|
612
654
|
]),
|
|
613
655
|
kek,
|
|
614
656
|
salt,
|
|
615
657
|
authenticators: []
|
|
616
658
|
};
|
|
617
659
|
}
|
|
660
|
+
function selectGranteeDekNames(role, requested, permissions, callerDeks) {
|
|
661
|
+
const mayHoldSecrets = role === "owner" || role === "admin";
|
|
662
|
+
const admits = (name) => name !== INBOX_KEY_ID && name !== BROKER_MEMBER_COLLECTION && !(isSecretBearingReservedCollection(name) && !mayHoldSecrets);
|
|
663
|
+
const selected = /* @__PURE__ */ new Set();
|
|
664
|
+
for (const collName of Object.keys(permissions)) {
|
|
665
|
+
if (collName === PERMISSION_WILDCARD) continue;
|
|
666
|
+
if (admits(collName) && callerDeks.has(collName)) selected.add(collName);
|
|
667
|
+
}
|
|
668
|
+
const wrapAll = role === "owner" || role === "admin" || role === "custodian" || role === "viewer" || permissionsAreWildcard(requested);
|
|
669
|
+
for (const name of callerDeks.keys()) {
|
|
670
|
+
if ((wrapAll || name.startsWith("_")) && admits(name)) selected.add(name);
|
|
671
|
+
}
|
|
672
|
+
return [...selected];
|
|
673
|
+
}
|
|
674
|
+
async function mintMissingDeksForGrant(store, vault, callerKeyring, permissions, mayHoldSecrets) {
|
|
675
|
+
let minted = false;
|
|
676
|
+
for (const collName of Object.keys(permissions)) {
|
|
677
|
+
if (collName === PERMISSION_WILDCARD) continue;
|
|
678
|
+
if (isSecretBearingReservedCollection(collName) && !mayHoldSecrets) continue;
|
|
679
|
+
if (callerKeyring.deks.has(collName)) continue;
|
|
680
|
+
if (await collectionHasRecords(store, vault, collName)) continue;
|
|
681
|
+
callerKeyring.deks.set(collName, await generateDEK());
|
|
682
|
+
minted = true;
|
|
683
|
+
}
|
|
684
|
+
return minted;
|
|
685
|
+
}
|
|
618
686
|
async function grant(store, vault, callerKeyring, options) {
|
|
619
687
|
if (!callerKeyring.kek) {
|
|
620
688
|
throw new ValidationError(
|
|
@@ -640,38 +708,13 @@ async function grant(store, vault, callerKeyring, options) {
|
|
|
640
708
|
const newSalt = generateSalt();
|
|
641
709
|
const newKek = await deriveKey(options.secret, newSalt);
|
|
642
710
|
const granteeMayHoldSecrets = options.role === "owner" || options.role === "admin";
|
|
643
|
-
|
|
644
|
-
for (const collName of Object.keys(permissions)) {
|
|
645
|
-
if (collName === PERMISSION_WILDCARD) continue;
|
|
646
|
-
if (isSecretBearingReservedCollection(collName) && !granteeMayHoldSecrets) continue;
|
|
647
|
-
if (callerKeyring.deks.has(collName)) continue;
|
|
648
|
-
if (await collectionHasRecords(store, vault, collName)) continue;
|
|
649
|
-
callerKeyring.deks.set(collName, await generateDEK());
|
|
650
|
-
mintedForGrant = true;
|
|
651
|
-
}
|
|
711
|
+
const mintedForGrant = await mintMissingDeksForGrant(store, vault, callerKeyring, permissions, granteeMayHoldSecrets);
|
|
652
712
|
if (mintedForGrant) await persistKeyring(store, vault, callerKeyring);
|
|
653
713
|
const previousGrantFound = await readKeyringFile(store, vault, options.userId);
|
|
654
714
|
const previousDekNames = previousGrantFound ? new Set(Object.keys(previousGrantFound.file.deks)) : null;
|
|
655
715
|
const wrappedDeks = {};
|
|
656
|
-
for (const collName of
|
|
657
|
-
|
|
658
|
-
if (isSecretBearingReservedCollection(collName) && !granteeMayHoldSecrets) continue;
|
|
659
|
-
const dek = callerKeyring.deks.get(collName);
|
|
660
|
-
if (dek) {
|
|
661
|
-
wrappedDeks[collName] = await wrapKey(dek, newKek);
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
if (options.role === "owner" || options.role === "admin" || options.role === "custodian" || options.role === "viewer" || permissionsAreWildcard(options.permissions)) {
|
|
665
|
-
for (const [collName, dek] of callerKeyring.deks) {
|
|
666
|
-
if (collName in wrappedDeks) continue;
|
|
667
|
-
if (isSecretBearingReservedCollection(collName) && !granteeMayHoldSecrets) continue;
|
|
668
|
-
wrappedDeks[collName] = await wrapKey(dek, newKek);
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
for (const [collName, dek] of callerKeyring.deks) {
|
|
672
|
-
if (!collName.startsWith("_") || collName in wrappedDeks) continue;
|
|
673
|
-
if (isSecretBearingReservedCollection(collName) && !granteeMayHoldSecrets) continue;
|
|
674
|
-
wrappedDeks[collName] = await wrapKey(dek, newKek);
|
|
716
|
+
for (const collName of selectGranteeDekNames(options.role, options.permissions, permissions, callerKeyring.deks)) {
|
|
717
|
+
wrappedDeks[collName] = await wrapKey(callerKeyring.deks.get(collName), newKek);
|
|
675
718
|
}
|
|
676
719
|
for (const collName of Object.keys(wrappedDeks)) {
|
|
677
720
|
if (!callerKeyring.deks.has(collName)) {
|
|
@@ -681,6 +724,8 @@ async function grant(store, vault, callerKeyring, options) {
|
|
|
681
724
|
if (!granteeMayHoldSecrets) {
|
|
682
725
|
wrappedDeks[BROKER_MEMBER_COLLECTION] = await wrapKey(await generateDEK(), newKek);
|
|
683
726
|
}
|
|
727
|
+
const inbox = await mintInboxKey(newKek);
|
|
728
|
+
wrappedDeks[INBOX_KEY_ID] = inbox.wrappedInboxKey;
|
|
684
729
|
const canary = await mintKeyringCanary(newKek);
|
|
685
730
|
const authority = {
|
|
686
731
|
user_id: options.userId,
|
|
@@ -691,7 +736,7 @@ async function grant(store, vault, callerKeyring, options) {
|
|
|
691
736
|
...options.exportCapability !== void 0 && { export_capability: options.exportCapability },
|
|
692
737
|
...options.importCapability !== void 0 && { import_capability: options.importCapability }
|
|
693
738
|
};
|
|
694
|
-
const authorityWithDeks = { ...authority, deks: wrappedDeks };
|
|
739
|
+
const authorityWithDeks = { ...authority, deks: wrappedDeks, inbox_key: inbox.inboxKey };
|
|
695
740
|
const withEpoch = stampAuthority(authorityWithDeks, previousGrantFound?.file.roster_epoch);
|
|
696
741
|
const keyringFile = {
|
|
697
742
|
_noydb_keyring: NOYDB_KEYRING_VERSION,
|
|
@@ -703,13 +748,13 @@ async function grant(store, vault, callerKeyring, options) {
|
|
|
703
748
|
// propagation loop above, so they can verify this tag on first unlock.
|
|
704
749
|
roster_tag: await mintRosterTag(withEpoch, callerRosterKey)
|
|
705
750
|
};
|
|
706
|
-
await writeKeyringFile(store, vault, options.userId, keyringFile);
|
|
751
|
+
await writeKeyringFile(store, vault, options.userId, keyringFile, basisOf(previousGrantFound));
|
|
707
752
|
if (previousDekNames !== null && options.userId !== callerKeyring.userId) {
|
|
708
753
|
const dropped = [...previousDekNames].filter(
|
|
709
754
|
(name) => !name.startsWith("_") && !(name in wrappedDeks)
|
|
710
755
|
);
|
|
711
756
|
if (dropped.length > 0) {
|
|
712
|
-
await rotateKeys(store, vault, callerKeyring, { collections: dropped });
|
|
757
|
+
await rotateKeys(store, vault, callerKeyring, { collections: dropped, exclude: [options.userId] });
|
|
713
758
|
}
|
|
714
759
|
}
|
|
715
760
|
const userEnvelopeDek = callerKeyring.deks.get(USER_ENVELOPE_COLLECTION);
|
|
@@ -724,6 +769,12 @@ async function grant(store, vault, callerKeyring, options) {
|
|
|
724
769
|
);
|
|
725
770
|
}
|
|
726
771
|
}
|
|
772
|
+
var NON_ROTATABLE_SLOTS = /* @__PURE__ */ new Set([
|
|
773
|
+
ROSTER_KEY_ID,
|
|
774
|
+
BLOB_ADDRESS_KEY_ID,
|
|
775
|
+
INBOX_KEY_ID,
|
|
776
|
+
BROKER_MEMBER_COLLECTION
|
|
777
|
+
]);
|
|
727
778
|
async function findAdminDescendants(store, vault, rootUserId, rosterKey) {
|
|
728
779
|
const allUserIds = await store.list(vault, "_keyring");
|
|
729
780
|
const childrenByParent = /* @__PURE__ */ new Map();
|
|
@@ -757,8 +808,8 @@ async function revoke(store, vault, callerKeyring, options) {
|
|
|
757
808
|
if (!targetFound) {
|
|
758
809
|
const pending = [...callerKeyring.pendingDeks?.keys() ?? []];
|
|
759
810
|
if (pending.length > 0) {
|
|
760
|
-
await rotateKeys(store, vault, callerKeyring, { collections: pending });
|
|
761
|
-
return;
|
|
811
|
+
const resumed = await rotateKeys(store, vault, callerKeyring, { collections: pending });
|
|
812
|
+
return { rewritten: resumed.rewritten };
|
|
762
813
|
}
|
|
763
814
|
throw new NoAccessError(`User "${options.userId}" has no keyring in vault "${vault}"`);
|
|
764
815
|
}
|
|
@@ -796,18 +847,24 @@ async function revoke(store, vault, callerKeyring, options) {
|
|
|
796
847
|
await deleteUserEnvelope(store, vault, userId);
|
|
797
848
|
await deleteUserVisibility(store, vault, userId);
|
|
798
849
|
}
|
|
799
|
-
affectedCollections.delete(
|
|
800
|
-
affectedCollections.
|
|
850
|
+
for (const slot of NON_ROTATABLE_SLOTS) affectedCollections.delete(slot);
|
|
851
|
+
for (const slot of inboxSlots(targetKeyring)) affectedCollections.add(slot);
|
|
852
|
+
let rewritten = [];
|
|
801
853
|
if (affectedCollections.size > 0) {
|
|
802
|
-
const
|
|
803
|
-
collections: [...affectedCollections]
|
|
854
|
+
const rotation = await rotateKeys(store, vault, callerKeyring, {
|
|
855
|
+
collections: [...affectedCollections],
|
|
856
|
+
exclude: usersToRevoke
|
|
857
|
+
// core#100 / #1043 — never deliver to the member(s) being revoked
|
|
804
858
|
});
|
|
859
|
+
const { unverified } = rotation;
|
|
860
|
+
rewritten = rotation.rewritten;
|
|
805
861
|
if (unverified.length > 0) {
|
|
806
862
|
console.warn(
|
|
807
863
|
`[noy-db] revoke(${options.userId}): ${unverified.length} member(s) were SKIPPED by the rotation because their keyring failed roster authentication: ${unverified.map((u) => `${u.userId} (${u.reason})`).join(", ")}. The revocation itself completed. Those members cannot open the vault and did not receive the rotated keys; their keyring files need repair or removal (vLannaAi/noy-db#1114).`
|
|
808
864
|
);
|
|
809
865
|
}
|
|
810
866
|
}
|
|
867
|
+
return { rewritten };
|
|
811
868
|
}
|
|
812
869
|
async function readKeyringForAudit(store, vault, userId) {
|
|
813
870
|
const envelope = await store.get(vault, "_keyring", userId);
|
|
@@ -885,8 +942,8 @@ async function quarantineKeyring(store, vault, callerKeyring, userId) {
|
|
|
885
942
|
await store.delete(vault, "_keyring", userId);
|
|
886
943
|
await deleteUserEnvelope(store, vault, userId);
|
|
887
944
|
await deleteUserVisibility(store, vault, userId);
|
|
888
|
-
const rotated = [...callerKeyring.deks.keys()].filter((c) => c
|
|
889
|
-
const result = rotated.length > 0 ? await rotateKeys(store, vault, callerKeyring, { collections: rotated }) : { needsRegrant: [], unverified: [] };
|
|
945
|
+
const rotated = [...callerKeyring.deks.keys()].filter((c) => !NON_ROTATABLE_SLOTS.has(c));
|
|
946
|
+
const result = rotated.length > 0 ? await rotateKeys(store, vault, callerKeyring, { collections: rotated, exclude: [userId] }) : { needsRegrant: [], unverified: [], rewritten: [] };
|
|
890
947
|
return {
|
|
891
948
|
userId,
|
|
892
949
|
reason,
|
|
@@ -920,7 +977,7 @@ async function updateKeyringIdentity(store, vault, callerKeyring, options) {
|
|
|
920
977
|
`Role "${callerKeyring.role}" cannot promote target to role "${options.role}"`
|
|
921
978
|
);
|
|
922
979
|
}
|
|
923
|
-
const
|
|
980
|
+
const header = {
|
|
924
981
|
...target,
|
|
925
982
|
...options.role !== void 0 && { role: options.role },
|
|
926
983
|
...options.displayName !== void 0 && {
|
|
@@ -929,9 +986,52 @@ async function updateKeyringIdentity(store, vault, callerKeyring, options) {
|
|
|
929
986
|
},
|
|
930
987
|
...options.permissions !== void 0 && { permissions: options.permissions }
|
|
931
988
|
};
|
|
989
|
+
const roleChanged = header.role !== target.role;
|
|
990
|
+
const mayHoldSecrets = header.role === "owner" || header.role === "admin";
|
|
991
|
+
const permissions = resolvePermissions(header.role, header.permissions);
|
|
992
|
+
const minted = await mintMissingDeksForGrant(store, vault, callerKeyring, permissions, mayHoldSecrets);
|
|
993
|
+
if (minted) await persistKeyring(store, vault, callerKeyring);
|
|
994
|
+
const wanted = new Set(selectGranteeDekNames(header.role, header.permissions, permissions, callerKeyring.deks));
|
|
995
|
+
const held = target.deks;
|
|
996
|
+
const pending = new Set(inboxSlots(target));
|
|
997
|
+
const retains = (name) => {
|
|
998
|
+
if (name === INBOX_KEY_ID) return true;
|
|
999
|
+
if (name === BROKER_MEMBER_COLLECTION) return !mayHoldSecrets && !roleChanged;
|
|
1000
|
+
if (wanted.has(name)) return true;
|
|
1001
|
+
if (!name.startsWith("_")) return false;
|
|
1002
|
+
return !(isSecretBearingReservedCollection(name) && !mayHoldSecrets);
|
|
1003
|
+
};
|
|
1004
|
+
const deks = {};
|
|
1005
|
+
for (const [name, wrapped] of Object.entries(held)) if (retains(name)) deks[name] = wrapped;
|
|
1006
|
+
const dropped = Object.keys(held).filter((name) => !name.startsWith("_") && !(name in deks));
|
|
1007
|
+
const deliver = /* @__PURE__ */ new Map();
|
|
1008
|
+
for (const name of wanted) {
|
|
1009
|
+
if (name in deks || pending.has(name)) continue;
|
|
1010
|
+
const dek = callerKeyring.deks.get(name);
|
|
1011
|
+
if (!dek) throw new PrivilegeEscalationError(name);
|
|
1012
|
+
deliver.set(name, dek);
|
|
1013
|
+
}
|
|
1014
|
+
for (const name of pending) if (!wanted.has(name) && !name.startsWith("_")) dropped.push(name);
|
|
1015
|
+
let brokerMemberDek;
|
|
1016
|
+
if (roleChanged && !mayHoldSecrets) {
|
|
1017
|
+
brokerMemberDek = await generateDEK();
|
|
1018
|
+
deliver.set(BROKER_MEMBER_COLLECTION, brokerMemberDek);
|
|
1019
|
+
}
|
|
1020
|
+
let inbox = target.inbox;
|
|
1021
|
+
if (deliver.size > 0) {
|
|
1022
|
+
if (target.inbox_key === void 0) throw new MemberInboxMissingError(options.userId);
|
|
1023
|
+
inbox = [...target.inbox ?? [], await sealInbox(target.inbox_key, deliver)];
|
|
1024
|
+
}
|
|
1025
|
+
const { inbox: _previousInbox, ...carried } = header;
|
|
1026
|
+
const edited = { ...carried, deks, ...inbox !== void 0 && inbox.length > 0 && { inbox } };
|
|
932
1027
|
const withEpoch = stampAuthority(edited, target.roster_epoch);
|
|
933
1028
|
const next = { ...withEpoch, roster_tag: await mintRosterTag(withEpoch, rosterKey) };
|
|
934
|
-
await writeKeyringFile(store, vault, options.userId, next);
|
|
1029
|
+
await writeKeyringFile(store, vault, options.userId, next, basisOf(found));
|
|
1030
|
+
const rotate = [...new Set(dropped)].filter((name) => !name.startsWith("_"));
|
|
1031
|
+
if (rotate.length > 0 && options.userId !== callerKeyring.userId) {
|
|
1032
|
+
await rotateKeys(store, vault, callerKeyring, { collections: rotate, exclude: [options.userId] });
|
|
1033
|
+
}
|
|
1034
|
+
return { roleChanged, ...brokerMemberDek !== void 0 && { brokerMemberDek } };
|
|
935
1035
|
}
|
|
936
1036
|
var HISTORY_COLLECTION = "_history";
|
|
937
1037
|
var LEDGER_COLLECTION = "_ledger";
|
|
@@ -984,6 +1084,12 @@ async function rotateKeys(store, vault, callerKeyring, opts) {
|
|
|
984
1084
|
`rotateKeys: "${ROSTER_KEY_ID}" is the vault roster key, not a collection, and cannot be rotated \u2014 doing so would strip it from every other member and leave the vault unopenable. Remove it from \`collections\`.`
|
|
985
1085
|
);
|
|
986
1086
|
}
|
|
1087
|
+
for (const name of [BROKER_MEMBER_COLLECTION, INBOX_KEY_ID]) {
|
|
1088
|
+
if (collections.includes(name)) {
|
|
1089
|
+
throw new ValidationError(`rotateKeys: "${name}" is a per-member key, not a collection, and cannot be rotated. Remove it from \`collections\`.`);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
const rewritten = [];
|
|
987
1093
|
if (callerKeyring.role === "custodian") {
|
|
988
1094
|
throw new PermissionDeniedError(
|
|
989
1095
|
"custodian cannot rotate keys (FR-6: re-key is an owner-only meta-capability; use the Deed owner)"
|
|
@@ -1009,6 +1115,12 @@ async function rotateKeys(store, vault, callerKeyring, opts) {
|
|
|
1009
1115
|
for (const [name, dek] of callerKeyring.deks) if (name !== collName) others.push(dek);
|
|
1010
1116
|
for (const [name, dek] of newDeks) if (name !== collName) others.push(dek);
|
|
1011
1117
|
await rekeyBlobSet(store, vault, oldDek, newDek, others);
|
|
1118
|
+
for (const blobColl of ["_blob_index", "_blob_chunks"]) {
|
|
1119
|
+
for (const id of await store.list(vault, blobColl)) {
|
|
1120
|
+
const env = await store.get(vault, blobColl, id);
|
|
1121
|
+
if (env) rewritten.push({ collection: blobColl, id, version: env._v });
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1012
1124
|
}
|
|
1013
1125
|
const { collection: baseColl } = parseDekKey(collName);
|
|
1014
1126
|
const siblingSlotDeks = [];
|
|
@@ -1031,7 +1143,10 @@ async function rotateKeys(store, vault, callerKeyring, opts) {
|
|
|
1031
1143
|
}
|
|
1032
1144
|
throw err;
|
|
1033
1145
|
}
|
|
1034
|
-
if (newEnvelope !== null)
|
|
1146
|
+
if (newEnvelope !== null) {
|
|
1147
|
+
await store.put(vault, refColl, id, newEnvelope);
|
|
1148
|
+
rewritten.push({ collection: refColl, id, version: newEnvelope._v });
|
|
1149
|
+
}
|
|
1035
1150
|
}
|
|
1036
1151
|
}
|
|
1037
1152
|
for (const [collName, newDek] of newDeks) {
|
|
@@ -1056,26 +1171,37 @@ async function rotateKeys(store, vault, callerKeyring, opts) {
|
|
|
1056
1171
|
}
|
|
1057
1172
|
const updatedDeks = { ...userKeyringFile.deks };
|
|
1058
1173
|
const updatedPermissions = { ...userKeyringFile.permissions };
|
|
1174
|
+
const deliver = /* @__PURE__ */ new Map();
|
|
1175
|
+
const pendingSlots = new Set(inboxSlots(userKeyringFile));
|
|
1059
1176
|
for (const collName of collections) {
|
|
1177
|
+
const held = collName in updatedDeks || pendingSlots.has(collName);
|
|
1178
|
+
if (held && userKeyringFile.inbox_key !== void 0 && !opts.exclude?.includes(userId)) {
|
|
1179
|
+
deliver.set(collName, newDeks.get(collName));
|
|
1180
|
+
delete updatedDeks[collName];
|
|
1181
|
+
continue;
|
|
1182
|
+
}
|
|
1060
1183
|
if (collName in updatedDeks || collName in updatedPermissions) {
|
|
1061
1184
|
needsRegrant.push({ userId, collection: collName });
|
|
1062
1185
|
}
|
|
1063
1186
|
delete updatedDeks[collName];
|
|
1064
1187
|
delete updatedPermissions[collName];
|
|
1065
1188
|
}
|
|
1189
|
+
const inbox = deliver.size > 0 && userKeyringFile.inbox_key !== void 0 ? [...userKeyringFile.inbox ?? [], await sealInbox(userKeyringFile.inbox_key, deliver)] : userKeyringFile.inbox;
|
|
1066
1190
|
const edited = {
|
|
1067
1191
|
...userKeyringFile,
|
|
1068
1192
|
deks: updatedDeks,
|
|
1069
|
-
permissions: updatedPermissions
|
|
1193
|
+
permissions: updatedPermissions,
|
|
1194
|
+
...inbox !== void 0 && inbox.length > 0 ? { inbox } : {}
|
|
1070
1195
|
};
|
|
1196
|
+
if (inbox === void 0 || inbox.length === 0) delete edited.inbox;
|
|
1071
1197
|
const withEpoch = stampAuthority(edited, userKeyringFile.roster_epoch);
|
|
1072
1198
|
const updatedKeyring = {
|
|
1073
1199
|
...withEpoch,
|
|
1074
1200
|
roster_tag: await mintRosterTag(withEpoch, callerRosterKey)
|
|
1075
1201
|
};
|
|
1076
|
-
await writeKeyringFile(store, vault, userId, updatedKeyring);
|
|
1202
|
+
await writeKeyringFile(store, vault, userId, updatedKeyring, basisOf(userFound));
|
|
1077
1203
|
}
|
|
1078
|
-
return { needsRegrant, unverified };
|
|
1204
|
+
return { needsRegrant, unverified, rewritten };
|
|
1079
1205
|
}
|
|
1080
1206
|
async function changeSecret(store, vault, keyring, opts) {
|
|
1081
1207
|
const existingFound = await readKeyringFile(store, vault, keyring.userId);
|
|
@@ -1117,7 +1243,7 @@ async function changeSecret(store, vault, keyring, opts) {
|
|
|
1117
1243
|
canary,
|
|
1118
1244
|
roster_tag: await mintRosterTag(withEpoch, rosterKey)
|
|
1119
1245
|
};
|
|
1120
|
-
await writeKeyringFile(store, vault, keyring.userId, keyringFile);
|
|
1246
|
+
await writeKeyringFile(store, vault, keyring.userId, keyringFile, basisOf(existingFound));
|
|
1121
1247
|
return {
|
|
1122
1248
|
userId: keyring.userId,
|
|
1123
1249
|
displayName: keyring.displayName,
|
|
@@ -1301,8 +1427,17 @@ async function ensureCollectionDEK(store, vault, keyring) {
|
|
|
1301
1427
|
}
|
|
1302
1428
|
const dek = await generateDEK();
|
|
1303
1429
|
keyring.deks.set(collectionName, dek);
|
|
1304
|
-
|
|
1305
|
-
|
|
1430
|
+
for (let attempt = 0; ; attempt++) {
|
|
1431
|
+
try {
|
|
1432
|
+
await persistKeyring(store, vault, keyring);
|
|
1433
|
+
return keyring.deks.get(collectionName) ?? dek;
|
|
1434
|
+
} catch (err) {
|
|
1435
|
+
if (!isConflictError(err)) throw err;
|
|
1436
|
+
const winner = await reloadPersistedDEK(store, vault, keyring, collectionName);
|
|
1437
|
+
if (winner) return winner;
|
|
1438
|
+
if (attempt >= 5) throw err;
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1306
1441
|
})();
|
|
1307
1442
|
inFlight.set(collectionName, promise);
|
|
1308
1443
|
try {
|
|
@@ -1328,6 +1463,58 @@ function hasAccess(keyring, collectionName) {
|
|
|
1328
1463
|
if (PERMISSION_WILDCARD in keyring.permissions) return true;
|
|
1329
1464
|
return collectionName in keyring.permissions;
|
|
1330
1465
|
}
|
|
1466
|
+
async function mintInboxKey(kek) {
|
|
1467
|
+
const inboxKey = await generateDEK();
|
|
1468
|
+
const pair = await generateRecipientKeyPair();
|
|
1469
|
+
const pub = await exportRecipientPublicKeySpki(pair);
|
|
1470
|
+
const priv = await exportRecipientPrivateKeyPkcs8(pair);
|
|
1471
|
+
try {
|
|
1472
|
+
const sealed = await encryptBytes(priv, inboxKey);
|
|
1473
|
+
return { wrappedInboxKey: await wrapKey(inboxKey, kek), inboxKeyAes: inboxKey, inboxKey: { pub: bufferToBase64(pub), priv: sealed } };
|
|
1474
|
+
} finally {
|
|
1475
|
+
priv.fill(0);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
function inboxSlots(file) {
|
|
1479
|
+
return [...new Set((file.inbox ?? []).flatMap((box) => box.slots))];
|
|
1480
|
+
}
|
|
1481
|
+
async function sealInbox(inboxKey, deks) {
|
|
1482
|
+
const pub = await importRecipientPublicKeySpki(base64ToBuffer(inboxKey.pub));
|
|
1483
|
+
const cekBytes = globalThis.crypto.getRandomValues(new Uint8Array(32));
|
|
1484
|
+
try {
|
|
1485
|
+
const cek = await importTransferKey(cekBytes);
|
|
1486
|
+
const payload = new TextEncoder().encode(JSON.stringify(await exportDekSet(deks)));
|
|
1487
|
+
const { iv, data } = await encryptBytes(payload, cek);
|
|
1488
|
+
const wrapped = await recipientWrap(pub, cekBytes);
|
|
1489
|
+
return { slots: [...deks.keys()].sort(), cek: bufferToBase64(wrapped), iv, data };
|
|
1490
|
+
} finally {
|
|
1491
|
+
cekBytes.fill(0);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
async function openInboxKeyPair(inboxKey, inboxKeyAes) {
|
|
1495
|
+
const priv = await decryptBytes(inboxKey.priv.iv, inboxKey.priv.data, inboxKeyAes);
|
|
1496
|
+
try {
|
|
1497
|
+
return await importRecipientKeyPair(priv, base64ToBuffer(inboxKey.pub));
|
|
1498
|
+
} finally {
|
|
1499
|
+
priv.fill(0);
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
async function openInbox(file, inboxKeyAes) {
|
|
1503
|
+
const out = /* @__PURE__ */ new Map();
|
|
1504
|
+
if (!file.inbox || file.inbox.length === 0 || !file.inbox_key) return out;
|
|
1505
|
+
const pair = await openInboxKeyPair(file.inbox_key, inboxKeyAes);
|
|
1506
|
+
for (const box of file.inbox) {
|
|
1507
|
+
const cekBytes = await recipientUnwrap(pair, base64ToBuffer(box.cek));
|
|
1508
|
+
try {
|
|
1509
|
+
const cek = await importTransferKey(cekBytes);
|
|
1510
|
+
const payload = await decryptBytes(box.iv, box.data, cek);
|
|
1511
|
+
for (const [name, dek] of await importDekSet(JSON.parse(new TextDecoder().decode(payload)))) out.set(name, dek);
|
|
1512
|
+
} finally {
|
|
1513
|
+
cekBytes.fill(0);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
return out;
|
|
1517
|
+
}
|
|
1331
1518
|
async function persistKeyring(store, vault, keyring) {
|
|
1332
1519
|
if (!keyring.kek) {
|
|
1333
1520
|
throw new ValidationError(
|
|
@@ -1341,6 +1528,9 @@ async function persistKeyring(store, vault, keyring) {
|
|
|
1341
1528
|
const existingGrantedBy = existingFound?.file.granted_by;
|
|
1342
1529
|
const existingCreatedAt = existingFound?.file.created_at;
|
|
1343
1530
|
const existingExpiresAt = existingFound?.file.expires_at;
|
|
1531
|
+
const existingInboxKey = existingFound?.file.inbox_key;
|
|
1532
|
+
const existingInbox = existingFound?.file.inbox;
|
|
1533
|
+
const undrainedInbox = existingInbox !== void 0 && existingInbox.length > 0 && !inboxSlots({ inbox: existingInbox }).every((slot) => keyring.deks.has(slot));
|
|
1344
1534
|
const wrappedDeks = {};
|
|
1345
1535
|
for (const [collName, dek] of keyring.deks) {
|
|
1346
1536
|
wrappedDeks[collName] = await wrapKey(dek, keyring.kek);
|
|
@@ -1363,7 +1553,11 @@ async function persistKeyring(store, vault, keyring) {
|
|
|
1363
1553
|
const authorityWithDeks = {
|
|
1364
1554
|
...authority,
|
|
1365
1555
|
deks: wrappedDeks,
|
|
1366
|
-
...Object.keys(wrappedPending).length > 0 ? { pending_deks: wrappedPending } : {}
|
|
1556
|
+
...Object.keys(wrappedPending).length > 0 ? { pending_deks: wrappedPending } : {},
|
|
1557
|
+
// core#96 — both tag-bound (`inbox_pub`, `inbox_slots`), so they must be
|
|
1558
|
+
// in the object the tag is minted from, not spread in afterwards.
|
|
1559
|
+
...existingInboxKey !== void 0 && { inbox_key: existingInboxKey },
|
|
1560
|
+
...undrainedInbox && existingInbox !== void 0 && { inbox: existingInbox }
|
|
1367
1561
|
};
|
|
1368
1562
|
const withEpoch = stampAuthority(authorityWithDeks, existingFound?.file.roster_epoch);
|
|
1369
1563
|
const keyringFile = {
|
|
@@ -1377,7 +1571,7 @@ async function persistKeyring(store, vault, keyring) {
|
|
|
1377
1571
|
...keyring.policy !== void 0 && { policy: keyring.policy },
|
|
1378
1572
|
...existingEcho !== void 0 && { echo: existingEcho }
|
|
1379
1573
|
};
|
|
1380
|
-
await writeKeyringFile(store, vault, keyring.userId, keyringFile);
|
|
1574
|
+
await writeKeyringFile(store, vault, keyring.userId, keyringFile, basisOf(existingFound));
|
|
1381
1575
|
}
|
|
1382
1576
|
function defaultBundleCapability(role) {
|
|
1383
1577
|
return role === "owner" || role === "admin";
|
|
@@ -1416,17 +1610,19 @@ function resolvePermissions(role, explicit) {
|
|
|
1416
1610
|
if (role === "owner" || role === "admin" || role === "custodian" || role === "viewer") return {};
|
|
1417
1611
|
return explicit ?? {};
|
|
1418
1612
|
}
|
|
1419
|
-
|
|
1613
|
+
var basisOf = (found) => found ? { on: found.envelope } : "create";
|
|
1614
|
+
async function writeKeyringFile(store, vault, userId, keyringFile, basis) {
|
|
1420
1615
|
if (keyringFile.roster_epoch === void 0) {
|
|
1421
1616
|
throw new Error(
|
|
1422
1617
|
`writeKeyringFile: refusing to write a keyring for "${userId}" with no roster_epoch (#1097). Stamp it with nextRosterEpoch(previous) onto the authority object BEFORE minting the roster tag, so it is covered by rosterCanonical.`
|
|
1423
1618
|
);
|
|
1424
1619
|
}
|
|
1620
|
+
const base = basis === "create" ? 0 : basis.on._v;
|
|
1425
1621
|
const envelope = buildRecordEnvelope(
|
|
1426
|
-
{ collection: "_keyring", id: userId, version: 1 },
|
|
1622
|
+
{ collection: "_keyring", id: userId, version: base + 1 },
|
|
1427
1623
|
{ iv: "", data: JSON.stringify(keyringFile) }
|
|
1428
1624
|
);
|
|
1429
|
-
await store.put(vault, "_keyring", userId, envelope);
|
|
1625
|
+
await store.put(vault, "_keyring", userId, envelope, base);
|
|
1430
1626
|
}
|
|
1431
1627
|
|
|
1432
1628
|
export {
|
|
@@ -1462,6 +1658,7 @@ export {
|
|
|
1462
1658
|
assertKeyringOpenAllowed,
|
|
1463
1659
|
createOwnerKeyring,
|
|
1464
1660
|
grant,
|
|
1661
|
+
NON_ROTATABLE_SLOTS,
|
|
1465
1662
|
revoke,
|
|
1466
1663
|
verifyRoster,
|
|
1467
1664
|
quarantineKeyring,
|
|
@@ -1474,10 +1671,15 @@ export {
|
|
|
1474
1671
|
ensureCollectionDEK,
|
|
1475
1672
|
hasWritePermission,
|
|
1476
1673
|
hasAccess,
|
|
1674
|
+
mintInboxKey,
|
|
1675
|
+
inboxSlots,
|
|
1676
|
+
openInboxKeyPair,
|
|
1477
1677
|
persistKeyring,
|
|
1478
1678
|
hasExportCapability,
|
|
1479
1679
|
evaluateExportCapability,
|
|
1480
1680
|
hasImportCapability,
|
|
1481
|
-
evaluateImportCapability
|
|
1681
|
+
evaluateImportCapability,
|
|
1682
|
+
basisOf,
|
|
1683
|
+
writeKeyringFile
|
|
1482
1684
|
};
|
|
1483
|
-
//# sourceMappingURL=chunk-
|
|
1685
|
+
//# sourceMappingURL=chunk-QVUMKG3Z.js.map
|