@noy-db/hub 0.10.0-pre.0 → 0.10.0-pre.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +90 -0
- package/README.md +2 -2
- package/dist/api-QSEKT4KS.js +15 -0
- package/dist/as/index.js +19 -12
- package/dist/as/index.js.map +1 -1
- package/dist/at/index.js +6 -9
- package/dist/attestation/index.js +16 -19
- package/dist/attestation/index.js.map +1 -1
- package/dist/{backup-E3GBMNDA.js → backup-BHKVK5SD.js} +9 -12
- package/dist/{backup-E3GBMNDA.js.map → backup-BHKVK5SD.js.map} +1 -1
- package/dist/blobs/index.js +10 -13
- package/dist/blobs/index.js.map +1 -1
- package/dist/broker/index.js +11 -14
- package/dist/broker/index.js.map +1 -1
- package/dist/by/index.js +2 -2
- package/dist/capsule/contract.d.ts +176 -16
- package/dist/capsule/contract.js +35 -30
- package/dist/capsule/enclave-aes/bound.d.ts +11 -1
- package/dist/capsule/enclave-aes/classify/digest.d.ts +4 -2
- package/dist/capsule/enclave-aes/index.d.ts +9 -0
- package/dist/capsule/enclave-aes/index.js +643 -78
- package/dist/capsule/enclave-aes/index.js.map +1 -1
- package/dist/capsule/enclave-aes/primitives.d.ts +2 -2
- package/dist/capsule/index.d.ts +1 -1
- package/dist/capsule/plumbing/classify-reveal.d.ts +29 -0
- package/dist/capsule/plumbing/classify-verify.d.ts +53 -0
- package/dist/capsule/plumbing/index.d.ts +17 -0
- package/dist/{capsule-YQKQZPH7.js → capsule-YAITMH77.js} +16 -9
- package/dist/cargo/index.js +34 -36
- package/dist/{chunk-U43RSPPX.js → chunk-23A4SBRR.js} +3 -4
- package/dist/{chunk-U43RSPPX.js.map → chunk-23A4SBRR.js.map} +1 -1
- package/dist/{chunk-PREYKC76.js → chunk-24AGG4PP.js} +3 -3
- package/dist/{chunk-ZVJKHGE5.js → chunk-24IJZA4M.js} +14 -8
- package/dist/chunk-24IJZA4M.js.map +1 -0
- package/dist/{chunk-4N4OIVK3.js → chunk-2NVQ5SEA.js} +15 -5
- package/dist/chunk-2NVQ5SEA.js.map +1 -0
- package/dist/{chunk-ZNVBCKMV.js → chunk-2SIREKBR.js} +2 -2
- package/dist/{chunk-N6EWQ5VB.js → chunk-37FOG6AE.js} +14 -7
- package/dist/chunk-37FOG6AE.js.map +1 -0
- package/dist/{chunk-UQRKAM2R.js → chunk-3M2KK7O7.js} +3 -3
- package/dist/{chunk-P6FATPXQ.js → chunk-3ZCVY3T6.js} +2 -2
- package/dist/{chunk-PBEHTFUG.js → chunk-4CGWLHPQ.js} +6 -6
- package/dist/{chunk-PFHDQY5L.js → chunk-56Z4NOC6.js} +3 -3
- package/dist/{chunk-GLSCL74M.js → chunk-5AVIUJP4.js} +13 -9
- package/dist/chunk-5AVIUJP4.js.map +1 -0
- package/dist/{chunk-F7X7MPK4.js → chunk-5BGHAVBN.js} +2 -2
- package/dist/{chunk-QHG7GQKM.js → chunk-5JNEDW7I.js} +2 -2
- package/dist/{chunk-GHMINSER.js → chunk-5OWJSDTO.js} +4 -4
- package/dist/{chunk-GHMINSER.js.map → chunk-5OWJSDTO.js.map} +1 -1
- package/dist/{chunk-DYIR6RC3.js → chunk-5Y4MO7UQ.js} +4 -4
- package/dist/{chunk-TLIFNRU5.js → chunk-63LZLRWG.js} +2 -2
- package/dist/{chunk-GZISWBCJ.js → chunk-74W56QPY.js} +4 -4
- package/dist/{chunk-CLOSXHR4.js → chunk-7KNYLHVX.js} +3 -3
- package/dist/chunk-7KNYLHVX.js.map +1 -0
- package/dist/{chunk-LFUID7OW.js → chunk-7VJ2SIEI.js} +42 -22
- package/dist/chunk-7VJ2SIEI.js.map +1 -0
- package/dist/{chunk-WVQDY3UM.js → chunk-AHA7UALU.js} +4 -4
- package/dist/{chunk-U277K5GR.js → chunk-AIHBYQHF.js} +259 -123
- package/dist/chunk-AIHBYQHF.js.map +1 -0
- package/dist/{chunk-S2ORTQGS.js → chunk-ANYX2M6P.js} +3 -3
- package/dist/{chunk-6WEPFEMJ.js → chunk-ATKYMRBC.js} +4 -4
- package/dist/{chunk-7UHLO4ZN.js → chunk-B2HU55QD.js} +2 -2
- package/dist/{chunk-Y22JWHCP.js → chunk-BEKMLYQ4.js} +4 -4
- package/dist/{chunk-27NCEPKM.js → chunk-BPFXD4EX.js} +23 -3
- package/dist/chunk-BPFXD4EX.js.map +1 -0
- package/dist/{chunk-7C7OF26T.js → chunk-C2NXAR3D.js} +5 -5
- package/dist/{chunk-Z2KP6PNF.js → chunk-CJBWJO5P.js} +6 -6
- package/dist/{chunk-Z2KP6PNF.js.map → chunk-CJBWJO5P.js.map} +1 -1
- package/dist/{chunk-6WIFF46H.js → chunk-CQLMRCKX.js} +2 -2
- package/dist/{chunk-URGHKZPL.js → chunk-CR5UPYIJ.js} +1 -1
- package/dist/chunk-CR5UPYIJ.js.map +1 -0
- package/dist/{chunk-LMC5L3MM.js → chunk-DS2JXSUA.js} +6 -6
- package/dist/{chunk-X6Z2SIRF.js → chunk-E2JIE4S3.js} +2 -2
- package/dist/{chunk-EQ6C2ZPT.js → chunk-E7Y4J4GL.js} +2 -2
- package/dist/{chunk-LZN6DTFI.js → chunk-ECDM6YRX.js} +2 -2
- package/dist/{chunk-WRLWEYHY.js → chunk-EFINFZIF.js} +11 -1
- package/dist/chunk-EFINFZIF.js.map +1 -0
- package/dist/{chunk-2T2TGRWE.js → chunk-EM56MHN5.js} +6 -6
- package/dist/{chunk-NK4LGBGQ.js → chunk-EQXOJH6O.js} +4 -4
- package/dist/{chunk-OK44MD3C.js → chunk-ET3U2C3A.js} +2 -2
- package/dist/{chunk-RF5WDM25.js → chunk-EU4G7PQH.js} +2 -2
- package/dist/{chunk-K5JNK63R.js → chunk-EUCUYK5E.js} +10 -10
- package/dist/{chunk-2ODEFG6K.js → chunk-EWSIJDWO.js} +4 -4
- package/dist/{chunk-LJ744WXU.js → chunk-F2FD4LSB.js} +2 -2
- package/dist/{chunk-L4UL4IAR.js → chunk-F7ENMZYJ.js} +2 -2
- package/dist/{chunk-KBIS64X4.js → chunk-FIIVYQOW.js} +5 -5
- package/dist/{chunk-TBVDI3LY.js → chunk-FPK2LPLR.js} +8 -8
- package/dist/chunk-FPK2LPLR.js.map +1 -0
- package/dist/{chunk-BQJ5ORU5.js → chunk-FQEUJGBV.js} +2 -2
- package/dist/{chunk-UORWAG7K.js → chunk-FY4FFNKK.js} +2 -2
- package/dist/{chunk-MMWX5OT5.js → chunk-GDCYZGPB.js} +2 -2
- package/dist/{chunk-7ONMS7QI.js → chunk-H6Q7GKLI.js} +2 -2
- package/dist/{chunk-654RE5YC.js → chunk-HDAPQF6Q.js} +3 -3
- package/dist/{chunk-5SMCBPJ2.js → chunk-HRLMUZLI.js} +5 -5
- package/dist/{chunk-R4GLRJ55.js → chunk-HRNQYGLQ.js} +2 -2
- package/dist/{chunk-HTRLQ4ZZ.js → chunk-I4S7IZSS.js} +321 -235
- package/dist/chunk-I4S7IZSS.js.map +1 -0
- package/dist/{chunk-UNAMWK2Q.js → chunk-IN4XZJYD.js} +4 -3
- package/dist/{chunk-UNAMWK2Q.js.map → chunk-IN4XZJYD.js.map} +1 -1
- package/dist/{chunk-2RH5SEY7.js → chunk-ISIXU45J.js} +2 -2
- package/dist/chunk-ISIXU45J.js.map +1 -0
- package/dist/{chunk-NHEKQWFI.js → chunk-J4L4AS2W.js} +2 -2
- package/dist/{chunk-UMV5GBTJ.js → chunk-JPSOFWJR.js} +2 -2
- package/dist/{chunk-A52BK5AY.js → chunk-JRCO67NG.js} +2 -2
- package/dist/{chunk-FVKQ5QUC.js → chunk-JW3I3NNZ.js} +2 -2
- package/dist/{chunk-BNYDOF2Q.js → chunk-JZMPSQBH.js} +4 -4
- package/dist/{chunk-ZK2WT532.js → chunk-K5TVSOPQ.js} +5 -5
- package/dist/{chunk-2IASHJPS.js → chunk-K75SL74I.js} +2 -2
- package/dist/{chunk-O3NGOHXQ.js → chunk-KA4AAUST.js} +2 -2
- package/dist/chunk-KHSBMLQE.js +161 -0
- package/dist/chunk-KHSBMLQE.js.map +1 -0
- package/dist/{chunk-QQLXKDGC.js → chunk-KUGUML7H.js} +3 -3
- package/dist/{chunk-AMSSAOOB.js → chunk-L4J5NC2Q.js} +2 -2
- package/dist/{chunk-AYOQZJDB.js → chunk-LIX4QPMM.js} +2 -2
- package/dist/{chunk-WIUH6EJ7.js → chunk-LWQFGR34.js} +3 -3
- package/dist/{chunk-QNOWNCZS.js → chunk-MMSSHMHW.js} +2 -2
- package/dist/{chunk-T5EXREMW.js → chunk-N25Z6PR4.js} +6 -5
- package/dist/chunk-N25Z6PR4.js.map +1 -0
- package/dist/{chunk-ND6S2DKC.js → chunk-N5S2BCW3.js} +2 -2
- package/dist/{chunk-X5RGG3ZW.js → chunk-NIZH2TYZ.js} +2 -2
- package/dist/{chunk-SXPLIRQH.js → chunk-NLDBQHDV.js} +2 -2
- package/dist/{chunk-AI35LNWQ.js → chunk-NQQ4MOPC.js} +4 -4
- package/dist/{chunk-B6EWMGFX.js → chunk-NUBI6PYH.js} +2 -2
- package/dist/{chunk-ID4ZBC3X.js → chunk-NYEXUZDW.js} +4 -4
- package/dist/{chunk-GU6QXHPZ.js → chunk-OIBFIWVJ.js} +4 -4
- package/dist/chunk-OIBFIWVJ.js.map +1 -0
- package/dist/{chunk-PWAMX5KU.js → chunk-OOLF5FU2.js} +2 -2
- package/dist/{chunk-WQUIJPN4.js → chunk-OQA7UF2Q.js} +3 -3
- package/dist/{chunk-7JRLCP2J.js → chunk-ORJPICJI.js} +2 -2
- package/dist/{chunk-IF2M43G4.js → chunk-PBRD75JF.js} +2 -2
- package/dist/{chunk-RKBCUP5D.js → chunk-PDCBL23X.js} +39 -17
- package/dist/chunk-PDCBL23X.js.map +1 -0
- package/dist/{chunk-BSEPI3HD.js → chunk-PR36DD2X.js} +7 -7
- package/dist/{chunk-52ZFNK46.js → chunk-PV4HIC4E.js} +2 -2
- package/dist/{chunk-TU6ZJTYT.js → chunk-PZNK4HTV.js} +3 -3
- package/dist/{chunk-LUQBG637.js → chunk-QBLPLNPE.js} +3 -3
- package/dist/{chunk-UADW5NOU.js → chunk-QZXUISRF.js} +5 -5
- package/dist/{chunk-BMAXBTYH.js → chunk-RBXYO7MD.js} +5 -5
- package/dist/{chunk-PZN76MMV.js → chunk-RIACRFWA.js} +4 -4
- package/dist/{chunk-ICHHNI5E.js → chunk-RL6RNDJQ.js} +8 -8
- package/dist/{chunk-4WLI37WK.js → chunk-SJ2P7UXD.js} +7 -7
- package/dist/{chunk-2QH3I7QC.js → chunk-SWXS4LV3.js} +11 -11
- package/dist/{chunk-4KYKRYRT.js → chunk-TOTCZFRF.js} +2 -2
- package/dist/{chunk-CSAN22QG.js → chunk-TT4D52EK.js} +6 -6
- package/dist/{chunk-VLRY2UH4.js → chunk-U7CMJY5P.js} +10 -10
- package/dist/{chunk-NIUHKKMM.js → chunk-UNKTZDA2.js} +11 -11
- package/dist/{chunk-NIUHKKMM.js.map → chunk-UNKTZDA2.js.map} +1 -1
- package/dist/{chunk-QVUMKG3Z.js → chunk-UXH4AKH3.js} +95 -151
- package/dist/chunk-UXH4AKH3.js.map +1 -0
- package/dist/{chunk-PU5ZEV65.js → chunk-UZVHSYIF.js} +2 -2
- package/dist/{chunk-3EXQXOQ2.js → chunk-VHKAW5OI.js} +29 -5
- package/dist/chunk-VHKAW5OI.js.map +1 -0
- package/dist/{chunk-XQGKS4OW.js → chunk-VKZ3TDET.js} +3 -3
- package/dist/{chunk-ZOFNZLAA.js → chunk-VLZPUG5A.js} +4 -4
- package/dist/{chunk-OR3OHKU6.js → chunk-VSN5FLMI.js} +2 -2
- package/dist/{chunk-JQMEXCUZ.js → chunk-VYBBE7RN.js} +8 -8
- package/dist/chunk-VYBBE7RN.js.map +1 -0
- package/dist/{chunk-SVXFCCSX.js → chunk-WHK4JVKF.js} +8 -8
- package/dist/{chunk-YVA6UPRN.js → chunk-X4LDBALX.js} +2 -2
- package/dist/{chunk-35CNOVQE.js → chunk-X67E7NIJ.js} +3 -3
- package/dist/{chunk-IPF5ORDI.js → chunk-XMARKBUC.js} +3 -3
- package/dist/{chunk-B3B6HV5S.js → chunk-XMBBTETD.js} +2 -2
- package/dist/{chunk-GQ4MF3CM.js → chunk-XMBTAN5E.js} +28 -14
- package/dist/chunk-XMBTAN5E.js.map +1 -0
- package/dist/{chunk-FUHUGKDN.js → chunk-XROQP6IQ.js} +4 -4
- package/dist/chunk-XWWDZKLS.js +196 -0
- package/dist/chunk-XWWDZKLS.js.map +1 -0
- package/dist/{chunk-DL4GCSTS.js → chunk-Y2RYUWSQ.js} +10 -10
- package/dist/{chunk-7IV7GVOS.js → chunk-YCTSQV7K.js} +5 -5
- package/dist/{chunk-IFUYLIEY.js → chunk-YF7P2DG7.js} +2 -2
- package/dist/{chunk-PIO6NW7O.js → chunk-ZG7DBIVX.js} +2 -2
- package/dist/{chunk-NUZ7ROUZ.js → chunk-ZGJ775X7.js} +2 -2
- package/dist/{chunk-6BEBWHNL.js → chunk-ZQQLOEWN.js} +3 -3
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-7HXDMYHI.js → classified-marker-HKMRC7SC.js} +3 -3
- package/dist/{reveal-UAPBG743.js → classify-reveal-YSJKJEIR.js} +7 -12
- package/dist/classify-reveal-YSJKJEIR.js.map +1 -0
- package/dist/{verify-QWO5UKD6.js → classify-verify-ZCTKYQ43.js} +31 -41
- package/dist/classify-verify-ZCTKYQ43.js.map +1 -0
- package/dist/collection-facade-PPKNUR2J.js +38 -0
- package/dist/{computed-LZLSYOPG.js → computed-UCYVPMZA.js} +3 -3
- package/dist/consent/index.js +6 -9
- package/dist/consent/index.js.map +1 -1
- package/dist/cover/index.js +6 -9
- package/dist/custody/index.js +11 -13
- package/dist/{dead-filter-PZIJ4F4G.js → dead-filter-YOBWRG4O.js} +8 -11
- package/dist/{dead-filter-PZIJ4F4G.js.map → dead-filter-YOBWRG4O.js.map} +1 -1
- package/dist/debug/index.js +5 -8
- package/dist/debug/index.js.map +1 -1
- package/dist/delegation-SNALWRMO.js +24 -0
- package/dist/derivations/index.js +20 -23
- package/dist/derive-4GNU4E4I.js +17 -0
- package/dist/directory/index.js +7 -10
- package/dist/{dispatch-4BUYPWMJ.js → dispatch-QW32QBLW.js} +17 -20
- package/dist/{dispatch-4BUYPWMJ.js.map → dispatch-QW32QBLW.js.map} +1 -1
- package/dist/{dispatch-KOPDDPEQ.js → dispatch-V5WLDTVX.js} +5 -5
- package/dist/executor-7QN22OKI.js +8 -0
- package/dist/executor-BJZJNVBB.js +8 -0
- package/dist/executor-JEAAEJUM.js +32 -0
- package/dist/export-accessible-TVO2KQPG.js +20 -0
- package/dist/extract-partition-43CLDRN4.js +33 -0
- package/dist/{fanout-sidecar-FYDRL7F3.js → fanout-sidecar-DDONAFJT.js} +6 -9
- package/dist/{fanout-sidecar-FYDRL7F3.js.map → fanout-sidecar-DDONAFJT.js.map} +1 -1
- package/dist/forget/index.js +6 -9
- package/dist/forget/index.js.map +1 -1
- package/dist/guards/index.js +4 -4
- package/dist/history/index.js +11 -14
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.js +11 -14
- package/dist/i18n/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +122 -123
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +5 -5
- package/dist/introspection/index.js +8 -11
- package/dist/issue-EIHEDAXM.js +16 -0
- package/dist/kernel/capsule-requirements.d.ts +84 -0
- package/dist/kernel/errors.d.ts +19 -3
- package/dist/kernel/export-scope.d.ts +28 -1
- package/dist/kernel/store-segment-guard.d.ts +29 -0
- package/dist/kernel/types.d.ts +169 -13
- package/dist/kernel/validation.d.ts +32 -0
- package/dist/kernel/vault.d.ts +5 -5
- package/dist/{ledger-UFJCB6T5.js → ledger-BMVUFQ3R.js} +8 -11
- package/dist/liberate-7KHXCLNJ.js +23 -0
- package/dist/link-set-PC2EJRKL.js +26 -0
- package/dist/{managed-secret-H5WYSJ46.js → managed-secret-RPRVEYZA.js} +7 -10
- package/dist/materialized-views/index.js +23 -26
- package/dist/{migrate-cek-SPESQAAO.js → migrate-cek-DTSCWGEF.js} +2 -2
- package/dist/money/index.js +5 -5
- package/dist/noydb-AYDNOXAX.js +98 -0
- package/dist/on/index.js +11 -13
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +9 -12
- package/dist/pod/index.js +65 -67
- package/dist/{pod-handle-GJLCOUGK.js → pod-handle-KBPQRN6Q.js} +6 -9
- package/dist/{pod-handle-GJLCOUGK.js.map → pod-handle-KBPQRN6Q.js.map} +1 -1
- package/dist/policy/index.js +7 -10
- package/dist/port/at/index.d.ts +1 -0
- package/dist/port/with/admission-authority.d.ts +2 -1
- package/dist/port/with/collection-registries.d.ts +37 -0
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-2AC2STHC.js → post-register-RITSNASO.js} +6 -6
- package/dist/query/all/index.js +15 -15
- package/dist/query/index.js +7 -7
- package/dist/query/live/index.js +7 -7
- package/dist/query/reduce/index.js +10 -10
- package/dist/query/relate/index.js +9 -9
- package/dist/reduce/index.js +8 -8
- package/dist/register-BB34SK7E.js +27 -0
- package/dist/registry-65L6V5TO.js +20 -0
- package/dist/registry-HU62GPWA.js +32 -0
- package/dist/registry-SMNK6UM4.js +8 -0
- package/dist/registry-X5VPBKCO.js +8 -0
- package/dist/request-withdrawal-4SKAH46W.js +26 -0
- package/dist/{restore-to-OOPKLAPU.js → restore-to-VQHT67OH.js} +7 -10
- package/dist/{restore-to-OOPKLAPU.js.map → restore-to-VQHT67OH.js.map} +1 -1
- package/dist/revoke-IF5PX2JY.js +21 -0
- package/dist/satellites/index.js +1 -1
- package/dist/schema-update/index.js +2 -2
- package/dist/sealed-record/index.js +9 -12
- package/dist/sealed-record/index.js.map +1 -1
- package/dist/search/index.js +4 -4
- package/dist/{seed-BVYDPVIW.js → seed-F2OSDZJR.js} +11 -13
- package/dist/{seed-BVYDPVIW.js.map → seed-F2OSDZJR.js.map} +1 -1
- package/dist/sequence/index.js +6 -9
- package/dist/session/index.js +6 -9
- package/dist/session/index.js.map +1 -1
- package/dist/shadow/index.js +2 -2
- package/dist/signer-5P7IZC2K.js +20 -0
- package/dist/snapshots/index.js +8 -10
- package/dist/snapshots/index.js.map +1 -1
- package/dist/{stale-CROGJBIJ.js → stale-PUCZH5GJ.js} +7 -10
- package/dist/storage-5EGY5OYE.js +18 -0
- package/dist/store/index.js +1 -1
- package/dist/{store-coordination-provider-2YD2PTTP.js → store-coordination-provider-SEQM7SHJ.js} +7 -10
- package/dist/{store-coordination-provider-2YD2PTTP.js.map → store-coordination-provider-SEQM7SHJ.js.map} +1 -1
- package/dist/sync/index.js +13 -15
- package/dist/sync/index.js.map +1 -1
- package/dist/team/index.js +14 -16
- package/dist/tiers/index.js +8 -11
- package/dist/to/index.js +2 -2
- package/dist/transactions/index.js +3 -3
- package/dist/util/index.js +1 -1
- package/dist/vault-diff-H7LT5ZBJ.js +8 -0
- package/dist/vault-head/index.js +5 -8
- package/dist/vault-head/index.js.map +1 -1
- package/dist/walk-Z4N7PCZ2.js +17 -0
- package/dist/with-audit/portability/export-accessible.d.ts +3 -1
- package/dist/with-cargo/vault-diff.d.ts +28 -0
- package/dist/with-commit/sequence/index.d.ts +22 -0
- package/dist/with-party/team/delegation.d.ts +16 -12
- package/dist/with-party/team/keyring.d.ts +77 -0
- package/dist/with-party/team/managed-secret.d.ts +40 -3
- package/dist/with-party/team/noydb-facade.d.ts +2 -2
- package/dist/with-party/team/peer-recover.d.ts +2 -2
- package/dist/with-party/team/rotate-recover.d.ts +3 -3
- package/dist/with-shape/manifest/storage.d.ts +2 -2
- package/dist/with-shape/manifest/writer.d.ts +2 -2
- package/dist/with-store/store-middleware.d.ts +18 -5
- package/dist/with-sync/engine.d.ts +0 -2
- package/dist/withdraw-accessible-CRCIQSTL.js +23 -0
- package/package.json +3 -3
- package/dist/api-H4B7ZQXP.js +0 -18
- package/dist/capsule/enclave-aes/classify/reveal.d.ts +0 -10
- package/dist/capsule/enclave-aes/classify/verify.d.ts +0 -36
- package/dist/chunk-27NCEPKM.js.map +0 -1
- package/dist/chunk-2RH5SEY7.js.map +0 -1
- package/dist/chunk-3EXQXOQ2.js.map +0 -1
- package/dist/chunk-4N4OIVK3.js.map +0 -1
- package/dist/chunk-5A3HOTP5.js +0 -591
- package/dist/chunk-5A3HOTP5.js.map +0 -1
- package/dist/chunk-CLOSXHR4.js.map +0 -1
- package/dist/chunk-EPPAEGH5.js +0 -157
- package/dist/chunk-EPPAEGH5.js.map +0 -1
- package/dist/chunk-GLSCL74M.js.map +0 -1
- package/dist/chunk-GQ4MF3CM.js.map +0 -1
- package/dist/chunk-GU6QXHPZ.js.map +0 -1
- package/dist/chunk-HTRLQ4ZZ.js.map +0 -1
- package/dist/chunk-JQMEXCUZ.js.map +0 -1
- package/dist/chunk-LFUID7OW.js.map +0 -1
- package/dist/chunk-N6EWQ5VB.js.map +0 -1
- package/dist/chunk-NH2UOV3B.js +0 -18
- package/dist/chunk-NH2UOV3B.js.map +0 -1
- package/dist/chunk-O6VOR4NH.js +0 -27
- package/dist/chunk-O6VOR4NH.js.map +0 -1
- package/dist/chunk-ODBOHPZU.js +0 -22
- package/dist/chunk-ODBOHPZU.js.map +0 -1
- package/dist/chunk-Q4DBU5RM.js +0 -78
- package/dist/chunk-Q4DBU5RM.js.map +0 -1
- package/dist/chunk-QVUMKG3Z.js.map +0 -1
- package/dist/chunk-RKBCUP5D.js.map +0 -1
- package/dist/chunk-T5EXREMW.js.map +0 -1
- package/dist/chunk-TBVDI3LY.js.map +0 -1
- package/dist/chunk-U277K5GR.js.map +0 -1
- package/dist/chunk-URGHKZPL.js.map +0 -1
- package/dist/chunk-VZFTON37.js +0 -40
- package/dist/chunk-VZFTON37.js.map +0 -1
- package/dist/chunk-WRLWEYHY.js.map +0 -1
- package/dist/chunk-ZVJKHGE5.js.map +0 -1
- package/dist/collection-facade-V63BEBGU.js +0 -41
- package/dist/delegation-7SSGIETH.js +0 -26
- package/dist/derive-IMI3BMDS.js +0 -20
- package/dist/executor-7SY3M6TZ.js +0 -8
- package/dist/executor-SNHW4ELF.js +0 -35
- package/dist/executor-Z3IKK7G3.js +0 -8
- package/dist/export-accessible-O7DIVFUO.js +0 -22
- package/dist/extract-partition-ELZEJKXM.js +0 -35
- package/dist/find-KWB2RYWJ.js +0 -10
- package/dist/issue-5ZHXK4HJ.js +0 -19
- package/dist/liberate-OEOSNNFH.js +0 -25
- package/dist/link-set-KMUBFN2L.js +0 -29
- package/dist/noydb-QDZ4QIKO.js +0 -100
- package/dist/register-PIORIMMR.js +0 -30
- package/dist/registry-BIMICFUH.js +0 -23
- package/dist/registry-JGWLW53D.js +0 -35
- package/dist/registry-SELCBYEQ.js +0 -8
- package/dist/registry-W327UNYH.js +0 -8
- package/dist/request-withdrawal-K3SXXODI.js +0 -28
- package/dist/reveal-UAPBG743.js.map +0 -1
- package/dist/revoke-6AFVXTWF.js +0 -24
- package/dist/signer-TW5MAQJP.js +0 -23
- package/dist/storage-SO2L2Z5J.js +0 -21
- package/dist/vault-diff-C6WUJFNP.js +0 -8
- package/dist/verify-QWO5UKD6.js.map +0 -1
- package/dist/walk-3KEOL7BY.js +0 -20
- package/dist/withdraw-accessible-OZU525ND.js +0 -25
- package/dist/withdraw-accessible-OZU525ND.js.map +0 -1
- /package/dist/{api-H4B7ZQXP.js.map → api-QSEKT4KS.js.map} +0 -0
- /package/dist/{capsule-YQKQZPH7.js.map → capsule-YAITMH77.js.map} +0 -0
- /package/dist/{chunk-PREYKC76.js.map → chunk-24AGG4PP.js.map} +0 -0
- /package/dist/{chunk-ZNVBCKMV.js.map → chunk-2SIREKBR.js.map} +0 -0
- /package/dist/{chunk-UQRKAM2R.js.map → chunk-3M2KK7O7.js.map} +0 -0
- /package/dist/{chunk-P6FATPXQ.js.map → chunk-3ZCVY3T6.js.map} +0 -0
- /package/dist/{chunk-PBEHTFUG.js.map → chunk-4CGWLHPQ.js.map} +0 -0
- /package/dist/{chunk-PFHDQY5L.js.map → chunk-56Z4NOC6.js.map} +0 -0
- /package/dist/{chunk-F7X7MPK4.js.map → chunk-5BGHAVBN.js.map} +0 -0
- /package/dist/{chunk-QHG7GQKM.js.map → chunk-5JNEDW7I.js.map} +0 -0
- /package/dist/{chunk-DYIR6RC3.js.map → chunk-5Y4MO7UQ.js.map} +0 -0
- /package/dist/{chunk-TLIFNRU5.js.map → chunk-63LZLRWG.js.map} +0 -0
- /package/dist/{chunk-GZISWBCJ.js.map → chunk-74W56QPY.js.map} +0 -0
- /package/dist/{chunk-WVQDY3UM.js.map → chunk-AHA7UALU.js.map} +0 -0
- /package/dist/{chunk-S2ORTQGS.js.map → chunk-ANYX2M6P.js.map} +0 -0
- /package/dist/{chunk-6WEPFEMJ.js.map → chunk-ATKYMRBC.js.map} +0 -0
- /package/dist/{chunk-7UHLO4ZN.js.map → chunk-B2HU55QD.js.map} +0 -0
- /package/dist/{chunk-Y22JWHCP.js.map → chunk-BEKMLYQ4.js.map} +0 -0
- /package/dist/{chunk-7C7OF26T.js.map → chunk-C2NXAR3D.js.map} +0 -0
- /package/dist/{chunk-6WIFF46H.js.map → chunk-CQLMRCKX.js.map} +0 -0
- /package/dist/{chunk-LMC5L3MM.js.map → chunk-DS2JXSUA.js.map} +0 -0
- /package/dist/{chunk-X6Z2SIRF.js.map → chunk-E2JIE4S3.js.map} +0 -0
- /package/dist/{chunk-EQ6C2ZPT.js.map → chunk-E7Y4J4GL.js.map} +0 -0
- /package/dist/{chunk-LZN6DTFI.js.map → chunk-ECDM6YRX.js.map} +0 -0
- /package/dist/{chunk-2T2TGRWE.js.map → chunk-EM56MHN5.js.map} +0 -0
- /package/dist/{chunk-NK4LGBGQ.js.map → chunk-EQXOJH6O.js.map} +0 -0
- /package/dist/{chunk-OK44MD3C.js.map → chunk-ET3U2C3A.js.map} +0 -0
- /package/dist/{chunk-RF5WDM25.js.map → chunk-EU4G7PQH.js.map} +0 -0
- /package/dist/{chunk-K5JNK63R.js.map → chunk-EUCUYK5E.js.map} +0 -0
- /package/dist/{chunk-2ODEFG6K.js.map → chunk-EWSIJDWO.js.map} +0 -0
- /package/dist/{chunk-LJ744WXU.js.map → chunk-F2FD4LSB.js.map} +0 -0
- /package/dist/{chunk-L4UL4IAR.js.map → chunk-F7ENMZYJ.js.map} +0 -0
- /package/dist/{chunk-KBIS64X4.js.map → chunk-FIIVYQOW.js.map} +0 -0
- /package/dist/{chunk-BQJ5ORU5.js.map → chunk-FQEUJGBV.js.map} +0 -0
- /package/dist/{chunk-UORWAG7K.js.map → chunk-FY4FFNKK.js.map} +0 -0
- /package/dist/{chunk-MMWX5OT5.js.map → chunk-GDCYZGPB.js.map} +0 -0
- /package/dist/{chunk-7ONMS7QI.js.map → chunk-H6Q7GKLI.js.map} +0 -0
- /package/dist/{chunk-654RE5YC.js.map → chunk-HDAPQF6Q.js.map} +0 -0
- /package/dist/{chunk-5SMCBPJ2.js.map → chunk-HRLMUZLI.js.map} +0 -0
- /package/dist/{chunk-R4GLRJ55.js.map → chunk-HRNQYGLQ.js.map} +0 -0
- /package/dist/{chunk-NHEKQWFI.js.map → chunk-J4L4AS2W.js.map} +0 -0
- /package/dist/{chunk-UMV5GBTJ.js.map → chunk-JPSOFWJR.js.map} +0 -0
- /package/dist/{chunk-A52BK5AY.js.map → chunk-JRCO67NG.js.map} +0 -0
- /package/dist/{chunk-FVKQ5QUC.js.map → chunk-JW3I3NNZ.js.map} +0 -0
- /package/dist/{chunk-BNYDOF2Q.js.map → chunk-JZMPSQBH.js.map} +0 -0
- /package/dist/{chunk-ZK2WT532.js.map → chunk-K5TVSOPQ.js.map} +0 -0
- /package/dist/{chunk-2IASHJPS.js.map → chunk-K75SL74I.js.map} +0 -0
- /package/dist/{chunk-O3NGOHXQ.js.map → chunk-KA4AAUST.js.map} +0 -0
- /package/dist/{chunk-QQLXKDGC.js.map → chunk-KUGUML7H.js.map} +0 -0
- /package/dist/{chunk-AMSSAOOB.js.map → chunk-L4J5NC2Q.js.map} +0 -0
- /package/dist/{chunk-AYOQZJDB.js.map → chunk-LIX4QPMM.js.map} +0 -0
- /package/dist/{chunk-WIUH6EJ7.js.map → chunk-LWQFGR34.js.map} +0 -0
- /package/dist/{chunk-QNOWNCZS.js.map → chunk-MMSSHMHW.js.map} +0 -0
- /package/dist/{chunk-ND6S2DKC.js.map → chunk-N5S2BCW3.js.map} +0 -0
- /package/dist/{chunk-X5RGG3ZW.js.map → chunk-NIZH2TYZ.js.map} +0 -0
- /package/dist/{chunk-SXPLIRQH.js.map → chunk-NLDBQHDV.js.map} +0 -0
- /package/dist/{chunk-AI35LNWQ.js.map → chunk-NQQ4MOPC.js.map} +0 -0
- /package/dist/{chunk-B6EWMGFX.js.map → chunk-NUBI6PYH.js.map} +0 -0
- /package/dist/{chunk-ID4ZBC3X.js.map → chunk-NYEXUZDW.js.map} +0 -0
- /package/dist/{chunk-PWAMX5KU.js.map → chunk-OOLF5FU2.js.map} +0 -0
- /package/dist/{chunk-WQUIJPN4.js.map → chunk-OQA7UF2Q.js.map} +0 -0
- /package/dist/{chunk-7JRLCP2J.js.map → chunk-ORJPICJI.js.map} +0 -0
- /package/dist/{chunk-IF2M43G4.js.map → chunk-PBRD75JF.js.map} +0 -0
- /package/dist/{chunk-BSEPI3HD.js.map → chunk-PR36DD2X.js.map} +0 -0
- /package/dist/{chunk-52ZFNK46.js.map → chunk-PV4HIC4E.js.map} +0 -0
- /package/dist/{chunk-TU6ZJTYT.js.map → chunk-PZNK4HTV.js.map} +0 -0
- /package/dist/{chunk-LUQBG637.js.map → chunk-QBLPLNPE.js.map} +0 -0
- /package/dist/{chunk-UADW5NOU.js.map → chunk-QZXUISRF.js.map} +0 -0
- /package/dist/{chunk-BMAXBTYH.js.map → chunk-RBXYO7MD.js.map} +0 -0
- /package/dist/{chunk-PZN76MMV.js.map → chunk-RIACRFWA.js.map} +0 -0
- /package/dist/{chunk-ICHHNI5E.js.map → chunk-RL6RNDJQ.js.map} +0 -0
- /package/dist/{chunk-4WLI37WK.js.map → chunk-SJ2P7UXD.js.map} +0 -0
- /package/dist/{chunk-2QH3I7QC.js.map → chunk-SWXS4LV3.js.map} +0 -0
- /package/dist/{chunk-4KYKRYRT.js.map → chunk-TOTCZFRF.js.map} +0 -0
- /package/dist/{chunk-CSAN22QG.js.map → chunk-TT4D52EK.js.map} +0 -0
- /package/dist/{chunk-VLRY2UH4.js.map → chunk-U7CMJY5P.js.map} +0 -0
- /package/dist/{chunk-PU5ZEV65.js.map → chunk-UZVHSYIF.js.map} +0 -0
- /package/dist/{chunk-XQGKS4OW.js.map → chunk-VKZ3TDET.js.map} +0 -0
- /package/dist/{chunk-ZOFNZLAA.js.map → chunk-VLZPUG5A.js.map} +0 -0
- /package/dist/{chunk-OR3OHKU6.js.map → chunk-VSN5FLMI.js.map} +0 -0
- /package/dist/{chunk-SVXFCCSX.js.map → chunk-WHK4JVKF.js.map} +0 -0
- /package/dist/{chunk-YVA6UPRN.js.map → chunk-X4LDBALX.js.map} +0 -0
- /package/dist/{chunk-35CNOVQE.js.map → chunk-X67E7NIJ.js.map} +0 -0
- /package/dist/{chunk-IPF5ORDI.js.map → chunk-XMARKBUC.js.map} +0 -0
- /package/dist/{chunk-B3B6HV5S.js.map → chunk-XMBBTETD.js.map} +0 -0
- /package/dist/{chunk-FUHUGKDN.js.map → chunk-XROQP6IQ.js.map} +0 -0
- /package/dist/{chunk-DL4GCSTS.js.map → chunk-Y2RYUWSQ.js.map} +0 -0
- /package/dist/{chunk-7IV7GVOS.js.map → chunk-YCTSQV7K.js.map} +0 -0
- /package/dist/{chunk-IFUYLIEY.js.map → chunk-YF7P2DG7.js.map} +0 -0
- /package/dist/{chunk-PIO6NW7O.js.map → chunk-ZG7DBIVX.js.map} +0 -0
- /package/dist/{chunk-NUZ7ROUZ.js.map → chunk-ZGJ775X7.js.map} +0 -0
- /package/dist/{chunk-6BEBWHNL.js.map → chunk-ZQQLOEWN.js.map} +0 -0
- /package/dist/{classified-marker-7HXDMYHI.js.map → classified-marker-HKMRC7SC.js.map} +0 -0
- /package/dist/{collection-facade-V63BEBGU.js.map → collection-facade-PPKNUR2J.js.map} +0 -0
- /package/dist/{computed-LZLSYOPG.js.map → computed-UCYVPMZA.js.map} +0 -0
- /package/dist/{delegation-7SSGIETH.js.map → delegation-SNALWRMO.js.map} +0 -0
- /package/dist/{derive-IMI3BMDS.js.map → derive-4GNU4E4I.js.map} +0 -0
- /package/dist/{dispatch-KOPDDPEQ.js.map → dispatch-V5WLDTVX.js.map} +0 -0
- /package/dist/{executor-7SY3M6TZ.js.map → executor-7QN22OKI.js.map} +0 -0
- /package/dist/{executor-SNHW4ELF.js.map → executor-BJZJNVBB.js.map} +0 -0
- /package/dist/{executor-Z3IKK7G3.js.map → executor-JEAAEJUM.js.map} +0 -0
- /package/dist/{export-accessible-O7DIVFUO.js.map → export-accessible-TVO2KQPG.js.map} +0 -0
- /package/dist/{extract-partition-ELZEJKXM.js.map → extract-partition-43CLDRN4.js.map} +0 -0
- /package/dist/{find-KWB2RYWJ.js.map → issue-EIHEDAXM.js.map} +0 -0
- /package/dist/{issue-5ZHXK4HJ.js.map → ledger-BMVUFQ3R.js.map} +0 -0
- /package/dist/{ledger-UFJCB6T5.js.map → liberate-7KHXCLNJ.js.map} +0 -0
- /package/dist/{liberate-OEOSNNFH.js.map → link-set-PC2EJRKL.js.map} +0 -0
- /package/dist/{link-set-KMUBFN2L.js.map → managed-secret-RPRVEYZA.js.map} +0 -0
- /package/dist/{migrate-cek-SPESQAAO.js.map → migrate-cek-DTSCWGEF.js.map} +0 -0
- /package/dist/{managed-secret-H5WYSJ46.js.map → noydb-AYDNOXAX.js.map} +0 -0
- /package/dist/{post-register-2AC2STHC.js.map → post-register-RITSNASO.js.map} +0 -0
- /package/dist/{noydb-QDZ4QIKO.js.map → register-BB34SK7E.js.map} +0 -0
- /package/dist/{register-PIORIMMR.js.map → registry-65L6V5TO.js.map} +0 -0
- /package/dist/{registry-BIMICFUH.js.map → registry-HU62GPWA.js.map} +0 -0
- /package/dist/{registry-JGWLW53D.js.map → registry-SMNK6UM4.js.map} +0 -0
- /package/dist/{registry-SELCBYEQ.js.map → registry-X5VPBKCO.js.map} +0 -0
- /package/dist/{registry-W327UNYH.js.map → request-withdrawal-4SKAH46W.js.map} +0 -0
- /package/dist/{request-withdrawal-K3SXXODI.js.map → revoke-IF5PX2JY.js.map} +0 -0
- /package/dist/{revoke-6AFVXTWF.js.map → signer-5P7IZC2K.js.map} +0 -0
- /package/dist/{signer-TW5MAQJP.js.map → stale-PUCZH5GJ.js.map} +0 -0
- /package/dist/{stale-CROGJBIJ.js.map → storage-5EGY5OYE.js.map} +0 -0
- /package/dist/{storage-SO2L2Z5J.js.map → vault-diff-H7LT5ZBJ.js.map} +0 -0
- /package/dist/{vault-diff-C6WUJFNP.js.map → walk-Z4N7PCZ2.js.map} +0 -0
- /package/dist/{walk-3KEOL7BY.js.map → withdraw-accessible-CRCIQSTL.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/capsule/enclave-aes/classify/compare.ts","../src/capsule/enclave-aes/crypto.ts","../src/capsule/enclave-aes/classify/vdig.ts","../src/capsule/enclave-aes/classify/write.ts","../src/capsule/enclave-aes/primitives.ts","../src/capsule/enclave-aes/bound.ts"],"sourcesContent":["/**\n * C2 — fixed-length-tag constant-time comparison (hub-portable; no\n * Node timingSafeEqual). Two mandatory rules (spec §3):\n * 1. Only fixed 32-byte tags are ever compared — ctEqualTags throws on\n * anything else (tag length is structural, never secret-dependent).\n * 2. Every comparand is reduced to a 32-byte tag under a FRESH ephemeral\n * HMAC-SHA256 key before comparison — keyed blinding makes compare\n * timing uncorrelated with underlying values; rule 1 (not blinding)\n * is what removes input-length timing. Length inequality folds into\n * unequal tags — never an early return.\n * @module\n */\n\nimport { ctEqualTags } from '../../plumbing/ct-equal.js'\nconst subtle = globalThis.crypto.subtle\n\n\n/**\n * Blinded equality of arbitrary-length byte strings: fresh K_e per\n * comparison (never stored, never reused), HMAC both sides to 32-byte\n * tags, then ctEqualTags. On the digest path the inputs are already\n * 32-byte PBKDF2 outputs but still route through this reduction so\n * there is exactly ONE comparison construction (spec §3 rule 2).\n */\nexport async function blindedEqual(a: Uint8Array, b: Uint8Array): Promise<boolean> {\n const ke = await subtle.generateKey({ name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])\n const tagA = new Uint8Array(await subtle.sign('HMAC', ke, a as BufferSource))\n const tagB = new Uint8Array(await subtle.sign('HMAC', ke, b as BufferSource))\n return ctEqualTags(tagA, tagB)\n}\n","/**\n * Cryptographic primitives — thin wrappers around the Web Crypto API.\n *\n * ## Design principle\n *\n * **Zero npm crypto dependencies.** Every operation uses `globalThis.crypto.subtle`,\n * which is available natively in Node.js ≥ 18, all modern browsers, and\n * Deno/Bun. This avoids supply-chain risk from third-party crypto packages and\n * ensures the library stays auditable.\n *\n * ## Algorithms\n *\n * | Use case | Algorithm | Parameters |\n * |----------|-----------|------------|\n * | Key derivation | PBKDF2-SHA256 | 600,000 iterations, 32-byte salt |\n * | Record encryption | AES-256-GCM | 12-byte random IV per operation |\n * | DEK wrapping | AES-KW (RFC 3394) | 256-bit KEK |\n * | Binary encrypt | AES-256-GCM | same as record encryption |\n * | Integrity | HMAC-SHA256 | for presence channels |\n * | Content hash | SHA-256 | for ledger and bundle integrity |\n *\n * ## Key lifecycle\n *\n * ```\n * secret + salt\n * └─► deriveKey() → KEK (CryptoKey, extractable: false)\n * └─► wrapKey() → wrapped DEK bytes [stored in keyring]\n * └─► unwrapKey() → DEK (CryptoKey) [memory only during session]\n * └─► encrypt() / decrypt() → ciphertext / plaintext\n * ```\n *\n * IVs are generated fresh by {@link generateIV} on every encrypt call.\n * Reusing an IV with the same key would break GCM's authentication guarantee —\n * this function should be the only place IVs are produced.\n *\n * @module\n */\n\nimport { DecryptionError, InvalidKeyError, TamperedError, ValidationError } from '../../kernel/errors.js'\nimport {\n KEY_BITS,\n IV_BYTES,\n bufferToBase64,\n base64ToBuffer,\n generateIV,\n encodeEchoParts,\n type EchoSecretParts,\n} from '../plumbing/digest.js'\n\n/**\n * **EnclaveKey** — the opaque key type at the enclave seam.\n *\n * In noy-db's reference enclave this is `CryptoKey` (the Web Crypto API's\n * key handle). A fork's enclave redefines this alias to its own key\n * representation (e.g. `type EnclaveKey = null` for a keyless HSM-backed\n * fork) — outside `capsule/enclave-aes/**`, every consumer must treat it as\n * opaque: never construct, inspect, or serialize it directly, only pass it\n * between barrel functions (`encrypt`/`decrypt`/`wrapKey`/`unwrapKey`/…).\n */\nexport type EnclaveKey = CryptoKey\n\n/** Opaque asymmetric pair at the enclave seam — `CryptoKeyPair` in the reference enclave. */\nexport type EnclaveKeyPair = CryptoKeyPair\n\nconst PBKDF2_ITERATIONS = 600_000\n\nconst subtle = globalThis.crypto.subtle\n\n// ─── Key Derivation ────────────────────────────────────────────────────\n\n/** Derive a KEK from a secret and salt using PBKDF2-SHA256. */\nexport async function deriveKey(\n secret: string,\n salt: Uint8Array,\n): Promise<CryptoKey> {\n return deriveKekFromMaterial(new TextEncoder().encode(secret), salt)\n}\n\n/**\n * Shared PBKDF2 → AES-KW derivation core. `material` is the raw\n * pre-KDF input bytes (a UTF-8 phrase for standard mode, an\n * AG-1-encoded 3-part structure for echo mode).\n */\nasync function deriveKekFromMaterial(\n material: Uint8Array,\n salt: Uint8Array,\n): Promise<CryptoKey> {\n const keyMaterial = await subtle.importKey('raw', material as BufferSource, 'PBKDF2', false, ['deriveKey'])\n return subtle.deriveKey(\n { name: 'PBKDF2', salt: salt as BufferSource, iterations: PBKDF2_ITERATIONS, hash: 'SHA-256' },\n keyMaterial,\n { name: 'AES-KW', length: KEY_BITS },\n false,\n ['wrapKey', 'unwrapKey'],\n )\n}\n\n/** One three-part echo secret: prompt (typed) → echo (revealed) → key (typed). */\n\n/**\n * Domain context for the AG-1 encoding. The leading `0xFF` is the load-bearing\n * byte: it is not a legal UTF-8 lead byte, so `TextEncoder` can never emit it —\n * no string's UTF-8 encoding can equal an AG-1 encoding, whatever the string.\n */\n\nexport async function deriveEchoKey(\n parts: EchoSecretParts,\n salt: Uint8Array,\n): Promise<CryptoKey> {\n return deriveKekFromMaterial(encodeEchoParts(parts), salt)\n}\n\n/**\n * Which AES algorithm/usage a {@link deriveSecretKey} result is for:\n * `'aes-kw'` mints a key-wrapping key (`wrapKey`/`unwrapKey`, e.g. for\n * KEK derivation); `'aes-gcm'` mints a direct encrypt/decrypt key (e.g.\n * for the wrap-DEKs primitive in `with-party/team/wrapped-deks.ts`).\n */\nexport type SecretKeyUsage = 'aes-kw' | 'aes-gcm'\n\n/**\n * Derive a non-extractable AES key from a secret/credential and salt\n * via PBKDF2-SHA256, generalizing {@link deriveKey}'s AES-KW derivation to\n * also cover AES-GCM-usage keys. Callers pin their own `iterations` and\n * `keyUsage` so an existing call site's exact parameters (and thus its\n * derived-key bytes) are preserved verbatim when migrated onto this\n * shared primitive — this is call-site consolidation, not a KDF change.\n */\nexport async function deriveSecretKey(\n secret: string,\n salt: Uint8Array,\n params: { iterations: number; keyUsage: SecretKeyUsage },\n): Promise<CryptoKey> {\n const keyMaterial = await subtle.importKey(\n 'raw',\n new TextEncoder().encode(secret),\n 'PBKDF2',\n false,\n ['deriveKey'],\n )\n\n return params.keyUsage === 'aes-gcm'\n ? subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt as BufferSource,\n iterations: params.iterations,\n hash: 'SHA-256',\n },\n keyMaterial,\n { name: 'AES-GCM', length: KEY_BITS },\n false,\n ['encrypt', 'decrypt'],\n )\n : subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt as BufferSource,\n iterations: params.iterations,\n hash: 'SHA-256',\n },\n keyMaterial,\n { name: 'AES-KW', length: KEY_BITS },\n false,\n ['wrapKey', 'unwrapKey'],\n )\n}\n\n// ─── DEK Generation ────────────────────────────────────────────────────\n\n/** Generate a random AES-256-GCM data encryption key. */\nexport async function generateDEK(): Promise<CryptoKey> {\n return subtle.generateKey(\n { name: 'AES-GCM', length: KEY_BITS },\n true, // extractable — needed for AES-KW wrapping\n ['encrypt', 'decrypt'],\n )\n}\n\n/**\n * Generate a NON-extractable AES-256-GCM key for in-memory-only use — a\n * session key, a device seal. Unlike {@link generateDEK} it can never be\n * wrapped or exported: WebCrypto enforces that, and it is the tab-scope\n * invariant `with-party/session` and `device-seal` rely on.\n */\nexport async function generateEphemeralKey(): Promise<CryptoKey> {\n return subtle.generateKey({ name: 'AES-GCM', length: KEY_BITS }, false, ['encrypt', 'decrypt'])\n}\n\n// ─── DEK-Set Codec ─────────────────────────────────────────────────────\n//\n// The portable form of a DEK set — `{ collection: base64(rawKey) }` — is the\n// plaintext body of every persisted WrappedDeksBlob (recovery-paper,\n// recovery-shamir, tier-2 password slots). It is an enclave door because it\n// is the one place a key's REPRESENTATION crosses into bytes: a fork with its\n// own EnclaveKey (hardware-backed, post-quantum, no encryption) decides here\n// what \"the bytes of a key\" means, and nothing outside capsule/enclave-aes has to\n// know. Byte-for-byte what wrapped-deks.ts did inline before #1317.\n\n/** Serialize a DEK set to `{ collection: base64(rawKey) }`. */\nexport async function exportDekSet(deks: Map<string, CryptoKey>): Promise<Record<string, string>> {\n const out: Record<string, string> = {}\n for (const [coll, dek] of deks) {\n out[coll] = bufferToBase64(await subtle.exportKey('raw', dek))\n }\n return out\n}\n\n/**\n * Reverse of {@link exportDekSet}. Keys come back extractable AES-GCM\n * (`encrypt`/`decrypt`), matching what `generateDEK` mints.\n */\nexport async function importDekSet(exported: Record<string, string>): Promise<Map<string, CryptoKey>> {\n const deks = new Map<string, CryptoKey>()\n for (const [coll, b64] of Object.entries(exported)) {\n const key = await subtle.importKey(\n 'raw',\n base64ToBuffer(b64) as BufferSource,\n { name: 'AES-GCM', length: KEY_BITS },\n true,\n ['encrypt', 'decrypt'],\n )\n deks.set(coll, key)\n }\n return deks\n}\n\n// ─── Key Wrapping ──────────────────────────────────────────────────────\n\n/** Wrap (encrypt) a DEK with a KEK using AES-KW. Returns base64 string. */\nexport async function wrapKey(dek: CryptoKey, kek: CryptoKey): Promise<string> {\n const wrapped = await subtle.wrapKey('raw', dek, kek, 'AES-KW')\n return bufferToBase64(wrapped)\n}\n\n/** Unwrap (decrypt) a DEK from base64 string using a KEK. */\nexport async function unwrapKey(\n wrappedBase64: string,\n kek: CryptoKey,\n): Promise<CryptoKey> {\n try {\n return await subtle.unwrapKey(\n 'raw',\n base64ToBuffer(wrappedBase64) as BufferSource,\n kek,\n 'AES-KW',\n { name: 'AES-GCM', length: KEY_BITS },\n true,\n ['encrypt', 'decrypt'],\n )\n } catch {\n throw new InvalidKeyError()\n }\n}\n\n// ─── Canary ────────────────────────────────────────────────────────────\n//\n// \"Is this KEK the right one?\" is answered by wrapping a CONSTANT key under\n// it and seeing whether the wrap opens later. AES-KW is deterministic\n// (RFC 3394 fixed IV), so the same constant under the same KEK always yields\n// the same bytes — every write site can re-mint on persist. The keyring\n// canary (32 zero bytes) and the echo prompt/echo verifiers (32 × 0x5a) are\n// both this primitive with a different constant.\n\n/** Wrap the constant AES-GCM key built from `plaintext` under `kek`. */\nexport async function mintCanary(kek: CryptoKey, plaintext: Uint8Array): Promise<string> {\n const constant = await subtle.importKey(\n 'raw', plaintext as BufferSource, { name: 'AES-GCM', length: KEY_BITS }, true, ['encrypt', 'decrypt'],\n )\n return wrapKey(constant, kek)\n}\n\n/** True iff `wrapped` unwraps under `kek` — the KEK is right AND the bytes are intact. */\nexport async function checkCanary(wrapped: string, kek: CryptoKey): Promise<boolean> {\n try {\n await unwrapKey(wrapped, kek)\n return true\n } catch {\n return false\n }\n}\n\n// ─── Per-record CEK wrapping ───────────────────────────────────────────\n\n/**\n * Derive a **dedicated** AES-KW wrapping key from a collection/tier DEK via\n * HKDF-SHA256, used to wrap/unwrap a per-record CEK.\n *\n * The collection/tier DEKs are AES-256-**GCM** keys (usages\n * `encrypt`/`decrypt`) and cannot themselves act as an AES-KW KEK. We do NOT\n * re-import the raw DEK bytes directly as an AES-KW key — that would reuse one\n * key across two primitives (AES-GCM for `_det`/presence, AES-KW for CEK\n * wrapping), violating key separation. Instead we HKDF-derive a domain-\n * separated KW key (salt `noydb-cek-wrap`), exactly as `derivePresenceKey`\n * derives a separate presence key. The derivation is deterministic, so\n * wrapping the same CEK under the same DEK always yields identical ciphertext\n * — which is what lets an update reuse a record's stable CEK and produce a\n * byte-identical `_cek`. The KW key is independent of the DEK's GCM key.\n *\n * The DEK must be extractable (it is — `generateDEK`/`unwrapKey` mint\n * extractable keys).\n */\nasync function asKwKey(dek: CryptoKey): Promise<CryptoKey> {\n const rawDek = await subtle.exportKey('raw', dek)\n const hkdfKey = await subtle.importKey('raw', rawDek, 'HKDF', false, ['deriveBits'])\n const salt = new TextEncoder().encode('noydb-cek-wrap')\n const info = new TextEncoder().encode('v1')\n const bits = await subtle.deriveBits(\n { name: 'HKDF', hash: 'SHA-256', salt, info },\n hkdfKey,\n KEY_BITS,\n )\n return subtle.importKey('raw', bits, 'AES-KW', false, ['wrapKey', 'unwrapKey'])\n}\n\n/**\n * AES-KW-wrap a per-record CEK under a collection/tier DEK. Returns base64.\n * Deterministic over `(cek, dek)`.\n */\nexport async function wrapCek(cek: CryptoKey, dek: CryptoKey): Promise<string> {\n const kw = await asKwKey(dek)\n const wrapped = await subtle.wrapKey('raw', cek, kw, 'AES-KW')\n return bufferToBase64(wrapped)\n}\n\n/**\n * Unwrap a per-record CEK from base64 under a collection/tier DEK. Throws\n * `InvalidKeyError` if the wrapped bytes do not authenticate under the DEK.\n */\nexport async function unwrapCek(wrappedBase64: string, dek: CryptoKey): Promise<CryptoKey> {\n const kw = await asKwKey(dek)\n try {\n return await subtle.unwrapKey(\n 'raw',\n base64ToBuffer(wrappedBase64) as BufferSource,\n kw,\n 'AES-KW',\n { name: 'AES-GCM', length: KEY_BITS },\n true,\n ['encrypt', 'decrypt'],\n )\n } catch {\n throw new InvalidKeyError()\n }\n}\n\n/**\n * Import a raw 32-byte AES-256-GCM record CEK (e.g. from a sealed-CEK\n * delivery binding). Non-extractable, decrypt-only — the imported key is\n * used solely to open the record's `_iv`/`_data` body under `decrypt()`.\n */\nexport async function importCek(rawKey: Uint8Array): Promise<CryptoKey> {\n return subtle.importKey('raw', rawKey as BufferSource, { name: 'AES-GCM', length: KEY_BITS }, false, ['decrypt'])\n}\n\n/**\n * Import a raw 32-byte pre-shared key as a NON-extractable AES-256-GCM key\n * (encrypt + decrypt). The transfer seal (`with-cargo`) and the RSA-OAEP\n * TLV's per-blob CEK (`managed-secret`) both hand raw bytes to the enclave\n * here; the bytes never become a key anywhere else.\n */\nexport async function importTransferKey(raw: Uint8Array): Promise<CryptoKey> {\n if (raw.byteLength !== 32) {\n throw new ValidationError(`transfer key must be 32 bytes, got ${raw.byteLength}.`)\n }\n return subtle.importKey('raw', raw as BufferSource, { name: 'AES-GCM', length: KEY_BITS }, false, ['encrypt', 'decrypt'])\n}\n\n/**\n * core#65 — import raw 32 bytes as a NON-extractable AES-KW key (wrap +\n * unwrap). The per-delegation CONTENT KEY: a delegation's tier DEKs are\n * AES-KW-wrapped under it exactly as they are under a KEK, and the key itself\n * travels RSA-OAEP-sealed to the target's inbox public half — so the token's\n * slot NAMES stay readable to any vault member for audit while its keys open\n * for the target alone. Distinct from {@link importTransferKey}, which imports\n * an AES-GCM key for body encryption and cannot wrap.\n */\nexport async function importWrappingKey(raw: Uint8Array): Promise<CryptoKey> {\n if (raw.byteLength !== 32) {\n throw new ValidationError(`wrapping key must be 32 bytes, got ${raw.byteLength}.`)\n }\n return subtle.importKey('raw', raw as BufferSource, { name: 'AES-KW', length: KEY_BITS }, false, ['wrapKey', 'unwrapKey'])\n}\n\n// ─── Encrypt / Decrypt ─────────────────────────────────────────────────\n\nexport interface EncryptResult {\n iv: string // base64\n data: string // base64\n}\n\n/**\n * Encrypt plaintext JSON string with AES-256-GCM. Fresh IV per call.\n *\n * `aad` binds the record's identity into the auth tag (#1041) — see\n * `record-aad.ts` for what is bound and why `_v` is not. A body sealed with\n * AAD can only be opened by a reader supplying the identical bytes, which is\n * what stops an untrusted store from relocating or re-tiering an envelope.\n *\n * Optional **only while the call-site sweep is in progress**. It becomes\n * mandatory once every `encrypt`/`decrypt` pair supplies it, at which point\n * the format version bumps and the reader rejects anything unbound. Until\n * then an omitted `aad` reproduces the previous, unauthenticated behaviour.\n */\nexport async function encrypt(\n plaintext: string,\n dek: CryptoKey,\n aad?: Uint8Array,\n): Promise<EncryptResult> {\n const iv = generateIV()\n const encoded = new TextEncoder().encode(plaintext)\n\n const ciphertext = await subtle.encrypt(\n {\n name: 'AES-GCM',\n iv: iv as BufferSource,\n ...(aad !== undefined && { additionalData: aad as BufferSource }),\n },\n dek,\n encoded,\n )\n\n return {\n iv: bufferToBase64(iv),\n data: bufferToBase64(ciphertext),\n }\n}\n\n/**\n * Decrypt AES-256-GCM ciphertext. Throws on wrong key or tampered data.\n *\n * `aad` must be byte-identical to what {@link encrypt} was given, or the auth\n * tag fails and this throws `TamperedError` (#1041). Note the asymmetry that\n * makes this useful: a mismatched identity is indistinguishable from a\n * corrupted body, so relocation fails **closed** rather than returning a\n * plausible record in the wrong place.\n */\nexport async function decrypt(\n ivBase64: string,\n dataBase64: string,\n dek: CryptoKey,\n aad?: Uint8Array,\n): Promise<string> {\n // A body that is not even base64 (`atob` throws a DOMException) is a corrupted\n // envelope, and must read as one: the same named error a wrong key produces,\n // never the raw WebCrypto/`atob` exception (measured by a consumer, core#67).\n let iv: Uint8Array\n let ciphertext: Uint8Array\n try {\n iv = base64ToBuffer(ivBase64)\n ciphertext = base64ToBuffer(dataBase64)\n } catch (err) {\n throw new DecryptionError(`envelope body is not valid base64: ${err instanceof Error ? err.message : String(err)}`)\n }\n\n try {\n const plaintext = await subtle.decrypt(\n {\n name: 'AES-GCM',\n iv: iv as BufferSource,\n ...(aad !== undefined && { additionalData: aad as BufferSource }),\n },\n dek,\n ciphertext as BufferSource,\n )\n return new TextDecoder().decode(plaintext)\n } catch (err) {\n if (err instanceof Error && err.name === 'OperationError') {\n throw new TamperedError(...(await classifyTagFailure(iv, ciphertext, dek, aad)))\n }\n throw new DecryptionError(\n err instanceof Error ? err.message : 'Decryption failed',\n )\n }\n}\n\n\n/**\n * Distinguish a FORMAT TRANSITION from an attack, when the enclave can (#1103).\n *\n * ## The problem\n *\n * Since #1041 switched identity AAD on, one `TamperedError` covers at least\n * four situations: legitimate pre-binding data, a store that reconstructs an\n * envelope and drops a bound field, a CEK/rotation mismatch, and actual\n * tampering. `SECURITY.md` and the subsystem docs teach the LAST reading — so a\n * user who upgrades, hits this on their own honest data, and consults the docs\n * is told their store has been compromised.\n *\n * That is a false positive on the product's central security claim, and the\n * cost is not merely a confusing message: **a tamper alarm that cries wolf is\n * one users learn to ignore.**\n *\n * ## Why the probe is sound, and why it is NOT a downgrade\n *\n * A body sealed before #1041 carries no AAD, so it opens under an empty one.\n * Retrying that way is **positive evidence** of the legacy format rather than a\n * guess: forging a body that decrypts under this DEK requires the DEK, and an\n * untrusted store does not hold one.\n *\n * ⚠️ **Classification ONLY — the plaintext is discarded and the caller still\n * throws.** That is the entire safety argument: the outcome is identical either\n * way, so this cannot become the lenient path #1041 exists to remove. A variant\n * that RETURNED the retry's plaintext would be exactly the accept-without-AAD\n * downgrade the binding was built to prevent. Do not \"optimise\" it into one.\n *\n * Note what the honest message concedes: pre-#1041 data had no authenticated\n * metadata, so a legacy record that was ALSO tampered with reads as legacy.\n * That is not a weakening — it is an accurate statement about data that\n * genuinely never carried a binding.\n */\nasync function classifyTagFailure(\n iv: Uint8Array,\n ciphertext: Uint8Array,\n dek: CryptoKey,\n aad: Uint8Array | undefined,\n): Promise<[] | [string, 'unbound-legacy-format']> {\n // Only meaningful when AAD was supplied: with none there is no second\n // interpretation to test, and the failure is a plain tag mismatch.\n if (aad === undefined) return []\n try {\n await subtle.decrypt({ name: 'AES-GCM', iv: iv as BufferSource }, dek, ciphertext as BufferSource)\n } catch {\n return [] // no benign explanation — the security alert stands\n }\n return [\n 'This record was sealed BEFORE record-identity binding (#1041) and cannot be read by this ' +\n 'version. Its body decrypts correctly under the record key, so this is a data-format ' +\n 'transition, not tampering — but it also means the record predates authenticated metadata. ' +\n 'There is no migration path; see noy-db #1100.',\n 'unbound-legacy-format',\n ]\n}\n\n// ─── Binary Encrypt / Decrypt ────────\n\n/**\n * Encrypt raw bytes with AES-256-GCM using a fresh random IV.\n * Used by the attachment store so binary blobs avoid double base64 encoding\n * (the existing `encrypt()` function calls `TextEncoder` on a string — here\n * we pass the `Uint8Array` directly to `subtle.encrypt`).\n */\nexport async function encryptBytes(\n data: Uint8Array,\n dek: CryptoKey,\n): Promise<EncryptResult> {\n const iv = generateIV()\n const ciphertext = await subtle.encrypt(\n { name: 'AES-GCM', iv: iv as BufferSource },\n dek,\n data as unknown as BufferSource,\n )\n return {\n iv: bufferToBase64(iv),\n data: bufferToBase64(ciphertext),\n }\n}\n\n/**\n * Decrypt AES-256-GCM ciphertext back to raw bytes.\n * Counterpart to `encryptBytes`. Throws `TamperedError` on auth-tag failure.\n */\nexport async function decryptBytes(\n ivBase64: string,\n dataBase64: string,\n dek: CryptoKey,\n): Promise<Uint8Array> {\n const iv = base64ToBuffer(ivBase64)\n const ciphertext = base64ToBuffer(dataBase64)\n try {\n const plaintext = await subtle.decrypt(\n { name: 'AES-GCM', iv: iv as BufferSource },\n dek,\n ciphertext as BufferSource,\n )\n return new Uint8Array(plaintext)\n } catch (err) {\n if (err instanceof Error && err.name === 'OperationError') {\n throw new TamperedError()\n }\n throw new DecryptionError(\n err instanceof Error ? err.message : 'Decryption failed',\n )\n }\n}\n\n\nexport async function encryptBytesWithAAD(\n data: Uint8Array,\n dek: CryptoKey,\n aad: Uint8Array,\n): Promise<EncryptResult> {\n const iv = generateIV()\n const ciphertext = await subtle.encrypt(\n {\n name: 'AES-GCM',\n iv: iv as BufferSource,\n additionalData: aad as BufferSource,\n },\n dek,\n data as unknown as BufferSource,\n )\n return {\n iv: bufferToBase64(iv),\n data: bufferToBase64(ciphertext),\n }\n}\n\n/**\n * Decrypt AES-256-GCM ciphertext with AAD verification.\n *\n * If the AAD does not match the one used at encryption time (e.g. because\n * a chunk was reordered or substituted from another blob), the GCM auth\n * tag fails and this throws `TamperedError`.\n */\nexport async function decryptBytesWithAAD(\n ivBase64: string,\n dataBase64: string,\n dek: CryptoKey,\n aad: Uint8Array,\n): Promise<Uint8Array> {\n const iv = base64ToBuffer(ivBase64)\n const ciphertext = base64ToBuffer(dataBase64)\n try {\n const plaintext = await subtle.decrypt(\n {\n name: 'AES-GCM',\n iv: iv as BufferSource,\n additionalData: aad as BufferSource,\n },\n dek,\n ciphertext as BufferSource,\n )\n return new Uint8Array(plaintext)\n } catch (err) {\n if (err instanceof Error && err.name === 'OperationError') {\n throw new TamperedError()\n }\n throw new DecryptionError(\n err instanceof Error ? err.message : 'Decryption failed',\n )\n }\n}\n\n// ─── Presence Key Derivation ──────────────────────────────\n\n\nexport async function deriveSealedFieldKey(\n dek: CryptoKey,\n collectionName: string,\n field: string,\n): Promise<CryptoKey> {\n const rawDek = await subtle.exportKey('raw', dek)\n const hkdfKey = await subtle.importKey('raw', rawDek, 'HKDF', false, ['deriveBits'])\n const salt = new TextEncoder().encode('noydb-sealed')\n // JSON-array encoding is injective: each element is separately quoted/\n // escaped, so collection `a/sealed/b` + field `c` cannot collide with\n // collection `a` + field `b/sealed/c`.\n const info = new TextEncoder().encode(JSON.stringify(['noydb-sealed', collectionName, field]))\n const bits = await subtle.deriveBits(\n { name: 'HKDF', hash: 'SHA-256', salt, info },\n hkdfKey,\n KEY_BITS,\n )\n return subtle.importKey(\n 'raw',\n bits,\n { name: 'AES-GCM', length: KEY_BITS },\n false,\n ['encrypt', 'decrypt'],\n )\n}\n\n/**\n * Derive a per-record sealed-field key from the record's **per-record CEK**\n * rather than the collection DEK. Same HKDF construction as\n * {@link deriveSealedFieldKey} but with salt `'noydb-sealed-cek'` (distinct\n * from `'noydb-sealed'`), so a CEK-derived key can never collide with a\n * DEK-derived one for the same `{collection, field}`.\n *\n * The point: the sealed ciphertext's only key now flows from the record's CEK.\n * Dropping the record's wrapped `_cek` (crypto-shred / `forget`) makes the key\n * — and thus `_sealed[field]` — unrecoverable, giving sealed fields the same\n * erasure guarantee `_data` already has. The CEK must be extractable (it is —\n * `unwrapCek`/`generateDEK` mint extractable keys).\n *\n * @param cek The record's AES-256-GCM CEK (extractable).\n * @param collectionName Part of the HKDF `info` for domain separation.\n * @param field Sensitive field name — the rest of the `info`.\n * @returns A non-extractable AES-256-GCM key for that field's sealed slot.\n */\nexport async function deriveSealedFieldKeyFromCek(\n cek: CryptoKey,\n collectionName: string,\n field: string,\n): Promise<CryptoKey> {\n const rawCek = await subtle.exportKey('raw', cek)\n const hkdfKey = await subtle.importKey('raw', rawCek, 'HKDF', false, ['deriveBits'])\n const salt = new TextEncoder().encode('noydb-sealed-cek')\n const info = new TextEncoder().encode(JSON.stringify(['noydb-sealed-cek', collectionName, field]))\n const bits = await subtle.deriveBits(\n { name: 'HKDF', hash: 'SHA-256', salt, info },\n hkdfKey,\n KEY_BITS,\n )\n return subtle.importKey(\n 'raw',\n bits,\n { name: 'AES-GCM', length: KEY_BITS },\n false,\n ['encrypt', 'decrypt'],\n )\n}\n\n// ─── Deterministic Encryption ────────────────────────────\n\n/**\n * Derive the collection's **dedicated deterministic-index key** from its DEK\n * via HKDF-SHA256 (L-1, #554).\n *\n * `_det` slots previously encrypted under the raw collection DEK — the same\n * key `_data` uses with a *randomized*-IV regime while `_det` uses a\n * *deterministic*-IV regime. Two IV regimes on one key is avoidable hygiene\n * debt (~2^-96 theoretical collision), so the deterministic index now gets its\n * own HKDF-separated key: salt `'noydb-det'`, info\n * `JSON.stringify(['noydb-det'])` (the injective JSON-array domain tag, same\n * convention as {@link deriveSealedFieldKey}). Per-field separation still\n * comes from the `'<collection>/<field>'` context inside\n * {@link encryptDeterministic}, exactly as before.\n *\n * The derived key stays **DEK-derived (collection-level)** on purpose: `_det`\n * is carried verbatim through per-record CEK rotation (see\n * `record-keys/sealing.ts`), so its key must not depend on the CEK. It rotates\n * with the collection DEK, like the presence key.\n *\n * The key is minted **extractable** — {@link encryptDeterministic} derives its\n * per-value IV via HKDF over the raw key bytes (an `exportKey` under the\n * hood), which a non-extractable key would forbid. Same in-memory posture as\n * the DEK itself (`generateDEK` mints extractable keys).\n *\n * @param dek The collection's AES-256-GCM DEK (extractable).\n * @returns A dedicated AES-256-GCM key for the `_det` deterministic index.\n */\nexport async function deriveDeterministicKey(dek: CryptoKey): Promise<CryptoKey> {\n const rawDek = await subtle.exportKey('raw', dek)\n const hkdfKey = await subtle.importKey('raw', rawDek, 'HKDF', false, ['deriveBits'])\n const salt = new TextEncoder().encode('noydb-det')\n const info = new TextEncoder().encode(JSON.stringify(['noydb-det']))\n const bits = await subtle.deriveBits(\n { name: 'HKDF', hash: 'SHA-256', salt, info },\n hkdfKey,\n KEY_BITS,\n )\n return subtle.importKey(\n 'raw',\n bits,\n { name: 'AES-GCM', length: KEY_BITS },\n true,\n ['encrypt', 'decrypt'],\n )\n}\n\n/**\n * Derive a deterministic 12-byte IV from `{ DEK, context, plaintext }`\n * via HKDF-SHA256. Given the same three inputs, the IV is identical, so\n * `encryptDeterministic` produces the same ciphertext on every call —\n * which is precisely what enables blind equality search on encrypted\n * fields.\n *\n * **The side channel this opens.** Two records whose field value is the\n * same produce the same ciphertext. An observer with store access can\n * therefore tell which records share a value — not *what* the value is,\n * but the equivalence class. This is the well-known trade-off of\n * deterministic encryption and is why the feature is strictly opt-in\n * per field, guarded by `acknowledgeDeterministicRisk: true` at\n * collection creation.\n *\n * The context string MUST include the collection name and field name,\n * so:\n * - The same plaintext in two different fields encrypts differently\n * (no cross-field equality leak).\n * - The same plaintext in two different collections (different DEKs)\n * encrypts differently by virtue of the key, even before HKDF\n * domain separation kicks in.\n */\nasync function deriveDeterministicIV(\n dek: CryptoKey,\n context: string,\n plaintext: string,\n): Promise<Uint8Array> {\n const rawDek = await subtle.exportKey('raw', dek)\n const hkdfKey = await subtle.importKey('raw', rawDek, 'HKDF', false, ['deriveBits'])\n const salt = new TextEncoder().encode('noydb-deterministic-v1')\n const info = new TextEncoder().encode(`${context}\\x00${plaintext}`)\n const bits = await subtle.deriveBits(\n { name: 'HKDF', hash: 'SHA-256', salt, info },\n hkdfKey,\n IV_BYTES * 8,\n )\n return new Uint8Array(bits)\n}\n\n/**\n * Encrypt a plaintext string with AES-256-GCM and a deterministic,\n * HKDF-derived IV.\n *\n * The same `{ dek, context, plaintext }` triple always produces the\n * same `{ iv, data }` — call this twice and you can string-compare the\n * ciphertexts to check equality of the inputs without decrypting them.\n *\n * @param context Domain-separation string — by convention\n * `'<collection>/<field>'`. Different contexts encrypt\n * the same plaintext to different ciphertexts, so\n * `email` in collection `users` does not collide with\n * `email` in collection `customers`.\n */\nexport async function encryptDeterministic(\n plaintext: string,\n dek: CryptoKey,\n context: string,\n): Promise<EncryptResult> {\n const iv = await deriveDeterministicIV(dek, context, plaintext)\n const encoded = new TextEncoder().encode(plaintext)\n const ciphertext = await subtle.encrypt(\n { name: 'AES-GCM', iv: iv as BufferSource },\n dek,\n encoded,\n )\n return {\n iv: bufferToBase64(iv),\n data: bufferToBase64(ciphertext),\n }\n}\n\n/**\n * Counterpart to {@link encryptDeterministic}. The IV is stored\n * alongside the ciphertext (exactly like the randomized path), so\n * decrypt uses the stored IV and verifies the GCM auth tag — a tampered\n * ciphertext throws `TamperedError` just like randomized AES-GCM.\n */\nexport async function decryptDeterministic(\n ivBase64: string,\n dataBase64: string,\n dek: CryptoKey,\n): Promise<string> {\n return decrypt(ivBase64, dataBase64, dek)\n}\n\n// ─── Random Generation ─────────────────────────────────────────────────\n\n\nexport async function generateRecipientKeyPair(): Promise<CryptoKeyPair> {\n return subtle.generateKey(\n { name: 'RSA-OAEP', modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: 'SHA-256' },\n true,\n ['encrypt', 'decrypt'],\n )\n}\n\nexport async function exportRecipientPublicKeySpki(pair: CryptoKeyPair): Promise<Uint8Array> {\n return new Uint8Array(await subtle.exportKey('spki', pair.publicKey))\n}\n\nexport async function importRecipientPublicKeySpki(spki: Uint8Array): Promise<CryptoKey> {\n return subtle.importKey('spki', spki as BufferSource, { name: 'RSA-OAEP', hash: 'SHA-256' }, false, ['encrypt'])\n}\n\n/** RSA-OAEP-encrypt `bytes` (a 32-byte CEK) to the recipient's public key. */\nexport async function recipientWrap(pub: CryptoKey, bytes: Uint8Array): Promise<Uint8Array> {\n return new Uint8Array(await subtle.encrypt({ name: 'RSA-OAEP' }, pub, bytes as BufferSource))\n}\n\n/**\n * RSA-OAEP-decrypt with the pair's private key. Propagates WebCrypto's own\n * error on failure — callers that need a typed error map it themselves.\n */\nexport async function recipientUnwrap(pair: CryptoKeyPair, wrapped: Uint8Array): Promise<Uint8Array> {\n return new Uint8Array(await subtle.decrypt({ name: 'RSA-OAEP' }, pair.privateKey, wrapped as BufferSource))\n}\n\n/**\n * core#96 — the private half of a recipient pair as PKCS#8 bytes, so a caller\n * can seal it under a key it holds and persist it (a member's keyring inbox\n * key pair lives in the keyring file). The caller zeroes the bytes after use.\n */\nexport async function exportRecipientPrivateKeyPkcs8(pair: CryptoKeyPair): Promise<Uint8Array> {\n return new Uint8Array(await subtle.exportKey('pkcs8', pair.privateKey))\n}\n\n/** core#96 — rebuild a recipient pair from persisted PKCS#8 private + SPKI public bytes. */\nexport async function importRecipientKeyPair(pkcs8: Uint8Array, spki: Uint8Array): Promise<CryptoKeyPair> {\n const alg = { name: 'RSA-OAEP', hash: 'SHA-256' } as const\n const [privateKey, publicKey] = await Promise.all([\n subtle.importKey('pkcs8', pkcs8 as BufferSource, alg, false, ['decrypt']),\n subtle.importKey('spki', spki as BufferSource, alg, false, ['encrypt']),\n ])\n return { privateKey, publicKey }\n}\n\n// ─── Base64 Helpers ────────────────────────────────────────────────────\n\n\n","/**\n * The `_vdig` slot payload + crypto (stage 2, spec §2).\n *\n * A `_vdig[field]` blob is AES-256-GCM `\"iv:data\"` sealed under an\n * HKDF(CEK) slot key with AAD = ['noydb-classify-vdig', collection,\n * recordId, field] (C1 rollback-splice hardening). The AAD is NOT stored —\n * readers reconstruct it. It is deliberately `_v`-independent: C6's\n * carry-forward copies blob bytes verbatim across version bumps; the\n * same-record same-field TEMPORAL rollback residual is detected by the\n * ledger's conditional `_vdig` binding (envelope-body.ts).\n *\n * CEK-ONLY (I3): there is no DEK derivation and no\n * 'noydb-classify-vdig-dek' salt domain — every vdig slot dies with the\n * record's `_cek` (forget() shreds it totally; no vdig-dekResidue class).\n * @module\n */\nimport { encryptBytesWithAAD, decryptBytesWithAAD, type EnclaveKey } from '../crypto.js'\nimport { base64ToBuffer } from '../../plumbing/digest.js'\nimport { TamperedError } from '../../../kernel/errors.js'\n\nconst subtle = globalThis.crypto.subtle\n\nexport const VDIG_SALT_DOMAIN = 'noydb-classify-vdig'\n\nexport interface VdigDigestEntry {\n readonly salt: string // base64 32-byte per-write random salt\n readonly hash: string // base64 32-byte pbkdf2VerifyDigest output\n}\n\nexport interface VdigPayload {\n readonly v: 1\n readonly alg: 'PBKDF2-SHA256'\n readonly iter: number\n readonly cur: VdigDigestEntry & { readonly at: string } // ISO write-time\n /** Previous digests, oldest-first, length ≤ notLastN (cap 8). */\n readonly ring?: readonly VdigDigestEntry[]\n}\n\n/** Injective JSON-array AAD — same collision argument as deriveSealedFieldKey. */\nexport function buildVdigAad(collection: string, recordId: string, field: string): Uint8Array {\n return new TextEncoder().encode(JSON.stringify([VDIG_SALT_DOMAIN, collection, recordId, field]))\n}\n\n/** HKDF(CEK) → non-extractable AES-256-GCM vdig slot key. CEK-only (I3). */\nexport async function deriveVdigSlotKey(\n cek: EnclaveKey,\n collection: string,\n field: string,\n): Promise<EnclaveKey> {\n const raw = await subtle.exportKey('raw', cek)\n const hkdf = await subtle.importKey('raw', raw, 'HKDF', false, ['deriveBits'])\n const salt = new TextEncoder().encode(VDIG_SALT_DOMAIN)\n const info = new TextEncoder().encode(JSON.stringify([VDIG_SALT_DOMAIN, collection, field]))\n const bits = await subtle.deriveBits({ name: 'HKDF', hash: 'SHA-256', salt, info }, hkdf, 256)\n return subtle.importKey('raw', bits, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'])\n}\n\nexport async function sealVdigPayload(\n payload: VdigPayload,\n cek: EnclaveKey,\n collection: string,\n recordId: string,\n field: string,\n): Promise<string> {\n const key = await deriveVdigSlotKey(cek, collection, field)\n const { iv, data } = await encryptBytesWithAAD(\n new TextEncoder().encode(JSON.stringify(payload)),\n key,\n buildVdigAad(collection, recordId, field),\n )\n return `${iv}:${data}`\n}\n\n/** Throws TamperedError on any AAD / auth-tag mismatch (C1). */\nexport async function openVdigPayload(\n blob: string,\n cek: EnclaveKey,\n collection: string,\n recordId: string,\n field: string,\n): Promise<VdigPayload> {\n const sep = blob.indexOf(':')\n if (sep === -1) throw new TamperedError()\n const ivPart = blob.slice(0, sep)\n const dataPart = blob.slice(sep + 1)\n try {\n base64ToBuffer(ivPart)\n base64ToBuffer(dataPart)\n } catch {\n throw new TamperedError()\n }\n const key = await deriveVdigSlotKey(cek, collection, field)\n const bytes = await decryptBytesWithAAD(\n ivPart,\n dataPart,\n key,\n buildVdigAad(collection, recordId, field),\n )\n return JSON.parse(new TextDecoder().decode(bytes)) as VdigPayload\n}\n","/**\n * Digest-only write engine (C6 rotate branch + notLastN ring, spec §2/§4).\n * Called ONLY by RecordCodec.encryptRecord — both live inside the enclave.\n * @module\n */\nimport { type EnclaveKey } from '../crypto.js'\nimport { generateSalt, bufferToBase64, base64ToBuffer } from '../../plumbing/digest.js'\nimport { pbkdf2VerifyDigest, VDIG_ITERATIONS } from './digest.js'\nimport { normalizeForVerify } from '../../plumbing/normalize.js'\nimport { blindedEqual } from './compare.js'\nimport { sealVdigPayload, openVdigPayload, type VdigPayload, type VdigDigestEntry } from './vdig.js'\nimport { ClassifiedRotationError, TamperedError } from '../../../kernel/errors.js'\nimport type { VdigFieldPolicy } from '../../../kernel/types.js'\n\nexport async function mintVdigSlot(\n rawValue: string,\n policy: VdigFieldPolicy,\n prevBlob: string | undefined,\n cek: EnclaveKey,\n collection: string,\n recordId: string,\n field: string,\n): Promise<string> {\n const normalized = normalizeForVerify(policy.normalize, rawValue)\n\n let prev: VdigPayload | null = null\n if (prevBlob !== undefined) {\n try {\n prev = await openVdigPayload(prevBlob, cek, collection, recordId, field)\n } catch {\n // Any failure opening a prior _vdig slot (auth-tag mismatch, malformed\n // JSON, wrong AAD) is a tamper/false condition — normalize to\n // TamperedError so the write path never sees a distinct error shape.\n throw new TamperedError()\n }\n if (!Number.isInteger(prev.iter) || prev.iter < 1) {\n // A corrupted/tampered iter count would silently weaken (or break)\n // the reuse-check PBKDF2 pass — floor/validate before trusting it.\n throw new TamperedError()\n }\n }\n\n // notLastN reuse refusal: candidate vs cur + every ring entry, each a full\n // PBKDF2 at the payload's own iteration count (n × 600K is the documented\n // write-time cost ceiling, cap 8 — spec Q4).\n if (prev !== null && policy.notLastN > 0) {\n const history: readonly VdigDigestEntry[] = [prev.cur, ...(prev.ring ?? [])]\n for (const entry of history) {\n const digest = await pbkdf2VerifyDigest(normalized, base64ToBuffer(entry.salt), prev.iter)\n if (await blindedEqual(digest, base64ToBuffer(entry.hash))) {\n throw new ClassifiedRotationError(collection, field, 'password was used recently')\n }\n }\n }\n\n const salt = generateSalt()\n const hash = await pbkdf2VerifyDigest(normalized, salt, VDIG_ITERATIONS)\n const ring = prev !== null && policy.notLastN > 0\n ? [...(prev.ring ?? []), { salt: prev.cur.salt, hash: prev.cur.hash }].slice(-policy.notLastN)\n : undefined\n\n const payload: VdigPayload = {\n v: 1,\n alg: 'PBKDF2-SHA256',\n iter: VDIG_ITERATIONS,\n cur: { salt: bufferToBase64(salt), hash: bufferToBase64(hash), at: new Date().toISOString() },\n ...(ring !== undefined && ring.length > 0 ? { ring } : {}),\n }\n return sealVdigPayload(payload, cek, collection, recordId, field)\n}\n","/**\n * `enclave-aes` as a {@link CapsulePrimitives} — the 13 functions the shared\n * plumbing binds to.\n *\n * ⭐ THE ASSIGNMENT BELOW IS A TEST, and it is the reason this file exists as\n * a file rather than an inline object at the `makeCapsule()` call. Declaring\n * the seam type and implementing it are two different acts; nothing checks a\n * hand-written interface against the module it claims to describe unless\n * something binds one to the other. This binding caught two errors in the\n * declaration within minutes of it being written:\n *\n * - `deriveDeterministicKey` was declared `(dek, context)`. It takes ONE\n * argument — the AES capsule derives the context into the IV, not the key.\n * - `bufferToBase64` was declared `(bytes: Uint8Array)`. It also accepts an\n * `ArrayBuffer`, which is what its callers actually pass.\n *\n * Both would have compiled here and failed at the far end of the refactor,\n * where the cause is no longer visible. (The same lesson as `#16`: a\n * structural declaration drifts silently from its implementation until an\n * assignment pins the two together.)\n *\n * ⚠️ Method shorthand in `CapsulePrimitives` is checked BIVARIANTLY, so this\n * assignment does NOT catch parameter-arity drift — that is exactly how the\n * `deriveDeterministicKey` mistake survived the type and was caught by a call\n * site instead. Keep the conformance kit's call-site coverage; this assignment\n * is necessary, not sufficient.\n */\nimport type { CapsulePrimitives } from '../contract.js'\nimport { encrypt, decrypt, encryptBytesWithAAD, decryptBytesWithAAD, encryptDeterministic, deriveDeterministicKey, deriveSealedFieldKey, deriveSealedFieldKeyFromCek, generateDEK, wrapCek, unwrapCek } from './crypto.js'\nimport { bufferToBase64 } from '../plumbing/digest.js'\nimport { mintVdigSlot } from './classify/write.js'\nimport { mintBidxTag } from './classify/bidx.js'\nimport { openVdigPayload, sealVdigPayload } from './classify/vdig.js'\n\nexport const aesPrimitives: CapsulePrimitives = {\n encrypt,\n decrypt,\n encryptBytesWithAAD,\n decryptBytesWithAAD,\n encryptDeterministic,\n deriveDeterministicKey,\n deriveSealedFieldKey,\n deriveSealedFieldKeyFromCek,\n generateDEK,\n wrapCek,\n unwrapCek,\n bufferToBase64,\n mintVdigSlot,\n mintBidxTag,\n openVdigPayload,\n sealVdigPayload,\n}\n","/**\n * The AES capsule, assembled: hub's shared plumbing bound to `aesPrimitives`.\n *\n * `classify/**` stays capsule-private (it is an optional group an exclave\n * refuses) but still needs `dualReadSealedSlot`, which is plumbing. Binding it\n * once here keeps `reveal.ts`/`verify.ts` from each building their own copy —\n * two bindings of the same primitives would work, but they would be two\n * objects, and `instanceof` across them is the class of bug the Stage B door\n * test caught by asserting identity rather than names.\n */\nimport { makeCapsule } from '../plumbing/index.js'\nimport { aesPrimitives } from './primitives.js'\n\nexport const aesCapsule = makeCapsule(aesPrimitives)\nexport const { dualReadSealedSlot } = aesCapsule\n"],"mappings":"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","names":["subtle","subtle"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/with-commit/sequence/active.ts","../src/with-commit/sequence/strategy.ts","../src/with-commit/sequence/index.ts"],"sourcesContent":["/**\n * Enable the atomic-sequence capability.\n * Pass to `createNoydb({ sequenceStrategy: withSequence() })` to make\n * `vault.sequence('name').next()` / `.peek()` / `.seedTo()` live. The\n * {@link SequenceStore} CAS engine is statically imported here, so it is pulled\n * into the bundle only when `withSequence()` is referenced (the floor never\n * imports it).\n */\nimport type { SequenceStrategy } from './strategy.js'\nimport { SequenceStore } from './index.js'\n\nexport function withSequence(): SequenceStrategy {\n return {\n createStore(opts) {\n return new SequenceStore(opts)\n },\n }\n}\n","/**\n * Sequence capability strategy — the single on-demand factory the vault routes\n * `vault.sequence()` through to build its atomic-CAS {@link SequenceStore}. The\n * active engine ({@link withSequence}) constructs the real store (kept out of\n * the floor bundle — the store class is reached only via the opt-in\n * `active.ts` chunk); {@link NO_SEQUENCE} throws. The vault always assembles the\n * per-call {@link SequenceStoreOptions} and delegates here, so an un-opted-in\n * caller hits `NO_SEQUENCE`'s throw at `vault.sequence()`.\n *\n * Note: `vault.sequence()` is synchronous, so the factory is a plain (sync)\n * constructor — the engine is tree-shaken by reachability (only `withSequence()`\n * pulls `active.ts`, which statically imports the store), not by a dynamic\n * import. Deferred-numbering series (`withDeferredNumbering`) are a distinct\n * capability and are NOT routed through this strategy.\n * @internal\n */\nimport type { SequenceStore, SequenceStoreOptions } from './index.js'\nimport { SequenceNotEnabledError } from '../../kernel/errors.js'\n\nexport interface SequenceStrategy {\n createStore(opts: SequenceStoreOptions): SequenceStore\n}\n\n/**\n * No-op stub — the floor default. The capability factory throws\n * {@link SequenceNotEnabledError}; opt in with `sequenceStrategy: withSequence()`\n * in createNoydb. @internal\n */\nexport const NO_SEQUENCE: SequenceStrategy = {\n createStore(): SequenceStore {\n throw new SequenceNotEnabledError()\n },\n}\n","/**\n * Atomic sequence primitive — online-coordinated gap-free numbering.\n *\n * `vault.sequence('invoice-2026').next()` returns 1, 2, 3, … with no\n * gaps and no duplicates, even under concurrent callers. Each named\n * sequence is an independent counter record at `_sequences/<name>`,\n * incremented with an optimistic compare-and-swap retry loop — the same\n * proven pattern as the ledger head (`history/ledger/store.ts`).\n *\n * **Explicitly online-only.** Gap-free numbering requires single-authority\n * serialization, which an offline / non-CAS store cannot provide. `next()`\n * throws {@link SequenceOfflineError} unless the backing store advertises\n * `capabilities.casAtomic`. This is a deliberate, honest wall — an offline\n * writer cannot safely allocate a global sequence number.\n *\n * Note on \"gap-free\": the *sequence* is gap-free (each `next()` yields a\n * unique, +1 value). If a caller discards a value without using it, that\n * is a gap in *usage*, not in the sequence — assign each `next()` result\n * to its record in the same operation.\n */\n\nimport { buildRecordAad, buildRecordEnvelope } from '../../capsule/index.js'\nimport type { NoydbStore, EncryptedEnvelope } from '../../kernel/types.js'\nimport { encrypt, openEnvelopeJson, type EnclaveKey } from '../../capsule/index.js'\nimport type { ConflictError} from '../../kernel/errors.js';\nimport { isConflictError, SequenceContentionError, SequenceOfflineError, ValidationError } from '../../kernel/errors.js'\n\n// Capability opt-in seam (S4): `vault.sequence()` builds its CAS store through\n// the sequenceStrategy, so it throws SequenceNotEnabledError unless opted in.\nexport { withSequence } from './active.js'\nexport { NO_SEQUENCE, type SequenceStrategy } from './strategy.js'\nexport { SequenceNotEnabledError } from '../../kernel/errors.js'\n\nexport const SEQUENCE_COLLECTION = '_sequences'\n// A sequence is a single hot CAS row — higher contention than a ledger\n// append. A larger budget + jittered backoff absorbs moderate concurrency;\n// a genuine burst beyond this surfaces SequenceContentionError so the\n// caller can retry / queue (the honest online-only contract).\nconst MAX_NEXT_ATTEMPTS = 16\n\ninterface SequenceState {\n value: number\n}\n\n/** Options for `SequenceHandle.next`. Deferred-numbering series use `for`; the CAS counter ignores all of these. */\nexport interface NextOptions {\n /** Deferred mode: the record id to number. Ignored by the CAS counter. */\n readonly for?: string\n /** Deferred mode: reject after this many ms if still unsealed (reserved; not yet enforced in this slice). */\n readonly timeoutMs?: number\n}\n\n/**\n * Partitioning for a CAS sequence. A partitioned sequence is an\n * independent counter scoped to one tuple of values — e.g.\n * `sequence('invoice', { partition: [2026, 'EU'] })` numbers EU-2026 invoices\n * separately from `[2026, 'US']` and from the bare `invoice` series.\n *\n * Partition components are URI-encoded (so `/`, null bytes and other\n * separators in a value can never collide with the structural separators) and\n * `'/'`-joined, then appended to the series with a null-byte (`\\x00`)\n * separator. The null byte is illegal in a plain series name, which guarantees\n * a partitioned key is always disjoint from any unpartitioned series.\n */\nexport interface SequenceOptions {\n /** Partition tuple. Each component is URI-encoded and `'/'`-joined. */\n readonly partition?: readonly (string | number)[]\n /**\n * Render template for the serial string. When set, `vault.sequence`\n * returns a {@link FormattedSequenceHandle} whose `next()` resolves to\n * `{ serial, formatted }`. Tokens:\n * - `{seq}` — the allocated integer\n * - `{seq:0N}` — zero-padded to width N (e.g. `{seq:04}` → `0001`)\n * - `{partition.i}` — the i-th `partition` component (original value)\n *\n * Any other token, or a `{partition.i}` index beyond the supplied\n * `partition`, throws `ValidationError` at `vault.sequence()` construction.\n * Per-partition reset is inherent: a new partition tuple starts at 1.\n */\n readonly format?: string\n}\n\n/**\n * A formatted sequence handle. Identical to {@link SequenceHandle}\n * except `next()` also returns the rendered `formatted` string. `peek()` /\n * `seedTo()` operate on the underlying integer counter, unchanged.\n */\nexport interface FormattedSequenceHandle {\n /** Allocate the next value and return it with its rendered serial string. */\n next(opts?: NextOptions): Promise<{ serial: number; formatted: string }>\n /** Read the current integer value without allocating. Returns 0 if never used. */\n peek(): Promise<number>\n /** Set-if-greater on the underlying integer counter. See {@link SequenceHandle.seedTo}. */\n seedTo(n: number): Promise<void>\n}\n\n// Matches a single `{...}` token with no nested braces.\nconst SEQ_FORMAT_TOKEN = /\\{([^{}]*)\\}/g\nconst SEQ_PAD_TOKEN = /^seq:0(\\d+)$/\nconst SEQ_PARTITION_TOKEN = /^partition\\.(\\d+)$/\n\n/**\n * Validate a sequence `format` against the supplied partition and return a\n * pure `(serial) => string` renderer. Eager validation: every token is\n * checked now, so a bad pattern throws `ValidationError` at construction —\n * never at `next()` time.\n */\nexport function compileSequenceFormat(\n format: string,\n series: string,\n partition: readonly (string | number)[] | undefined,\n): (serial: number) => string {\n const parts = partition ?? []\n for (const m of format.matchAll(SEQ_FORMAT_TOKEN)) {\n const token = m[1] ?? ''\n if (token === 'seq') continue\n if (SEQ_PAD_TOKEN.test(token)) continue\n const partMatch = SEQ_PARTITION_TOKEN.exec(token)\n if (partMatch) {\n const idx = Number(partMatch[1])\n if (idx >= parts.length) {\n throw new ValidationError(\n `sequence(\"${series}\"): format token \"{${token}}\" references partition index ${idx}, ` +\n `but only ${parts.length} partition component(s) were supplied.`,\n )\n }\n continue\n }\n throw new ValidationError(\n `sequence(\"${series}\"): format contains unknown token \"{${token}}\". ` +\n `Accepted tokens: {seq}, {seq:0N}, {partition.i}.`,\n )\n }\n return (serial: number): string =>\n format.replace(SEQ_FORMAT_TOKEN, (full, token: string) => {\n if (token === 'seq') return String(serial)\n const padMatch = SEQ_PAD_TOKEN.exec(token)\n if (padMatch) return String(serial).padStart(Number(padMatch[1]), '0')\n const partMatch = SEQ_PARTITION_TOKEN.exec(token)\n if (partMatch) return String(parts[Number(partMatch[1])])\n return full // unreachable — validated above\n })\n}\n\n/**\n * Resolve the CAS storage key for a (series, partition) pair.\n *\n * With no partition the key is `series` verbatim. With a partition the key is\n * `${series}\\x00${parts}` where `parts` is each component passed through\n * `encodeURIComponent(String(part))` and `'/'`-joined. The null-byte separator\n * is illegal in a plain series name, so partitioned keys never collide with\n * unpartitioned ones; URI-encoding keeps any component containing `/` distinct\n * from a multi-component partition.\n *\n * @throws {ValidationError} if any partition component is empty after `String()`\n * or is a non-finite number (`NaN`, `±Infinity`).\n */\nexport function resolveSequenceKey(series: string, opts?: SequenceOptions): string {\n const partition = opts?.partition\n if (!partition || partition.length === 0) return series\n const parts = partition.map((p) => {\n if (typeof p === 'number' && !Number.isFinite(p)) {\n throw new ValidationError(`sequence partition component must be a finite number, got ${p}`)\n }\n const s = String(p)\n if (s === '') {\n throw new ValidationError('sequence partition component must not be empty')\n }\n return encodeURIComponent(s)\n })\n return `${series}\\x00${parts.join('/')}`\n}\n\nexport interface SequenceHandle {\n /** Atomically allocate and return the next value (1, 2, 3, …). Deferred series resolve at the next pass. */\n next(opts?: NextOptions): Promise<number>\n /** Read the current value without allocating. Returns 0 if never used. */\n peek(): Promise<number>\n /**\n * Set-if-greater: advance the counter to at least `n`. A no-op if the\n * current value is already `>= n` (so it never rewinds), and `seedTo(0)` is\n * a no-op. Idempotent and CAS-safe under concurrent `next()` / `seedTo()`.\n *\n * Use after a bundle / CSV import to fast-forward the counter past the\n * highest imported serial, so subsequent `next()` calls cannot re-use a\n * number that is already on a record.\n *\n * Online-only: throws {@link SequenceOfflineError} on a non-CAS store.\n */\n seedTo(n: number): Promise<void>\n}\n\nasync function sleepBackoff(attempt: number): Promise<void> {\n // Exponential backoff with full jitter to break the thundering herd\n // when many writers contend on the same counter row.\n const ceil = Math.min(2 ** attempt, 32)\n const ms = Math.floor(Math.random() * ceil)\n await new Promise((r) => setTimeout(r, ms))\n}\n\n/** Per-call context the vault assembles to build a {@link SequenceStore}. */\nexport interface SequenceStoreOptions {\n adapter: NoydbStore\n vault: string\n encrypted: boolean\n getDEK: (collectionName: string) => Promise<EnclaveKey>\n actor: string\n}\n\nexport class SequenceStore {\n private readonly adapter: NoydbStore\n private readonly vault: string\n private readonly encrypted: boolean\n private readonly getDEK: (collectionName: string) => Promise<EnclaveKey>\n private readonly actor: string\n /**\n * Memoized DEK promise. The `_sequences` collection DEK is created on\n * first access; without sharing one promise, a burst of concurrent\n * `next()` calls would each trigger DEK creation and diverge (one\n * writer's ciphertext unreadable by another). One shared promise → one\n * DEK.\n */\n private dekPromise: Promise<EnclaveKey> | null = null\n\n constructor(opts: SequenceStoreOptions) {\n this.adapter = opts.adapter\n this.vault = opts.vault\n this.encrypted = opts.encrypted\n this.getDEK = opts.getDEK\n this.actor = opts.actor\n }\n\n /** A handle bound to one sequence name. */\n handle(name: string): SequenceHandle {\n return {\n next: () => this.next(name),\n peek: () => this.peek(name),\n seedTo: (n) => this.seedTo(name, n),\n }\n }\n\n private assertOnline(): void {\n if (this.adapter.capabilities?.casAtomic !== true) {\n throw new SequenceOfflineError()\n }\n }\n\n private dek(): Promise<EnclaveKey> {\n if (!this.dekPromise) this.dekPromise = this.getDEK(SEQUENCE_COLLECTION)\n return this.dekPromise\n }\n\n private async read(name: string): Promise<{ env: EncryptedEnvelope | null; value: number }> {\n const env = await this.adapter.get(this.vault, SEQUENCE_COLLECTION, name)\n if (!env) return { env: null, value: 0 }\n const json = this.encrypted ? await openEnvelopeJson({ collection: SEQUENCE_COLLECTION, id: name }, env, await this.dek()) : (env._data ?? '')\n const state = JSON.parse(json) as SequenceState\n return { env, value: state.value }\n }\n\n private async encryptState(name: string, state: SequenceState, version: number): Promise<EncryptedEnvelope> {\n const json = JSON.stringify(state)\n if (!this.encrypted) {\n return buildRecordEnvelope({ collection: SEQUENCE_COLLECTION, id: name, version }, { iv: '', data: json})\n }\n const identity = { collection: SEQUENCE_COLLECTION, id: name, version }\n const { iv, data } = await encrypt(json, await this.dek(), buildRecordAad(identity))\n return buildRecordEnvelope(identity, { iv, data})\n }\n\n async peek(name: string): Promise<number> {\n return (await this.read(name)).value\n }\n\n async next(name: string): Promise<number> {\n this.assertOnline()\n let lastConflict: ConflictError | undefined\n for (let attempt = 0; attempt < MAX_NEXT_ATTEMPTS; attempt++) {\n const { env, value } = await this.read(name)\n const nextValue = value + 1\n const expectedVersion = env?._v ?? 0 // 0 ≡ \"must not yet exist\" (create)\n const envelope = await this.encryptState(name, { value: nextValue }, expectedVersion + 1)\n try {\n await this.adapter.put(this.vault, SEQUENCE_COLLECTION, name, envelope, expectedVersion)\n return nextValue\n } catch (err) {\n if (isConflictError(err)) {\n lastConflict = err\n if (attempt < MAX_NEXT_ATTEMPTS - 1) await sleepBackoff(attempt)\n continue\n }\n throw err\n }\n }\n void lastConflict\n throw new SequenceContentionError(name, MAX_NEXT_ATTEMPTS)\n }\n\n async seedTo(name: string, n: number): Promise<void> {\n this.assertOnline()\n if (n <= 0) return // set-if-greater: 0 (and any non-positive seed) is a no-op\n let lastConflict: ConflictError | undefined\n for (let attempt = 0; attempt < MAX_NEXT_ATTEMPTS; attempt++) {\n const { env, value } = await this.read(name)\n if (value >= n) return // already at or past the floor — no write, idempotent\n const expectedVersion = env?._v ?? 0 // 0 ≡ \"must not yet exist\" (create)\n const envelope = await this.encryptState(name, { value: n }, expectedVersion + 1)\n try {\n await this.adapter.put(this.vault, SEQUENCE_COLLECTION, name, envelope, expectedVersion)\n return\n } catch (err) {\n if (isConflictError(err)) {\n lastConflict = err\n if (attempt < MAX_NEXT_ATTEMPTS - 1) await sleepBackoff(attempt)\n continue\n }\n throw err\n }\n }\n void lastConflict\n throw new SequenceContentionError(name, MAX_NEXT_ATTEMPTS)\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-EPPAEGH5.js
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ValidationError
|
|
3
|
-
} from "./chunk-2RH5SEY7.js";
|
|
4
|
-
|
|
5
|
-
// src/capsule/plumbing/normalize.ts
|
|
6
|
-
function normalizeForVerify(mode, value) {
|
|
7
|
-
const nfc = value.normalize("NFC");
|
|
8
|
-
if (mode === "password") return nfc;
|
|
9
|
-
return nfc.toLowerCase().normalize("NFC").trim().replace(/\s+/g, " ");
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// src/capsule/plumbing/digest.ts
|
|
13
|
-
var subtle = globalThis.crypto.subtle;
|
|
14
|
-
var KEY_BITS = 256;
|
|
15
|
-
var SALT_BYTES = 32;
|
|
16
|
-
var IV_BYTES = 12;
|
|
17
|
-
var RECOVERY_SECRET_BYTES = 32;
|
|
18
|
-
var PRESENCE_TAG_KEY_DOMAIN = "noydb.presence.tag.v1";
|
|
19
|
-
var ECHO_KDF_CONTEXT = new Uint8Array([255, ...new TextEncoder().encode("noydb-echo-secret-v1")]);
|
|
20
|
-
function encodeEchoParts(parts) {
|
|
21
|
-
for (const name of ["prompt", "echo", "key"]) {
|
|
22
|
-
if (typeof parts?.[name] !== "string") {
|
|
23
|
-
throw new ValidationError("echo secret parts must be three strings: prompt, echo, key");
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
const enc = new TextEncoder();
|
|
27
|
-
const segments = [parts.prompt, parts.echo, parts.key].map((p) => enc.encode(p));
|
|
28
|
-
const total = ECHO_KDF_CONTEXT.length + segments.reduce((n, s) => n + 4 + s.length, 0);
|
|
29
|
-
const out = new Uint8Array(total);
|
|
30
|
-
out.set(ECHO_KDF_CONTEXT, 0);
|
|
31
|
-
let offset = ECHO_KDF_CONTEXT.length;
|
|
32
|
-
for (const s of segments) {
|
|
33
|
-
new DataView(out.buffer).setUint32(offset, s.length, false);
|
|
34
|
-
out.set(s, offset + 4);
|
|
35
|
-
offset += 4 + s.length;
|
|
36
|
-
}
|
|
37
|
-
return out;
|
|
38
|
-
}
|
|
39
|
-
async function sha256Hex(data) {
|
|
40
|
-
const hash = await subtle.digest("SHA-256", data);
|
|
41
|
-
return Array.from(new Uint8Array(hash)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
42
|
-
}
|
|
43
|
-
async function sha256Bytes(data) {
|
|
44
|
-
return new Uint8Array(await subtle.digest("SHA-256", data));
|
|
45
|
-
}
|
|
46
|
-
async function deriveBlobAddressKey(root, tier) {
|
|
47
|
-
const rawRoot = await subtle.exportKey("raw", root);
|
|
48
|
-
const hkdfKey = await subtle.importKey("raw", rawRoot, "HKDF", false, ["deriveBits"]);
|
|
49
|
-
const salt = new TextEncoder().encode("noydb-blob-address");
|
|
50
|
-
const info = new TextEncoder().encode(`tier:${tier}`);
|
|
51
|
-
const bits = await subtle.deriveBits({ name: "HKDF", hash: "SHA-256", salt, info }, hkdfKey, KEY_BITS);
|
|
52
|
-
return subtle.importKey("raw", bits, { name: "AES-GCM" }, true, ["encrypt", "decrypt"]);
|
|
53
|
-
}
|
|
54
|
-
async function hmacSha256Hex(key, data) {
|
|
55
|
-
const rawKey = await subtle.exportKey("raw", key);
|
|
56
|
-
const hmacKey = await subtle.importKey(
|
|
57
|
-
"raw",
|
|
58
|
-
rawKey,
|
|
59
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
60
|
-
false,
|
|
61
|
-
["sign"]
|
|
62
|
-
);
|
|
63
|
-
const sig = await subtle.sign("HMAC", hmacKey, data);
|
|
64
|
-
return Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
65
|
-
}
|
|
66
|
-
async function derivePresenceKey(dek, collectionName) {
|
|
67
|
-
const rawDek = await subtle.exportKey("raw", dek);
|
|
68
|
-
const hkdfKey = await subtle.importKey(
|
|
69
|
-
"raw",
|
|
70
|
-
rawDek,
|
|
71
|
-
"HKDF",
|
|
72
|
-
false,
|
|
73
|
-
["deriveBits"]
|
|
74
|
-
);
|
|
75
|
-
const salt = new TextEncoder().encode("noydb-presence");
|
|
76
|
-
const info = new TextEncoder().encode(collectionName);
|
|
77
|
-
const bits = await subtle.deriveBits(
|
|
78
|
-
{ name: "HKDF", hash: "SHA-256", salt, info },
|
|
79
|
-
hkdfKey,
|
|
80
|
-
KEY_BITS
|
|
81
|
-
);
|
|
82
|
-
return subtle.importKey(
|
|
83
|
-
"raw",
|
|
84
|
-
bits,
|
|
85
|
-
{ name: "AES-GCM", length: KEY_BITS },
|
|
86
|
-
false,
|
|
87
|
-
["encrypt", "decrypt"]
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
async function derivePresenceTagKey(dek, collectionName) {
|
|
91
|
-
const rawDek = await subtle.exportKey("raw", dek);
|
|
92
|
-
const hkdfKey = await subtle.importKey("raw", rawDek, "HKDF", false, ["deriveBits"]);
|
|
93
|
-
const salt = new TextEncoder().encode(PRESENCE_TAG_KEY_DOMAIN);
|
|
94
|
-
const info = new TextEncoder().encode(collectionName);
|
|
95
|
-
const bits = await subtle.deriveBits({ name: "HKDF", hash: "SHA-256", salt, info }, hkdfKey, KEY_BITS);
|
|
96
|
-
return subtle.importKey("raw", bits, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
97
|
-
}
|
|
98
|
-
async function hmacSignHex(key, data) {
|
|
99
|
-
const sig = await subtle.sign("HMAC", key, data);
|
|
100
|
-
return Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
101
|
-
}
|
|
102
|
-
async function hkdfAesGcmKey(ikm, salt, info) {
|
|
103
|
-
const key = await subtle.importKey("raw", ikm, "HKDF", false, ["deriveKey"]);
|
|
104
|
-
return subtle.deriveKey(
|
|
105
|
-
{ name: "HKDF", hash: "SHA-256", salt, info },
|
|
106
|
-
key,
|
|
107
|
-
{ name: "AES-GCM", length: KEY_BITS },
|
|
108
|
-
false,
|
|
109
|
-
["encrypt", "decrypt"]
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
function generateIV() {
|
|
113
|
-
return globalThis.crypto.getRandomValues(new Uint8Array(IV_BYTES));
|
|
114
|
-
}
|
|
115
|
-
function generateSalt() {
|
|
116
|
-
return globalThis.crypto.getRandomValues(new Uint8Array(SALT_BYTES));
|
|
117
|
-
}
|
|
118
|
-
function generateRecoverySecret() {
|
|
119
|
-
return globalThis.crypto.getRandomValues(new Uint8Array(RECOVERY_SECRET_BYTES));
|
|
120
|
-
}
|
|
121
|
-
function bufferToBase64(buffer) {
|
|
122
|
-
const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
123
|
-
let binary = "";
|
|
124
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
125
|
-
binary += String.fromCharCode(bytes[i]);
|
|
126
|
-
}
|
|
127
|
-
return btoa(binary);
|
|
128
|
-
}
|
|
129
|
-
function base64ToBuffer(base64) {
|
|
130
|
-
const binary = atob(base64);
|
|
131
|
-
const bytes = new Uint8Array(binary.length);
|
|
132
|
-
for (let i = 0; i < binary.length; i++) {
|
|
133
|
-
bytes[i] = binary.charCodeAt(i);
|
|
134
|
-
}
|
|
135
|
-
return bytes;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export {
|
|
139
|
-
normalizeForVerify,
|
|
140
|
-
KEY_BITS,
|
|
141
|
-
IV_BYTES,
|
|
142
|
-
encodeEchoParts,
|
|
143
|
-
sha256Hex,
|
|
144
|
-
sha256Bytes,
|
|
145
|
-
deriveBlobAddressKey,
|
|
146
|
-
hmacSha256Hex,
|
|
147
|
-
derivePresenceKey,
|
|
148
|
-
derivePresenceTagKey,
|
|
149
|
-
hmacSignHex,
|
|
150
|
-
hkdfAesGcmKey,
|
|
151
|
-
generateIV,
|
|
152
|
-
generateSalt,
|
|
153
|
-
generateRecoverySecret,
|
|
154
|
-
bufferToBase64,
|
|
155
|
-
base64ToBuffer
|
|
156
|
-
};
|
|
157
|
-
//# sourceMappingURL=chunk-EPPAEGH5.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/capsule/plumbing/normalize.ts","../src/capsule/plumbing/digest.ts"],"sourcesContent":["/**\n * Preset normalization for verify candidates AND stored comparands (§4).\n * Both sides of every comparison route through the SAME function so\n * write-time digests and verify-time candidates agree. @module\n */\nexport type VerifyNormalizeMode = 'password' | 'secret-answer'\n\nexport function normalizeForVerify(mode: VerifyNormalizeMode, value: string): string {\n const nfc = value.normalize('NFC')\n if (mode === 'password') return nfc\n // secret-answer: NFC -> casefold -> re-NFC -> trim -> collapse internal\n // whitespace runs. `.toLowerCase()` is the chosen casefold approximation\n // (JS has no full Unicode caseless-match in the stdlib, e.g. ß stays ß);\n // the re-NFC after lowercasing keeps the result deterministic.\n return nfc.toLowerCase().normalize('NFC').trim().replace(/\\s+/g, ' ')\n}\n","/**\n * The digest group — hashing, HKDF over public inputs, randomness, base64.\n *\n * Shared by every capsule, and that is the design's own answer rather than a\n * convenience: the capsule-seam spec's group table marks `digest` \"as today\"\n * for `enclave-aes`, `exclave-plain` AND `enclave-pqc` alike. Hashes are not\n * secrets, so there is nothing here to swap — a plaintext capsule computes the\n * same SHA-256 as an encrypting one, and a blob address derived differently\n * per capsule would simply be a bug.\n *\n * ⚠️ This module calls `crypto.subtle`, inside `capsule/**`, which is where the\n * `subtle-outside-capsule` ban permits it. The ban's TARGET is code outside the\n * capsule reaching for WebCrypto on its own; a shared capsule-layer primitive\n * is the thing it is pushing callers toward.\n */\nimport { ValidationError } from '../../kernel/errors.js'\n\nconst subtle = globalThis.crypto.subtle\n\n/** AES key size in bits. Shared: every capsule that derives an AES-GCM subkey\n * from the digest group produces a 256-bit key, or the derivations diverge. */\nexport const KEY_BITS = 256\n\nconst SALT_BYTES = 32\nexport const IV_BYTES = 12\nconst RECOVERY_SECRET_BYTES = 32\nconst PRESENCE_TAG_KEY_DOMAIN = 'noydb.presence.tag.v1'\n\n/** The echo-secret typed parts. Encoding lives here with `encodeEchoParts`; the\n * KEK derivation that consumes it stays in the capsule's `authenticate` group. */\nexport interface EchoSecretParts {\n readonly prompt: string\n readonly echo: string\n readonly key: string\n}\n\nconst ECHO_KDF_CONTEXT = new Uint8Array([0xff, ...new TextEncoder().encode('noydb-echo-secret-v1')])\n\n/**\n * AG-1 encoding: domain context + 4-byte big-endian length prefix per\n * part. Two independent guarantees make a single typed string unable to\n * derive an echo vault's KEK (spec AG-1):\n *\n * 1. The `0xFF` context prefix — UTF-8 never produces that byte, so the\n * encoding is provably not the encoding of ANY string (not merely of\n * no separator-joined form).\n * 2. Structural length prefixes — part boundaries are key material, so\n * re-splitting the same characters changes the derived KEK.\n *\n * @throws ValidationError when any part is not a string — the single\n * chokepoint every echo KEK derivation and block mint passes through, so a\n * malformed parts object cannot be `TextEncoder`-coerced into key material.\n */\nexport function encodeEchoParts(parts: EchoSecretParts): Uint8Array {\n for (const name of ['prompt', 'echo', 'key'] as const) {\n if (typeof parts?.[name] !== 'string') {\n throw new ValidationError('echo secret parts must be three strings: prompt, echo, key')\n }\n }\n const enc = new TextEncoder()\n const segments = [parts.prompt, parts.echo, parts.key].map((p) => enc.encode(p))\n const total = ECHO_KDF_CONTEXT.length + segments.reduce((n, s) => n + 4 + s.length, 0)\n const out = new Uint8Array(total)\n out.set(ECHO_KDF_CONTEXT, 0)\n let offset = ECHO_KDF_CONTEXT.length\n for (const s of segments) {\n new DataView(out.buffer).setUint32(offset, s.length, false)\n out.set(s, offset + 4)\n offset += 4 + s.length\n }\n return out\n}\n\n/**\n * SHA-256 hex digest of raw bytes. Used to derive content-addressed\n * eTags for blob deduplication. Computed on plaintext bytes\n * before compression and encryption so the eTag identifies content, not\n * ciphertext, and survives re-encryption (key rotation, re-upload).\n */\nexport async function sha256Hex(data: Uint8Array): Promise<string> {\n const hash = await subtle.digest('SHA-256', data as unknown as BufferSource)\n return Array.from(new Uint8Array(hash))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/** SHA-256 of raw bytes, as bytes. */\nexport async function sha256Bytes(data: Uint8Array): Promise<Uint8Array> {\n return new Uint8Array(await subtle.digest('SHA-256', data as unknown as BufferSource))\n}\n\n// ─── HMAC-SHA-256 ─────────────────────────────\n\n/**\n * Derive the blob CONTENT-ADDRESSING key for one tier (#1126).\n *\n * The blob eTag is an HMAC over the plaintext. It used to be keyed by the\n * `_blob` DEK — the very key `rotateKeys` replaces — so after any rotation\n * `HMAC(live DEK, plaintext) !== storedETag` for every blob written before it,\n * permanently. `decryptResponse()` checks that unconditionally, so the\n * presigned-URL read path raised `TamperedError` on legitimate data forever;\n * dedup also split, minting a second address for identical bytes.\n *\n * The fix is a `root` that rotation never touches (`_blob_addr`, refused by\n * `rotateKeys` exactly as `_roster` is). Rotation then re-keys chunk BODIES\n * while every address stays stable, which is what makes the AAD\n * `{eTag}:{i}:{count}` and every `_blob_index` / `_blob_slots_*` /\n * `_blob_versions_*` row survive it untouched.\n *\n * **Derived PER TIER, deliberately.** A single vault-wide address would make an\n * elevated blob and a tier-0 blob with identical content share an eTag,\n * leaking equality across a boundary the tier system exists to enforce — and\n * `rehomeForTier` re-addresses on a tier move precisely because the address is\n * tier-scoped today. Domain separation keeps that property while removing the\n * rotation coupling: the two are independent axes, and only one of them was\n * ever meant to change the address.\n *\n * Same HKDF idiom as `asKwKey`, with its own salt so the addressing key can\n * never coincide with a wrapping or encryption key.\n */\nexport async function deriveBlobAddressKey(root: CryptoKey, tier: number): Promise<CryptoKey> {\n const rawRoot = await subtle.exportKey('raw', root)\n const hkdfKey = await subtle.importKey('raw', rawRoot, 'HKDF', false, ['deriveBits'])\n const salt = new TextEncoder().encode('noydb-blob-address')\n const info = new TextEncoder().encode(`tier:${tier}`)\n const bits = await subtle.deriveBits({ name: 'HKDF', hash: 'SHA-256', salt, info }, hkdfKey, KEY_BITS)\n // Imported as AES-GCM only because `hmacSha256Hex` re-exports raw and\n // re-imports as HMAC; the algorithm tag here is a carrier, never used to\n // encrypt anything.\n return subtle.importKey('raw', bits, { name: 'AES-GCM' }, true, ['encrypt', 'decrypt'])\n}\n\n/**\n * HMAC-SHA-256(key, data) as hex.\n *\n * Keyed, unlike {@link sha256Hex}: blob eTags derived with this are opaque to\n * the store, so an attacker with store access cannot pre-compute the address of\n * a file they guess at. Dedup still works inside a vault, where the key is shared.\n */\nexport async function hmacSha256Hex(key: CryptoKey, data: Uint8Array): Promise<string> {\n // Export AES-GCM DEK raw bytes → import as HMAC key\n const rawKey = await subtle.exportKey('raw', key)\n const hmacKey = await subtle.importKey(\n 'raw',\n rawKey,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n )\n const sig = await subtle.sign('HMAC', hmacKey, data as unknown as BufferSource)\n return Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n// ─── AAD-aware Binary Encrypt / Decrypt ──\n\n/**\n * Derive an AES-256-GCM presence key from a collection DEK using HKDF-SHA256.\n *\n * The presence key is domain-separated from the data DEK by the fixed salt\n * `'noydb-presence'` and the `info` = collection name. This means:\n * - The adapter never sees the presence key.\n * - Presence payloads rotate automatically when the collection DEK is rotated.\n * - Revoked users cannot derive the new presence key after a DEK rotation.\n *\n * @param dek The collection's AES-256-GCM DEK (extractable).\n * @param collectionName Used as the HKDF `info` parameter for domain separation.\n * @returns A non-extractable AES-256-GCM key suitable for presence payload encryption.\n */\nexport async function derivePresenceKey(dek: CryptoKey, collectionName: string): Promise<CryptoKey> {\n // Step 1: export DEK raw bytes\n const rawDek = await subtle.exportKey('raw', dek)\n\n // Step 2: import as HKDF key material\n const hkdfKey = await subtle.importKey(\n 'raw',\n rawDek,\n 'HKDF',\n false,\n ['deriveBits'],\n )\n\n // Step 3: derive 256 bits with salt='noydb-presence' and info=collectionName\n const salt = new TextEncoder().encode('noydb-presence')\n const info = new TextEncoder().encode(collectionName)\n const bits = await subtle.deriveBits(\n { name: 'HKDF', hash: 'SHA-256', salt, info },\n hkdfKey,\n KEY_BITS,\n )\n\n // Step 4: import derived bits as AES-GCM key\n return subtle.importKey(\n 'raw',\n bits,\n { name: 'AES-GCM', length: KEY_BITS },\n false,\n ['encrypt', 'decrypt'],\n )\n}\n\n/**\n * Derive the presence-TAG key from a collection DEK: a non-extractable,\n * sign-only HMAC-SHA256 key, HKDF-separated from the presence PAYLOAD key\n * ({@link derivePresenceKey}) by its own salt. The tag is the adapter-opaque\n * record id for storage-polled presence; the adapter never sees the userId.\n */\nexport async function derivePresenceTagKey(dek: CryptoKey, collectionName: string): Promise<CryptoKey> {\n const rawDek = await subtle.exportKey('raw', dek)\n const hkdfKey = await subtle.importKey('raw', rawDek, 'HKDF', false, ['deriveBits'])\n const salt = new TextEncoder().encode(PRESENCE_TAG_KEY_DOMAIN)\n const info = new TextEncoder().encode(collectionName)\n const bits = await subtle.deriveBits({ name: 'HKDF', hash: 'SHA-256', salt, info }, hkdfKey, KEY_BITS)\n return subtle.importKey('raw', bits, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])\n}\n\n/**\n * HMAC-SHA256 hex with a key that IS an HMAC key (e.g. from\n * {@link derivePresenceTagKey}). {@link hmacSha256Hex} takes an AES-GCM\n * carrier and re-imports its raw bytes, which needs an extractable key;\n * this one signs directly and works with non-extractable keys.\n */\nexport async function hmacSignHex(key: CryptoKey, data: Uint8Array): Promise<string> {\n const sig = await subtle.sign('HMAC', key, data as unknown as BufferSource)\n return Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/**\n * HKDF-SHA256 → non-extractable AES-256-GCM key from caller-supplied input\n * key material. The magic-link content key derives here from\n * `(serverSecret, SHA-256(token), info)`; `salt`/`info` are the caller's\n * domain separation, this function adds none.\n */\nexport async function hkdfAesGcmKey(ikm: Uint8Array, salt: Uint8Array, info: Uint8Array): Promise<CryptoKey> {\n const key = await subtle.importKey('raw', ikm as BufferSource, 'HKDF', false, ['deriveKey'])\n return subtle.deriveKey(\n { name: 'HKDF', hash: 'SHA-256', salt: salt as BufferSource, info: info as BufferSource },\n key,\n { name: 'AES-GCM', length: KEY_BITS },\n false,\n ['encrypt', 'decrypt'],\n )\n}\n\n// ─── Sealed Field Key Derivation ──────────────────────────\n\n/** Generate a random 12-byte IV for AES-GCM. */\nexport function generateIV(): Uint8Array {\n return globalThis.crypto.getRandomValues(new Uint8Array(IV_BYTES))\n}\n\n/** Generate a random 32-byte salt for PBKDF2. */\nexport function generateSalt(): Uint8Array {\n return globalThis.crypto.getRandomValues(new Uint8Array(SALT_BYTES))\n}\n\n/**\n * Mint a fresh recovery secret — the high-entropy value a recovery profile\n * wraps the DEK set under and then hands out (Shamir splits it into shares;\n * paper prints it). Not a salt: a salt is public, this is not, and a fork\n * may size them differently. The reference enclave returns 32 bytes.\n *\n * Callers must zero the buffer once it has been wrapped and split.\n */\nexport function generateRecoverySecret(): Uint8Array {\n return globalThis.crypto.getRandomValues(new Uint8Array(RECOVERY_SECRET_BYTES))\n}\n\n// ─── Recipient sealing (RSA-OAEP-SHA256) ───────────────────────────────\n//\n// The managed-secret TLV wraps a per-blob CEK for a recipient who holds an\n// RSA private key — locally (`MemoryRecipientSealer`) or in a KMS\n// (`@noy-db/at-aws-kms`, wire-compatible with RSAES_OAEP_SHA_256). Only the\n// asymmetric steps live here; the TLV layout stays in `managed-secret.ts`.\nexport function bufferToBase64(buffer: ArrayBuffer | Uint8Array): string {\n const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer)\n let binary = ''\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]!)\n }\n return btoa(binary)\n}\nexport function base64ToBuffer(base64: string): Uint8Array<ArrayBuffer> {\n const binary = atob(base64)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return bytes\n}\n"],"mappings":"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","names":[]}
|