@noy-db/hub 0.8.0-pre.0 → 0.8.0
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 +50 -0
- package/dist/api-OS747DS4.js +18 -0
- package/dist/as/index.js +11 -12
- package/dist/as/index.js.map +1 -1
- package/dist/at/index.js +9 -10
- package/dist/attestation/index.js +39 -28
- package/dist/attestation/index.js.map +1 -1
- package/dist/{backup-7TFRVFLH.js → backup-YE2VQ26S.js} +15 -16
- package/dist/backup-YE2VQ26S.js.map +1 -0
- package/dist/blobs/index.js +13 -14
- package/dist/blobs/index.js.map +1 -1
- package/dist/broker/index.js +12 -13
- package/dist/broker/index.js.map +1 -1
- package/dist/by/index.js +2 -2
- package/dist/capsule/contract.d.ts +159 -0
- package/dist/capsule/contract.js +95 -0
- package/dist/capsule/enclave-aes/bound.d.ts +52 -0
- package/dist/capsule/enclave-aes/capabilities.d.ts +2 -0
- package/dist/capsule/enclave-aes/classify/compare.d.ts +20 -0
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/find.d.ts +1 -1
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/reveal.d.ts +1 -1
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/verify.d.ts +2 -2
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/write.d.ts +1 -1
- package/dist/{kernel/enclave → capsule/enclave-aes}/crypto.d.ts +33 -129
- package/dist/capsule/enclave-aes/index.d.ts +113 -0
- package/dist/capsule/enclave-aes/index.js +335 -0
- package/dist/capsule/enclave-aes/index.js.map +1 -0
- package/dist/capsule/enclave-aes/primitives.d.ts +29 -0
- package/dist/capsule/index.d.ts +27 -0
- package/dist/capsule/plumbing/ct-equal.d.ts +11 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/deterministic.d.ts +8 -21
- package/dist/capsule/plumbing/digest.d.ts +122 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/envelope-body.d.ts +44 -48
- package/dist/capsule/plumbing/index.d.ts +100 -0
- package/dist/capsule/plumbing/lifecycle.d.ts +50 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/record-codec.d.ts +55 -20
- package/dist/{kernel/enclave → capsule/plumbing}/record-envelope.d.ts +1 -1
- package/dist/capsule/plumbing/rekey-blob.d.ts +33 -0
- package/dist/capsule/plumbing/rekey.d.ts +44 -0
- package/dist/capsule/plumbing/sealed-slot.d.ts +22 -0
- package/dist/capsule/plumbing/sealed-slots.d.ts +37 -0
- package/dist/capsule/plumbing/sealing.d.ts +29 -0
- package/dist/capsule/plumbing/sign.d.ts +9 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/tombstone.d.ts +2 -2
- package/dist/capsule-VOLX3QRQ.js +209 -0
- package/dist/cargo/index.js +36 -36
- package/dist/{chunk-DF73H4UN.js → chunk-23D6M6VM.js} +5 -5
- package/dist/chunk-23D6M6VM.js.map +1 -0
- package/dist/{chunk-FH2L2E34.js → chunk-244QBK7Z.js} +4 -4
- package/dist/{chunk-FH2L2E34.js.map → chunk-244QBK7Z.js.map} +1 -1
- package/dist/{chunk-YSK2CU2Q.js → chunk-2AFX33YA.js} +2 -2
- package/dist/{chunk-TKUOEU2F.js → chunk-2GHDLTPE.js} +2 -2
- package/dist/{chunk-GYGLAVCX.js → chunk-2MG3SW7Q.js} +6 -2
- package/dist/chunk-2MG3SW7Q.js.map +1 -0
- package/dist/{chunk-6OWXYZK2.js → chunk-2ODVB6LZ.js} +2 -2
- package/dist/{chunk-X25NWUZB.js → chunk-2PVXF5CS.js} +3 -3
- package/dist/{chunk-IEX7NK2K.js → chunk-2RH777HH.js} +21 -20
- package/dist/{chunk-IEX7NK2K.js.map → chunk-2RH777HH.js.map} +1 -1
- package/dist/{chunk-244VXYPG.js → chunk-37EPTBBR.js} +14 -1
- package/dist/chunk-37EPTBBR.js.map +1 -0
- package/dist/{chunk-NRT6QZQB.js → chunk-3A5DUZ56.js} +6 -6
- package/dist/chunk-3A5DUZ56.js.map +1 -0
- package/dist/{chunk-ORDURZBU.js → chunk-3EWS67C7.js} +2 -2
- package/dist/{chunk-3H5KLDZN.js → chunk-3L2NBKDR.js} +4 -8
- package/dist/chunk-3L2NBKDR.js.map +1 -0
- package/dist/{chunk-ENAG3IY7.js → chunk-3XJQBBZD.js} +26 -28
- package/dist/chunk-3XJQBBZD.js.map +1 -0
- package/dist/{chunk-KJFW62P4.js → chunk-42ALPZ2B.js} +652 -662
- package/dist/chunk-42ALPZ2B.js.map +1 -0
- package/dist/{chunk-FXQBGFOX.js → chunk-4CIQDWRB.js} +8 -8
- package/dist/{chunk-HT2AHGQI.js → chunk-4JPMZTJY.js} +2 -2
- package/dist/{chunk-FQ5VRHIB.js → chunk-4T3SE27M.js} +5 -9
- package/dist/chunk-4T3SE27M.js.map +1 -0
- package/dist/{chunk-MKXXMNJH.js → chunk-4V3Q35WG.js} +2 -2
- package/dist/{chunk-A6IJU4TK.js → chunk-52MGURXO.js} +2 -2
- package/dist/{chunk-IUWCVHQ7.js → chunk-5A4345TG.js} +4 -4
- package/dist/{chunk-IUWCVHQ7.js.map → chunk-5A4345TG.js.map} +1 -1
- package/dist/{chunk-ISZQJBML.js → chunk-5FE75J4S.js} +6 -6
- package/dist/chunk-5FE75J4S.js.map +1 -0
- package/dist/chunk-5KC7QYEC.js +565 -0
- package/dist/chunk-5KC7QYEC.js.map +1 -0
- package/dist/{chunk-NNARWO72.js → chunk-5UMK7GRI.js} +13 -12
- package/dist/chunk-5UMK7GRI.js.map +1 -0
- package/dist/{chunk-HLEK5VAN.js → chunk-5WWDGFOS.js} +2 -2
- package/dist/{chunk-CKNGS5MH.js → chunk-6QVKPHBF.js} +3 -5
- package/dist/chunk-6QVKPHBF.js.map +1 -0
- package/dist/{chunk-PSIV7CJV.js → chunk-747G6CT3.js} +2 -2
- package/dist/chunk-747G6CT3.js.map +1 -0
- package/dist/{chunk-LGRLME4M.js → chunk-7R2Q7CPL.js} +16 -16
- package/dist/chunk-7R2Q7CPL.js.map +1 -0
- package/dist/{chunk-SOIQ4MM4.js → chunk-7XMHMVTS.js} +3 -3
- package/dist/{chunk-BUDAGWL5.js → chunk-A4XMIZT3.js} +6 -6
- package/dist/{chunk-BUDAGWL5.js.map → chunk-A4XMIZT3.js.map} +1 -1
- package/dist/{chunk-4MXI3ODD.js → chunk-AEQGFRU4.js} +3 -3
- package/dist/{chunk-7JE7BDYJ.js → chunk-AL6ML4LA.js} +5 -5
- package/dist/{chunk-ZUVBC32X.js → chunk-AUKKUPVB.js} +2 -2
- package/dist/chunk-BNWA3WG5.js +22 -0
- package/dist/chunk-BNWA3WG5.js.map +1 -0
- package/dist/{chunk-WY2XXTET.js → chunk-BPWYQ25R.js} +4 -4
- package/dist/{chunk-EOVMT6TB.js → chunk-BVCUTXE3.js} +2 -2
- package/dist/{chunk-UPD5NWI5.js → chunk-DHHGL42E.js} +13 -16
- package/dist/chunk-DHHGL42E.js.map +1 -0
- package/dist/{chunk-3JWHAR6E.js → chunk-DIZLQVAA.js} +2 -2
- package/dist/{chunk-QWFHIOD2.js → chunk-DLD5LGDS.js} +11 -12
- package/dist/chunk-DLD5LGDS.js.map +1 -0
- package/dist/{chunk-ZE4CHIED.js → chunk-DQESF6RP.js} +17 -28
- package/dist/chunk-DQESF6RP.js.map +1 -0
- package/dist/{chunk-IT22PWKV.js → chunk-E2N2T5ZO.js} +2 -2
- package/dist/{chunk-3ELRMVJK.js → chunk-EGVJ7TM4.js} +31 -34
- package/dist/chunk-EGVJ7TM4.js.map +1 -0
- package/dist/{chunk-WNJ4AVGE.js → chunk-EJLV62NI.js} +2 -2
- package/dist/{chunk-QBBUZ3I3.js → chunk-EYG2CY2X.js} +11 -11
- package/dist/{enclave-27SMF6GF.js → chunk-EZGV6F47.js} +83 -56
- package/dist/chunk-EZGV6F47.js.map +1 -0
- package/dist/{chunk-LQ4ZHOKP.js → chunk-EZOAKKTB.js} +36 -27
- package/dist/chunk-EZOAKKTB.js.map +1 -0
- package/dist/{chunk-BJ2IXQ5Q.js → chunk-FFJFE4T7.js} +2 -2
- package/dist/{chunk-JCN44NCY.js → chunk-FLPCETP6.js} +2 -2
- package/dist/{chunk-5O7D6ZTW.js → chunk-FOEDQATO.js} +2 -2
- package/dist/{chunk-VNNRUGMM.js → chunk-FVH5QYY2.js} +2 -2
- package/dist/{chunk-ANWPSTZU.js → chunk-G2MVBDFP.js} +23 -26
- package/dist/chunk-G2MVBDFP.js.map +1 -0
- package/dist/chunk-GMKGGY7V.js +234 -0
- package/dist/chunk-GMKGGY7V.js.map +1 -0
- package/dist/{chunk-EIPVYUEP.js → chunk-GQ4MF3CM.js} +3 -3
- package/dist/chunk-GQ4MF3CM.js.map +1 -0
- package/dist/{chunk-PEOZ34EM.js → chunk-GSAK56VF.js} +1 -1
- package/dist/chunk-GSAK56VF.js.map +1 -0
- package/dist/{chunk-QOOUUR4A.js → chunk-GUZET4SG.js} +10 -4
- package/dist/chunk-GUZET4SG.js.map +1 -0
- package/dist/{chunk-4AF3TUMP.js → chunk-GZT3NQRA.js} +2 -2
- package/dist/{chunk-N5DNADLQ.js → chunk-H23XHRTT.js} +19 -34
- package/dist/chunk-H23XHRTT.js.map +1 -0
- package/dist/{chunk-MVZ2TPVP.js → chunk-H427H63K.js} +2 -2
- package/dist/{chunk-6B3VNR4P.js → chunk-H7JBY4P7.js} +23 -32
- package/dist/chunk-H7JBY4P7.js.map +1 -0
- package/dist/{chunk-MLPHLJIQ.js → chunk-HS554XAF.js} +2 -2
- package/dist/{chunk-HK67PX4J.js → chunk-HW7CMKUG.js} +1 -1
- package/dist/chunk-HW7CMKUG.js.map +1 -0
- package/dist/{chunk-S57HTZ6X.js → chunk-IMQKWR46.js} +5 -7
- package/dist/chunk-IMQKWR46.js.map +1 -0
- package/dist/{chunk-FCKWQE2H.js → chunk-IUBMZPHM.js} +7 -7
- package/dist/chunk-IUBMZPHM.js.map +1 -0
- package/dist/{chunk-UD5EVGZ7.js → chunk-IUT3GWP3.js} +49 -13
- package/dist/chunk-IUT3GWP3.js.map +1 -0
- package/dist/{chunk-J6UOHJY5.js → chunk-JDEYF3PJ.js} +4 -8
- package/dist/{chunk-J6UOHJY5.js.map → chunk-JDEYF3PJ.js.map} +1 -1
- package/dist/{chunk-NWHBJQAL.js → chunk-JIBUPZHA.js} +4 -4
- package/dist/chunk-JIBUPZHA.js.map +1 -0
- package/dist/{chunk-TROR3ALR.js → chunk-JOSPH3E5.js} +2 -2
- package/dist/{chunk-F24ZZTHQ.js → chunk-JQYKPKG6.js} +4 -4
- package/dist/{chunk-GF5BZ7D4.js → chunk-JSMTXZR3.js} +8 -12
- package/dist/chunk-JSMTXZR3.js.map +1 -0
- package/dist/chunk-JWWYRR4Q.js +12 -0
- package/dist/chunk-JWWYRR4Q.js.map +1 -0
- package/dist/{chunk-HBPPGWUM.js → chunk-KZXDLBY6.js} +14 -9
- package/dist/chunk-KZXDLBY6.js.map +1 -0
- package/dist/{chunk-7VCXZDA4.js → chunk-LIOVX5TJ.js} +7 -11
- package/dist/chunk-LIOVX5TJ.js.map +1 -0
- package/dist/{chunk-QWGU66MP.js → chunk-LNSVGRHO.js} +5 -7
- package/dist/chunk-LNSVGRHO.js.map +1 -0
- package/dist/{chunk-MDWKM2XC.js → chunk-M5B2W6YY.js} +3 -3
- package/dist/{chunk-F2TDU7MQ.js → chunk-MBMTND6D.js} +2 -2
- package/dist/{chunk-K6W7BVZ6.js → chunk-MILI22XQ.js} +3 -3
- package/dist/{chunk-YNIUIERI.js → chunk-MXKI4ABF.js} +18 -59
- package/dist/chunk-MXKI4ABF.js.map +1 -0
- package/dist/{chunk-T2LBQ5DV.js → chunk-MXOQ5JCG.js} +252 -214
- package/dist/chunk-MXOQ5JCG.js.map +1 -0
- package/dist/{chunk-ZXABPVM6.js → chunk-N7EVQD5S.js} +9 -13
- package/dist/chunk-N7EVQD5S.js.map +1 -0
- package/dist/{chunk-CF5UU4S7.js → chunk-N7UDP5VU.js} +7 -7
- package/dist/{chunk-FQ54DWUQ.js → chunk-NBQ3KK6X.js} +4 -4
- package/dist/{chunk-4I522ERM.js → chunk-NCO25JZO.js} +4 -4
- package/dist/chunk-NH2UOV3B.js +18 -0
- package/dist/chunk-NH2UOV3B.js.map +1 -0
- package/dist/{chunk-SI3V7D4G.js → chunk-O2IMQSNA.js} +2 -2
- package/dist/{chunk-T52GX4SA.js → chunk-O46CHQT7.js} +4 -4
- package/dist/chunk-OIEO4WDL.js +27 -0
- package/dist/chunk-OIEO4WDL.js.map +1 -0
- package/dist/{chunk-GHLTDZRS.js → chunk-OKSTSITU.js} +25 -4
- package/dist/chunk-OKSTSITU.js.map +1 -0
- package/dist/{chunk-TOPYQ6GA.js → chunk-OYW3I5M4.js} +6 -6
- package/dist/{chunk-X4773RBR.js → chunk-PD64727P.js} +2 -2
- package/dist/chunk-PD64727P.js.map +1 -0
- package/dist/{chunk-BP6DARYA.js → chunk-PP3K67AJ.js} +4 -4
- package/dist/chunk-PP3K67AJ.js.map +1 -0
- package/dist/chunk-Q2XRFWOI.js +40 -0
- package/dist/chunk-Q2XRFWOI.js.map +1 -0
- package/dist/{chunk-AOWGXU6D.js → chunk-Q4UHJ5SN.js} +2 -2
- package/dist/{chunk-FW22ZCXT.js → chunk-QBLT6POL.js} +2 -2
- package/dist/chunk-QMWY2FDS.js +157 -0
- package/dist/chunk-QMWY2FDS.js.map +1 -0
- package/dist/{chunk-I3JDRCMW.js → chunk-RB4DOPGZ.js} +10 -10
- package/dist/{chunk-32YV3TJT.js → chunk-SMV2HRDU.js} +2 -2
- package/dist/{chunk-ODVPTDPK.js → chunk-SV2PM2OY.js} +1 -1
- package/dist/chunk-SV2PM2OY.js.map +1 -0
- package/dist/{chunk-Z5HTYMMQ.js → chunk-SYNY3VB5.js} +2 -2
- package/dist/{chunk-SYVZW77S.js → chunk-TEHHROZL.js} +6 -8
- package/dist/chunk-TEHHROZL.js.map +1 -0
- package/dist/{chunk-ZSX4S5XB.js → chunk-TKVUE4JF.js} +9 -9
- package/dist/{chunk-B57AFBY2.js → chunk-TZZBXPZK.js} +2 -2
- package/dist/{chunk-VNPEWFPD.js → chunk-U2FZNEWJ.js} +4 -4
- package/dist/chunk-U2FZNEWJ.js.map +1 -0
- package/dist/{chunk-5FDLC6G7.js → chunk-UA372JHH.js} +3 -3
- package/dist/{chunk-PDCG6PR5.js → chunk-UEFOQH74.js} +2 -2
- package/dist/chunk-UEFOQH74.js.map +1 -0
- package/dist/{chunk-HVSCEIYL.js → chunk-UIYESRD6.js} +9 -11
- package/dist/chunk-UIYESRD6.js.map +1 -0
- package/dist/{chunk-B6SJIBQK.js → chunk-V3RWOOSO.js} +4 -4
- package/dist/{chunk-HBRLNOHL.js → chunk-V7ADQF5O.js} +4 -4
- package/dist/{chunk-L7DOS3TE.js → chunk-VAORSCSU.js} +3 -3
- package/dist/chunk-VAORSCSU.js.map +1 -0
- package/dist/{chunk-M522UYZ2.js → chunk-VFHCKG5M.js} +6 -10
- package/dist/chunk-VFHCKG5M.js.map +1 -0
- package/dist/{chunk-DC5QVPV7.js → chunk-VHBKYN2J.js} +3 -3
- package/dist/chunk-VHBKYN2J.js.map +1 -0
- package/dist/{chunk-WX5ADGTZ.js → chunk-VKI2EB3N.js} +3 -3
- package/dist/chunk-VKI2EB3N.js.map +1 -0
- package/dist/{chunk-MTL7MXGR.js → chunk-VMV5SBE4.js} +16 -17
- package/dist/chunk-VMV5SBE4.js.map +1 -0
- package/dist/{chunk-F7XGHL5O.js → chunk-VQDZYB2B.js} +3 -3
- package/dist/{chunk-BK2HHQGN.js → chunk-VVOLDVIR.js} +2 -2
- package/dist/{chunk-6LMQ5R26.js → chunk-WPOYWFSE.js} +7 -7
- package/dist/{chunk-6LMQ5R26.js.map → chunk-WPOYWFSE.js.map} +1 -1
- package/dist/{chunk-3F7GLNAE.js → chunk-WXE4W2U6.js} +7 -11
- package/dist/chunk-WXE4W2U6.js.map +1 -0
- package/dist/{chunk-6K7DPM7D.js → chunk-XQRFSKYM.js} +2 -2
- package/dist/{chunk-M7NI3IWE.js → chunk-XSPFDUDG.js} +22 -50
- package/dist/chunk-XSPFDUDG.js.map +1 -0
- package/dist/{chunk-ID6Z6E66.js → chunk-Y2RKVFKR.js} +2 -2
- package/dist/{chunk-6LNL42F5.js → chunk-Y3LPTBG7.js} +12 -12
- package/dist/chunk-Y3LPTBG7.js.map +1 -0
- package/dist/{chunk-FN5EBVTQ.js → chunk-YRXFFWG4.js} +2 -2
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-W3USLL5M.js → classified-marker-SIYKUU5L.js} +3 -3
- package/dist/classified-marker-SIYKUU5L.js.map +1 -0
- package/dist/collection-facade-CS7CA2XO.js +47 -0
- package/dist/{computed-TPFBX7U4.js → computed-FAD7SED4.js} +3 -3
- package/dist/consent/index.js +10 -11
- package/dist/consent/index.js.map +1 -1
- package/dist/cover/index.js +9 -10
- package/dist/custody/index.js +12 -13
- package/dist/{dead-filter-U2UYKSZL.js → dead-filter-4F3LWYKH.js} +11 -3
- package/dist/dead-filter-4F3LWYKH.js.map +1 -0
- package/dist/debug/index.js +11 -2
- package/dist/debug/index.js.map +1 -1
- package/dist/{delegation-S3AEPW2T.js → delegation-NANZDG4N.js} +13 -16
- package/dist/delegation-NANZDG4N.js.map +1 -0
- package/dist/derivations/index.js +23 -24
- package/dist/derive-XLOJVXPU.js +20 -0
- package/dist/directory/index.js +10 -11
- package/dist/{dispatch-3CQDJV5Q.js → dispatch-H4HV32AM.js} +5 -5
- package/dist/{dispatch-RH4LHKBH.js → dispatch-JDZNGEB3.js} +21 -22
- package/dist/dispatch-JDZNGEB3.js.map +1 -0
- package/dist/executor-FMPVN6DT.js +35 -0
- package/dist/executor-LBBBRTN5.js +8 -0
- package/dist/executor-OSRZST2U.js +8 -0
- package/dist/export-accessible-RAOJAAU5.js +22 -0
- package/dist/extract-partition-JD5CUSTG.js +37 -0
- package/dist/{fanout-sidecar-OT6RYLOL.js → fanout-sidecar-L7NHPIOC.js} +13 -15
- package/dist/fanout-sidecar-L7NHPIOC.js.map +1 -0
- package/dist/find-JRN4RNQ5.js +10 -0
- package/dist/forget/index.js +9 -10
- package/dist/forget/index.js.map +1 -1
- package/dist/guards/index.js +4 -4
- package/dist/history/index.js +13 -14
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.js +14 -15
- package/dist/i18n/index.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +183 -184
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +5 -5
- package/dist/introspection/index.js +11 -12
- package/dist/issue-YIVBZUTH.js +19 -0
- package/dist/kernel/attestation-types.d.ts +62 -0
- package/dist/kernel/collection-config.d.ts +1 -48
- package/dist/kernel/collection.d.ts +1 -1
- package/dist/kernel/cutover-transform.d.ts +1 -1
- package/dist/kernel/errors.d.ts +30 -2
- package/dist/kernel/merge-authority.d.ts +1 -1
- package/dist/kernel/paths.d.ts +29 -5
- package/dist/kernel/prepared-write.d.ts +1 -1
- package/dist/kernel/secret-mode.d.ts +1 -1
- package/dist/kernel/types.d.ts +42 -5
- package/dist/kernel/vault.d.ts +2 -2
- package/dist/kernel/write-queue.d.ts +17 -0
- package/dist/{ledger-KZPCMVZY.js → ledger-5ZMGE44K.js} +11 -12
- package/dist/liberate-WZSZM2W6.js +24 -0
- package/dist/link-set-MFXC24VK.js +29 -0
- package/dist/{managed-secret-S3MQ6SH6.js → managed-secret-MFTFT22X.js} +10 -11
- package/dist/materialized-views/index.js +26 -27
- package/dist/{migrate-cek-V7GKJZ7O.js → migrate-cek-DZRFFOHW.js} +2 -2
- package/dist/money/index.js +5 -5
- package/dist/noydb-ITIGNKUF.js +96 -0
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +12 -13
- package/dist/pod/index.js +72 -72
- package/dist/{pod-handle-WGDFB4C2.js → pod-handle-A3LET7NO.js} +10 -11
- package/dist/pod-handle-A3LET7NO.js.map +1 -0
- package/dist/policy/index.js +10 -11
- package/dist/port/on/index.d.ts +1 -1
- package/dist/port/to/index.d.ts +1 -1
- package/dist/port/with/blob-strategy.d.ts +1 -1
- package/dist/port/with/classified-strategy.d.ts +1 -1
- package/dist/port/with/collection-options.d.ts +1 -1
- package/dist/port/with/collection-registries.d.ts +1 -1
- package/dist/port/with/lookup-strategy.d.ts +2 -2
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-SLSXIPBV.js → post-register-7ND27CF2.js} +6 -6
- package/dist/post-register-7ND27CF2.js.map +1 -0
- 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-DT5HZ2LZ.js +30 -0
- package/dist/registry-BHRZGZHF.js +8 -0
- package/dist/registry-ET6ZFFWA.js +34 -0
- package/dist/registry-HXFGLGTG.js +8 -0
- package/dist/registry-THCPDEOD.js +23 -0
- package/dist/request-withdrawal-AV2MJJKY.js +30 -0
- package/dist/{reveal-4BCKPEC2.js → reveal-B2TLP4JQ.js} +10 -9
- package/dist/reveal-B2TLP4JQ.js.map +1 -0
- package/dist/revoke-6DWIEOCV.js +24 -0
- package/dist/satellites/index.js +1 -1
- package/dist/schema-update/index.js +2 -2
- package/dist/sealed-record/index.js +16 -18
- package/dist/sealed-record/index.js.map +1 -1
- package/dist/search/index.js +4 -4
- package/dist/{seed-4JS2RJ4A.js → seed-XNSE4U3S.js} +15 -18
- package/dist/seed-XNSE4U3S.js.map +1 -0
- package/dist/sequence/index.js +9 -10
- package/dist/session/index.js +9 -10
- package/dist/session/index.js.map +1 -1
- package/dist/shadow/index.js +2 -2
- package/dist/signer-MHGW3OIL.js +23 -0
- package/dist/snapshots/index.js +11 -11
- package/dist/stale-6GCFMOOR.js +28 -0
- package/dist/storage-BYN5LO6Z.js +21 -0
- package/dist/store/index.js +1 -1
- package/dist/{store-coordination-provider-2O2VUHKW.js → store-coordination-provider-C4BPT5XF.js} +11 -12
- package/dist/store-coordination-provider-C4BPT5XF.js.map +1 -0
- package/dist/sync/index.js +10 -11
- package/dist/sync/index.js.map +1 -1
- package/dist/team/index.js +15 -16
- package/dist/tiers/index.js +11 -12
- 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 +11 -14
- package/dist/vault-head/index.js.map +1 -1
- package/dist/{verify-RVT67IMH.js → verify-UKALW7C2.js} +14 -12
- package/dist/verify-UKALW7C2.js.map +1 -0
- package/dist/via/classified/binding.d.ts +2 -2
- package/dist/via/classified/config-drift.d.ts +2 -2
- package/dist/via/classified/errors.d.ts +1 -1
- package/dist/via/lookup/handle.d.ts +4 -4
- package/dist/walk-4VPK7AS4.js +20 -0
- package/dist/with-audit/attestation/index.d.ts +2 -1
- package/dist/with-audit/attestation/issue.d.ts +2 -2
- package/dist/with-audit/attestation/revoke.d.ts +2 -2
- package/dist/with-audit/attestation/scheme.d.ts +7 -0
- package/dist/with-audit/attestation/signer.d.ts +1 -1
- package/dist/with-audit/attestation/strategy.d.ts +2 -2
- package/dist/with-audit/attestation/types.d.ts +10 -0
- package/dist/with-audit/attestation/vault-facade.d.ts +2 -2
- package/dist/with-audit/attestation/verifier.d.ts +6 -0
- package/dist/with-audit/consent/consent.d.ts +1 -1
- package/dist/with-audit/consent/strategy.d.ts +1 -1
- package/dist/with-audit/forget/subject-index.d.ts +1 -1
- package/dist/with-audit/periods/vault-facade.d.ts +1 -1
- package/dist/with-audit/sealed-record/index.d.ts +2 -2
- package/dist/with-audit/sealed-record/strategy.d.ts +1 -1
- package/dist/with-audit/tiers/index.d.ts +2 -2
- package/dist/with-cargo/adopt-partition.d.ts +1 -1
- package/dist/with-cargo/extract-partition.d.ts +1 -1
- package/dist/with-cargo/floor.d.ts +1 -1
- package/dist/with-commit/history/history.d.ts +2 -2
- package/dist/with-commit/history/index.d.ts +1 -1
- package/dist/with-commit/history/ledger/store.d.ts +1 -1
- package/dist/with-commit/history/strategy.d.ts +1 -1
- package/dist/with-commit/history/time-machine.d.ts +1 -1
- package/dist/with-commit/numbering/index.d.ts +1 -1
- package/dist/with-commit/sequence/index.d.ts +1 -1
- package/dist/with-commit/vault-head/head.d.ts +1 -1
- package/dist/with-commit/vault-head/index.d.ts +1 -1
- package/dist/with-commit/vault-head/strategy.d.ts +1 -1
- package/dist/with-commit/vault-head/verify.d.ts +1 -1
- package/dist/with-formula/derivations/dispatch.d.ts +1 -1
- package/dist/with-formula/derivations/fanout-sidecar.d.ts +1 -1
- package/dist/with-lookup/indexing/collection-facade.d.ts +1 -1
- package/dist/with-lookup/search/collection-facade.d.ts +1 -1
- package/dist/with-party/broker/index.d.ts +3 -3
- package/dist/with-party/directory/user-envelope/storage.d.ts +1 -1
- package/dist/with-party/team/delegation.d.ts +1 -1
- package/dist/with-party/team/echo-secret.d.ts +2 -2
- package/dist/with-party/team/index.d.ts +1 -1
- package/dist/with-party/team/keyring.d.ts +1 -1
- package/dist/with-party/team/magic-link-grant.d.ts +1 -1
- package/dist/with-party/team/recovery.d.ts +1 -1
- package/dist/with-party/team/roster-tag.d.ts +1 -1
- package/dist/with-party/team/rotate-recover.d.ts +1 -1
- package/dist/with-party/team/wrapped-deks.d.ts +1 -1
- package/dist/with-pod/index.d.ts +1 -1
- package/dist/with-shape/blobs/blob-compaction.d.ts +1 -1
- package/dist/with-shape/blobs/blob-intent.d.ts +1 -1
- package/dist/with-shape/blobs/blob-set.d.ts +2 -2
- package/dist/with-shape/blobs/legacy-sweep.d.ts +1 -1
- package/dist/with-shape/introspection/describe.d.ts +1 -1
- package/dist/with-shape/introspection/walk.d.ts +1 -1
- package/dist/with-shape/links/lazy-handle.d.ts +1 -1
- package/dist/with-shape/links/link-set.d.ts +1 -1
- package/dist/with-shape/manifest/derive.d.ts +1 -1
- package/dist/with-shape/manifest/storage.d.ts +1 -1
- package/dist/with-shape/persisted-schemas/register.d.ts +1 -1
- package/dist/with-shape/persisted-schemas/storage.d.ts +1 -1
- package/dist/with-shape/satellites/dead-filter.d.ts +1 -1
- package/dist/with-shape/satellites/declare.d.ts +1 -1
- package/dist/with-shape/satellites/marker.d.ts +1 -1
- package/dist/with-shape/satellites/post-register.d.ts +1 -1
- package/dist/with-sync/presence.d.ts +5 -10
- package/dist/withdraw-accessible-HL7GACUE.js +27 -0
- package/dist/withdraw-accessible-HL7GACUE.js.map +1 -0
- package/package.json +14 -5
- package/dist/api-GVYEKSJE.js +0 -19
- package/dist/backup-7TFRVFLH.js.map +0 -1
- package/dist/chunk-244VXYPG.js.map +0 -1
- package/dist/chunk-3ELRMVJK.js.map +0 -1
- package/dist/chunk-3F7GLNAE.js.map +0 -1
- package/dist/chunk-3H5KLDZN.js.map +0 -1
- package/dist/chunk-6B3VNR4P.js.map +0 -1
- package/dist/chunk-6LNL42F5.js.map +0 -1
- package/dist/chunk-6QSQQLSE.js +0 -95
- package/dist/chunk-6QSQQLSE.js.map +0 -1
- package/dist/chunk-7VCXZDA4.js.map +0 -1
- package/dist/chunk-ANWPSTZU.js.map +0 -1
- package/dist/chunk-BP6DARYA.js.map +0 -1
- package/dist/chunk-CKNGS5MH.js.map +0 -1
- package/dist/chunk-DC5QVPV7.js.map +0 -1
- package/dist/chunk-DE4DH2RZ.js +0 -29
- package/dist/chunk-DE4DH2RZ.js.map +0 -1
- package/dist/chunk-DF73H4UN.js.map +0 -1
- package/dist/chunk-EIPVYUEP.js.map +0 -1
- package/dist/chunk-ENAG3IY7.js.map +0 -1
- package/dist/chunk-FCKWQE2H.js.map +0 -1
- package/dist/chunk-FQ5VRHIB.js.map +0 -1
- package/dist/chunk-GF5BZ7D4.js.map +0 -1
- package/dist/chunk-GHLTDZRS.js.map +0 -1
- package/dist/chunk-GYGLAVCX.js.map +0 -1
- package/dist/chunk-HBPPGWUM.js.map +0 -1
- package/dist/chunk-HK67PX4J.js.map +0 -1
- package/dist/chunk-HVSCEIYL.js.map +0 -1
- package/dist/chunk-ISZQJBML.js.map +0 -1
- package/dist/chunk-KJFW62P4.js.map +0 -1
- package/dist/chunk-L7DOS3TE.js.map +0 -1
- package/dist/chunk-LGRLME4M.js.map +0 -1
- package/dist/chunk-LP7BEXCT.js +0 -32
- package/dist/chunk-LP7BEXCT.js.map +0 -1
- package/dist/chunk-LQ4ZHOKP.js.map +0 -1
- package/dist/chunk-M522UYZ2.js.map +0 -1
- package/dist/chunk-M7NI3IWE.js.map +0 -1
- package/dist/chunk-MTL7MXGR.js.map +0 -1
- package/dist/chunk-N5DNADLQ.js.map +0 -1
- package/dist/chunk-NNARWO72.js.map +0 -1
- package/dist/chunk-NRT6QZQB.js.map +0 -1
- package/dist/chunk-NWHBJQAL.js.map +0 -1
- package/dist/chunk-ODVPTDPK.js.map +0 -1
- package/dist/chunk-PDCG6PR5.js.map +0 -1
- package/dist/chunk-PEOZ34EM.js.map +0 -1
- package/dist/chunk-PSIV7CJV.js.map +0 -1
- package/dist/chunk-QOOUUR4A.js.map +0 -1
- package/dist/chunk-QWFHIOD2.js.map +0 -1
- package/dist/chunk-QWGU66MP.js.map +0 -1
- package/dist/chunk-S57HTZ6X.js.map +0 -1
- package/dist/chunk-SEE332EV.js +0 -66
- package/dist/chunk-SEE332EV.js.map +0 -1
- package/dist/chunk-SYVZW77S.js.map +0 -1
- package/dist/chunk-T2LBQ5DV.js.map +0 -1
- package/dist/chunk-UD5EVGZ7.js.map +0 -1
- package/dist/chunk-UPD5NWI5.js.map +0 -1
- package/dist/chunk-UYB234ZR.js +0 -479
- package/dist/chunk-UYB234ZR.js.map +0 -1
- package/dist/chunk-VNPEWFPD.js.map +0 -1
- package/dist/chunk-WX5ADGTZ.js.map +0 -1
- package/dist/chunk-X4773RBR.js.map +0 -1
- package/dist/chunk-YNIUIERI.js.map +0 -1
- package/dist/chunk-ZE4CHIED.js.map +0 -1
- package/dist/chunk-ZXABPVM6.js.map +0 -1
- package/dist/classified-marker-W3USLL5M.js.map +0 -1
- package/dist/collection-facade-QU6IJBN3.js +0 -48
- package/dist/dead-filter-U2UYKSZL.js.map +0 -1
- package/dist/delegation-S3AEPW2T.js.map +0 -1
- package/dist/derive-OX7F6TGG.js +0 -21
- package/dist/dispatch-RH4LHKBH.js.map +0 -1
- package/dist/executor-B6SRO2QS.js +0 -36
- package/dist/executor-BI5CHWRY.js +0 -8
- package/dist/executor-RBKM5W5K.js +0 -8
- package/dist/export-accessible-VMA3YM5V.js +0 -22
- package/dist/extract-partition-NF7PXGPP.js +0 -37
- package/dist/fanout-sidecar-OT6RYLOL.js.map +0 -1
- package/dist/find-LZMP26KF.js +0 -10
- package/dist/issue-IHARXWW5.js +0 -18
- package/dist/kernel/enclave/classify/compare.d.ts +0 -10
- package/dist/kernel/enclave/index.d.ts +0 -87
- package/dist/kernel/enclave/record-keys/lifecycle.d.ts +0 -124
- package/dist/kernel/enclave/record-keys/rekey-blob.d.ts +0 -88
- package/dist/kernel/enclave/record-keys/rekey.d.ts +0 -91
- package/dist/kernel/enclave/record-keys/sealed-slot.d.ts +0 -14
- package/dist/kernel/enclave/record-keys/sealed-slots.d.ts +0 -123
- package/dist/kernel/enclave/record-keys/sealing.d.ts +0 -70
- package/dist/liberate-GRLCZMW4.js +0 -24
- package/dist/link-set-JCMJ7ULP.js +0 -30
- package/dist/noydb-SWQJ3MZS.js +0 -97
- package/dist/pod-handle-WGDFB4C2.js.map +0 -1
- package/dist/post-register-SLSXIPBV.js.map +0 -1
- package/dist/register-F3OYE7MJ.js +0 -31
- package/dist/registry-CILQFXFK.js +0 -8
- package/dist/registry-XNNYQVKV.js +0 -8
- package/dist/registry-YCDZV3VW.js +0 -35
- package/dist/registry-ZGYS33TE.js +0 -24
- package/dist/request-withdrawal-Z5NC6TXT.js +0 -30
- package/dist/reveal-4BCKPEC2.js.map +0 -1
- package/dist/revoke-ZL62WC2D.js +0 -23
- package/dist/seed-4JS2RJ4A.js.map +0 -1
- package/dist/signer-MBZZMXTC.js +0 -24
- package/dist/stale-TJ3DYZMQ.js +0 -29
- package/dist/storage-SVMKRGCW.js +0 -22
- package/dist/store-coordination-provider-2O2VUHKW.js.map +0 -1
- package/dist/verify-RVT67IMH.js.map +0 -1
- package/dist/walk-HJ42EISE.js +0 -21
- package/dist/withdraw-accessible-5NZUPAVA.js +0 -27
- /package/dist/{api-GVYEKSJE.js.map → api-OS747DS4.js.map} +0 -0
- /package/dist/{computed-TPFBX7U4.js.map → capsule/contract.js.map} +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/broker/proof.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/bidx.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/digest.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/vdig.d.ts +0 -0
- /package/dist/{kernel/enclave/classify → capsule/plumbing}/kofn.d.ts +0 -0
- /package/dist/{kernel/enclave/classify → capsule/plumbing}/normalize.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/plumbing}/record-aad.d.ts +0 -0
- /package/dist/{collection-facade-QU6IJBN3.js.map → capsule-VOLX3QRQ.js.map} +0 -0
- /package/dist/{chunk-YSK2CU2Q.js.map → chunk-2AFX33YA.js.map} +0 -0
- /package/dist/{chunk-TKUOEU2F.js.map → chunk-2GHDLTPE.js.map} +0 -0
- /package/dist/{chunk-6OWXYZK2.js.map → chunk-2ODVB6LZ.js.map} +0 -0
- /package/dist/{chunk-X25NWUZB.js.map → chunk-2PVXF5CS.js.map} +0 -0
- /package/dist/{chunk-ORDURZBU.js.map → chunk-3EWS67C7.js.map} +0 -0
- /package/dist/{chunk-FXQBGFOX.js.map → chunk-4CIQDWRB.js.map} +0 -0
- /package/dist/{chunk-HT2AHGQI.js.map → chunk-4JPMZTJY.js.map} +0 -0
- /package/dist/{chunk-MKXXMNJH.js.map → chunk-4V3Q35WG.js.map} +0 -0
- /package/dist/{chunk-A6IJU4TK.js.map → chunk-52MGURXO.js.map} +0 -0
- /package/dist/{chunk-HLEK5VAN.js.map → chunk-5WWDGFOS.js.map} +0 -0
- /package/dist/{chunk-SOIQ4MM4.js.map → chunk-7XMHMVTS.js.map} +0 -0
- /package/dist/{chunk-4MXI3ODD.js.map → chunk-AEQGFRU4.js.map} +0 -0
- /package/dist/{chunk-7JE7BDYJ.js.map → chunk-AL6ML4LA.js.map} +0 -0
- /package/dist/{chunk-ZUVBC32X.js.map → chunk-AUKKUPVB.js.map} +0 -0
- /package/dist/{chunk-WY2XXTET.js.map → chunk-BPWYQ25R.js.map} +0 -0
- /package/dist/{chunk-EOVMT6TB.js.map → chunk-BVCUTXE3.js.map} +0 -0
- /package/dist/{chunk-3JWHAR6E.js.map → chunk-DIZLQVAA.js.map} +0 -0
- /package/dist/{chunk-IT22PWKV.js.map → chunk-E2N2T5ZO.js.map} +0 -0
- /package/dist/{chunk-WNJ4AVGE.js.map → chunk-EJLV62NI.js.map} +0 -0
- /package/dist/{chunk-QBBUZ3I3.js.map → chunk-EYG2CY2X.js.map} +0 -0
- /package/dist/{chunk-BJ2IXQ5Q.js.map → chunk-FFJFE4T7.js.map} +0 -0
- /package/dist/{chunk-JCN44NCY.js.map → chunk-FLPCETP6.js.map} +0 -0
- /package/dist/{chunk-5O7D6ZTW.js.map → chunk-FOEDQATO.js.map} +0 -0
- /package/dist/{chunk-VNNRUGMM.js.map → chunk-FVH5QYY2.js.map} +0 -0
- /package/dist/{chunk-4AF3TUMP.js.map → chunk-GZT3NQRA.js.map} +0 -0
- /package/dist/{chunk-MVZ2TPVP.js.map → chunk-H427H63K.js.map} +0 -0
- /package/dist/{chunk-MLPHLJIQ.js.map → chunk-HS554XAF.js.map} +0 -0
- /package/dist/{chunk-TROR3ALR.js.map → chunk-JOSPH3E5.js.map} +0 -0
- /package/dist/{chunk-F24ZZTHQ.js.map → chunk-JQYKPKG6.js.map} +0 -0
- /package/dist/{chunk-MDWKM2XC.js.map → chunk-M5B2W6YY.js.map} +0 -0
- /package/dist/{chunk-F2TDU7MQ.js.map → chunk-MBMTND6D.js.map} +0 -0
- /package/dist/{chunk-K6W7BVZ6.js.map → chunk-MILI22XQ.js.map} +0 -0
- /package/dist/{chunk-CF5UU4S7.js.map → chunk-N7UDP5VU.js.map} +0 -0
- /package/dist/{chunk-FQ54DWUQ.js.map → chunk-NBQ3KK6X.js.map} +0 -0
- /package/dist/{chunk-4I522ERM.js.map → chunk-NCO25JZO.js.map} +0 -0
- /package/dist/{chunk-SI3V7D4G.js.map → chunk-O2IMQSNA.js.map} +0 -0
- /package/dist/{chunk-T52GX4SA.js.map → chunk-O46CHQT7.js.map} +0 -0
- /package/dist/{chunk-TOPYQ6GA.js.map → chunk-OYW3I5M4.js.map} +0 -0
- /package/dist/{chunk-AOWGXU6D.js.map → chunk-Q4UHJ5SN.js.map} +0 -0
- /package/dist/{chunk-FW22ZCXT.js.map → chunk-QBLT6POL.js.map} +0 -0
- /package/dist/{chunk-I3JDRCMW.js.map → chunk-RB4DOPGZ.js.map} +0 -0
- /package/dist/{chunk-32YV3TJT.js.map → chunk-SMV2HRDU.js.map} +0 -0
- /package/dist/{chunk-Z5HTYMMQ.js.map → chunk-SYNY3VB5.js.map} +0 -0
- /package/dist/{chunk-ZSX4S5XB.js.map → chunk-TKVUE4JF.js.map} +0 -0
- /package/dist/{chunk-B57AFBY2.js.map → chunk-TZZBXPZK.js.map} +0 -0
- /package/dist/{chunk-5FDLC6G7.js.map → chunk-UA372JHH.js.map} +0 -0
- /package/dist/{chunk-B6SJIBQK.js.map → chunk-V3RWOOSO.js.map} +0 -0
- /package/dist/{chunk-HBRLNOHL.js.map → chunk-V7ADQF5O.js.map} +0 -0
- /package/dist/{chunk-F7XGHL5O.js.map → chunk-VQDZYB2B.js.map} +0 -0
- /package/dist/{chunk-BK2HHQGN.js.map → chunk-VVOLDVIR.js.map} +0 -0
- /package/dist/{chunk-6K7DPM7D.js.map → chunk-XQRFSKYM.js.map} +0 -0
- /package/dist/{chunk-ID6Z6E66.js.map → chunk-Y2RKVFKR.js.map} +0 -0
- /package/dist/{chunk-FN5EBVTQ.js.map → chunk-YRXFFWG4.js.map} +0 -0
- /package/dist/{derive-OX7F6TGG.js.map → collection-facade-CS7CA2XO.js.map} +0 -0
- /package/dist/{enclave-27SMF6GF.js.map → computed-FAD7SED4.js.map} +0 -0
- /package/dist/{executor-B6SRO2QS.js.map → derive-XLOJVXPU.js.map} +0 -0
- /package/dist/{dispatch-3CQDJV5Q.js.map → dispatch-H4HV32AM.js.map} +0 -0
- /package/dist/{executor-BI5CHWRY.js.map → executor-FMPVN6DT.js.map} +0 -0
- /package/dist/{executor-RBKM5W5K.js.map → executor-LBBBRTN5.js.map} +0 -0
- /package/dist/{export-accessible-VMA3YM5V.js.map → executor-OSRZST2U.js.map} +0 -0
- /package/dist/{extract-partition-NF7PXGPP.js.map → export-accessible-RAOJAAU5.js.map} +0 -0
- /package/dist/{find-LZMP26KF.js.map → extract-partition-JD5CUSTG.js.map} +0 -0
- /package/dist/{issue-IHARXWW5.js.map → find-JRN4RNQ5.js.map} +0 -0
- /package/dist/{ledger-KZPCMVZY.js.map → issue-YIVBZUTH.js.map} +0 -0
- /package/dist/{liberate-GRLCZMW4.js.map → ledger-5ZMGE44K.js.map} +0 -0
- /package/dist/{link-set-JCMJ7ULP.js.map → liberate-WZSZM2W6.js.map} +0 -0
- /package/dist/{managed-secret-S3MQ6SH6.js.map → link-set-MFXC24VK.js.map} +0 -0
- /package/dist/{noydb-SWQJ3MZS.js.map → managed-secret-MFTFT22X.js.map} +0 -0
- /package/dist/{migrate-cek-V7GKJZ7O.js.map → migrate-cek-DZRFFOHW.js.map} +0 -0
- /package/dist/{register-F3OYE7MJ.js.map → noydb-ITIGNKUF.js.map} +0 -0
- /package/dist/{registry-CILQFXFK.js.map → register-DT5HZ2LZ.js.map} +0 -0
- /package/dist/{registry-XNNYQVKV.js.map → registry-BHRZGZHF.js.map} +0 -0
- /package/dist/{registry-YCDZV3VW.js.map → registry-ET6ZFFWA.js.map} +0 -0
- /package/dist/{registry-ZGYS33TE.js.map → registry-HXFGLGTG.js.map} +0 -0
- /package/dist/{request-withdrawal-Z5NC6TXT.js.map → registry-THCPDEOD.js.map} +0 -0
- /package/dist/{revoke-ZL62WC2D.js.map → request-withdrawal-AV2MJJKY.js.map} +0 -0
- /package/dist/{signer-MBZZMXTC.js.map → revoke-6DWIEOCV.js.map} +0 -0
- /package/dist/{stale-TJ3DYZMQ.js.map → signer-MHGW3OIL.js.map} +0 -0
- /package/dist/{storage-SVMKRGCW.js.map → stale-6GCFMOOR.js.map} +0 -0
- /package/dist/{walk-HJ42EISE.js.map → storage-BYN5LO6Z.js.map} +0 -0
- /package/dist/{withdraw-accessible-5NZUPAVA.js.map → walk-4VPK7AS4.js.map} +0 -0
|
@@ -1,56 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
isTombstone
|
|
5
|
-
} from "./chunk-SEE332EV.js";
|
|
6
|
-
import {
|
|
7
|
-
blindedEqual,
|
|
8
|
-
openVdigPayload,
|
|
9
|
-
sealVdigPayload
|
|
10
|
-
} from "./chunk-6QSQQLSE.js";
|
|
11
|
-
import {
|
|
12
|
-
dualReadSealedSlot,
|
|
13
|
-
parseSealedSlot
|
|
14
|
-
} from "./chunk-DE4DH2RZ.js";
|
|
15
|
-
import {
|
|
16
|
-
mintBidxTag
|
|
17
|
-
} from "./chunk-LQ4ZHOKP.js";
|
|
18
|
-
import {
|
|
19
|
-
VDIG_ITERATIONS,
|
|
20
|
-
normalizeForVerify,
|
|
21
|
-
pbkdf2VerifyDigest
|
|
22
|
-
} from "./chunk-LP7BEXCT.js";
|
|
23
|
-
import {
|
|
24
|
-
base64ToBuffer,
|
|
25
|
-
bufferToBase64,
|
|
26
|
-
decrypt,
|
|
27
|
-
decryptBytesWithAAD,
|
|
28
|
-
deriveDeterministicKey,
|
|
29
|
-
deriveSealedFieldKey,
|
|
30
|
-
deriveSealedFieldKeyFromCek,
|
|
31
|
-
encrypt,
|
|
32
|
-
encryptBytesWithAAD,
|
|
33
|
-
encryptDeterministic,
|
|
34
|
-
generateDEK,
|
|
35
|
-
generateSalt,
|
|
36
|
-
unwrapCek,
|
|
37
|
-
wrapCek
|
|
38
|
-
} from "./chunk-UYB234ZR.js";
|
|
2
|
+
normalizeForVerify
|
|
3
|
+
} from "./chunk-QMWY2FDS.js";
|
|
39
4
|
import {
|
|
40
5
|
NOYDB_FORMAT_VERSION,
|
|
41
6
|
SealedHandle
|
|
42
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SV2PM2OY.js";
|
|
43
8
|
import {
|
|
44
9
|
ClassifiedConfigError,
|
|
45
|
-
ClassifiedRotationError,
|
|
46
10
|
DebugReservedFieldError,
|
|
11
|
+
MissingEnvelopeBodyError,
|
|
47
12
|
RecordCekNotFoundError,
|
|
48
13
|
SchemaValidationError,
|
|
49
|
-
TamperedError,
|
|
50
14
|
ValidationError
|
|
51
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-37EPTBBR.js";
|
|
52
16
|
|
|
53
|
-
// src/
|
|
17
|
+
// src/capsule/plumbing/record-aad.ts
|
|
54
18
|
var SCHEME = "noydb-aad/2";
|
|
55
19
|
var encoder = new TextEncoder();
|
|
56
20
|
function buildRecordAad(identity) {
|
|
@@ -98,309 +62,148 @@ function recordAadFor(ref, envelope) {
|
|
|
98
62
|
});
|
|
99
63
|
}
|
|
100
64
|
|
|
101
|
-
// src/
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const live = await deps.getLive(id);
|
|
106
|
-
if (live?._cek !== void 0) {
|
|
107
|
-
const cek = await unwrapCek(live._cek, await deps.getDEK());
|
|
108
|
-
deps.cache?.set(id, cek, 1);
|
|
109
|
-
return cek;
|
|
110
|
-
}
|
|
111
|
-
const fresh = await generateDEK();
|
|
112
|
-
deps.cache?.set(id, fresh, 1);
|
|
113
|
-
return fresh;
|
|
65
|
+
// src/capsule/plumbing/envelope-body.ts
|
|
66
|
+
function requireSealedBody(env, where) {
|
|
67
|
+
if (env._iv === void 0 || env._data === void 0) throw new MissingEnvelopeBodyError(where);
|
|
68
|
+
return { iv: env._iv, data: env._data };
|
|
114
69
|
}
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const { iv: iv2, data: data2 } = await encrypt(plaintext2, cek, sealAad);
|
|
122
|
-
return { _iv: iv2, _data: data2, _cek: await wrapCek(cek, toDek), cek };
|
|
123
|
-
}
|
|
124
|
-
const plaintext = await decrypt(envelope._iv, envelope._data, fromDek, openAad);
|
|
125
|
-
const { iv, data } = await encrypt(plaintext, toDek, sealAad);
|
|
126
|
-
return { _iv: iv, _data: data, cek: null };
|
|
70
|
+
function sealedBodyArgs(env, where) {
|
|
71
|
+
const { iv, data } = requireSealedBody(env, where);
|
|
72
|
+
return [iv, data];
|
|
73
|
+
}
|
|
74
|
+
function envelopeBodySize(env) {
|
|
75
|
+
return (env._data?.length ?? 0) + (env._iv?.length ?? 0);
|
|
127
76
|
}
|
|
128
|
-
function
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
77
|
+
function hasPerRecordKey(env) {
|
|
78
|
+
return env._cek !== void 0;
|
|
79
|
+
}
|
|
80
|
+
function envelopeBodyForHash(env) {
|
|
81
|
+
const data = env._data ?? "";
|
|
82
|
+
if (env._sealed === void 0 && env._vdig === void 0 && env._bidx === void 0) return data;
|
|
83
|
+
const mapPart = (key, map) => {
|
|
84
|
+
const parts = Object.keys(map).sort().map(
|
|
85
|
+
(k) => `${JSON.stringify(k)}:${JSON.stringify(map[k])}`
|
|
86
|
+
);
|
|
87
|
+
return `${JSON.stringify(key)}:{${parts.join(",")}}`;
|
|
134
88
|
};
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
89
|
+
const segments = [`"_data":${JSON.stringify(data)}`];
|
|
90
|
+
if (env._sealed !== void 0) segments.push(mapPart("_sealed", env._sealed));
|
|
91
|
+
if (env._vdig !== void 0) segments.push(mapPart("_vdig", env._vdig));
|
|
92
|
+
if (env._bidx !== void 0) segments.push(mapPart("_bidx", env._bidx));
|
|
93
|
+
return `{${segments.join(",")}}`;
|
|
139
94
|
}
|
|
140
|
-
|
|
141
|
-
return
|
|
95
|
+
function hasSealedBody(env) {
|
|
96
|
+
return env._iv !== void 0 && env._iv !== "";
|
|
142
97
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
98
|
+
function makeEnvelopeBody(p) {
|
|
99
|
+
const { encrypt, decrypt, generateDEK, wrapCek, unwrapCek } = p;
|
|
100
|
+
async function openEnvelopeJson(ref, env, key, opts) {
|
|
101
|
+
if (opts?.encrypted === false) return env._data ?? "";
|
|
102
|
+
const aad = recordAadFor(ref, env);
|
|
103
|
+
const { iv, data } = requireSealedBody(env, "openEnvelopeJson");
|
|
104
|
+
if (env._cek !== void 0) {
|
|
105
|
+
const cek = await unwrapCek(env._cek, key);
|
|
106
|
+
return decrypt(iv, data, cek, aad);
|
|
149
107
|
}
|
|
150
|
-
return
|
|
151
|
-
} catch {
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// src/kernel/enclave/record-keys/rekey.ts
|
|
157
|
-
async function rekeyEnvelopeToDek(ref, envelope, oldDek, newDek) {
|
|
158
|
-
const aad = recordAadFor(ref, envelope);
|
|
159
|
-
const { _bidx, ...carried } = envelope;
|
|
160
|
-
void _bidx;
|
|
161
|
-
if (envelope._cek !== void 0) {
|
|
162
|
-
const cek = await unwrapCek(envelope._cek, oldDek);
|
|
163
|
-
return { ...carried, _cek: await wrapCek(cek, newDek) };
|
|
108
|
+
return decrypt(iv, data, key, aad);
|
|
164
109
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
try {
|
|
174
|
-
if (envelope._cek !== void 0) await unwrapCek(envelope._cek, newDek);
|
|
175
|
-
else await decrypt(envelope._iv, envelope._data, newDek, recordAadFor(ref, envelope));
|
|
176
|
-
return null;
|
|
177
|
-
} catch {
|
|
178
|
-
throw errUnderOld;
|
|
110
|
+
async function writeEnvelopeBody(identity, json, key, opts) {
|
|
111
|
+
if (opts?.encrypted === false) return { _iv: "", _data: json };
|
|
112
|
+
const aad = buildRecordAad(identity);
|
|
113
|
+
if (opts?.perRecordKey === true) {
|
|
114
|
+
const cek = await generateDEK();
|
|
115
|
+
const { iv: iv2, data: data2 } = await encrypt(json, cek, aad);
|
|
116
|
+
const wrapped = await wrapCek(cek, key);
|
|
117
|
+
return { _iv: iv2, _data: data2, _cek: wrapped };
|
|
179
118
|
}
|
|
119
|
+
const { iv, data } = await encrypt(json, key, aad);
|
|
120
|
+
return { _iv: iv, _data: data };
|
|
180
121
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
for (const key of keys) {
|
|
122
|
+
async function verifyRecordIdentity(ref, env, key) {
|
|
123
|
+
if (!hasSealedBody(env)) return true;
|
|
184
124
|
try {
|
|
185
|
-
|
|
186
|
-
else await decrypt(envelope._iv, envelope._data, key, recordAadFor(ref, envelope));
|
|
125
|
+
await openEnvelopeJson(ref, env, key);
|
|
187
126
|
return true;
|
|
188
127
|
} catch {
|
|
128
|
+
return false;
|
|
189
129
|
}
|
|
190
130
|
}
|
|
191
|
-
return
|
|
131
|
+
return { openEnvelopeJson, writeEnvelopeBody, verifyRecordIdentity };
|
|
192
132
|
}
|
|
193
133
|
|
|
194
|
-
// src/
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return new TextEncoder().encode(`${eTag}:${index}:${chunkCount}`);
|
|
134
|
+
// src/capsule/plumbing/sealed-slot.ts
|
|
135
|
+
function parseSealedSlot(blob) {
|
|
136
|
+
const sep = blob.indexOf(":");
|
|
137
|
+
return { iv: blob.slice(0, sep), data: blob.slice(sep + 1) };
|
|
199
138
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
async function rekeyBlobSet(adapter, vault, oldDek, newDek, otherDeks = []) {
|
|
208
|
-
let blobs = 0;
|
|
209
|
-
let chunks = 0;
|
|
210
|
-
let foreign = 0;
|
|
211
|
-
let alreadyMoved = 0;
|
|
212
|
-
let eTags;
|
|
213
|
-
try {
|
|
214
|
-
eTags = await adapter.list(vault, BLOB_INDEX_COLLECTION);
|
|
215
|
-
} catch {
|
|
216
|
-
return { blobs, chunks, foreign, alreadyMoved };
|
|
217
|
-
}
|
|
218
|
-
for (const eTag of eTags) {
|
|
219
|
-
const idxEnv = await adapter.get(vault, BLOB_INDEX_COLLECTION, eTag);
|
|
220
|
-
if (!idxEnv || !idxEnv._iv) continue;
|
|
221
|
-
const ref = { collection: BLOB_INDEX_COLLECTION, id: eTag };
|
|
222
|
-
const json = await opensJson(ref, idxEnv, oldDek);
|
|
223
|
-
if (json === null) {
|
|
224
|
-
if (await opensJson(ref, idxEnv, newDek) !== null) {
|
|
225
|
-
alreadyMoved++;
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
let claimed = false;
|
|
229
|
-
for (const key of otherDeks) {
|
|
230
|
-
if (await opensJson(ref, idxEnv, key) !== null) {
|
|
231
|
-
claimed = true;
|
|
232
|
-
break;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
if (claimed) {
|
|
236
|
-
foreign++;
|
|
237
|
-
continue;
|
|
238
|
-
}
|
|
239
|
-
throw new Error(
|
|
240
|
-
`[noy-db] rotateKeys: blob index entry "${eTag}" opens under neither the retiring nor the new \`_blob\` DEK, nor any other key this keyring holds. Rotation stopped rather than leaving it unreadable and unreported.`
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
const blob = JSON.parse(json);
|
|
244
|
-
for (let i = 0; i < blob.chunkCount; i++) {
|
|
245
|
-
const id = `${eTag}_${i}`;
|
|
246
|
-
const chunkEnv = await adapter.get(vault, BLOB_CHUNKS_COLLECTION, id);
|
|
247
|
-
if (!chunkEnv || !chunkEnv._iv) continue;
|
|
248
|
-
const aad = chunkAad(eTag, i, blob.chunkCount);
|
|
249
|
-
let plain;
|
|
139
|
+
function makeSealedSlot(p) {
|
|
140
|
+
const { decrypt, deriveSealedFieldKey, deriveSealedFieldKeyFromCek } = p;
|
|
141
|
+
async function dualReadSealedSlot(blob, field, collection, cek, dek) {
|
|
142
|
+
const { iv, data } = parseSealedSlot(blob);
|
|
143
|
+
if (cek !== void 0) {
|
|
250
144
|
try {
|
|
251
|
-
|
|
145
|
+
const fieldKey2 = await deriveSealedFieldKeyFromCek(cek, collection, field);
|
|
146
|
+
return await decrypt(iv, data, fieldKey2);
|
|
252
147
|
} catch {
|
|
253
|
-
if (blob._cek !== void 0 || blob._cekPending !== void 0) continue;
|
|
254
|
-
try {
|
|
255
|
-
await decryptBytesWithAAD(chunkEnv._iv, chunkEnv._data, newDek, aad);
|
|
256
|
-
continue;
|
|
257
|
-
} catch {
|
|
258
|
-
throw new Error(
|
|
259
|
-
`[noy-db] rotateKeys: blob chunk "${id}" (${i + 1}/${blob.chunkCount} of eTag "${eTag}") opens under neither the retiring nor the new \`_blob\` DEK, and its blob holds no content CEK that could explain it. Rotation stopped rather than leaving it unreadable and unreported.`
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
148
|
}
|
|
263
|
-
const { iv: iv2, data: data2 } = await encryptBytesWithAAD(plain, newDek, aad);
|
|
264
|
-
await adapter.put(vault, BLOB_CHUNKS_COLLECTION, id, { ...chunkEnv, _iv: iv2, _data: data2 });
|
|
265
|
-
chunks++;
|
|
266
149
|
}
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
...blob._cek !== void 0 ? { _cek: await wrapCek(await unwrapCek(blob._cek, oldDek), newDek) } : {},
|
|
270
|
-
...blob._cekPending !== void 0 ? { _cekPending: await wrapCek(await unwrapCek(blob._cekPending, oldDek), newDek) } : {}
|
|
271
|
-
};
|
|
272
|
-
const { iv, data } = await encrypt(JSON.stringify(rewrapped), newDek, recordAadFor(ref, idxEnv));
|
|
273
|
-
await adapter.put(vault, BLOB_INDEX_COLLECTION, eTag, { ...idxEnv, _iv: iv, _data: data });
|
|
274
|
-
blobs++;
|
|
150
|
+
const fieldKey = await deriveSealedFieldKey(dek, collection, field);
|
|
151
|
+
return decrypt(iv, data, fieldKey);
|
|
275
152
|
}
|
|
276
|
-
return {
|
|
153
|
+
return { dualReadSealedSlot };
|
|
277
154
|
}
|
|
278
155
|
|
|
279
|
-
// src/
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
156
|
+
// src/capsule/plumbing/record-envelope.ts
|
|
157
|
+
function buildRecordEnvelope(identity, body) {
|
|
158
|
+
return {
|
|
159
|
+
_noydb: NOYDB_FORMAT_VERSION,
|
|
160
|
+
_v: identity.version,
|
|
161
|
+
_ts: body.ts ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
162
|
+
_iv: body.iv,
|
|
163
|
+
_data: body.data,
|
|
164
|
+
...identity.by !== void 0 ? { _by: identity.by } : {},
|
|
165
|
+
...identity.tier !== void 0 && identity.tier > 0 ? { _tier: identity.tier } : {},
|
|
166
|
+
...body.cek !== void 0 ? { _cek: body.cek } : {},
|
|
167
|
+
...body.provenance !== void 0 ? { _source: body.provenance.source, _sourceTs: body.provenance.sourceTs } : {},
|
|
168
|
+
...body.extra ?? {}
|
|
169
|
+
};
|
|
283
170
|
}
|
|
284
|
-
async function
|
|
285
|
-
const
|
|
286
|
-
|
|
171
|
+
async function buildSealedRecordEnvelope(identity, seal, body) {
|
|
172
|
+
const sealed = await seal(identity);
|
|
173
|
+
const { iv, data } = requireSealedBody(sealed, "buildSealedRecordEnvelope");
|
|
174
|
+
return buildRecordEnvelope(identity, {
|
|
175
|
+
...body,
|
|
176
|
+
iv,
|
|
177
|
+
data,
|
|
178
|
+
cek: sealed._cek
|
|
179
|
+
});
|
|
287
180
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
for (const field of sensitiveFields) {
|
|
293
|
-
if (!(field in record)) continue;
|
|
294
|
-
const value = record[field];
|
|
295
|
-
if (value === void 0) continue;
|
|
296
|
-
const { iv, data } = await sealOneFieldWithDek(field, value, dek, keyMaterial);
|
|
297
|
-
slots[field] = `${iv}:${data}`;
|
|
298
|
-
delete open[field];
|
|
299
|
-
}
|
|
300
|
-
if (Object.keys(slots).length === 0) return { openRecord: record, sealed: void 0 };
|
|
301
|
-
return { openRecord: open, sealed: slots };
|
|
181
|
+
|
|
182
|
+
// src/capsule/plumbing/tombstone.ts
|
|
183
|
+
function isTombstoneShape(envelope) {
|
|
184
|
+
return envelope._data === "" && envelope._cek === void 0 && envelope._del !== true;
|
|
302
185
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
return
|
|
186
|
+
function isTombstone(envelope, encrypted) {
|
|
187
|
+
if (!encrypted) return false;
|
|
188
|
+
return isTombstoneShape(envelope);
|
|
306
189
|
}
|
|
307
|
-
function
|
|
308
|
-
return (
|
|
190
|
+
function buildTombstone(ref, version, actor) {
|
|
191
|
+
return buildRecordEnvelope(
|
|
192
|
+
{ ...ref, version, ...actor ? { by: actor } : {} },
|
|
193
|
+
{ iv: "", data: "" }
|
|
194
|
+
);
|
|
309
195
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
for (const [field, blob] of Object.entries(sealed)) {
|
|
313
|
-
record[field] = makeHandle !== void 0 ? makeHandle(field, blob) : await unsealOneField(field, blob, keyMaterial);
|
|
314
|
-
}
|
|
315
|
-
return record;
|
|
196
|
+
function isDeleteMarker(envelope) {
|
|
197
|
+
return envelope._del === true;
|
|
316
198
|
}
|
|
317
|
-
function
|
|
318
|
-
const keyMaterial = {
|
|
319
|
-
collection: ctx.name,
|
|
320
|
-
...cek !== void 0 ? { cek } : {},
|
|
321
|
-
getDEK: () => ctx.getDEK()
|
|
322
|
-
};
|
|
323
|
-
const deletedFields = /* @__PURE__ */ new Set();
|
|
199
|
+
function buildDeleteMarker(ref, version, actor) {
|
|
324
200
|
return {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
async unseal(field, ref) {
|
|
331
|
-
if (deletedFields.has(field)) {
|
|
332
|
-
throw new ValidationError(`sealedSlots.unseal: field "${field}" on record "${recordId}" was deleted from this capability`);
|
|
333
|
-
}
|
|
334
|
-
return unsealOneField(field, `${ref.iv}:${ref.data}`, keyMaterial);
|
|
335
|
-
},
|
|
336
|
-
async delete(field) {
|
|
337
|
-
deletedFields.add(field);
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
function makeReservedEnvelopes(dekResolver, declaredPrefixes) {
|
|
342
|
-
const declared = new Set(declaredPrefixes);
|
|
343
|
-
return (prefix) => {
|
|
344
|
-
if (!declared.has(prefix)) {
|
|
345
|
-
throw new ValidationError(`reservedEnvelopes: prefix "${prefix}" is not declared by this binding's reservedPrefixes`);
|
|
346
|
-
}
|
|
347
|
-
const assertPrefixed = (collection, method) => {
|
|
348
|
-
if (!collection.startsWith(prefix)) {
|
|
349
|
-
throw new ValidationError(
|
|
350
|
-
`reservedEnvelopes('${prefix}').${method}: collection "${collection}" does not start with "${prefix}"`
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
};
|
|
354
|
-
const encryptForPrefix = async (ref, json, v) => {
|
|
355
|
-
assertPrefixed(ref.collection, "encrypt");
|
|
356
|
-
const dek = await dekResolver(ref.collection);
|
|
357
|
-
const identity = { ...ref, version: v };
|
|
358
|
-
const { iv, data } = await encrypt(json, dek, buildRecordAad(identity));
|
|
359
|
-
return buildRecordEnvelope(identity, { iv, data });
|
|
360
|
-
};
|
|
361
|
-
const decryptForPrefix = async (collection, id, env) => {
|
|
362
|
-
assertPrefixed(collection, "decrypt");
|
|
363
|
-
const dek = await dekResolver(collection);
|
|
364
|
-
return decrypt(env._iv, env._data, dek, recordAadFor({ collection, id }, env));
|
|
365
|
-
};
|
|
366
|
-
return { encrypt: encryptForPrefix, decrypt: decryptForPrefix };
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// src/kernel/enclave/classify/write.ts
|
|
371
|
-
async function mintVdigSlot(rawValue, policy, prevBlob, cek, collection, recordId, field) {
|
|
372
|
-
const normalized = normalizeForVerify(policy.normalize, rawValue);
|
|
373
|
-
let prev = null;
|
|
374
|
-
if (prevBlob !== void 0) {
|
|
375
|
-
try {
|
|
376
|
-
prev = await openVdigPayload(prevBlob, cek, collection, recordId, field);
|
|
377
|
-
} catch {
|
|
378
|
-
throw new TamperedError();
|
|
379
|
-
}
|
|
380
|
-
if (!Number.isInteger(prev.iter) || prev.iter < 1) {
|
|
381
|
-
throw new TamperedError();
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
if (prev !== null && policy.notLastN > 0) {
|
|
385
|
-
const history = [prev.cur, ...prev.ring ?? []];
|
|
386
|
-
for (const entry of history) {
|
|
387
|
-
const digest = await pbkdf2VerifyDigest(normalized, base64ToBuffer(entry.salt), prev.iter);
|
|
388
|
-
if (await blindedEqual(digest, base64ToBuffer(entry.hash))) {
|
|
389
|
-
throw new ClassifiedRotationError(collection, field, "password was used recently");
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
const salt = generateSalt();
|
|
394
|
-
const hash = await pbkdf2VerifyDigest(normalized, salt, VDIG_ITERATIONS);
|
|
395
|
-
const ring = prev !== null && policy.notLastN > 0 ? [...prev.ring ?? [], { salt: prev.cur.salt, hash: prev.cur.hash }].slice(-policy.notLastN) : void 0;
|
|
396
|
-
const payload = {
|
|
397
|
-
v: 1,
|
|
398
|
-
alg: "PBKDF2-SHA256",
|
|
399
|
-
iter: VDIG_ITERATIONS,
|
|
400
|
-
cur: { salt: bufferToBase64(salt), hash: bufferToBase64(hash), at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
401
|
-
...ring !== void 0 && ring.length > 0 ? { ring } : {}
|
|
201
|
+
...buildRecordEnvelope(
|
|
202
|
+
{ ...ref, version, ...actor ? { by: actor } : {} },
|
|
203
|
+
{ iv: "", data: "" }
|
|
204
|
+
),
|
|
205
|
+
_del: true
|
|
402
206
|
};
|
|
403
|
-
return sealVdigPayload(payload, cek, collection, recordId, field);
|
|
404
207
|
}
|
|
405
208
|
|
|
406
209
|
// src/kernel/schema.ts
|
|
@@ -441,11 +244,109 @@ function formatPath(path) {
|
|
|
441
244
|
).join(".");
|
|
442
245
|
}
|
|
443
246
|
|
|
444
|
-
// src/
|
|
445
|
-
|
|
446
|
-
|
|
247
|
+
// src/capsule/plumbing/sealed-slots.ts
|
|
248
|
+
function makeSealedSlots(p, sealedSlot) {
|
|
249
|
+
const { decrypt, deriveSealedFieldKey, deriveSealedFieldKeyFromCek, encrypt } = p;
|
|
250
|
+
const { dualReadSealedSlot } = sealedSlot;
|
|
251
|
+
async function sealOneFieldWithDek(field, value, dek, keyMaterial) {
|
|
252
|
+
const fieldKey = keyMaterial.cek !== void 0 ? await deriveSealedFieldKeyFromCek(keyMaterial.cek, keyMaterial.collection, field) : await deriveSealedFieldKey(dek, keyMaterial.collection, field);
|
|
253
|
+
return encrypt(JSON.stringify(value), fieldKey);
|
|
254
|
+
}
|
|
255
|
+
async function sealOneField(field, value, keyMaterial) {
|
|
256
|
+
const dek = await keyMaterial.getDEK();
|
|
257
|
+
return sealOneFieldWithDek(field, value, dek, keyMaterial);
|
|
258
|
+
}
|
|
259
|
+
async function sealFields(record, sensitiveFields, keyMaterial) {
|
|
260
|
+
const dek = await keyMaterial.getDEK();
|
|
261
|
+
const open = { ...record };
|
|
262
|
+
const slots = {};
|
|
263
|
+
for (const field of sensitiveFields) {
|
|
264
|
+
if (!(field in record)) continue;
|
|
265
|
+
const value = record[field];
|
|
266
|
+
if (value === void 0) continue;
|
|
267
|
+
const { iv, data } = await sealOneFieldWithDek(field, value, dek, keyMaterial);
|
|
268
|
+
slots[field] = `${iv}:${data}`;
|
|
269
|
+
delete open[field];
|
|
270
|
+
}
|
|
271
|
+
if (Object.keys(slots).length === 0) return { openRecord: record, sealed: void 0 };
|
|
272
|
+
return { openRecord: open, sealed: slots };
|
|
273
|
+
}
|
|
274
|
+
async function unsealOneField(field, blob, keyMaterial) {
|
|
275
|
+
const dek = await keyMaterial.getDEK();
|
|
276
|
+
return JSON.parse(await dualReadSealedSlot(blob, field, keyMaterial.collection, keyMaterial.cek, dek));
|
|
277
|
+
}
|
|
278
|
+
function makeHandleProducer(keyMaterial) {
|
|
279
|
+
return (field, blob) => new SealedHandle(() => unsealOneField(field, blob, keyMaterial));
|
|
280
|
+
}
|
|
281
|
+
async function unsealFields(record, sealed, keyMaterial, opts) {
|
|
282
|
+
const makeHandle = opts?.asHandles === true ? makeHandleProducer(keyMaterial) : void 0;
|
|
283
|
+
for (const [field, blob] of Object.entries(sealed)) {
|
|
284
|
+
record[field] = makeHandle !== void 0 ? makeHandle(field, blob) : await unsealOneField(field, blob, keyMaterial);
|
|
285
|
+
}
|
|
286
|
+
return record;
|
|
287
|
+
}
|
|
288
|
+
function makeSealedSlotCapability(ctx, recordId, cek) {
|
|
289
|
+
const keyMaterial = {
|
|
290
|
+
collection: ctx.name,
|
|
291
|
+
...cek !== void 0 ? { cek } : {},
|
|
292
|
+
getDEK: () => ctx.getDEK()
|
|
293
|
+
};
|
|
294
|
+
const deletedFields = /* @__PURE__ */ new Set();
|
|
295
|
+
return {
|
|
296
|
+
async seal(field, plaintext) {
|
|
297
|
+
const ref = await sealOneField(field, plaintext, keyMaterial);
|
|
298
|
+
deletedFields.delete(field);
|
|
299
|
+
return ref;
|
|
300
|
+
},
|
|
301
|
+
async unseal(field, ref) {
|
|
302
|
+
if (deletedFields.has(field)) {
|
|
303
|
+
throw new ValidationError(`sealedSlots.unseal: field "${field}" on record "${recordId}" was deleted from this capability`);
|
|
304
|
+
}
|
|
305
|
+
return unsealOneField(field, `${ref.iv}:${ref.data}`, keyMaterial);
|
|
306
|
+
},
|
|
307
|
+
async delete(field) {
|
|
308
|
+
deletedFields.add(field);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function makeReservedEnvelopes(dekResolver, declaredPrefixes) {
|
|
313
|
+
const declared = new Set(declaredPrefixes);
|
|
314
|
+
return (prefix) => {
|
|
315
|
+
if (!declared.has(prefix)) {
|
|
316
|
+
throw new ValidationError(`reservedEnvelopes: prefix "${prefix}" is not declared by this binding's reservedPrefixes`);
|
|
317
|
+
}
|
|
318
|
+
const assertPrefixed = (collection, method) => {
|
|
319
|
+
if (!collection.startsWith(prefix)) {
|
|
320
|
+
throw new ValidationError(
|
|
321
|
+
`reservedEnvelopes('${prefix}').${method}: collection "${collection}" does not start with "${prefix}"`
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
const encryptForPrefix = async (ref, json, v) => {
|
|
326
|
+
assertPrefixed(ref.collection, "encrypt");
|
|
327
|
+
const dek = await dekResolver(ref.collection);
|
|
328
|
+
const identity = { ...ref, version: v };
|
|
329
|
+
const { iv, data } = await encrypt(json, dek, buildRecordAad(identity));
|
|
330
|
+
return buildRecordEnvelope(identity, { iv, data });
|
|
331
|
+
};
|
|
332
|
+
const decryptForPrefix = async (collection, id, env) => {
|
|
333
|
+
assertPrefixed(collection, "decrypt");
|
|
334
|
+
const dek = await dekResolver(collection);
|
|
335
|
+
return decrypt(...sealedBodyArgs(env, "openSealedSlots"), dek, recordAadFor({ collection, id }, env));
|
|
336
|
+
};
|
|
337
|
+
return { encrypt: encryptForPrefix, decrypt: decryptForPrefix };
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
return { sealFields, unsealOneField, makeHandleProducer, unsealFields, makeSealedSlotCapability, makeReservedEnvelopes };
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// src/capsule/plumbing/record-codec.ts
|
|
344
|
+
var RecordCodecBase = class _RecordCodecBase {
|
|
345
|
+
constructor(caps, ctx) {
|
|
346
|
+
this.caps = caps;
|
|
447
347
|
this.ctx = ctx;
|
|
448
348
|
}
|
|
349
|
+
caps;
|
|
449
350
|
ctx;
|
|
450
351
|
/**
|
|
451
352
|
* @internal Update the live Via pipeline this codec's at-rest hooks read
|
|
@@ -479,8 +380,8 @@ var RecordCodec = class _RecordCodec {
|
|
|
479
380
|
viaCryptoCtx(recordId, cek) {
|
|
480
381
|
const declaredPrefixes = this.ctx.via?.bindings.flatMap((b) => b.reservedPrefixes ?? []) ?? [];
|
|
481
382
|
return {
|
|
482
|
-
sealedSlots: makeSealedSlotCapability(this.ctx, recordId, cek),
|
|
483
|
-
reservedEnvelopes: makeReservedEnvelopes((collection) => this.ctx.getDEK(collection), declaredPrefixes)
|
|
383
|
+
sealedSlots: this.caps.makeSealedSlotCapability(this.ctx, recordId, cek),
|
|
384
|
+
reservedEnvelopes: this.caps.makeReservedEnvelopes((collection) => this.ctx.getDEK(collection), declaredPrefixes)
|
|
484
385
|
};
|
|
485
386
|
}
|
|
486
387
|
// ──────────────────────────────────────────────────────────────────────
|
|
@@ -561,17 +462,17 @@ var RecordCodec = class _RecordCodec {
|
|
|
561
462
|
const identity = { ...ref, version, by: this.ctx.actor };
|
|
562
463
|
const provenance = this.ctx.provenance && source !== void 0 ? { source, sourceTs: sourceTs ?? (/* @__PURE__ */ new Date()).toISOString() } : void 0;
|
|
563
464
|
if (!this.ctx.storeCiphertext) {
|
|
564
|
-
return
|
|
465
|
+
return _RecordCodecBase.buildPlaintextEnvelope(identity, { data: json, provenance });
|
|
565
466
|
}
|
|
566
467
|
const dek = await this.ctx.getDEK();
|
|
567
468
|
const aad = buildRecordAad(identity);
|
|
568
469
|
if (cek !== void 0) {
|
|
569
|
-
const { iv: iv2, data: data2 } = await encrypt(json, cek, aad);
|
|
570
|
-
const wrapped = await wrapCek(cek, dek);
|
|
571
|
-
return
|
|
470
|
+
const { iv: iv2, data: data2 } = await this.caps.encrypt(json, cek, aad);
|
|
471
|
+
const wrapped = await this.caps.wrapCek(cek, dek);
|
|
472
|
+
return _RecordCodecBase.buildEnvelope(identity, { iv: iv2, data: data2, cek: wrapped, provenance });
|
|
572
473
|
}
|
|
573
|
-
const { iv, data } = await encrypt(json, dek, aad);
|
|
574
|
-
return
|
|
474
|
+
const { iv, data } = await this.caps.encrypt(json, dek, aad);
|
|
475
|
+
return _RecordCodecBase.buildEnvelope(identity, { iv, data, provenance });
|
|
575
476
|
}
|
|
576
477
|
/**
|
|
577
478
|
* `ref` is FIRST and required (#1051). It was previously a trailing optional
|
|
@@ -616,7 +517,7 @@ var RecordCodec = class _RecordCodec {
|
|
|
616
517
|
if (this.ctx.storeCiphertext && this.ctx.via?.hasAtRestHooks) {
|
|
617
518
|
if (id === "") {
|
|
618
519
|
throw new Error(
|
|
619
|
-
`
|
|
520
|
+
`RecordCodecBase.encryptRecord: collection "${this.ctx.name}" has via at-rest hooks but this write path supplied an empty record id (needed to scope the sealed-slot capability) \u2014 caller bug.`
|
|
620
521
|
);
|
|
621
522
|
}
|
|
622
523
|
const src = record;
|
|
@@ -628,7 +529,7 @@ var RecordCodec = class _RecordCodec {
|
|
|
628
529
|
}
|
|
629
530
|
} else if (this.ctx.storeCiphertext && this.ctx.sensitiveFields.size > 0) {
|
|
630
531
|
const src = record;
|
|
631
|
-
const result = await sealFields(src, this.ctx.sensitiveFields, this.sealKeyMaterial(cek));
|
|
532
|
+
const result = await this.caps.sealFields(src, this.ctx.sensitiveFields, this.sealKeyMaterial(cek));
|
|
632
533
|
if (result.sealed !== void 0) {
|
|
633
534
|
sealed = result.sealed;
|
|
634
535
|
openRecord = result.openRecord;
|
|
@@ -639,12 +540,12 @@ var RecordCodec = class _RecordCodec {
|
|
|
639
540
|
if (this.ctx.vdigFields !== null && this.ctx.vdigFields.size > 0 && this.ctx.storeCiphertext) {
|
|
640
541
|
if (vdig === void 0) {
|
|
641
542
|
throw new Error(
|
|
642
|
-
`
|
|
543
|
+
`RecordCodecBase.encryptRecord: collection "${this.ctx.name}" declares digest-only classified fields but this write path supplied no { id, prev } context \u2014 it would silently destroy _vdig (C6). Caller bug.`
|
|
643
544
|
);
|
|
644
545
|
}
|
|
645
546
|
if (cek === void 0) {
|
|
646
547
|
throw new Error(
|
|
647
|
-
`
|
|
548
|
+
`RecordCodecBase.encryptRecord: digest-only fields require a per-record CEK (R1 invariant) \u2014 collection "${this.ctx.name}" wrote without one. Caller bug.`
|
|
648
549
|
);
|
|
649
550
|
}
|
|
650
551
|
const open = { ...openRecord };
|
|
@@ -677,11 +578,11 @@ var RecordCodec = class _RecordCodec {
|
|
|
677
578
|
`digest-only classified field "${field}" in "${this.ctx.name}" must be a string (rotate) or null (clear), got ${typeof value}`
|
|
678
579
|
);
|
|
679
580
|
}
|
|
680
|
-
out[field] = await mintVdigSlot(value, policy, prevBlob, cek, this.ctx.name, vdig.id, field);
|
|
581
|
+
out[field] = await this.caps.mintVdigSlot(value, policy, prevBlob, cek, this.ctx.name, vdig.id, field);
|
|
681
582
|
if (policy.equatable === true) {
|
|
682
583
|
if (bidxDek === void 0) bidxDek = await this.ctx.getDEK();
|
|
683
584
|
const normalized = normalizeForVerify(policy.normalize, value);
|
|
684
|
-
bidxOut[field] = await mintBidxTag(normalized, bidxDek, this.ctx.name, field);
|
|
585
|
+
bidxOut[field] = await this.caps.mintBidxTag(normalized, bidxDek, this.ctx.name, field);
|
|
685
586
|
}
|
|
686
587
|
delete open[field];
|
|
687
588
|
}
|
|
@@ -695,7 +596,7 @@ var RecordCodec = class _RecordCodec {
|
|
|
695
596
|
const withBidx = bidxOutMap ? { ...withVdig, _bidx: bidxOutMap } : withVdig;
|
|
696
597
|
if (!this.ctx.deterministicFields || !this.ctx.storeCiphertext) return withBidx;
|
|
697
598
|
const dek = await this.ctx.getDEK();
|
|
698
|
-
const detKey = await deriveDeterministicKey(dek);
|
|
599
|
+
const detKey = await this.caps.deriveDeterministicKey(dek);
|
|
699
600
|
const rec = record;
|
|
700
601
|
const det = {};
|
|
701
602
|
for (const field of this.ctx.deterministicFields) {
|
|
@@ -704,7 +605,7 @@ var RecordCodec = class _RecordCodec {
|
|
|
704
605
|
const value = rec[field];
|
|
705
606
|
if (value === void 0 || value === null) continue;
|
|
706
607
|
const plaintext = typeof value === "string" ? value : JSON.stringify(value);
|
|
707
|
-
const { iv, data } = await encryptDeterministic(plaintext, detKey, `${this.ctx.name}/${field}`);
|
|
608
|
+
const { iv, data } = await this.caps.encryptDeterministic(plaintext, detKey, `${this.ctx.name}/${field}`);
|
|
708
609
|
det[field] = `${iv}:${data}`;
|
|
709
610
|
}
|
|
710
611
|
if (Object.keys(det).length === 0) return withBidx;
|
|
@@ -726,7 +627,7 @@ var RecordCodec = class _RecordCodec {
|
|
|
726
627
|
const cached = id !== void 0 ? this.ctx.cekCache?.get(id) : void 0;
|
|
727
628
|
if (cached !== void 0) return cached;
|
|
728
629
|
const dek = await this.ctx.getDEK();
|
|
729
|
-
const cek = await unwrapCek(envelope._cek, dek);
|
|
630
|
+
const cek = await this.caps.unwrapCek(envelope._cek, dek);
|
|
730
631
|
if (id !== void 0) this.ctx.cekCache?.set(id, cek, 1);
|
|
731
632
|
return cek;
|
|
732
633
|
}
|
|
@@ -762,11 +663,12 @@ var RecordCodec = class _RecordCodec {
|
|
|
762
663
|
}
|
|
763
664
|
return JSON.stringify(rec);
|
|
764
665
|
}
|
|
765
|
-
|
|
666
|
+
const plain = envelope._data ?? "";
|
|
667
|
+
return plain === "" ? null : plain;
|
|
766
668
|
}
|
|
767
669
|
const aad = recordAadFor(ref, envelope);
|
|
768
670
|
const cek = await this.resolveEnvelopeCek(envelope, id);
|
|
769
|
-
const json = cek !== void 0 ? await decrypt(envelope
|
|
671
|
+
const json = cek !== void 0 ? await this.caps.decrypt(...sealedBodyArgs(envelope, "RecordCodec"), cek, aad) : await this.caps.decrypt(...sealedBodyArgs(envelope, "RecordCodec"), await this.ctx.getDEK(), aad);
|
|
770
672
|
this.observeDecrypt(ref);
|
|
771
673
|
return json;
|
|
772
674
|
}
|
|
@@ -795,7 +697,7 @@ var RecordCodec = class _RecordCodec {
|
|
|
795
697
|
* materialisation always agree byte-for-byte.
|
|
796
698
|
*/
|
|
797
699
|
async unsealField(field, blob, cek) {
|
|
798
|
-
return unsealOneField(field, blob, this.sealKeyMaterial(cek));
|
|
700
|
+
return this.caps.unsealOneField(field, blob, this.sealKeyMaterial(cek));
|
|
799
701
|
}
|
|
800
702
|
/**
|
|
801
703
|
* Build the `ViaCryptoCtx` for forget()'s per-ref via-erase fold (#629
|
|
@@ -837,7 +739,7 @@ var RecordCodec = class _RecordCodec {
|
|
|
837
739
|
}
|
|
838
740
|
const { iv, data } = parseSealedSlot(blob);
|
|
839
741
|
try {
|
|
840
|
-
await decrypt(iv, data, await deriveSealedFieldKeyFromCek(cek, this.ctx.name, field));
|
|
742
|
+
await this.caps.decrypt(iv, data, await this.caps.deriveSealedFieldKeyFromCek(cek, this.ctx.name, field));
|
|
841
743
|
slots.push({ field, class: "shreddable" });
|
|
842
744
|
} catch {
|
|
843
745
|
slots.push({ field, class: "dekResidue" });
|
|
@@ -853,7 +755,7 @@ var RecordCodec = class _RecordCodec {
|
|
|
853
755
|
* exposing the value, which decrypts only on `reveal()`.
|
|
854
756
|
*/
|
|
855
757
|
makeSealedHandle(field, blob, cek) {
|
|
856
|
-
return makeHandleProducer(this.sealKeyMaterial(cek))(field, blob);
|
|
758
|
+
return this.caps.makeHandleProducer(this.sealKeyMaterial(cek))(field, blob);
|
|
857
759
|
}
|
|
858
760
|
/**
|
|
859
761
|
* Replace every field the just-written envelope actually sealed with a
|
|
@@ -911,7 +813,7 @@ var RecordCodec = class _RecordCodec {
|
|
|
911
813
|
if (this.ctx.via?.hasAtRestHooks) {
|
|
912
814
|
if (opts.id === void 0 || opts.id === "") {
|
|
913
815
|
throw new Error(
|
|
914
|
-
`
|
|
816
|
+
`RecordCodecBase.decryptRecord: collection "${this.ctx.name}" has via at-rest hooks but this read path supplied no record id (needed to scope the sealed-slot capability) \u2014 caller bug.`
|
|
915
817
|
);
|
|
916
818
|
}
|
|
917
819
|
const sealedRefs = {};
|
|
@@ -926,7 +828,7 @@ var RecordCodec = class _RecordCodec {
|
|
|
926
828
|
{ asHandles: opts.sealedAsHandles === true }
|
|
927
829
|
);
|
|
928
830
|
}
|
|
929
|
-
return await unsealFields(
|
|
831
|
+
return await this.caps.unsealFields(
|
|
930
832
|
record,
|
|
931
833
|
sealed,
|
|
932
834
|
this.sealKeyMaterial(cek),
|
|
@@ -966,10 +868,10 @@ var RecordCodec = class _RecordCodec {
|
|
|
966
868
|
let cek;
|
|
967
869
|
const aad = recordAadFor(ref, envelope);
|
|
968
870
|
if (envelope._cek !== void 0) {
|
|
969
|
-
cek = await unwrapCek(envelope._cek, dek);
|
|
970
|
-
plaintext = await decrypt(envelope
|
|
871
|
+
cek = await this.caps.unwrapCek(envelope._cek, dek);
|
|
872
|
+
plaintext = await this.caps.decrypt(...sealedBodyArgs(envelope, "RecordCodec"), cek, aad);
|
|
971
873
|
} else {
|
|
972
|
-
plaintext = await decrypt(envelope
|
|
874
|
+
plaintext = await this.caps.decrypt(...sealedBodyArgs(envelope, "RecordCodec"), dek, aad);
|
|
973
875
|
}
|
|
974
876
|
let record = JSON.parse(plaintext);
|
|
975
877
|
if (envelope._sealed !== void 0 && this.ctx.storeCiphertext) {
|
|
@@ -1019,367 +921,455 @@ var RecordCodec = class _RecordCodec {
|
|
|
1019
921
|
return record;
|
|
1020
922
|
}
|
|
1021
923
|
};
|
|
924
|
+
function makeRecordCodec(p, slots) {
|
|
925
|
+
const caps = { ...p, ...slots };
|
|
926
|
+
const RecordCodec = class extends RecordCodecBase {
|
|
927
|
+
constructor(ctx) {
|
|
928
|
+
super(caps, ctx);
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
return { RecordCodec };
|
|
932
|
+
}
|
|
1022
933
|
|
|
1023
|
-
// src/
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
async function
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
934
|
+
// src/capsule/plumbing/lifecycle.ts
|
|
935
|
+
function makeLifecycle(p) {
|
|
936
|
+
const { decrypt, encrypt, generateDEK, unwrapCek, wrapCek } = p;
|
|
937
|
+
async function resolveStableCek(deps, id) {
|
|
938
|
+
const cached = deps.cache?.get(id);
|
|
939
|
+
if (cached) return cached;
|
|
940
|
+
const live = await deps.getLive(id);
|
|
941
|
+
if (live?._cek !== void 0) {
|
|
942
|
+
const cek = await unwrapCek(live._cek, await deps.getDEK());
|
|
943
|
+
deps.cache?.set(id, cek, 1);
|
|
944
|
+
return cek;
|
|
945
|
+
}
|
|
946
|
+
const fresh = await generateDEK();
|
|
947
|
+
deps.cache?.set(id, fresh, 1);
|
|
948
|
+
return fresh;
|
|
1031
949
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
950
|
+
async function rewrapBodyToDek(from, to, envelope, fromDek, toDek) {
|
|
951
|
+
const openAad = buildRecordAad(from);
|
|
952
|
+
const sealAad = buildRecordAad(to);
|
|
953
|
+
if (envelope._cek !== void 0) {
|
|
954
|
+
const cek = await unwrapCek(envelope._cek, fromDek);
|
|
955
|
+
const plaintext2 = await decrypt(...sealedBodyArgs(envelope, "rewrapBodyToDek"), cek, openAad);
|
|
956
|
+
const { iv: iv2, data: data2 } = await encrypt(plaintext2, cek, sealAad);
|
|
957
|
+
return { _iv: iv2, _data: data2, _cek: await wrapCek(cek, toDek), cek };
|
|
958
|
+
}
|
|
959
|
+
const plaintext = await decrypt(...sealedBodyArgs(envelope, "rewrapBodyToDek"), fromDek, openAad);
|
|
960
|
+
const { iv, data } = await encrypt(plaintext, toDek, sealAad);
|
|
961
|
+
return { _iv: iv, _data: data, cek: null };
|
|
1035
962
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
cek: cekB64,
|
|
1046
|
-
expiresAt: opts.expiresAt
|
|
1047
|
-
};
|
|
1048
|
-
const sealed = await hostSealer.sealForRecipient(
|
|
1049
|
-
new TextEncoder().encode(JSON.stringify(binding)),
|
|
1050
|
-
hint
|
|
1051
|
-
);
|
|
1052
|
-
const delivery = {
|
|
1053
|
-
v: 1,
|
|
1054
|
-
_noydb_sealed_cek: 1,
|
|
1055
|
-
pid: hint.pid,
|
|
1056
|
-
payload: bufferToBase64(sealed),
|
|
1057
|
-
expiresAt: opts.expiresAt
|
|
1058
|
-
};
|
|
1059
|
-
const envelopeKey = `${collection}/${id}/${hint.pid}`;
|
|
1060
|
-
const prior = await ctx.adapter.get(ctx.vault, SEALED_CEK_NS, envelopeKey);
|
|
1061
|
-
const env = buildRecordEnvelope(
|
|
1062
|
-
{ collection: SEALED_CEK_NS, id: envelopeKey, version: (prior?._v ?? 0) + 1 },
|
|
1063
|
-
{
|
|
1064
|
-
// AES-GCM bypassed — the sealing layer is the security boundary, exactly
|
|
1065
|
-
// like the managed-secret `_meta/sealed-secret` envelope.
|
|
1066
|
-
iv: "",
|
|
1067
|
-
data: JSON.stringify(delivery),
|
|
1068
|
-
...ctx.actor ? { by: ctx.actor } : {}
|
|
963
|
+
function applyRewrappedBody(envelope, body) {
|
|
964
|
+
const next = {
|
|
965
|
+
...envelope,
|
|
966
|
+
_iv: body._iv,
|
|
967
|
+
_data: body._data,
|
|
968
|
+
...body._cek !== void 0 ? { _cek: body._cek } : {}
|
|
969
|
+
};
|
|
970
|
+
if (body._cek === void 0 && envelope._cek !== void 0) {
|
|
971
|
+
delete next._cek;
|
|
1069
972
|
}
|
|
1070
|
-
|
|
1071
|
-
await ctx.adapter.put(ctx.vault, SEALED_CEK_NS, envelopeKey, env);
|
|
1072
|
-
return { pid: hint.pid, envelopeKey };
|
|
1073
|
-
}
|
|
1074
|
-
async function revokeSealedRecord(ctx, collection, id, pid, opts) {
|
|
1075
|
-
if (opts?.hard === true) {
|
|
1076
|
-
await rotateRecordCek(ctx, collection, id);
|
|
1077
|
-
return;
|
|
973
|
+
return next;
|
|
1078
974
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
async function rotateRecordCek(ctx, collection, id) {
|
|
1082
|
-
const live = await ctx.adapter.get(ctx.vault, collection, id);
|
|
1083
|
-
if (!live || live._cek === void 0) {
|
|
1084
|
-
throw new RecordCekNotFoundError(collection, id);
|
|
975
|
+
async function rewrapEnvelope(identity, envelope, fromDek, toDek) {
|
|
976
|
+
return applyRewrappedBody(envelope, await rewrapBodyToDek(identity, identity, envelope, fromDek, toDek));
|
|
1085
977
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
// which PRESERVES `_v` (#1074) because it re-keys a record without writing
|
|
1097
|
-
// one. Two rotations, opposite answers — and with `_v` bound (#1093) getting
|
|
1098
|
-
// it backwards no longer produces a wrong number, it produces an
|
|
1099
|
-
// unreadable record.
|
|
1100
|
-
collection,
|
|
1101
|
-
id,
|
|
1102
|
-
version: live._v + 1,
|
|
1103
|
-
...live._tier !== void 0 ? { tier: live._tier } : {},
|
|
1104
|
-
...ctx.actor ? { by: ctx.actor } : live._by !== void 0 ? { by: live._by } : {}
|
|
1105
|
-
};
|
|
1106
|
-
const newCek = await generateDEK();
|
|
1107
|
-
const { iv, data } = await encrypt(json, newCek, buildRecordAad(rotatedIdentity));
|
|
1108
|
-
let sealedOut;
|
|
1109
|
-
if (live._sealed !== void 0) {
|
|
1110
|
-
const out = {};
|
|
1111
|
-
for (const [field, slot] of Object.entries(live._sealed)) {
|
|
1112
|
-
const plaintext = await dualReadSealedSlot(slot, field, collection, oldCek, dek);
|
|
1113
|
-
const resealed = await encrypt(plaintext, await deriveSealedFieldKeyFromCek(newCek, collection, field));
|
|
1114
|
-
out[field] = `${resealed.iv}:${resealed.data}`;
|
|
978
|
+
async function isRewrappedUnder(identity, envelope, dek) {
|
|
979
|
+
try {
|
|
980
|
+
if (envelope._cek !== void 0) {
|
|
981
|
+
await unwrapCek(envelope._cek, dek);
|
|
982
|
+
} else {
|
|
983
|
+
await decrypt(...sealedBodyArgs(envelope, "rewrapBodyToDek"), dek, buildRecordAad(identity));
|
|
984
|
+
}
|
|
985
|
+
return true;
|
|
986
|
+
} catch {
|
|
987
|
+
return false;
|
|
1115
988
|
}
|
|
1116
|
-
sealedOut = out;
|
|
1117
989
|
}
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
990
|
+
return { resolveStableCek, rewrapBodyToDek, applyRewrappedBody, rewrapEnvelope, isRewrappedUnder };
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// src/capsule/plumbing/rekey.ts
|
|
994
|
+
function makeRekey(p) {
|
|
995
|
+
const { decrypt, encrypt, unwrapCek, wrapCek } = p;
|
|
996
|
+
async function rekeyEnvelopeToDek(ref, envelope, oldDek, newDek) {
|
|
997
|
+
const aad = recordAadFor(ref, envelope);
|
|
998
|
+
const { _bidx, ...carried } = envelope;
|
|
999
|
+
void _bidx;
|
|
1000
|
+
if (envelope._cek !== void 0) {
|
|
1001
|
+
const cek = await unwrapCek(envelope._cek, oldDek);
|
|
1002
|
+
return { ...carried, _cek: await wrapCek(cek, newDek) };
|
|
1124
1003
|
}
|
|
1125
|
-
|
|
1004
|
+
const plaintext = await decrypt(...sealedBodyArgs(envelope, "rekeyRecord"), oldDek, aad);
|
|
1005
|
+
const { iv, data } = await encrypt(plaintext, newDek, aad);
|
|
1006
|
+
return { ...carried, _ts: (/* @__PURE__ */ new Date()).toISOString(), _iv: iv, _data: data };
|
|
1126
1007
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
...live._bidx !== void 0 ? { _bidx: live._bidx } : {},
|
|
1139
|
-
// Re-encrypt sealed (`sensitive`) fields under the new CEK. Sealed
|
|
1140
|
-
// keys derive off the per-record CEK, so the rotated record's old CEK is
|
|
1141
|
-
// destroyed here — carrying the old `_sealed` slots forward verbatim would
|
|
1142
|
-
// orphan them (unreadable under the new CEK). `sealedOut` holds the slots
|
|
1143
|
-
// dual-read from the old CEK (or the legacy DEK) and re-sealed under newCek.
|
|
1144
|
-
...sealedOut !== void 0 ? { _sealed: sealedOut } : {},
|
|
1145
|
-
...vdigOut !== void 0 ? { _vdig: vdigOut } : {}
|
|
1008
|
+
async function rekeyEnvelopeIfNeeded(ref, envelope, oldDek, newDek) {
|
|
1009
|
+
try {
|
|
1010
|
+
return await rekeyEnvelopeToDek(ref, envelope, oldDek, newDek);
|
|
1011
|
+
} catch (errUnderOld) {
|
|
1012
|
+
try {
|
|
1013
|
+
if (envelope._cek !== void 0) await unwrapCek(envelope._cek, newDek);
|
|
1014
|
+
else await decrypt(...sealedBodyArgs(envelope, "rekeyRecord"), newDek, recordAadFor(ref, envelope));
|
|
1015
|
+
return null;
|
|
1016
|
+
} catch {
|
|
1017
|
+
throw errUnderOld;
|
|
1018
|
+
}
|
|
1146
1019
|
}
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1020
|
+
}
|
|
1021
|
+
async function envelopeOpensUnderAny(ref, envelope, keys) {
|
|
1022
|
+
for (const key of keys) {
|
|
1023
|
+
try {
|
|
1024
|
+
if (envelope._cek !== void 0) await unwrapCek(envelope._cek, key);
|
|
1025
|
+
else await decrypt(...sealedBodyArgs(envelope, "rekeyRecord"), key, recordAadFor(ref, envelope));
|
|
1026
|
+
return true;
|
|
1027
|
+
} catch {
|
|
1028
|
+
}
|
|
1155
1029
|
}
|
|
1030
|
+
return false;
|
|
1156
1031
|
}
|
|
1032
|
+
return { rekeyEnvelopeToDek, rekeyEnvelopeIfNeeded, envelopeOpensUnderAny };
|
|
1157
1033
|
}
|
|
1158
1034
|
|
|
1159
|
-
// src/
|
|
1160
|
-
|
|
1161
|
-
const
|
|
1162
|
-
const
|
|
1163
|
-
const
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
encryptDeterministic(plaintext, detKey, context),
|
|
1167
|
-
encryptDeterministic(plaintext, dek, context)
|
|
1168
|
-
]);
|
|
1169
|
-
return [`${current.iv}:${current.data}`, `${legacy.iv}:${legacy.data}`];
|
|
1170
|
-
}
|
|
1171
|
-
function assertDetField(ctx, field, method) {
|
|
1172
|
-
if (!ctx.deterministicFields || !ctx.deterministicFields.has(field)) {
|
|
1173
|
-
throw new Error(
|
|
1174
|
-
`Collection "${ctx.name}": field "${field}" is not declared in deterministicFields`
|
|
1175
|
-
);
|
|
1176
|
-
}
|
|
1177
|
-
if (!ctx.storeCiphertext) {
|
|
1178
|
-
throw new Error(
|
|
1179
|
-
`Collection "${ctx.name}": ${method} is only meaningful on encrypted collections`
|
|
1180
|
-
);
|
|
1035
|
+
// src/capsule/plumbing/rekey-blob.ts
|
|
1036
|
+
function makeRekeyBlob(p) {
|
|
1037
|
+
const { decrypt, decryptBytesWithAAD, encrypt, encryptBytesWithAAD, unwrapCek, wrapCek } = p;
|
|
1038
|
+
const BLOB_INDEX_COLLECTION = "_blob_index";
|
|
1039
|
+
const BLOB_CHUNKS_COLLECTION = "_blob_chunks";
|
|
1040
|
+
function chunkAad(eTag, index, chunkCount) {
|
|
1041
|
+
return new TextEncoder().encode(`${eTag}:${index}:${chunkCount}`);
|
|
1181
1042
|
}
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
for (const id of ids) {
|
|
1188
|
-
const env = await ctx.adapter.get(ctx.vault, ctx.name, id);
|
|
1189
|
-
if (!env || !env._det || (env._tier ?? 0) > 0) continue;
|
|
1190
|
-
if (env._det[field] === target || env._det[field] === legacyTarget) {
|
|
1191
|
-
return ctx.codec.decryptRecord({ collection: ctx.name, id }, env);
|
|
1043
|
+
async function opensJson(ref, env, key) {
|
|
1044
|
+
try {
|
|
1045
|
+
return await decrypt(...sealedBodyArgs(env, "rekeyBlob"), key, recordAadFor(ref, env));
|
|
1046
|
+
} catch {
|
|
1047
|
+
return null;
|
|
1192
1048
|
}
|
|
1193
1049
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1050
|
+
async function rekeyBlobSet(adapter, vault, oldDek, newDek, otherDeks = []) {
|
|
1051
|
+
let blobs = 0;
|
|
1052
|
+
let chunks = 0;
|
|
1053
|
+
let foreign = 0;
|
|
1054
|
+
let alreadyMoved = 0;
|
|
1055
|
+
let eTags;
|
|
1056
|
+
try {
|
|
1057
|
+
eTags = await adapter.list(vault, BLOB_INDEX_COLLECTION);
|
|
1058
|
+
} catch {
|
|
1059
|
+
return { blobs, chunks, foreign, alreadyMoved };
|
|
1060
|
+
}
|
|
1061
|
+
for (const eTag of eTags) {
|
|
1062
|
+
const idxEnv = await adapter.get(vault, BLOB_INDEX_COLLECTION, eTag);
|
|
1063
|
+
if (!idxEnv || !idxEnv._iv) continue;
|
|
1064
|
+
const ref = { collection: BLOB_INDEX_COLLECTION, id: eTag };
|
|
1065
|
+
const json = await opensJson(ref, idxEnv, oldDek);
|
|
1066
|
+
if (json === null) {
|
|
1067
|
+
if (await opensJson(ref, idxEnv, newDek) !== null) {
|
|
1068
|
+
alreadyMoved++;
|
|
1069
|
+
continue;
|
|
1070
|
+
}
|
|
1071
|
+
let claimed = false;
|
|
1072
|
+
for (const key of otherDeks) {
|
|
1073
|
+
if (await opensJson(ref, idxEnv, key) !== null) {
|
|
1074
|
+
claimed = true;
|
|
1075
|
+
break;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
if (claimed) {
|
|
1079
|
+
foreign++;
|
|
1080
|
+
continue;
|
|
1081
|
+
}
|
|
1082
|
+
throw new Error(
|
|
1083
|
+
`[noy-db] rotateKeys: blob index entry "${eTag}" opens under neither the retiring nor the new \`_blob\` DEK, nor any other key this keyring holds. Rotation stopped rather than leaving it unreadable and unreported.`
|
|
1084
|
+
);
|
|
1085
|
+
}
|
|
1086
|
+
const blob = JSON.parse(json);
|
|
1087
|
+
for (let i = 0; i < blob.chunkCount; i++) {
|
|
1088
|
+
const id = `${eTag}_${i}`;
|
|
1089
|
+
const chunkEnv = await adapter.get(vault, BLOB_CHUNKS_COLLECTION, id);
|
|
1090
|
+
if (!chunkEnv || !chunkEnv._iv) continue;
|
|
1091
|
+
const aad = chunkAad(eTag, i, blob.chunkCount);
|
|
1092
|
+
let plain;
|
|
1093
|
+
try {
|
|
1094
|
+
plain = await decryptBytesWithAAD(...sealedBodyArgs(chunkEnv, "rekeyBlob"), oldDek, aad);
|
|
1095
|
+
} catch {
|
|
1096
|
+
if (blob._cek !== void 0 || blob._cekPending !== void 0) continue;
|
|
1097
|
+
try {
|
|
1098
|
+
await decryptBytesWithAAD(...sealedBodyArgs(chunkEnv, "rekeyBlob"), newDek, aad);
|
|
1099
|
+
continue;
|
|
1100
|
+
} catch {
|
|
1101
|
+
throw new Error(
|
|
1102
|
+
`[noy-db] rotateKeys: blob chunk "${id}" (${i + 1}/${blob.chunkCount} of eTag "${eTag}") opens under neither the retiring nor the new \`_blob\` DEK, and its blob holds no content CEK that could explain it. Rotation stopped rather than leaving it unreadable and unreported.`
|
|
1103
|
+
);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
const { iv: iv2, data: data2 } = await encryptBytesWithAAD(plain, newDek, aad);
|
|
1107
|
+
await adapter.put(vault, BLOB_CHUNKS_COLLECTION, id, { ...chunkEnv, _iv: iv2, _data: data2 });
|
|
1108
|
+
chunks++;
|
|
1109
|
+
}
|
|
1110
|
+
const rewrapped = {
|
|
1111
|
+
...blob,
|
|
1112
|
+
...blob._cek !== void 0 ? { _cek: await wrapCek(await unwrapCek(blob._cek, oldDek), newDek) } : {},
|
|
1113
|
+
...blob._cekPending !== void 0 ? { _cekPending: await wrapCek(await unwrapCek(blob._cekPending, oldDek), newDek) } : {}
|
|
1114
|
+
};
|
|
1115
|
+
const { iv, data } = await encrypt(JSON.stringify(rewrapped), newDek, recordAadFor(ref, idxEnv));
|
|
1116
|
+
await adapter.put(vault, BLOB_INDEX_COLLECTION, eTag, { ...idxEnv, _iv: iv, _data: data });
|
|
1117
|
+
blobs++;
|
|
1207
1118
|
}
|
|
1119
|
+
return { blobs, chunks, foreign, alreadyMoved };
|
|
1208
1120
|
}
|
|
1209
|
-
return
|
|
1121
|
+
return { rekeyBlobSet };
|
|
1210
1122
|
}
|
|
1211
1123
|
|
|
1212
|
-
// src/
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
const
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1124
|
+
// src/capsule/plumbing/sealing.ts
|
|
1125
|
+
function makeSealing(p, sealedSlot) {
|
|
1126
|
+
const { openVdigPayload, sealVdigPayload, bufferToBase64, decrypt, deriveSealedFieldKeyFromCek, encrypt, generateDEK, unwrapCek, wrapCek } = p;
|
|
1127
|
+
const { dualReadSealedSlot } = sealedSlot;
|
|
1128
|
+
const subtle = globalThis.crypto.subtle;
|
|
1129
|
+
const SEALED_CEK_NS = "_sealed_cek";
|
|
1130
|
+
async function sealRecordToHost(ctx, collection, id, hostSealer, opts) {
|
|
1131
|
+
if (collection.includes("/")) throw new ValidationError(`sealRecordToHost: collection "${collection}" must not contain "/"`);
|
|
1132
|
+
if (id.includes("/")) throw new ValidationError(`sealRecordToHost: id "${id}" must not contain "/"`);
|
|
1133
|
+
if (Number.isNaN(Date.parse(opts.expiresAt))) {
|
|
1134
|
+
throw new ValidationError(`sealRecordToHost: expiresAt "${opts.expiresAt}" is not a valid ISO 8601 timestamp`);
|
|
1135
|
+
}
|
|
1136
|
+
const live = await ctx.adapter.get(ctx.vault, collection, id);
|
|
1137
|
+
if (!live || live._cek === void 0) {
|
|
1138
|
+
throw new RecordCekNotFoundError(collection, id);
|
|
1139
|
+
}
|
|
1140
|
+
const dek = await ctx.getDEK(collection);
|
|
1141
|
+
const cek = await unwrapCek(live._cek, dek);
|
|
1142
|
+
const rawCek = await subtle.exportKey("raw", cek);
|
|
1143
|
+
const cekB64 = bufferToBase64(rawCek);
|
|
1144
|
+
const hint = await hostSealer.publishRecipientHint();
|
|
1145
|
+
if (hint.pid.includes("/")) throw new ValidationError(`sealRecordToHost: recipient pid "${hint.pid}" must not contain "/"`);
|
|
1146
|
+
const binding = {
|
|
1147
|
+
collection,
|
|
1148
|
+
id,
|
|
1149
|
+
cek: cekB64,
|
|
1150
|
+
expiresAt: opts.expiresAt
|
|
1151
|
+
};
|
|
1152
|
+
const sealed = await hostSealer.sealForRecipient(
|
|
1153
|
+
new TextEncoder().encode(JSON.stringify(binding)),
|
|
1154
|
+
hint
|
|
1155
|
+
);
|
|
1156
|
+
const delivery = {
|
|
1157
|
+
v: 1,
|
|
1158
|
+
_noydb_sealed_cek: 1,
|
|
1159
|
+
pid: hint.pid,
|
|
1160
|
+
payload: bufferToBase64(sealed),
|
|
1161
|
+
expiresAt: opts.expiresAt
|
|
1162
|
+
};
|
|
1163
|
+
const envelopeKey = `${collection}/${id}/${hint.pid}`;
|
|
1164
|
+
const prior = await ctx.adapter.get(ctx.vault, SEALED_CEK_NS, envelopeKey);
|
|
1165
|
+
const env = buildRecordEnvelope(
|
|
1166
|
+
{ collection: SEALED_CEK_NS, id: envelopeKey, version: (prior?._v ?? 0) + 1 },
|
|
1167
|
+
{
|
|
1168
|
+
// AES-GCM bypassed — the sealing layer is the security boundary, exactly
|
|
1169
|
+
// like the managed-secret `_meta/sealed-secret` envelope.
|
|
1170
|
+
iv: "",
|
|
1171
|
+
data: JSON.stringify(delivery),
|
|
1172
|
+
...ctx.actor ? { by: ctx.actor } : {}
|
|
1173
|
+
}
|
|
1174
|
+
);
|
|
1175
|
+
await ctx.adapter.put(ctx.vault, SEALED_CEK_NS, envelopeKey, env);
|
|
1176
|
+
return { pid: hint.pid, envelopeKey };
|
|
1219
1177
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
const cek = await generateDEK();
|
|
1227
|
-
const { iv: iv2, data: data2 } = await encrypt(json, cek, aad);
|
|
1228
|
-
const wrapped = await wrapCek(cek, key);
|
|
1229
|
-
return { _iv: iv2, _data: data2, _cek: wrapped };
|
|
1178
|
+
async function revokeSealedRecord(ctx, collection, id, pid, opts) {
|
|
1179
|
+
if (opts?.hard === true) {
|
|
1180
|
+
await rotateRecordCek(ctx, collection, id);
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1183
|
+
await ctx.adapter.delete(ctx.vault, SEALED_CEK_NS, `${collection}/${id}/${pid}`);
|
|
1230
1184
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1185
|
+
async function rotateRecordCek(ctx, collection, id) {
|
|
1186
|
+
const live = await ctx.adapter.get(ctx.vault, collection, id);
|
|
1187
|
+
if (!live || live._cek === void 0) {
|
|
1188
|
+
throw new RecordCekNotFoundError(collection, id);
|
|
1189
|
+
}
|
|
1190
|
+
const dek = await ctx.getDEK(collection);
|
|
1191
|
+
const oldCek = await unwrapCek(live._cek, dek);
|
|
1192
|
+
const openAad = recordAadFor({ collection, id }, live);
|
|
1193
|
+
const json = await decrypt(...sealedBodyArgs(live, "reseal"), oldCek, openAad);
|
|
1194
|
+
const rotatedIdentity = {
|
|
1195
|
+
// A CEK rotation DOES bump `_v` (asserted in `record-scoped-cek-sealing`:
|
|
1196
|
+
// "the live envelope was re-keyed — new `_cek`, bumped `_v`"), so it seals
|
|
1197
|
+
// at the new version, not the one it just opened.
|
|
1198
|
+
//
|
|
1199
|
+
// ⚠️ Do not confuse this with `rekeyEnvelopeToDek`, the DEK-rotation helper,
|
|
1200
|
+
// which PRESERVES `_v` (#1074) because it re-keys a record without writing
|
|
1201
|
+
// one. Two rotations, opposite answers — and with `_v` bound (#1093) getting
|
|
1202
|
+
// it backwards no longer produces a wrong number, it produces an
|
|
1203
|
+
// unreadable record.
|
|
1204
|
+
collection,
|
|
1205
|
+
id,
|
|
1206
|
+
version: live._v + 1,
|
|
1207
|
+
...live._tier !== void 0 ? { tier: live._tier } : {},
|
|
1208
|
+
...ctx.actor ? { by: ctx.actor } : live._by !== void 0 ? { by: live._by } : {}
|
|
1209
|
+
};
|
|
1210
|
+
const newCek = await generateDEK();
|
|
1211
|
+
const { iv, data } = await encrypt(json, newCek, buildRecordAad(rotatedIdentity));
|
|
1212
|
+
let sealedOut;
|
|
1213
|
+
if (live._sealed !== void 0) {
|
|
1214
|
+
const out = {};
|
|
1215
|
+
for (const [field, slot] of Object.entries(live._sealed)) {
|
|
1216
|
+
const plaintext = await dualReadSealedSlot(slot, field, collection, oldCek, dek);
|
|
1217
|
+
const resealed = await encrypt(plaintext, await deriveSealedFieldKeyFromCek(newCek, collection, field));
|
|
1218
|
+
out[field] = `${resealed.iv}:${resealed.data}`;
|
|
1219
|
+
}
|
|
1220
|
+
sealedOut = out;
|
|
1221
|
+
}
|
|
1222
|
+
let vdigOut;
|
|
1223
|
+
if (live._vdig !== void 0) {
|
|
1224
|
+
const out = {};
|
|
1225
|
+
for (const [field, blob] of Object.entries(live._vdig)) {
|
|
1226
|
+
const payload = await openVdigPayload(blob, oldCek, collection, id, field);
|
|
1227
|
+
out[field] = await sealVdigPayload(payload, newCek, collection, id, field);
|
|
1228
|
+
}
|
|
1229
|
+
vdigOut = out;
|
|
1230
|
+
}
|
|
1231
|
+
const env = buildRecordEnvelope(rotatedIdentity, {
|
|
1232
|
+
iv,
|
|
1233
|
+
data,
|
|
1234
|
+
cek: await wrapCek(newCek, dek),
|
|
1235
|
+
extra: {
|
|
1236
|
+
...live._det !== void 0 ? { _det: live._det } : {},
|
|
1237
|
+
// `_bidx` (equality-index tag) is DEK-rooted and CEK-independent, so it is
|
|
1238
|
+
// carried forward VERBATIM — not recomputed — unlike `_vdig`/`_sealed`
|
|
1239
|
+
// below, which are CEK-bound and must be re-sealed under the new CEK.
|
|
1240
|
+
// Dropping this line would silently orphan the equality index on rotation
|
|
1241
|
+
// (the #306 Slice-A data-loss bug, replayed on the index).
|
|
1242
|
+
...live._bidx !== void 0 ? { _bidx: live._bidx } : {},
|
|
1243
|
+
// Re-encrypt sealed (`sensitive`) fields under the new CEK. Sealed
|
|
1244
|
+
// keys derive off the per-record CEK, so the rotated record's old CEK is
|
|
1245
|
+
// destroyed here — carrying the old `_sealed` slots forward verbatim would
|
|
1246
|
+
// orphan them (unreadable under the new CEK). `sealedOut` holds the slots
|
|
1247
|
+
// dual-read from the old CEK (or the legacy DEK) and re-sealed under newCek.
|
|
1248
|
+
...sealedOut !== void 0 ? { _sealed: sealedOut } : {},
|
|
1249
|
+
...vdigOut !== void 0 ? { _vdig: vdigOut } : {}
|
|
1250
|
+
}
|
|
1251
|
+
});
|
|
1252
|
+
await ctx.adapter.put(ctx.vault, collection, id, env);
|
|
1253
|
+
await ctx.invalidateRecordCaches(collection, id);
|
|
1254
|
+
const prefix = `${collection}/${id}/`;
|
|
1255
|
+
const keys = await ctx.adapter.list(ctx.vault, SEALED_CEK_NS);
|
|
1256
|
+
for (const key of keys) {
|
|
1257
|
+
if (key.startsWith(prefix)) {
|
|
1258
|
+
await ctx.adapter.delete(ctx.vault, SEALED_CEK_NS, key);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1264
1261
|
}
|
|
1262
|
+
return { SEALED_CEK_NS, sealRecordToHost, revokeSealedRecord, rotateRecordCek };
|
|
1265
1263
|
}
|
|
1266
1264
|
|
|
1267
|
-
// src/
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
parts.challenge,
|
|
1281
|
-
parts.expiresAt
|
|
1282
|
-
]);
|
|
1283
|
-
}
|
|
1284
|
-
async function deriveBrokerProofBits(seed, vaultId, brokerId) {
|
|
1285
|
-
const hkdfKey = await subtle2.importKey("raw", seed, "HKDF", false, ["deriveBits"]);
|
|
1286
|
-
const salt = new TextEncoder().encode(BROKER_PROOF_DOMAIN);
|
|
1287
|
-
const info = new TextEncoder().encode(JSON.stringify([BROKER_PROOF_DOMAIN, vaultId, brokerId]));
|
|
1288
|
-
const bits = await subtle2.deriveBits({ name: "HKDF", hash: "SHA-256", salt, info }, hkdfKey, 256);
|
|
1289
|
-
return new Uint8Array(bits);
|
|
1290
|
-
}
|
|
1291
|
-
async function deriveBrokerProofKey(seed, vaultId, brokerId) {
|
|
1292
|
-
const proofBits = await deriveBrokerProofBits(seed, vaultId, brokerId);
|
|
1293
|
-
try {
|
|
1294
|
-
return await subtle2.importKey("raw", proofBits, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
1295
|
-
} finally {
|
|
1296
|
-
proofBits.fill(0);
|
|
1265
|
+
// src/capsule/plumbing/deterministic.ts
|
|
1266
|
+
function makeDeterministic(p) {
|
|
1267
|
+
const { deriveDeterministicKey, encryptDeterministic } = p;
|
|
1268
|
+
async function detTargets(ctx, field, value) {
|
|
1269
|
+
const dek = await ctx.getDEK();
|
|
1270
|
+
const detKey = await deriveDeterministicKey(dek);
|
|
1271
|
+
const plaintext = typeof value === "string" ? value : JSON.stringify(value);
|
|
1272
|
+
const context = `${ctx.name}/${field}`;
|
|
1273
|
+
const [current, legacy] = await Promise.all([
|
|
1274
|
+
encryptDeterministic(plaintext, detKey, context),
|
|
1275
|
+
encryptDeterministic(plaintext, dek, context)
|
|
1276
|
+
]);
|
|
1277
|
+
return [`${current.iv}:${current.data}`, `${legacy.iv}:${legacy.data}`];
|
|
1297
1278
|
}
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
throw new ValidationError(
|
|
1303
|
-
"computeBrokerProof: instancePid must not be an empty string \u2014 omit the field entirely for 'no instance' (F7); '' would alias onto a registered instance."
|
|
1279
|
+
function assertDetField(ctx, field, method) {
|
|
1280
|
+
if (!ctx.deterministicFields || !ctx.deterministicFields.has(field)) {
|
|
1281
|
+
throw new Error(
|
|
1282
|
+
`Collection "${ctx.name}": field "${field}" is not declared in deterministicFields`
|
|
1304
1283
|
);
|
|
1305
1284
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1285
|
+
if (!ctx.storeCiphertext) {
|
|
1286
|
+
throw new Error(
|
|
1287
|
+
`Collection "${ctx.name}": ${method} is only meaningful on encrypted collections`
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
async function findByDet(ctx, field, value) {
|
|
1292
|
+
assertDetField(ctx, field, "findByDet");
|
|
1293
|
+
const [target, legacyTarget] = await detTargets(ctx, field, value);
|
|
1294
|
+
const ids = await ctx.adapter.list(ctx.vault, ctx.name);
|
|
1295
|
+
for (const id of ids) {
|
|
1296
|
+
const env = await ctx.adapter.get(ctx.vault, ctx.name, id);
|
|
1297
|
+
if (!env || !env._det || (env._tier ?? 0) > 0) continue;
|
|
1298
|
+
if (env._det[field] === target || env._det[field] === legacyTarget) {
|
|
1299
|
+
return ctx.codec.decryptRecord({ collection: ctx.name, id }, env);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
return null;
|
|
1303
|
+
}
|
|
1304
|
+
async function queryByDet(ctx, field, value) {
|
|
1305
|
+
assertDetField(ctx, field, "queryByDet");
|
|
1306
|
+
const [target, legacyTarget] = await detTargets(ctx, field, value);
|
|
1307
|
+
const ids = await ctx.adapter.list(ctx.vault, ctx.name);
|
|
1308
|
+
const matches = [];
|
|
1309
|
+
for (const id of ids) {
|
|
1310
|
+
const env = await ctx.adapter.get(ctx.vault, ctx.name, id);
|
|
1311
|
+
if (!env || !env._det || (env._tier ?? 0) > 0) continue;
|
|
1312
|
+
if (env._det[field] === target || env._det[field] === legacyTarget) {
|
|
1313
|
+
const rec = await ctx.codec.decryptRecord({ collection: ctx.name, id }, env);
|
|
1314
|
+
if (rec !== null) matches.push(rec);
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
return matches;
|
|
1312
1318
|
}
|
|
1319
|
+
return { findByDet, queryByDet };
|
|
1313
1320
|
}
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1321
|
+
|
|
1322
|
+
// src/capsule/plumbing/index.ts
|
|
1323
|
+
function makeCapsule(p) {
|
|
1324
|
+
const sealedSlot = makeSealedSlot(p);
|
|
1325
|
+
const envelopeBody = makeEnvelopeBody(p);
|
|
1326
|
+
const sealedSlots = makeSealedSlots(p, sealedSlot);
|
|
1327
|
+
const codec = makeRecordCodec(p, sealedSlots);
|
|
1317
1328
|
return {
|
|
1318
|
-
|
|
1319
|
-
|
|
1329
|
+
...envelopeBody,
|
|
1330
|
+
...sealedSlot,
|
|
1331
|
+
...sealedSlots,
|
|
1332
|
+
...codec,
|
|
1333
|
+
...makeLifecycle(p),
|
|
1334
|
+
...makeRekey(p),
|
|
1335
|
+
...makeRekeyBlob(p),
|
|
1336
|
+
...makeSealing(p, sealedSlot),
|
|
1337
|
+
...makeDeterministic(p)
|
|
1320
1338
|
};
|
|
1321
1339
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
if (
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
const key = await subtle2.importKey(
|
|
1334
|
-
"raw",
|
|
1335
|
-
args.registeredProofKey,
|
|
1336
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
1337
|
-
false,
|
|
1338
|
-
["verify"]
|
|
1339
|
-
);
|
|
1340
|
-
const ok = await subtle2.verify(
|
|
1341
|
-
"HMAC",
|
|
1342
|
-
key,
|
|
1343
|
-
base64ToBuffer(args.proof),
|
|
1344
|
-
new TextEncoder().encode(canonical)
|
|
1345
|
-
);
|
|
1346
|
-
if (!ok) return false;
|
|
1347
|
-
return Date.now() < Date.parse(args.expiresAt);
|
|
1340
|
+
|
|
1341
|
+
// src/capsule/plumbing/ct-equal.ts
|
|
1342
|
+
function ctEqualTags(a, b) {
|
|
1343
|
+
if (a.length !== 32 || b.length !== 32) {
|
|
1344
|
+
throw new Error(
|
|
1345
|
+
`ctEqualTags: tags must be exactly 32 bytes (got ${a.length}/${b.length}) \u2014 caller bug; reduce comparands with blindedEqual first`
|
|
1346
|
+
);
|
|
1347
|
+
}
|
|
1348
|
+
let diff = 0;
|
|
1349
|
+
for (let i = 0; i < 32; i++) diff |= a[i] ^ b[i];
|
|
1350
|
+
return diff === 0;
|
|
1348
1351
|
}
|
|
1349
1352
|
|
|
1350
1353
|
export {
|
|
1351
1354
|
buildRecordAad,
|
|
1352
1355
|
recordAadFor,
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
applyRewrappedBody,
|
|
1356
|
-
rewrapEnvelope,
|
|
1357
|
-
isRewrappedUnder,
|
|
1358
|
-
rekeyEnvelopeToDek,
|
|
1359
|
-
rekeyEnvelopeIfNeeded,
|
|
1360
|
-
envelopeOpensUnderAny,
|
|
1361
|
-
rekeyBlobSet,
|
|
1362
|
-
makeReservedEnvelopes,
|
|
1363
|
-
validateSchemaInput,
|
|
1364
|
-
validateSchemaOutput,
|
|
1365
|
-
RecordCodec,
|
|
1366
|
-
SEALED_CEK_NS,
|
|
1367
|
-
sealRecordToHost,
|
|
1368
|
-
revokeSealedRecord,
|
|
1369
|
-
rotateRecordCek,
|
|
1370
|
-
findByDet,
|
|
1371
|
-
queryByDet,
|
|
1372
|
-
openEnvelopeJson,
|
|
1373
|
-
writeEnvelopeBody,
|
|
1356
|
+
requireSealedBody,
|
|
1357
|
+
sealedBodyArgs,
|
|
1374
1358
|
envelopeBodySize,
|
|
1375
1359
|
hasPerRecordKey,
|
|
1376
1360
|
envelopeBodyForHash,
|
|
1377
1361
|
hasSealedBody,
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1362
|
+
parseSealedSlot,
|
|
1363
|
+
buildRecordEnvelope,
|
|
1364
|
+
buildSealedRecordEnvelope,
|
|
1365
|
+
isTombstoneShape,
|
|
1366
|
+
isTombstone,
|
|
1367
|
+
buildTombstone,
|
|
1368
|
+
isDeleteMarker,
|
|
1369
|
+
buildDeleteMarker,
|
|
1370
|
+
validateSchemaInput,
|
|
1371
|
+
validateSchemaOutput,
|
|
1372
|
+
makeCapsule,
|
|
1373
|
+
ctEqualTags
|
|
1384
1374
|
};
|
|
1385
|
-
//# sourceMappingURL=chunk-
|
|
1375
|
+
//# sourceMappingURL=chunk-42ALPZ2B.js.map
|