@noy-db/hub 0.8.0-pre.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/dist/api-OS747DS4.js +18 -0
- package/dist/as/index.js +11 -12
- package/dist/as/index.js.map +1 -1
- package/dist/at/index.js +9 -10
- package/dist/attestation/index.js +39 -28
- package/dist/attestation/index.js.map +1 -1
- package/dist/{backup-7TFRVFLH.js → backup-YE2VQ26S.js} +15 -16
- package/dist/backup-YE2VQ26S.js.map +1 -0
- package/dist/blobs/index.js +13 -14
- package/dist/blobs/index.js.map +1 -1
- package/dist/broker/index.js +12 -13
- package/dist/broker/index.js.map +1 -1
- package/dist/by/index.js +2 -2
- package/dist/capsule/contract.d.ts +159 -0
- package/dist/capsule/contract.js +95 -0
- package/dist/capsule/enclave-aes/bound.d.ts +52 -0
- package/dist/capsule/enclave-aes/capabilities.d.ts +2 -0
- package/dist/capsule/enclave-aes/classify/compare.d.ts +20 -0
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/find.d.ts +1 -1
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/reveal.d.ts +1 -1
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/verify.d.ts +2 -2
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/write.d.ts +1 -1
- package/dist/{kernel/enclave → capsule/enclave-aes}/crypto.d.ts +33 -129
- package/dist/capsule/enclave-aes/index.d.ts +113 -0
- package/dist/capsule/enclave-aes/index.js +335 -0
- package/dist/capsule/enclave-aes/index.js.map +1 -0
- package/dist/capsule/enclave-aes/primitives.d.ts +29 -0
- package/dist/capsule/index.d.ts +27 -0
- package/dist/capsule/plumbing/ct-equal.d.ts +11 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/deterministic.d.ts +8 -21
- package/dist/capsule/plumbing/digest.d.ts +122 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/envelope-body.d.ts +44 -48
- package/dist/capsule/plumbing/index.d.ts +100 -0
- package/dist/capsule/plumbing/lifecycle.d.ts +50 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/record-codec.d.ts +55 -20
- package/dist/{kernel/enclave → capsule/plumbing}/record-envelope.d.ts +1 -1
- package/dist/capsule/plumbing/rekey-blob.d.ts +33 -0
- package/dist/capsule/plumbing/rekey.d.ts +44 -0
- package/dist/capsule/plumbing/sealed-slot.d.ts +22 -0
- package/dist/capsule/plumbing/sealed-slots.d.ts +37 -0
- package/dist/capsule/plumbing/sealing.d.ts +29 -0
- package/dist/capsule/plumbing/sign.d.ts +9 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/tombstone.d.ts +2 -2
- package/dist/capsule-VOLX3QRQ.js +209 -0
- package/dist/cargo/index.js +36 -36
- package/dist/{chunk-DF73H4UN.js → chunk-23D6M6VM.js} +5 -5
- package/dist/chunk-23D6M6VM.js.map +1 -0
- package/dist/{chunk-FH2L2E34.js → chunk-244QBK7Z.js} +4 -4
- package/dist/{chunk-FH2L2E34.js.map → chunk-244QBK7Z.js.map} +1 -1
- package/dist/{chunk-YSK2CU2Q.js → chunk-2AFX33YA.js} +2 -2
- package/dist/{chunk-TKUOEU2F.js → chunk-2GHDLTPE.js} +2 -2
- package/dist/{chunk-GYGLAVCX.js → chunk-2MG3SW7Q.js} +6 -2
- package/dist/chunk-2MG3SW7Q.js.map +1 -0
- package/dist/{chunk-6OWXYZK2.js → chunk-2ODVB6LZ.js} +2 -2
- package/dist/{chunk-X25NWUZB.js → chunk-2PVXF5CS.js} +3 -3
- package/dist/{chunk-IEX7NK2K.js → chunk-2RH777HH.js} +21 -20
- package/dist/{chunk-IEX7NK2K.js.map → chunk-2RH777HH.js.map} +1 -1
- package/dist/{chunk-244VXYPG.js → chunk-37EPTBBR.js} +14 -1
- package/dist/chunk-37EPTBBR.js.map +1 -0
- package/dist/{chunk-NRT6QZQB.js → chunk-3A5DUZ56.js} +6 -6
- package/dist/chunk-3A5DUZ56.js.map +1 -0
- package/dist/{chunk-ORDURZBU.js → chunk-3EWS67C7.js} +2 -2
- package/dist/{chunk-3H5KLDZN.js → chunk-3L2NBKDR.js} +4 -8
- package/dist/chunk-3L2NBKDR.js.map +1 -0
- package/dist/{chunk-ENAG3IY7.js → chunk-3XJQBBZD.js} +26 -28
- package/dist/chunk-3XJQBBZD.js.map +1 -0
- package/dist/{chunk-KJFW62P4.js → chunk-42ALPZ2B.js} +652 -662
- package/dist/chunk-42ALPZ2B.js.map +1 -0
- package/dist/{chunk-FXQBGFOX.js → chunk-4CIQDWRB.js} +8 -8
- package/dist/{chunk-HT2AHGQI.js → chunk-4JPMZTJY.js} +2 -2
- package/dist/{chunk-FQ5VRHIB.js → chunk-4T3SE27M.js} +5 -9
- package/dist/chunk-4T3SE27M.js.map +1 -0
- package/dist/{chunk-MKXXMNJH.js → chunk-4V3Q35WG.js} +2 -2
- package/dist/{chunk-A6IJU4TK.js → chunk-52MGURXO.js} +2 -2
- package/dist/{chunk-IUWCVHQ7.js → chunk-5A4345TG.js} +4 -4
- package/dist/{chunk-IUWCVHQ7.js.map → chunk-5A4345TG.js.map} +1 -1
- package/dist/{chunk-ISZQJBML.js → chunk-5FE75J4S.js} +6 -6
- package/dist/chunk-5FE75J4S.js.map +1 -0
- package/dist/chunk-5KC7QYEC.js +565 -0
- package/dist/chunk-5KC7QYEC.js.map +1 -0
- package/dist/{chunk-NNARWO72.js → chunk-5UMK7GRI.js} +13 -12
- package/dist/chunk-5UMK7GRI.js.map +1 -0
- package/dist/{chunk-HLEK5VAN.js → chunk-5WWDGFOS.js} +2 -2
- package/dist/{chunk-CKNGS5MH.js → chunk-6QVKPHBF.js} +3 -5
- package/dist/chunk-6QVKPHBF.js.map +1 -0
- package/dist/{chunk-PSIV7CJV.js → chunk-747G6CT3.js} +2 -2
- package/dist/chunk-747G6CT3.js.map +1 -0
- package/dist/{chunk-LGRLME4M.js → chunk-7R2Q7CPL.js} +16 -16
- package/dist/chunk-7R2Q7CPL.js.map +1 -0
- package/dist/{chunk-SOIQ4MM4.js → chunk-7XMHMVTS.js} +3 -3
- package/dist/{chunk-BUDAGWL5.js → chunk-A4XMIZT3.js} +6 -6
- package/dist/{chunk-BUDAGWL5.js.map → chunk-A4XMIZT3.js.map} +1 -1
- package/dist/{chunk-4MXI3ODD.js → chunk-AEQGFRU4.js} +3 -3
- package/dist/{chunk-7JE7BDYJ.js → chunk-AL6ML4LA.js} +5 -5
- package/dist/{chunk-ZUVBC32X.js → chunk-AUKKUPVB.js} +2 -2
- package/dist/chunk-BNWA3WG5.js +22 -0
- package/dist/chunk-BNWA3WG5.js.map +1 -0
- package/dist/{chunk-WY2XXTET.js → chunk-BPWYQ25R.js} +4 -4
- package/dist/{chunk-EOVMT6TB.js → chunk-BVCUTXE3.js} +2 -2
- package/dist/{chunk-UPD5NWI5.js → chunk-DHHGL42E.js} +13 -16
- package/dist/chunk-DHHGL42E.js.map +1 -0
- package/dist/{chunk-3JWHAR6E.js → chunk-DIZLQVAA.js} +2 -2
- package/dist/{chunk-QWFHIOD2.js → chunk-DLD5LGDS.js} +11 -12
- package/dist/chunk-DLD5LGDS.js.map +1 -0
- package/dist/{chunk-ZE4CHIED.js → chunk-DQESF6RP.js} +17 -28
- package/dist/chunk-DQESF6RP.js.map +1 -0
- package/dist/{chunk-IT22PWKV.js → chunk-E2N2T5ZO.js} +2 -2
- package/dist/{chunk-3ELRMVJK.js → chunk-EGVJ7TM4.js} +31 -34
- package/dist/chunk-EGVJ7TM4.js.map +1 -0
- package/dist/{chunk-WNJ4AVGE.js → chunk-EJLV62NI.js} +2 -2
- package/dist/{chunk-QBBUZ3I3.js → chunk-EYG2CY2X.js} +11 -11
- package/dist/{enclave-27SMF6GF.js → chunk-EZGV6F47.js} +83 -56
- package/dist/chunk-EZGV6F47.js.map +1 -0
- package/dist/{chunk-LQ4ZHOKP.js → chunk-EZOAKKTB.js} +36 -27
- package/dist/chunk-EZOAKKTB.js.map +1 -0
- package/dist/{chunk-BJ2IXQ5Q.js → chunk-FFJFE4T7.js} +2 -2
- package/dist/{chunk-JCN44NCY.js → chunk-FLPCETP6.js} +2 -2
- package/dist/{chunk-5O7D6ZTW.js → chunk-FOEDQATO.js} +2 -2
- package/dist/{chunk-VNNRUGMM.js → chunk-FVH5QYY2.js} +2 -2
- package/dist/{chunk-ANWPSTZU.js → chunk-G2MVBDFP.js} +23 -26
- package/dist/chunk-G2MVBDFP.js.map +1 -0
- package/dist/chunk-GMKGGY7V.js +234 -0
- package/dist/chunk-GMKGGY7V.js.map +1 -0
- package/dist/{chunk-EIPVYUEP.js → chunk-GQ4MF3CM.js} +3 -3
- package/dist/chunk-GQ4MF3CM.js.map +1 -0
- package/dist/{chunk-PEOZ34EM.js → chunk-GSAK56VF.js} +1 -1
- package/dist/chunk-GSAK56VF.js.map +1 -0
- package/dist/{chunk-QOOUUR4A.js → chunk-GUZET4SG.js} +10 -4
- package/dist/chunk-GUZET4SG.js.map +1 -0
- package/dist/{chunk-4AF3TUMP.js → chunk-GZT3NQRA.js} +2 -2
- package/dist/{chunk-N5DNADLQ.js → chunk-H23XHRTT.js} +19 -34
- package/dist/chunk-H23XHRTT.js.map +1 -0
- package/dist/{chunk-MVZ2TPVP.js → chunk-H427H63K.js} +2 -2
- package/dist/{chunk-6B3VNR4P.js → chunk-H7JBY4P7.js} +23 -32
- package/dist/chunk-H7JBY4P7.js.map +1 -0
- package/dist/{chunk-MLPHLJIQ.js → chunk-HS554XAF.js} +2 -2
- package/dist/{chunk-HK67PX4J.js → chunk-HW7CMKUG.js} +1 -1
- package/dist/chunk-HW7CMKUG.js.map +1 -0
- package/dist/{chunk-S57HTZ6X.js → chunk-IMQKWR46.js} +5 -7
- package/dist/chunk-IMQKWR46.js.map +1 -0
- package/dist/{chunk-FCKWQE2H.js → chunk-IUBMZPHM.js} +7 -7
- package/dist/chunk-IUBMZPHM.js.map +1 -0
- package/dist/{chunk-UD5EVGZ7.js → chunk-IUT3GWP3.js} +49 -13
- package/dist/chunk-IUT3GWP3.js.map +1 -0
- package/dist/{chunk-J6UOHJY5.js → chunk-JDEYF3PJ.js} +4 -8
- package/dist/{chunk-J6UOHJY5.js.map → chunk-JDEYF3PJ.js.map} +1 -1
- package/dist/{chunk-NWHBJQAL.js → chunk-JIBUPZHA.js} +4 -4
- package/dist/chunk-JIBUPZHA.js.map +1 -0
- package/dist/{chunk-TROR3ALR.js → chunk-JOSPH3E5.js} +2 -2
- package/dist/{chunk-F24ZZTHQ.js → chunk-JQYKPKG6.js} +4 -4
- package/dist/{chunk-GF5BZ7D4.js → chunk-JSMTXZR3.js} +8 -12
- package/dist/chunk-JSMTXZR3.js.map +1 -0
- package/dist/chunk-JWWYRR4Q.js +12 -0
- package/dist/chunk-JWWYRR4Q.js.map +1 -0
- package/dist/{chunk-HBPPGWUM.js → chunk-KZXDLBY6.js} +14 -9
- package/dist/chunk-KZXDLBY6.js.map +1 -0
- package/dist/{chunk-7VCXZDA4.js → chunk-LIOVX5TJ.js} +7 -11
- package/dist/chunk-LIOVX5TJ.js.map +1 -0
- package/dist/{chunk-QWGU66MP.js → chunk-LNSVGRHO.js} +5 -7
- package/dist/chunk-LNSVGRHO.js.map +1 -0
- package/dist/{chunk-MDWKM2XC.js → chunk-M5B2W6YY.js} +3 -3
- package/dist/{chunk-F2TDU7MQ.js → chunk-MBMTND6D.js} +2 -2
- package/dist/{chunk-K6W7BVZ6.js → chunk-MILI22XQ.js} +3 -3
- package/dist/{chunk-YNIUIERI.js → chunk-MXKI4ABF.js} +18 -59
- package/dist/chunk-MXKI4ABF.js.map +1 -0
- package/dist/{chunk-T2LBQ5DV.js → chunk-MXOQ5JCG.js} +252 -214
- package/dist/chunk-MXOQ5JCG.js.map +1 -0
- package/dist/{chunk-ZXABPVM6.js → chunk-N7EVQD5S.js} +9 -13
- package/dist/chunk-N7EVQD5S.js.map +1 -0
- package/dist/{chunk-CF5UU4S7.js → chunk-N7UDP5VU.js} +7 -7
- package/dist/{chunk-FQ54DWUQ.js → chunk-NBQ3KK6X.js} +4 -4
- package/dist/{chunk-4I522ERM.js → chunk-NCO25JZO.js} +4 -4
- package/dist/chunk-NH2UOV3B.js +18 -0
- package/dist/chunk-NH2UOV3B.js.map +1 -0
- package/dist/{chunk-SI3V7D4G.js → chunk-O2IMQSNA.js} +2 -2
- package/dist/{chunk-T52GX4SA.js → chunk-O46CHQT7.js} +4 -4
- package/dist/chunk-OIEO4WDL.js +27 -0
- package/dist/chunk-OIEO4WDL.js.map +1 -0
- package/dist/{chunk-GHLTDZRS.js → chunk-OKSTSITU.js} +25 -4
- package/dist/chunk-OKSTSITU.js.map +1 -0
- package/dist/{chunk-TOPYQ6GA.js → chunk-OYW3I5M4.js} +6 -6
- package/dist/{chunk-X4773RBR.js → chunk-PD64727P.js} +2 -2
- package/dist/chunk-PD64727P.js.map +1 -0
- package/dist/{chunk-BP6DARYA.js → chunk-PP3K67AJ.js} +4 -4
- package/dist/chunk-PP3K67AJ.js.map +1 -0
- package/dist/chunk-Q2XRFWOI.js +40 -0
- package/dist/chunk-Q2XRFWOI.js.map +1 -0
- package/dist/{chunk-AOWGXU6D.js → chunk-Q4UHJ5SN.js} +2 -2
- package/dist/{chunk-FW22ZCXT.js → chunk-QBLT6POL.js} +2 -2
- package/dist/chunk-QMWY2FDS.js +157 -0
- package/dist/chunk-QMWY2FDS.js.map +1 -0
- package/dist/{chunk-I3JDRCMW.js → chunk-RB4DOPGZ.js} +10 -10
- package/dist/{chunk-32YV3TJT.js → chunk-SMV2HRDU.js} +2 -2
- package/dist/{chunk-ODVPTDPK.js → chunk-SV2PM2OY.js} +1 -1
- package/dist/chunk-SV2PM2OY.js.map +1 -0
- package/dist/{chunk-Z5HTYMMQ.js → chunk-SYNY3VB5.js} +2 -2
- package/dist/{chunk-SYVZW77S.js → chunk-TEHHROZL.js} +6 -8
- package/dist/chunk-TEHHROZL.js.map +1 -0
- package/dist/{chunk-ZSX4S5XB.js → chunk-TKVUE4JF.js} +9 -9
- package/dist/{chunk-B57AFBY2.js → chunk-TZZBXPZK.js} +2 -2
- package/dist/{chunk-VNPEWFPD.js → chunk-U2FZNEWJ.js} +4 -4
- package/dist/chunk-U2FZNEWJ.js.map +1 -0
- package/dist/{chunk-5FDLC6G7.js → chunk-UA372JHH.js} +3 -3
- package/dist/{chunk-PDCG6PR5.js → chunk-UEFOQH74.js} +2 -2
- package/dist/chunk-UEFOQH74.js.map +1 -0
- package/dist/{chunk-HVSCEIYL.js → chunk-UIYESRD6.js} +9 -11
- package/dist/chunk-UIYESRD6.js.map +1 -0
- package/dist/{chunk-B6SJIBQK.js → chunk-V3RWOOSO.js} +4 -4
- package/dist/{chunk-HBRLNOHL.js → chunk-V7ADQF5O.js} +4 -4
- package/dist/{chunk-L7DOS3TE.js → chunk-VAORSCSU.js} +3 -3
- package/dist/chunk-VAORSCSU.js.map +1 -0
- package/dist/{chunk-M522UYZ2.js → chunk-VFHCKG5M.js} +6 -10
- package/dist/chunk-VFHCKG5M.js.map +1 -0
- package/dist/{chunk-DC5QVPV7.js → chunk-VHBKYN2J.js} +3 -3
- package/dist/chunk-VHBKYN2J.js.map +1 -0
- package/dist/{chunk-WX5ADGTZ.js → chunk-VKI2EB3N.js} +3 -3
- package/dist/chunk-VKI2EB3N.js.map +1 -0
- package/dist/{chunk-MTL7MXGR.js → chunk-VMV5SBE4.js} +16 -17
- package/dist/chunk-VMV5SBE4.js.map +1 -0
- package/dist/{chunk-F7XGHL5O.js → chunk-VQDZYB2B.js} +3 -3
- package/dist/{chunk-BK2HHQGN.js → chunk-VVOLDVIR.js} +2 -2
- package/dist/{chunk-6LMQ5R26.js → chunk-WPOYWFSE.js} +7 -7
- package/dist/{chunk-6LMQ5R26.js.map → chunk-WPOYWFSE.js.map} +1 -1
- package/dist/{chunk-3F7GLNAE.js → chunk-WXE4W2U6.js} +7 -11
- package/dist/chunk-WXE4W2U6.js.map +1 -0
- package/dist/{chunk-6K7DPM7D.js → chunk-XQRFSKYM.js} +2 -2
- package/dist/{chunk-M7NI3IWE.js → chunk-XSPFDUDG.js} +22 -50
- package/dist/chunk-XSPFDUDG.js.map +1 -0
- package/dist/{chunk-ID6Z6E66.js → chunk-Y2RKVFKR.js} +2 -2
- package/dist/{chunk-6LNL42F5.js → chunk-Y3LPTBG7.js} +12 -12
- package/dist/chunk-Y3LPTBG7.js.map +1 -0
- package/dist/{chunk-FN5EBVTQ.js → chunk-YRXFFWG4.js} +2 -2
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-W3USLL5M.js → classified-marker-SIYKUU5L.js} +3 -3
- package/dist/classified-marker-SIYKUU5L.js.map +1 -0
- package/dist/collection-facade-CS7CA2XO.js +47 -0
- package/dist/{computed-TPFBX7U4.js → computed-FAD7SED4.js} +3 -3
- package/dist/consent/index.js +10 -11
- package/dist/consent/index.js.map +1 -1
- package/dist/cover/index.js +9 -10
- package/dist/custody/index.js +12 -13
- package/dist/{dead-filter-U2UYKSZL.js → dead-filter-4F3LWYKH.js} +11 -3
- package/dist/dead-filter-4F3LWYKH.js.map +1 -0
- package/dist/debug/index.js +11 -2
- package/dist/debug/index.js.map +1 -1
- package/dist/{delegation-S3AEPW2T.js → delegation-NANZDG4N.js} +13 -16
- package/dist/delegation-NANZDG4N.js.map +1 -0
- package/dist/derivations/index.js +23 -24
- package/dist/derive-XLOJVXPU.js +20 -0
- package/dist/directory/index.js +10 -11
- package/dist/{dispatch-3CQDJV5Q.js → dispatch-H4HV32AM.js} +5 -5
- package/dist/{dispatch-RH4LHKBH.js → dispatch-JDZNGEB3.js} +21 -22
- package/dist/dispatch-JDZNGEB3.js.map +1 -0
- package/dist/executor-FMPVN6DT.js +35 -0
- package/dist/executor-LBBBRTN5.js +8 -0
- package/dist/executor-OSRZST2U.js +8 -0
- package/dist/export-accessible-RAOJAAU5.js +22 -0
- package/dist/extract-partition-JD5CUSTG.js +37 -0
- package/dist/{fanout-sidecar-OT6RYLOL.js → fanout-sidecar-L7NHPIOC.js} +13 -15
- package/dist/fanout-sidecar-L7NHPIOC.js.map +1 -0
- package/dist/find-JRN4RNQ5.js +10 -0
- package/dist/forget/index.js +9 -10
- package/dist/forget/index.js.map +1 -1
- package/dist/guards/index.js +4 -4
- package/dist/history/index.js +13 -14
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.js +14 -15
- package/dist/i18n/index.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +183 -184
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +5 -5
- package/dist/introspection/index.js +11 -12
- package/dist/issue-YIVBZUTH.js +19 -0
- package/dist/kernel/attestation-types.d.ts +62 -0
- package/dist/kernel/collection-config.d.ts +1 -48
- package/dist/kernel/collection.d.ts +1 -1
- package/dist/kernel/cutover-transform.d.ts +1 -1
- package/dist/kernel/errors.d.ts +30 -2
- package/dist/kernel/merge-authority.d.ts +1 -1
- package/dist/kernel/paths.d.ts +29 -5
- package/dist/kernel/prepared-write.d.ts +1 -1
- package/dist/kernel/secret-mode.d.ts +1 -1
- package/dist/kernel/types.d.ts +42 -5
- package/dist/kernel/vault.d.ts +2 -2
- package/dist/kernel/write-queue.d.ts +17 -0
- package/dist/{ledger-KZPCMVZY.js → ledger-5ZMGE44K.js} +11 -12
- package/dist/liberate-WZSZM2W6.js +24 -0
- package/dist/link-set-MFXC24VK.js +29 -0
- package/dist/{managed-secret-S3MQ6SH6.js → managed-secret-MFTFT22X.js} +10 -11
- package/dist/materialized-views/index.js +26 -27
- package/dist/{migrate-cek-V7GKJZ7O.js → migrate-cek-DZRFFOHW.js} +2 -2
- package/dist/money/index.js +5 -5
- package/dist/noydb-ITIGNKUF.js +96 -0
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +12 -13
- package/dist/pod/index.js +72 -72
- package/dist/{pod-handle-WGDFB4C2.js → pod-handle-A3LET7NO.js} +10 -11
- package/dist/pod-handle-A3LET7NO.js.map +1 -0
- package/dist/policy/index.js +10 -11
- package/dist/port/on/index.d.ts +1 -1
- package/dist/port/to/index.d.ts +1 -1
- package/dist/port/with/blob-strategy.d.ts +1 -1
- package/dist/port/with/classified-strategy.d.ts +1 -1
- package/dist/port/with/collection-options.d.ts +1 -1
- package/dist/port/with/collection-registries.d.ts +1 -1
- package/dist/port/with/lookup-strategy.d.ts +2 -2
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-SLSXIPBV.js → post-register-7ND27CF2.js} +6 -6
- package/dist/post-register-7ND27CF2.js.map +1 -0
- package/dist/query/all/index.js +15 -15
- package/dist/query/index.js +7 -7
- package/dist/query/live/index.js +7 -7
- package/dist/query/reduce/index.js +10 -10
- package/dist/query/relate/index.js +9 -9
- package/dist/reduce/index.js +8 -8
- package/dist/register-DT5HZ2LZ.js +30 -0
- package/dist/registry-BHRZGZHF.js +8 -0
- package/dist/registry-ET6ZFFWA.js +34 -0
- package/dist/registry-HXFGLGTG.js +8 -0
- package/dist/registry-THCPDEOD.js +23 -0
- package/dist/request-withdrawal-AV2MJJKY.js +30 -0
- package/dist/{reveal-4BCKPEC2.js → reveal-B2TLP4JQ.js} +10 -9
- package/dist/reveal-B2TLP4JQ.js.map +1 -0
- package/dist/revoke-6DWIEOCV.js +24 -0
- package/dist/satellites/index.js +1 -1
- package/dist/schema-update/index.js +2 -2
- package/dist/sealed-record/index.js +16 -18
- package/dist/sealed-record/index.js.map +1 -1
- package/dist/search/index.js +4 -4
- package/dist/{seed-4JS2RJ4A.js → seed-XNSE4U3S.js} +15 -18
- package/dist/seed-XNSE4U3S.js.map +1 -0
- package/dist/sequence/index.js +9 -10
- package/dist/session/index.js +9 -10
- package/dist/session/index.js.map +1 -1
- package/dist/shadow/index.js +2 -2
- package/dist/signer-MHGW3OIL.js +23 -0
- package/dist/snapshots/index.js +11 -11
- package/dist/stale-6GCFMOOR.js +28 -0
- package/dist/storage-BYN5LO6Z.js +21 -0
- package/dist/store/index.js +1 -1
- package/dist/{store-coordination-provider-2O2VUHKW.js → store-coordination-provider-C4BPT5XF.js} +11 -12
- package/dist/store-coordination-provider-C4BPT5XF.js.map +1 -0
- package/dist/sync/index.js +10 -11
- package/dist/sync/index.js.map +1 -1
- package/dist/team/index.js +15 -16
- package/dist/tiers/index.js +11 -12
- package/dist/to/index.js +2 -2
- package/dist/transactions/index.js +3 -3
- package/dist/util/index.js +1 -1
- package/dist/vault-head/index.js +11 -14
- package/dist/vault-head/index.js.map +1 -1
- package/dist/{verify-RVT67IMH.js → verify-UKALW7C2.js} +14 -12
- package/dist/verify-UKALW7C2.js.map +1 -0
- package/dist/via/classified/binding.d.ts +2 -2
- package/dist/via/classified/config-drift.d.ts +2 -2
- package/dist/via/classified/errors.d.ts +1 -1
- package/dist/via/lookup/handle.d.ts +4 -4
- package/dist/walk-4VPK7AS4.js +20 -0
- package/dist/with-audit/attestation/index.d.ts +2 -1
- package/dist/with-audit/attestation/issue.d.ts +2 -2
- package/dist/with-audit/attestation/revoke.d.ts +2 -2
- package/dist/with-audit/attestation/scheme.d.ts +7 -0
- package/dist/with-audit/attestation/signer.d.ts +1 -1
- package/dist/with-audit/attestation/strategy.d.ts +2 -2
- package/dist/with-audit/attestation/types.d.ts +10 -0
- package/dist/with-audit/attestation/vault-facade.d.ts +2 -2
- package/dist/with-audit/attestation/verifier.d.ts +6 -0
- package/dist/with-audit/consent/consent.d.ts +1 -1
- package/dist/with-audit/consent/strategy.d.ts +1 -1
- package/dist/with-audit/forget/subject-index.d.ts +1 -1
- package/dist/with-audit/periods/vault-facade.d.ts +1 -1
- package/dist/with-audit/sealed-record/index.d.ts +2 -2
- package/dist/with-audit/sealed-record/strategy.d.ts +1 -1
- package/dist/with-audit/tiers/index.d.ts +2 -2
- package/dist/with-cargo/adopt-partition.d.ts +1 -1
- package/dist/with-cargo/extract-partition.d.ts +1 -1
- package/dist/with-cargo/floor.d.ts +1 -1
- package/dist/with-commit/history/history.d.ts +2 -2
- package/dist/with-commit/history/index.d.ts +1 -1
- package/dist/with-commit/history/ledger/store.d.ts +1 -1
- package/dist/with-commit/history/strategy.d.ts +1 -1
- package/dist/with-commit/history/time-machine.d.ts +1 -1
- package/dist/with-commit/numbering/index.d.ts +1 -1
- package/dist/with-commit/sequence/index.d.ts +1 -1
- package/dist/with-commit/vault-head/head.d.ts +1 -1
- package/dist/with-commit/vault-head/index.d.ts +1 -1
- package/dist/with-commit/vault-head/strategy.d.ts +1 -1
- package/dist/with-commit/vault-head/verify.d.ts +1 -1
- package/dist/with-formula/derivations/dispatch.d.ts +1 -1
- package/dist/with-formula/derivations/fanout-sidecar.d.ts +1 -1
- package/dist/with-lookup/indexing/collection-facade.d.ts +1 -1
- package/dist/with-lookup/search/collection-facade.d.ts +1 -1
- package/dist/with-party/broker/index.d.ts +3 -3
- package/dist/with-party/directory/user-envelope/storage.d.ts +1 -1
- package/dist/with-party/team/delegation.d.ts +1 -1
- package/dist/with-party/team/echo-secret.d.ts +2 -2
- package/dist/with-party/team/index.d.ts +1 -1
- package/dist/with-party/team/keyring.d.ts +1 -1
- package/dist/with-party/team/magic-link-grant.d.ts +1 -1
- package/dist/with-party/team/recovery.d.ts +1 -1
- package/dist/with-party/team/roster-tag.d.ts +1 -1
- package/dist/with-party/team/rotate-recover.d.ts +1 -1
- package/dist/with-party/team/wrapped-deks.d.ts +1 -1
- package/dist/with-pod/index.d.ts +1 -1
- package/dist/with-shape/blobs/blob-compaction.d.ts +1 -1
- package/dist/with-shape/blobs/blob-intent.d.ts +1 -1
- package/dist/with-shape/blobs/blob-set.d.ts +2 -2
- package/dist/with-shape/blobs/legacy-sweep.d.ts +1 -1
- package/dist/with-shape/introspection/describe.d.ts +1 -1
- package/dist/with-shape/introspection/walk.d.ts +1 -1
- package/dist/with-shape/links/lazy-handle.d.ts +1 -1
- package/dist/with-shape/links/link-set.d.ts +1 -1
- package/dist/with-shape/manifest/derive.d.ts +1 -1
- package/dist/with-shape/manifest/storage.d.ts +1 -1
- package/dist/with-shape/persisted-schemas/register.d.ts +1 -1
- package/dist/with-shape/persisted-schemas/storage.d.ts +1 -1
- package/dist/with-shape/satellites/dead-filter.d.ts +1 -1
- package/dist/with-shape/satellites/declare.d.ts +1 -1
- package/dist/with-shape/satellites/marker.d.ts +1 -1
- package/dist/with-shape/satellites/post-register.d.ts +1 -1
- package/dist/with-sync/presence.d.ts +5 -10
- package/dist/withdraw-accessible-HL7GACUE.js +27 -0
- package/dist/withdraw-accessible-HL7GACUE.js.map +1 -0
- package/package.json +14 -5
- package/dist/api-GVYEKSJE.js +0 -19
- package/dist/backup-7TFRVFLH.js.map +0 -1
- package/dist/chunk-244VXYPG.js.map +0 -1
- package/dist/chunk-3ELRMVJK.js.map +0 -1
- package/dist/chunk-3F7GLNAE.js.map +0 -1
- package/dist/chunk-3H5KLDZN.js.map +0 -1
- package/dist/chunk-6B3VNR4P.js.map +0 -1
- package/dist/chunk-6LNL42F5.js.map +0 -1
- package/dist/chunk-6QSQQLSE.js +0 -95
- package/dist/chunk-6QSQQLSE.js.map +0 -1
- package/dist/chunk-7VCXZDA4.js.map +0 -1
- package/dist/chunk-ANWPSTZU.js.map +0 -1
- package/dist/chunk-BP6DARYA.js.map +0 -1
- package/dist/chunk-CKNGS5MH.js.map +0 -1
- package/dist/chunk-DC5QVPV7.js.map +0 -1
- package/dist/chunk-DE4DH2RZ.js +0 -29
- package/dist/chunk-DE4DH2RZ.js.map +0 -1
- package/dist/chunk-DF73H4UN.js.map +0 -1
- package/dist/chunk-EIPVYUEP.js.map +0 -1
- package/dist/chunk-ENAG3IY7.js.map +0 -1
- package/dist/chunk-FCKWQE2H.js.map +0 -1
- package/dist/chunk-FQ5VRHIB.js.map +0 -1
- package/dist/chunk-GF5BZ7D4.js.map +0 -1
- package/dist/chunk-GHLTDZRS.js.map +0 -1
- package/dist/chunk-GYGLAVCX.js.map +0 -1
- package/dist/chunk-HBPPGWUM.js.map +0 -1
- package/dist/chunk-HK67PX4J.js.map +0 -1
- package/dist/chunk-HVSCEIYL.js.map +0 -1
- package/dist/chunk-ISZQJBML.js.map +0 -1
- package/dist/chunk-KJFW62P4.js.map +0 -1
- package/dist/chunk-L7DOS3TE.js.map +0 -1
- package/dist/chunk-LGRLME4M.js.map +0 -1
- package/dist/chunk-LP7BEXCT.js +0 -32
- package/dist/chunk-LP7BEXCT.js.map +0 -1
- package/dist/chunk-LQ4ZHOKP.js.map +0 -1
- package/dist/chunk-M522UYZ2.js.map +0 -1
- package/dist/chunk-M7NI3IWE.js.map +0 -1
- package/dist/chunk-MTL7MXGR.js.map +0 -1
- package/dist/chunk-N5DNADLQ.js.map +0 -1
- package/dist/chunk-NNARWO72.js.map +0 -1
- package/dist/chunk-NRT6QZQB.js.map +0 -1
- package/dist/chunk-NWHBJQAL.js.map +0 -1
- package/dist/chunk-ODVPTDPK.js.map +0 -1
- package/dist/chunk-PDCG6PR5.js.map +0 -1
- package/dist/chunk-PEOZ34EM.js.map +0 -1
- package/dist/chunk-PSIV7CJV.js.map +0 -1
- package/dist/chunk-QOOUUR4A.js.map +0 -1
- package/dist/chunk-QWFHIOD2.js.map +0 -1
- package/dist/chunk-QWGU66MP.js.map +0 -1
- package/dist/chunk-S57HTZ6X.js.map +0 -1
- package/dist/chunk-SEE332EV.js +0 -66
- package/dist/chunk-SEE332EV.js.map +0 -1
- package/dist/chunk-SYVZW77S.js.map +0 -1
- package/dist/chunk-T2LBQ5DV.js.map +0 -1
- package/dist/chunk-UD5EVGZ7.js.map +0 -1
- package/dist/chunk-UPD5NWI5.js.map +0 -1
- package/dist/chunk-UYB234ZR.js +0 -479
- package/dist/chunk-UYB234ZR.js.map +0 -1
- package/dist/chunk-VNPEWFPD.js.map +0 -1
- package/dist/chunk-WX5ADGTZ.js.map +0 -1
- package/dist/chunk-X4773RBR.js.map +0 -1
- package/dist/chunk-YNIUIERI.js.map +0 -1
- package/dist/chunk-ZE4CHIED.js.map +0 -1
- package/dist/chunk-ZXABPVM6.js.map +0 -1
- package/dist/classified-marker-W3USLL5M.js.map +0 -1
- package/dist/collection-facade-QU6IJBN3.js +0 -48
- package/dist/dead-filter-U2UYKSZL.js.map +0 -1
- package/dist/delegation-S3AEPW2T.js.map +0 -1
- package/dist/derive-OX7F6TGG.js +0 -21
- package/dist/dispatch-RH4LHKBH.js.map +0 -1
- package/dist/executor-B6SRO2QS.js +0 -36
- package/dist/executor-BI5CHWRY.js +0 -8
- package/dist/executor-RBKM5W5K.js +0 -8
- package/dist/export-accessible-VMA3YM5V.js +0 -22
- package/dist/extract-partition-NF7PXGPP.js +0 -37
- package/dist/fanout-sidecar-OT6RYLOL.js.map +0 -1
- package/dist/find-LZMP26KF.js +0 -10
- package/dist/issue-IHARXWW5.js +0 -18
- package/dist/kernel/enclave/classify/compare.d.ts +0 -10
- package/dist/kernel/enclave/index.d.ts +0 -87
- package/dist/kernel/enclave/record-keys/lifecycle.d.ts +0 -124
- package/dist/kernel/enclave/record-keys/rekey-blob.d.ts +0 -88
- package/dist/kernel/enclave/record-keys/rekey.d.ts +0 -91
- package/dist/kernel/enclave/record-keys/sealed-slot.d.ts +0 -14
- package/dist/kernel/enclave/record-keys/sealed-slots.d.ts +0 -123
- package/dist/kernel/enclave/record-keys/sealing.d.ts +0 -70
- package/dist/liberate-GRLCZMW4.js +0 -24
- package/dist/link-set-JCMJ7ULP.js +0 -30
- package/dist/noydb-SWQJ3MZS.js +0 -97
- package/dist/pod-handle-WGDFB4C2.js.map +0 -1
- package/dist/post-register-SLSXIPBV.js.map +0 -1
- package/dist/register-F3OYE7MJ.js +0 -31
- package/dist/registry-CILQFXFK.js +0 -8
- package/dist/registry-XNNYQVKV.js +0 -8
- package/dist/registry-YCDZV3VW.js +0 -35
- package/dist/registry-ZGYS33TE.js +0 -24
- package/dist/request-withdrawal-Z5NC6TXT.js +0 -30
- package/dist/reveal-4BCKPEC2.js.map +0 -1
- package/dist/revoke-ZL62WC2D.js +0 -23
- package/dist/seed-4JS2RJ4A.js.map +0 -1
- package/dist/signer-MBZZMXTC.js +0 -24
- package/dist/stale-TJ3DYZMQ.js +0 -29
- package/dist/storage-SVMKRGCW.js +0 -22
- package/dist/store-coordination-provider-2O2VUHKW.js.map +0 -1
- package/dist/verify-RVT67IMH.js.map +0 -1
- package/dist/walk-HJ42EISE.js +0 -21
- package/dist/withdraw-accessible-5NZUPAVA.js +0 -27
- /package/dist/{api-GVYEKSJE.js.map → api-OS747DS4.js.map} +0 -0
- /package/dist/{computed-TPFBX7U4.js.map → capsule/contract.js.map} +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/broker/proof.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/bidx.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/digest.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/vdig.d.ts +0 -0
- /package/dist/{kernel/enclave/classify → capsule/plumbing}/kofn.d.ts +0 -0
- /package/dist/{kernel/enclave/classify → capsule/plumbing}/normalize.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/plumbing}/record-aad.d.ts +0 -0
- /package/dist/{collection-facade-QU6IJBN3.js.map → capsule-VOLX3QRQ.js.map} +0 -0
- /package/dist/{chunk-YSK2CU2Q.js.map → chunk-2AFX33YA.js.map} +0 -0
- /package/dist/{chunk-TKUOEU2F.js.map → chunk-2GHDLTPE.js.map} +0 -0
- /package/dist/{chunk-6OWXYZK2.js.map → chunk-2ODVB6LZ.js.map} +0 -0
- /package/dist/{chunk-X25NWUZB.js.map → chunk-2PVXF5CS.js.map} +0 -0
- /package/dist/{chunk-ORDURZBU.js.map → chunk-3EWS67C7.js.map} +0 -0
- /package/dist/{chunk-FXQBGFOX.js.map → chunk-4CIQDWRB.js.map} +0 -0
- /package/dist/{chunk-HT2AHGQI.js.map → chunk-4JPMZTJY.js.map} +0 -0
- /package/dist/{chunk-MKXXMNJH.js.map → chunk-4V3Q35WG.js.map} +0 -0
- /package/dist/{chunk-A6IJU4TK.js.map → chunk-52MGURXO.js.map} +0 -0
- /package/dist/{chunk-HLEK5VAN.js.map → chunk-5WWDGFOS.js.map} +0 -0
- /package/dist/{chunk-SOIQ4MM4.js.map → chunk-7XMHMVTS.js.map} +0 -0
- /package/dist/{chunk-4MXI3ODD.js.map → chunk-AEQGFRU4.js.map} +0 -0
- /package/dist/{chunk-7JE7BDYJ.js.map → chunk-AL6ML4LA.js.map} +0 -0
- /package/dist/{chunk-ZUVBC32X.js.map → chunk-AUKKUPVB.js.map} +0 -0
- /package/dist/{chunk-WY2XXTET.js.map → chunk-BPWYQ25R.js.map} +0 -0
- /package/dist/{chunk-EOVMT6TB.js.map → chunk-BVCUTXE3.js.map} +0 -0
- /package/dist/{chunk-3JWHAR6E.js.map → chunk-DIZLQVAA.js.map} +0 -0
- /package/dist/{chunk-IT22PWKV.js.map → chunk-E2N2T5ZO.js.map} +0 -0
- /package/dist/{chunk-WNJ4AVGE.js.map → chunk-EJLV62NI.js.map} +0 -0
- /package/dist/{chunk-QBBUZ3I3.js.map → chunk-EYG2CY2X.js.map} +0 -0
- /package/dist/{chunk-BJ2IXQ5Q.js.map → chunk-FFJFE4T7.js.map} +0 -0
- /package/dist/{chunk-JCN44NCY.js.map → chunk-FLPCETP6.js.map} +0 -0
- /package/dist/{chunk-5O7D6ZTW.js.map → chunk-FOEDQATO.js.map} +0 -0
- /package/dist/{chunk-VNNRUGMM.js.map → chunk-FVH5QYY2.js.map} +0 -0
- /package/dist/{chunk-4AF3TUMP.js.map → chunk-GZT3NQRA.js.map} +0 -0
- /package/dist/{chunk-MVZ2TPVP.js.map → chunk-H427H63K.js.map} +0 -0
- /package/dist/{chunk-MLPHLJIQ.js.map → chunk-HS554XAF.js.map} +0 -0
- /package/dist/{chunk-TROR3ALR.js.map → chunk-JOSPH3E5.js.map} +0 -0
- /package/dist/{chunk-F24ZZTHQ.js.map → chunk-JQYKPKG6.js.map} +0 -0
- /package/dist/{chunk-MDWKM2XC.js.map → chunk-M5B2W6YY.js.map} +0 -0
- /package/dist/{chunk-F2TDU7MQ.js.map → chunk-MBMTND6D.js.map} +0 -0
- /package/dist/{chunk-K6W7BVZ6.js.map → chunk-MILI22XQ.js.map} +0 -0
- /package/dist/{chunk-CF5UU4S7.js.map → chunk-N7UDP5VU.js.map} +0 -0
- /package/dist/{chunk-FQ54DWUQ.js.map → chunk-NBQ3KK6X.js.map} +0 -0
- /package/dist/{chunk-4I522ERM.js.map → chunk-NCO25JZO.js.map} +0 -0
- /package/dist/{chunk-SI3V7D4G.js.map → chunk-O2IMQSNA.js.map} +0 -0
- /package/dist/{chunk-T52GX4SA.js.map → chunk-O46CHQT7.js.map} +0 -0
- /package/dist/{chunk-TOPYQ6GA.js.map → chunk-OYW3I5M4.js.map} +0 -0
- /package/dist/{chunk-AOWGXU6D.js.map → chunk-Q4UHJ5SN.js.map} +0 -0
- /package/dist/{chunk-FW22ZCXT.js.map → chunk-QBLT6POL.js.map} +0 -0
- /package/dist/{chunk-I3JDRCMW.js.map → chunk-RB4DOPGZ.js.map} +0 -0
- /package/dist/{chunk-32YV3TJT.js.map → chunk-SMV2HRDU.js.map} +0 -0
- /package/dist/{chunk-Z5HTYMMQ.js.map → chunk-SYNY3VB5.js.map} +0 -0
- /package/dist/{chunk-ZSX4S5XB.js.map → chunk-TKVUE4JF.js.map} +0 -0
- /package/dist/{chunk-B57AFBY2.js.map → chunk-TZZBXPZK.js.map} +0 -0
- /package/dist/{chunk-5FDLC6G7.js.map → chunk-UA372JHH.js.map} +0 -0
- /package/dist/{chunk-B6SJIBQK.js.map → chunk-V3RWOOSO.js.map} +0 -0
- /package/dist/{chunk-HBRLNOHL.js.map → chunk-V7ADQF5O.js.map} +0 -0
- /package/dist/{chunk-F7XGHL5O.js.map → chunk-VQDZYB2B.js.map} +0 -0
- /package/dist/{chunk-BK2HHQGN.js.map → chunk-VVOLDVIR.js.map} +0 -0
- /package/dist/{chunk-6K7DPM7D.js.map → chunk-XQRFSKYM.js.map} +0 -0
- /package/dist/{chunk-ID6Z6E66.js.map → chunk-Y2RKVFKR.js.map} +0 -0
- /package/dist/{chunk-FN5EBVTQ.js.map → chunk-YRXFFWG4.js.map} +0 -0
- /package/dist/{derive-OX7F6TGG.js.map → collection-facade-CS7CA2XO.js.map} +0 -0
- /package/dist/{enclave-27SMF6GF.js.map → computed-FAD7SED4.js.map} +0 -0
- /package/dist/{executor-B6SRO2QS.js.map → derive-XLOJVXPU.js.map} +0 -0
- /package/dist/{dispatch-3CQDJV5Q.js.map → dispatch-H4HV32AM.js.map} +0 -0
- /package/dist/{executor-BI5CHWRY.js.map → executor-FMPVN6DT.js.map} +0 -0
- /package/dist/{executor-RBKM5W5K.js.map → executor-LBBBRTN5.js.map} +0 -0
- /package/dist/{export-accessible-VMA3YM5V.js.map → executor-OSRZST2U.js.map} +0 -0
- /package/dist/{extract-partition-NF7PXGPP.js.map → export-accessible-RAOJAAU5.js.map} +0 -0
- /package/dist/{find-LZMP26KF.js.map → extract-partition-JD5CUSTG.js.map} +0 -0
- /package/dist/{issue-IHARXWW5.js.map → find-JRN4RNQ5.js.map} +0 -0
- /package/dist/{ledger-KZPCMVZY.js.map → issue-YIVBZUTH.js.map} +0 -0
- /package/dist/{liberate-GRLCZMW4.js.map → ledger-5ZMGE44K.js.map} +0 -0
- /package/dist/{link-set-JCMJ7ULP.js.map → liberate-WZSZM2W6.js.map} +0 -0
- /package/dist/{managed-secret-S3MQ6SH6.js.map → link-set-MFXC24VK.js.map} +0 -0
- /package/dist/{noydb-SWQJ3MZS.js.map → managed-secret-MFTFT22X.js.map} +0 -0
- /package/dist/{migrate-cek-V7GKJZ7O.js.map → migrate-cek-DZRFFOHW.js.map} +0 -0
- /package/dist/{register-F3OYE7MJ.js.map → noydb-ITIGNKUF.js.map} +0 -0
- /package/dist/{registry-CILQFXFK.js.map → register-DT5HZ2LZ.js.map} +0 -0
- /package/dist/{registry-XNNYQVKV.js.map → registry-BHRZGZHF.js.map} +0 -0
- /package/dist/{registry-YCDZV3VW.js.map → registry-ET6ZFFWA.js.map} +0 -0
- /package/dist/{registry-ZGYS33TE.js.map → registry-HXFGLGTG.js.map} +0 -0
- /package/dist/{request-withdrawal-Z5NC6TXT.js.map → registry-THCPDEOD.js.map} +0 -0
- /package/dist/{revoke-ZL62WC2D.js.map → request-withdrawal-AV2MJJKY.js.map} +0 -0
- /package/dist/{signer-MBZZMXTC.js.map → revoke-6DWIEOCV.js.map} +0 -0
- /package/dist/{stale-TJ3DYZMQ.js.map → signer-MHGW3OIL.js.map} +0 -0
- /package/dist/{storage-SVMKRGCW.js.map → stale-6GCFMOOR.js.map} +0 -0
- /package/dist/{walk-HJ42EISE.js.map → storage-BYN5LO6Z.js.map} +0 -0
- /package/dist/{withdraw-accessible-5NZUPAVA.js.map → walk-4VPK7AS4.js.map} +0 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// ../attestation/dist/index.js
|
|
2
|
+
function utf8(s) {
|
|
3
|
+
return new TextEncoder().encode(s);
|
|
4
|
+
}
|
|
5
|
+
function bytesToB64url(bytes) {
|
|
6
|
+
let s = "";
|
|
7
|
+
for (const b of bytes) s += String.fromCharCode(b);
|
|
8
|
+
return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
9
|
+
}
|
|
10
|
+
function b64urlToBytes(s) {
|
|
11
|
+
const pad = s.length % 4 === 0 ? "" : "=".repeat(4 - s.length % 4);
|
|
12
|
+
const b64 = s.replace(/-/g, "+").replace(/_/g, "/") + pad;
|
|
13
|
+
const bin = atob(b64);
|
|
14
|
+
const out = new Uint8Array(bin.length);
|
|
15
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
function canonicalJson(value) {
|
|
19
|
+
if (value === null) return "null";
|
|
20
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
21
|
+
if (typeof value === "number") {
|
|
22
|
+
if (!Number.isFinite(value)) {
|
|
23
|
+
throw new Error(`canonicalJson: refusing to encode non-finite number ${String(value)}`);
|
|
24
|
+
}
|
|
25
|
+
return JSON.stringify(value);
|
|
26
|
+
}
|
|
27
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
28
|
+
if (typeof value === "bigint") throw new Error("canonicalJson: BigInt is not JSON-serializable");
|
|
29
|
+
if (typeof value === "undefined" || typeof value === "function") {
|
|
30
|
+
throw new Error(`canonicalJson: refusing to encode ${typeof value} \u2014 include all fields explicitly`);
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(value)) return "[" + value.map((v) => canonicalJson(v)).join(",") + "]";
|
|
33
|
+
if (typeof value === "object") {
|
|
34
|
+
const obj = value;
|
|
35
|
+
const keys = Object.keys(obj).sort();
|
|
36
|
+
const parts = [];
|
|
37
|
+
for (const key of keys) parts.push(JSON.stringify(key) + ":" + canonicalJson(obj[key]));
|
|
38
|
+
return "{" + parts.join(",") + "}";
|
|
39
|
+
}
|
|
40
|
+
throw new Error(`canonicalJson: unexpected value type: ${typeof value}`);
|
|
41
|
+
}
|
|
42
|
+
async function sha256Bytes(input) {
|
|
43
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", utf8(input));
|
|
44
|
+
return new Uint8Array(digest);
|
|
45
|
+
}
|
|
46
|
+
function getPath(obj, path) {
|
|
47
|
+
return path.split(".").reduce(
|
|
48
|
+
(o, k) => o == null ? void 0 : o[k],
|
|
49
|
+
obj
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
function normalizeField(value, n) {
|
|
53
|
+
switch (n) {
|
|
54
|
+
case "trim":
|
|
55
|
+
return String(value).trim();
|
|
56
|
+
case "lower":
|
|
57
|
+
return String(value).trim().toLowerCase();
|
|
58
|
+
case "upper":
|
|
59
|
+
return String(value).trim().toUpperCase();
|
|
60
|
+
case "alnum-upper":
|
|
61
|
+
return String(value).replace(/[^A-Za-z0-9]/g, "").toUpperCase();
|
|
62
|
+
case "digits":
|
|
63
|
+
return String(value).replace(/[^0-9]/g, "");
|
|
64
|
+
case "cents": {
|
|
65
|
+
if (typeof value === "number") {
|
|
66
|
+
if (!Number.isFinite(value)) {
|
|
67
|
+
throw new Error(`normalizeField(cents): not a finite number: ${String(value)}`);
|
|
68
|
+
}
|
|
69
|
+
return String(Math.round(value * 100));
|
|
70
|
+
}
|
|
71
|
+
const stripped = String(value).replace(/[^0-9.-]/g, "");
|
|
72
|
+
if (!/[0-9]/.test(stripped)) {
|
|
73
|
+
throw new Error(`normalizeField(cents): not a finite number: ${String(value)}`);
|
|
74
|
+
}
|
|
75
|
+
const num = Number(stripped);
|
|
76
|
+
if (!Number.isFinite(num)) {
|
|
77
|
+
throw new Error(`normalizeField(cents): not a finite number: ${String(value)}`);
|
|
78
|
+
}
|
|
79
|
+
return String(Math.round(num * 100));
|
|
80
|
+
}
|
|
81
|
+
case "iso-date": {
|
|
82
|
+
const d = value instanceof Date ? value : new Date(String(value));
|
|
83
|
+
if (Number.isNaN(d.getTime())) {
|
|
84
|
+
throw new Error(`normalizeField(iso-date): unparseable date: ${String(value)}`);
|
|
85
|
+
}
|
|
86
|
+
return d.toISOString().slice(0, 10);
|
|
87
|
+
}
|
|
88
|
+
default: {
|
|
89
|
+
const exhaustive = n;
|
|
90
|
+
throw new Error(`normalizeField: unknown normalizer ${String(exhaustive)}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function computeFieldHashes(saltB64, schema, values) {
|
|
95
|
+
const out = [];
|
|
96
|
+
for (const f of schema.fields) {
|
|
97
|
+
const raw = getPath(values, f.path);
|
|
98
|
+
if (raw === void 0 || raw === null) {
|
|
99
|
+
throw new Error(`computeFieldHashes: missing value at declared path '${f.path}'`);
|
|
100
|
+
}
|
|
101
|
+
const norm = normalizeField(raw, f.normalize);
|
|
102
|
+
const digest = await sha256Bytes(canonicalJson([saltB64, f.path, norm]));
|
|
103
|
+
out.push(bytesToB64url(digest));
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
var ALG = "Ed25519";
|
|
108
|
+
async function ed25519Sign(privateKeyPkcs8B64, message) {
|
|
109
|
+
const key = await globalThis.crypto.subtle.importKey(
|
|
110
|
+
"pkcs8",
|
|
111
|
+
b64urlToBytes(privateKeyPkcs8B64),
|
|
112
|
+
ALG,
|
|
113
|
+
false,
|
|
114
|
+
["sign"]
|
|
115
|
+
);
|
|
116
|
+
const sig = new Uint8Array(await globalThis.crypto.subtle.sign(ALG, key, message));
|
|
117
|
+
return bytesToB64url(sig);
|
|
118
|
+
}
|
|
119
|
+
async function ed25519Verify(publicKeyB64, sigB64url, message) {
|
|
120
|
+
try {
|
|
121
|
+
const key = await globalThis.crypto.subtle.importKey(
|
|
122
|
+
"raw",
|
|
123
|
+
b64urlToBytes(publicKeyB64),
|
|
124
|
+
ALG,
|
|
125
|
+
false,
|
|
126
|
+
["verify"]
|
|
127
|
+
);
|
|
128
|
+
return await globalThis.crypto.subtle.verify(
|
|
129
|
+
ALG,
|
|
130
|
+
key,
|
|
131
|
+
b64urlToBytes(sigB64url),
|
|
132
|
+
message
|
|
133
|
+
);
|
|
134
|
+
} catch {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
var ed25519Scheme = { sign: ed25519Sign, verify: ed25519Verify };
|
|
139
|
+
function encodeQr(p) {
|
|
140
|
+
return bytesToB64url(utf8(JSON.stringify(p)));
|
|
141
|
+
}
|
|
142
|
+
function decodeQr(s) {
|
|
143
|
+
let parsed;
|
|
144
|
+
try {
|
|
145
|
+
parsed = JSON.parse(new TextDecoder().decode(b64urlToBytes(s)));
|
|
146
|
+
} catch {
|
|
147
|
+
throw new Error("decodeQr: invalid base64url-encoded JSON payload");
|
|
148
|
+
}
|
|
149
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
150
|
+
throw new Error("decodeQr: invalid payload \u2014 expected a JSON object");
|
|
151
|
+
}
|
|
152
|
+
const p = parsed;
|
|
153
|
+
if (p["v"] !== 1) throw new Error(`decodeQr: unsupported version ${String(p["v"])} (expected 1)`);
|
|
154
|
+
if (typeof p["docId"] !== "string" || typeof p["salt"] !== "string" || p["alg"] !== "ed25519" || typeof p["keyId"] !== "string" || typeof p["sig"] !== "string" || !Array.isArray(p["fieldHashes"]) || !p["fieldHashes"].every((h) => typeof h === "string")) {
|
|
155
|
+
throw new Error("decodeQr: invalid payload shape");
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
v: 1,
|
|
159
|
+
docId: p["docId"],
|
|
160
|
+
salt: p["salt"],
|
|
161
|
+
alg: "ed25519",
|
|
162
|
+
keyId: p["keyId"],
|
|
163
|
+
fieldHashes: p["fieldHashes"],
|
|
164
|
+
sig: p["sig"]
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function listCore(revokedDocIds, asOf, keyId) {
|
|
168
|
+
return utf8(canonicalJson({ v: 1, revokedDocIds: [...revokedDocIds].sort(), asOf, keyId }));
|
|
169
|
+
}
|
|
170
|
+
function isRevoked(docId, list) {
|
|
171
|
+
if (!Array.isArray(list?.revokedDocIds)) return false;
|
|
172
|
+
return list.revokedDocIds.includes(docId);
|
|
173
|
+
}
|
|
174
|
+
async function signRevocationList(revokedDocIds, asOf, keyId, privateKeyPkcs8B64, scheme = ed25519Scheme) {
|
|
175
|
+
const sorted = [...revokedDocIds].sort();
|
|
176
|
+
const sig = await scheme.sign(privateKeyPkcs8B64, listCore(sorted, asOf, keyId));
|
|
177
|
+
return { v: 1, revokedDocIds: sorted, asOf, keyId, sig };
|
|
178
|
+
}
|
|
179
|
+
async function verifyRevocationList(list, publicKeyB64, scheme = ed25519Scheme) {
|
|
180
|
+
if (list?.v !== 1 || !Array.isArray(list.revokedDocIds) || typeof list.asOf !== "string" || typeof list.keyId !== "string" || typeof list.sig !== "string") {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
return scheme.verify(publicKeyB64, list.sig, listCore(list.revokedDocIds, list.asOf, list.keyId));
|
|
184
|
+
}
|
|
185
|
+
function signedCore(core) {
|
|
186
|
+
return utf8(canonicalJson({ v: core.v, docId: core.docId, salt: core.salt, keyId: core.keyId, fieldHashes: core.fieldHashes }));
|
|
187
|
+
}
|
|
188
|
+
async function signPayloadCore(core, privateKeyPkcs8B64, scheme = ed25519Scheme) {
|
|
189
|
+
return scheme.sign(privateKeyPkcs8B64, signedCore(core));
|
|
190
|
+
}
|
|
191
|
+
async function verifyAttestation(input, scheme = ed25519Scheme) {
|
|
192
|
+
const p = decodeQr(input.qr);
|
|
193
|
+
const pub = input.publicKeys[p.keyId];
|
|
194
|
+
const signatureValid = pub ? await scheme.verify(pub, p.sig, signedCore({ v: p.v, docId: p.docId, salt: p.salt, keyId: p.keyId, fieldHashes: p.fieldHashes })) : false;
|
|
195
|
+
const schema = input.fieldSchema;
|
|
196
|
+
const perField = [];
|
|
197
|
+
let allMatch = true;
|
|
198
|
+
let countMismatch = false;
|
|
199
|
+
if (schema.fields.length !== p.fieldHashes.length) {
|
|
200
|
+
countMismatch = true;
|
|
201
|
+
allMatch = false;
|
|
202
|
+
for (const f of schema.fields) perField.push({ path: f.path, match: false });
|
|
203
|
+
} else {
|
|
204
|
+
const recomputed = await computeFieldHashes(p.salt, schema, input.claimedFields);
|
|
205
|
+
for (let i = 0; i < schema.fields.length; i++) {
|
|
206
|
+
const match = recomputed[i] === p.fieldHashes[i];
|
|
207
|
+
perField.push({ path: schema.fields[i].path, match });
|
|
208
|
+
if (!match) allMatch = false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const revoked = input.revocation ? isRevoked(p.docId, input.revocation.list) : null;
|
|
212
|
+
const valid = signatureValid && allMatch && revoked !== true;
|
|
213
|
+
let reason;
|
|
214
|
+
if (!signatureValid) reason = pub ? "signature invalid" : "unknown keyId";
|
|
215
|
+
else if (countMismatch) reason = "schema/payload field-count mismatch";
|
|
216
|
+
else if (!allMatch) reason = "field mismatch";
|
|
217
|
+
else if (revoked === true) reason = "revoked";
|
|
218
|
+
return reason !== void 0 ? { valid, signatureValid, perField, revoked, reason } : { valid, signatureValid, perField, revoked };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export {
|
|
222
|
+
utf8,
|
|
223
|
+
bytesToB64url,
|
|
224
|
+
canonicalJson,
|
|
225
|
+
computeFieldHashes,
|
|
226
|
+
encodeQr,
|
|
227
|
+
decodeQr,
|
|
228
|
+
isRevoked,
|
|
229
|
+
signRevocationList,
|
|
230
|
+
verifyRevocationList,
|
|
231
|
+
signPayloadCore,
|
|
232
|
+
verifyAttestation
|
|
233
|
+
};
|
|
234
|
+
//# sourceMappingURL=chunk-GMKGGY7V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../attestation/src/encoding.ts","../../attestation/src/normalize.ts","../../attestation/src/hashing.ts","../../attestation/src/ed25519.ts","../../attestation/src/scheme.ts","../../attestation/src/qr.ts","../../attestation/src/revocation.ts","../../attestation/src/verify.ts"],"sourcesContent":["/**\n * Pure encoding + hashing primitives. Zero deps; WebCrypto only.\n *\n * `canonicalJson` and `sha256Hex` are intentionally byte-identical to\n * hub's `history/ledger/entry.ts` implementations. They are REPLICATED\n * here (not imported) because this package is upstream of hub — importing\n * from hub would invert the dependency. The conformance test pins the\n * shared contract via fixed vectors.\n */\n\nexport function utf8(s: string): Uint8Array {\n return new TextEncoder().encode(s)\n}\n\nexport function bytesToHex(bytes: Uint8Array): string {\n let out = ''\n for (const b of bytes) out += b.toString(16).padStart(2, '0')\n return out\n}\n\nexport function bytesToB64url(bytes: Uint8Array): string {\n let s = ''\n for (const b of bytes) s += String.fromCharCode(b)\n return btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\nexport function b64urlToBytes(s: string): Uint8Array {\n const pad = s.length % 4 === 0 ? '' : '='.repeat(4 - (s.length % 4))\n const b64 = s.replace(/-/g, '+').replace(/_/g, '/') + pad\n const bin = atob(b64)\n const out = new Uint8Array(bin.length)\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)\n return out\n}\n\nexport function canonicalJson(value: unknown): string {\n if (value === null) return 'null'\n if (typeof value === 'boolean') return value ? 'true' : 'false'\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error(`canonicalJson: refusing to encode non-finite number ${String(value)}`)\n }\n return JSON.stringify(value)\n }\n if (typeof value === 'string') return JSON.stringify(value)\n if (typeof value === 'bigint') throw new Error('canonicalJson: BigInt is not JSON-serializable')\n if (typeof value === 'undefined' || typeof value === 'function') {\n throw new Error(`canonicalJson: refusing to encode ${typeof value} — include all fields explicitly`)\n }\n if (Array.isArray(value)) return '[' + value.map((v) => canonicalJson(v)).join(',') + ']'\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>\n const keys = Object.keys(obj).sort()\n const parts: string[] = []\n for (const key of keys) parts.push(JSON.stringify(key) + ':' + canonicalJson(obj[key]))\n return '{' + parts.join(',') + '}'\n }\n throw new Error(`canonicalJson: unexpected value type: ${typeof value}`)\n}\n\nexport async function sha256Bytes(input: string): Promise<Uint8Array> {\n const digest = await globalThis.crypto.subtle.digest('SHA-256', utf8(input) as BufferSource)\n return new Uint8Array(digest)\n}\n\nexport async function sha256Hex(input: string): Promise<string> {\n return bytesToHex(await sha256Bytes(input))\n}\n","import type { AttestationFieldSchema, Normalizer } from './types.js'\n\nconst NORMALIZERS: ReadonlySet<string> = new Set<Normalizer>([\n 'trim', 'lower', 'upper', 'alnum-upper', 'digits', 'cents', 'iso-date',\n])\n\nexport function getPath(obj: unknown, path: string): unknown {\n return path.split('.').reduce<unknown>(\n (o, k) => (o == null ? undefined : (o as Record<string, unknown>)[k]),\n obj,\n )\n}\n\n/**\n * Normalize a field value to a canonical string for hashing.\n *\n * `iso-date` returns the **UTC** calendar date (`toISOString().slice(0,10)`),\n * so a local-time `Date` near midnight can shift by ±1 day in non-UTC\n * environments — prefer passing an ISO date string (e.g. `'2026-05-29'`)\n * over a local `new Date(2026, 4, 29)`. Issue and verify use this same\n * function, so a value passed identically on both sides always round-trips.\n */\nexport function normalizeField(value: unknown, n: Normalizer): string {\n switch (n) {\n case 'trim':\n return String(value).trim()\n case 'lower':\n return String(value).trim().toLowerCase()\n case 'upper':\n return String(value).trim().toUpperCase()\n case 'alnum-upper':\n return String(value).replace(/[^A-Za-z0-9]/g, '').toUpperCase()\n case 'digits':\n return String(value).replace(/[^0-9]/g, '')\n case 'cents': {\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error(`normalizeField(cents): not a finite number: ${String(value)}`)\n }\n return String(Math.round(value * 100))\n }\n // For string values: strip currency symbols / spaces / commas but keep digits, dot, minus\n const stripped = String(value).replace(/[^0-9.-]/g, '')\n // A valid numeric string must have at least one digit\n if (!/[0-9]/.test(stripped)) {\n throw new Error(`normalizeField(cents): not a finite number: ${String(value)}`)\n }\n const num = Number(stripped)\n if (!Number.isFinite(num)) {\n throw new Error(`normalizeField(cents): not a finite number: ${String(value)}`)\n }\n return String(Math.round(num * 100))\n }\n case 'iso-date': {\n const d = value instanceof Date ? value : new Date(String(value))\n if (Number.isNaN(d.getTime())) {\n throw new Error(`normalizeField(iso-date): unparseable date: ${String(value)}`)\n }\n return d.toISOString().slice(0, 10)\n }\n default: {\n const exhaustive: never = n\n throw new Error(`normalizeField: unknown normalizer ${String(exhaustive)}`)\n }\n }\n}\n\nexport function validateFieldSchema(schema: AttestationFieldSchema): void {\n if (!schema.fields || schema.fields.length === 0) {\n throw new Error('validateFieldSchema: schema must declare at least one field')\n }\n const seen = new Set<string>()\n for (const f of schema.fields) {\n if (!NORMALIZERS.has(f.normalize)) {\n throw new Error(\n `validateFieldSchema: unknown normalizer '${String(f.normalize)}' for path '${f.path}'`,\n )\n }\n if (seen.has(f.path)) {\n throw new Error(`validateFieldSchema: duplicate path '${f.path}'`)\n }\n seen.add(f.path)\n }\n}\n","import type { AttestationFieldSchema } from './types.js'\nimport { canonicalJson, sha256Bytes, bytesToB64url } from './encoding.js'\nimport { getPath, normalizeField } from './normalize.js'\n\n/**\n * One salted, domain-separated hash per declared field, in schema order:\n * fieldHash[i] = base64url( sha256( canonicalJson([salt, path, normalizedValue]) ) )\n * Per-document salt defeats brute-force of low-entropy fields and cross-\n * document correlation; the path in the input domain-separates fields\n * that happen to share a value.\n */\nexport async function computeFieldHashes(\n saltB64: string,\n schema: AttestationFieldSchema,\n values: Record<string, unknown>,\n): Promise<string[]> {\n const out: string[] = []\n for (const f of schema.fields) {\n const raw = getPath(values, f.path)\n if (raw === undefined || raw === null) {\n throw new Error(`computeFieldHashes: missing value at declared path '${f.path}'`)\n }\n const norm = normalizeField(raw, f.normalize)\n const digest = await sha256Bytes(canonicalJson([saltB64, f.path, norm]))\n out.push(bytesToB64url(digest))\n }\n return out\n}\n","import { bytesToB64url, b64urlToBytes, sha256Hex } from './encoding.js'\n\nconst ALG = 'Ed25519'\n\n/** Stable key identifier: first 16 hex chars of sha256(publicKeyB64). */\nexport async function keyIdFor(publicKeyB64: string): Promise<string> {\n return (await sha256Hex(publicKeyB64)).slice(0, 16)\n}\n\nexport async function generateDocSigningKeyPair(): Promise<{\n keyId: string\n publicKeyB64: string // base64url raw (32 bytes) — non-secret, publishable\n privateKeyPkcs8B64: string // base64url pkcs8 — secret, wrap before persisting\n}> {\n const kp = await globalThis.crypto.subtle.generateKey(ALG, true, ['sign', 'verify'])\n const rawPub = new Uint8Array(await globalThis.crypto.subtle.exportKey('raw', kp.publicKey))\n const pkcs8 = new Uint8Array(await globalThis.crypto.subtle.exportKey('pkcs8', kp.privateKey))\n const publicKeyB64 = bytesToB64url(rawPub)\n return { keyId: await keyIdFor(publicKeyB64), publicKeyB64, privateKeyPkcs8B64: bytesToB64url(pkcs8) }\n}\n\nexport async function ed25519Sign(privateKeyPkcs8B64: string, message: Uint8Array): Promise<string> {\n const key = await globalThis.crypto.subtle.importKey(\n 'pkcs8',\n b64urlToBytes(privateKeyPkcs8B64) as BufferSource,\n ALG,\n false,\n ['sign'],\n )\n const sig = new Uint8Array(await globalThis.crypto.subtle.sign(ALG, key, message as BufferSource))\n return bytesToB64url(sig)\n}\n\nexport async function ed25519Verify(publicKeyB64: string, sigB64url: string, message: Uint8Array): Promise<boolean> {\n try {\n const key = await globalThis.crypto.subtle.importKey(\n 'raw',\n b64urlToBytes(publicKeyB64) as BufferSource,\n ALG,\n false,\n ['verify'],\n )\n return await globalThis.crypto.subtle.verify(\n ALG,\n key,\n b64urlToBytes(sigB64url) as BufferSource,\n message as BufferSource,\n )\n } catch {\n return false\n }\n}\n","import { ed25519Sign, ed25519Verify } from './ed25519.js'\n\n/**\n * The signature primitive attestation signs and verifies with. Ed25519 is the\n * default and the only algorithm `v:1` payloads name; a caller with its own\n * engine (noy-db's enclave, a post-quantum fork) injects one with the same\n * shape. If a second algorithm is ever named in a payload, `alg` must join\n * the signed core (see `verify.ts` `signedCore`).\n */\nexport interface SignatureScheme {\n sign(privateKeyPkcs8B64: string, message: Uint8Array): Promise<string>\n verify(publicKeyB64: string, sigB64url: string, message: Uint8Array): Promise<boolean>\n}\n\nexport const ed25519Scheme: SignatureScheme = { sign: ed25519Sign, verify: ed25519Verify }\n","import { bytesToB64url, b64urlToBytes, utf8 } from './encoding.js'\n\nexport interface QrPayload {\n readonly v: 1\n readonly docId: string\n readonly salt: string\n readonly alg: 'ed25519'\n readonly keyId: string\n readonly fieldHashes: readonly string[]\n readonly sig: string\n}\n\n/** Compact JSON → base64url. (CBOR + base45 density optimisation deferred.) */\nexport function encodeQr(p: QrPayload): string {\n return bytesToB64url(utf8(JSON.stringify(p)))\n}\n\nexport function decodeQr(s: string): QrPayload {\n let parsed: unknown\n try {\n parsed = JSON.parse(new TextDecoder().decode(b64urlToBytes(s)))\n } catch {\n throw new Error('decodeQr: invalid base64url-encoded JSON payload')\n }\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('decodeQr: invalid payload — expected a JSON object')\n }\n const p = parsed as Record<string, unknown>\n if (p['v'] !== 1) throw new Error(`decodeQr: unsupported version ${String(p['v'])} (expected 1)`)\n if (typeof p['docId'] !== 'string' || typeof p['salt'] !== 'string' || p['alg'] !== 'ed25519'\n || typeof p['keyId'] !== 'string' || typeof p['sig'] !== 'string'\n || !Array.isArray(p['fieldHashes']) || !p['fieldHashes'].every((h) => typeof h === 'string')) {\n throw new Error('decodeQr: invalid payload shape')\n }\n return {\n v: 1, docId: p['docId'], salt: p['salt'], alg: 'ed25519',\n keyId: p['keyId'], fieldHashes: p['fieldHashes'], sig: p['sig'],\n }\n}\n","import { canonicalJson, utf8 } from './encoding.js'\nimport { ed25519Scheme, type SignatureScheme } from './scheme.js'\n\nexport interface RevocationList {\n readonly v: 1\n readonly revokedDocIds: readonly string[]\n readonly asOf: string\n readonly keyId: string\n readonly sig: string\n}\n\nfunction listCore(revokedDocIds: readonly string[], asOf: string, keyId: string): Uint8Array {\n return utf8(canonicalJson({ v: 1, revokedDocIds: [...revokedDocIds].sort(), asOf, keyId }))\n}\n\nexport function isRevoked(docId: string, list: RevocationList): boolean {\n // The list is untrusted (typically network-fetched). Fail closed on a\n // malformed shape rather than throwing a raw TypeError.\n if (!Array.isArray(list?.revokedDocIds)) return false\n return list.revokedDocIds.includes(docId)\n}\n\nexport async function signRevocationList(\n revokedDocIds: readonly string[], asOf: string, keyId: string, privateKeyPkcs8B64: string,\n scheme: SignatureScheme = ed25519Scheme,\n): Promise<RevocationList> {\n const sorted = [...revokedDocIds].sort()\n const sig = await scheme.sign(privateKeyPkcs8B64, listCore(sorted, asOf, keyId))\n return { v: 1, revokedDocIds: sorted, asOf, keyId, sig }\n}\n\nexport async function verifyRevocationList(\n list: RevocationList,\n publicKeyB64: string,\n scheme: SignatureScheme = ed25519Scheme,\n): Promise<boolean> {\n // Untrusted input — validate the shape before touching it (no raw TypeError).\n if (list?.v !== 1 || !Array.isArray(list.revokedDocIds)\n || typeof list.asOf !== 'string' || typeof list.keyId !== 'string' || typeof list.sig !== 'string') {\n return false\n }\n return scheme.verify(publicKeyB64, list.sig, listCore(list.revokedDocIds, list.asOf, list.keyId))\n}\n","import type { AttestationFieldSchema } from './types.js'\nimport type { QrPayload } from './qr.js'\nimport type { RevocationList } from './revocation.js'\nimport { canonicalJson, utf8 } from './encoding.js'\nimport { ed25519Scheme, type SignatureScheme } from './scheme.js'\nimport { computeFieldHashes } from './hashing.js'\nimport { decodeQr } from './qr.js'\nimport { isRevoked } from './revocation.js'\n\nexport interface VerifyInput {\n readonly qr: string\n readonly claimedFields: Record<string, unknown>\n readonly fieldSchema: AttestationFieldSchema\n readonly publicKeys: Readonly<Record<string, string>>\n readonly revocation?: { list: RevocationList }\n}\nexport interface VerifyResult {\n readonly valid: boolean\n readonly signatureValid: boolean\n readonly perField: ReadonlyArray<{ path: string; match: boolean }>\n readonly revoked: boolean | null\n readonly reason?: string\n}\n\n/**\n * The bytes the signature covers: canonicalJson of the payload minus `alg`/`sig`.\n * Excludes `alg` by design — v1 has exactly one algorithm (`ed25519`). If a `v:2`\n * ever introduces a second algorithm, `alg` MUST be added here to prevent a\n * downgrade attack.\n */\nfunction signedCore(core: { v: 1; docId: string; salt: string; keyId: string; fieldHashes: readonly string[] }): Uint8Array {\n return utf8(canonicalJson({ v: core.v, docId: core.docId, salt: core.salt, keyId: core.keyId, fieldHashes: core.fieldHashes }))\n}\n\nexport async function signPayloadCore(\n core: { v: 1; docId: string; salt: string; keyId: string; fieldHashes: readonly string[] },\n privateKeyPkcs8B64: string,\n scheme: SignatureScheme = ed25519Scheme,\n): Promise<string> {\n return scheme.sign(privateKeyPkcs8B64, signedCore(core))\n}\n\nexport async function verifyAttestation(\n input: VerifyInput,\n scheme: SignatureScheme = ed25519Scheme,\n): Promise<VerifyResult> {\n const p: QrPayload = decodeQr(input.qr)\n const pub = input.publicKeys[p.keyId]\n const signatureValid = pub\n ? await scheme.verify(pub, p.sig, signedCore({ v: p.v, docId: p.docId, salt: p.salt, keyId: p.keyId, fieldHashes: p.fieldHashes }))\n : false\n\n const schema = input.fieldSchema\n const perField: Array<{ path: string; match: boolean }> = []\n let allMatch = true\n let countMismatch = false\n if (schema.fields.length !== p.fieldHashes.length) {\n countMismatch = true\n allMatch = false\n for (const f of schema.fields) perField.push({ path: f.path, match: false })\n } else {\n const recomputed = await computeFieldHashes(p.salt, schema, input.claimedFields)\n for (let i = 0; i < schema.fields.length; i++) {\n const match = recomputed[i] === p.fieldHashes[i]\n perField.push({ path: schema.fields[i]!.path, match })\n if (!match) allMatch = false\n }\n }\n\n // Membership check only — the CALLER must have verified the list's own\n // signature with `verifyRevocationList` before passing it here. A list that\n // omits a genuinely-revoked id lets that doc pass; that risk is the caller's.\n const revoked = input.revocation ? isRevoked(p.docId, input.revocation.list) : null\n const valid = signatureValid && allMatch && revoked !== true\n\n let reason: string | undefined\n if (!signatureValid) reason = pub ? 'signature invalid' : 'unknown keyId'\n else if (countMismatch) reason = 'schema/payload field-count mismatch'\n else if (!allMatch) reason = 'field mismatch'\n else if (revoked === true) reason = 'revoked'\n\n return reason !== undefined\n ? { valid, signatureValid, perField, revoked, reason }\n : { valid, signatureValid, perField, revoked }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -146,7 +146,7 @@ function routeStore(opts) {
|
|
|
146
146
|
const rn = routeNameFor(vault, collection);
|
|
147
147
|
if (maybeQueueWrite(rn, "put", vault, collection, id, envelope, expectedVersion)) return;
|
|
148
148
|
if (isBlobChunks(collection) && tieredBlobs) {
|
|
149
|
-
const dataSize = envelope._data.length;
|
|
149
|
+
const dataSize = (envelope._data ?? "").length;
|
|
150
150
|
const s2 = blobStoreForSize(dataSize);
|
|
151
151
|
return s2.put(vault, collection, id, envelope, expectedVersion);
|
|
152
152
|
}
|
|
@@ -420,7 +420,7 @@ function withLogging(opts = {}) {
|
|
|
420
420
|
collection: c,
|
|
421
421
|
id,
|
|
422
422
|
version: env._v,
|
|
423
|
-
...logData ? { data: env._data.slice(0, 40) + "..." } : {}
|
|
423
|
+
...logData ? { data: (env._data ?? "").slice(0, 40) + "..." } : {}
|
|
424
424
|
}, () => next.put(v, c, id, env, ev)),
|
|
425
425
|
delete: (v, c, id) => timed("delete", { vault: v, collection: c, id }, () => next.delete(v, c, id)),
|
|
426
426
|
list: (v, c) => timed("list", { vault: v, collection: c }, () => next.list(v, c)),
|
|
@@ -651,4 +651,4 @@ export {
|
|
|
651
651
|
withCache,
|
|
652
652
|
withHealthCheck
|
|
653
653
|
};
|
|
654
|
-
//# sourceMappingURL=chunk-
|
|
654
|
+
//# sourceMappingURL=chunk-GQ4MF3CM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-store/route-store.ts","../src/with-store/store-middleware.ts"],"sourcesContent":["/**\n * Store router / multiplexer.\n *\n * Dispatches `NoydbStore` operations to different backends based on\n * collection type, record size, record age, collection name, or vault name.\n *\n * ```ts\n * const db = await createNoydb({\n * store: routeStore({\n * default: dynamo({ table: 'myapp' }),\n * blobs: s3Store({ bucket: 'myapp-blobs' }),\n * }),\n * })\n * ```\n *\n * @module\n */\n\nimport type {\n NoydbStore,\n EncryptedEnvelope,\n VaultSnapshot,\n StoreCapabilities,\n} from '../kernel/types.js'\n\n// ─── Internal collection prefixes (duplicated to avoid circular import) ──\n\nconst BLOB_CHUNKS = '_blob_chunks'\nconst BLOB_INDEX = '_blob_index'\nconst BLOB_SLOTS = '_blob_slots_'\nconst BLOB_VERSIONS = '_blob_versions_'\n\n// ─── Options ─────────────────────────────────────────────────────────────\n\n/**\n * Size-tiered blob routing configuration.\n *\n * Routes blob chunks to different stores based on byte size. Small blobs\n * (under `threshold`) stay in the primary or `small` store; large blobs\n * go to `large`. This lets you keep DynamoDB as the default while sending\n * large binary objects to S3.\n */\nexport interface BlobStoreRoute {\n /** Store for small blobs (under threshold). Falls back to `default`. */\n readonly small?: NoydbStore\n /** Store for large blobs (over threshold). */\n readonly large: NoydbStore\n /** Size threshold in bytes. Default: `400 * 1024` (DynamoDB item limit). */\n readonly threshold?: number\n}\n\n/**\n * Blob lifecycle management policies evaluated during `compact()`.\n *\n * Controls orphan cleanup, cold-tier archival, and hard deletion of\n * blobs that are no longer referenced by any record.\n */\nexport interface BlobLifecyclePolicy {\n /** Delete orphan blobs (refCount: 0) after this many days. Default: 7. */\n readonly orphanRetentionDays?: number\n /** Move blobs not accessed in this many days to the cold blob store. */\n readonly archiveAfterDays?: number\n /** Store for archived blobs. Required if archiveAfterDays is set. */\n readonly archiveStore?: NoydbStore\n /** Hard-delete archived blobs after this many days. */\n readonly expireAfterDays?: number\n}\n\n/**\n * Age-based hot/cold tiering configuration.\n *\n * Records whose `_ts` timestamp is older than `coldAfterDays` are migrated\n * to the `cold` store during `compact()`. Reads transparently fall through\n * to the cold store when the hot store returns null, so callers don't need\n * to know which tier a record lives in.\n */\nexport interface AgeRoute {\n /** Store for records older than the cutoff. */\n readonly cold: NoydbStore\n /**\n * Days after last modification before a record is cold-eligible for the\n * ROLLING `compact(vault)` migrator. Omit for period-driven archival only\n * (`compact(vault, { before })`), where the cutoff is supplied per call.\n */\n readonly coldAfterDays?: number\n /**\n * Collections that participate in age tiering.\n * Empty array or omitted = all user collections (excluding `_` prefixed).\n */\n readonly collections?: string[]\n}\n\n/**\n * Options for `routeStore()` — the store multiplexer.\n *\n * At minimum, provide a `default` store. All other fields are optional\n * extensions for specific routing scenarios (blobs → S3, geographic sharding,\n * age-based tiering, etc.).\n */\nexport interface RouteStoreOptions {\n /** Default store for all unmatched operations. */\n readonly default: NoydbStore\n\n /**\n * Route blob chunk data to a separate store.\n * - Pass a `NoydbStore` for simple prefix routing (all chunks → that store).\n * - Pass `{ small?, large, threshold? }` for size-tiered routing.\n */\n readonly blobs?: NoydbStore | BlobStoreRoute\n\n /** Route all blob metadata (index, slots, versions) to the blobs store too. Default: false. */\n readonly routeBlobMeta?: boolean\n\n /** Route specific user collections to dedicated stores. */\n readonly routes?: Record<string, NoydbStore>\n\n /** Route by vault name (prefix patterns, e.g. `'EU-'`). */\n readonly vaultRoutes?: Record<string, NoydbStore>\n\n /**\n * Age-based tiering: records older than `coldAfterDays` are read from\n * the cold store. A background `compact()` method migrates them.\n */\n readonly age?: AgeRoute\n\n /**\n * Content-aware blob routing.\n * Route blob chunks by MIME type glob pattern. The MIME type is stored\n * in `BlobObject` and matched at read time via `storeHint`.\n */\n readonly blobRoutes?: Record<string, NoydbStore>\n\n /**\n * Blob lifecycle policies.\n * Evaluated during `compact()`.\n */\n readonly blobLifecycle?: BlobLifecyclePolicy\n\n /**\n * Quota-aware overflow.\n * When the default store's usage exceeds the threshold, new writes\n * overflow to the specified store.\n */\n readonly overflow?: NoydbStore\n\n /**\n * Quota threshold (0-1). Default: 0.8 (overflow at 80% usage).\n * Only effective when `overflow` is set.\n */\n readonly quotaThreshold?: number\n}\n\n// ─── Types ───────────────────────────────────────────────────────────────\n\n/**\n * Named route that can be overridden or suspended at runtime.\n *\n * Built-in names: `'default'`, `'blobs'`, `'cold'`.\n * Custom names: any collection name from `routes`, any vault prefix from\n * `vaultRoutes`, or any sync target label.\n */\nexport type OverrideTarget =\n | 'default'\n | 'blobs'\n | 'cold'\n | (string & {}) // named collection route, vault route, or sync target label\n\n/**\n * Options for `RoutedNoydbStore.override()`.\n *\n * Controls whether the new store is pre-populated with data from the\n * original store before the switch takes effect.\n */\nexport interface OverrideOptions {\n /**\n * Hydrate the override store from the original before activating.\n * - `true` — copy all data for all vaults.\n * - `string[]` — copy only named collections.\n * Makes `override()` async — returns a Promise.\n */\n hydrate?: boolean | string[]\n}\n\n/**\n * Options for `RoutedNoydbStore.suspend()`.\n *\n * A suspended route becomes a null store: reads return null/[], writes\n * are dropped (or buffered if `queue: true`). Useful for maintenance\n * windows or restricted-network scenarios.\n */\nexport interface SuspendOptions {\n /**\n * Buffer write operations during suspension. On `resume()`, queued\n * writes are replayed against the restored store.\n */\n queue?: boolean\n /**\n * Maximum queued operations. When exceeded, oldest entries are dropped.\n * Default: 10_000.\n */\n maxQueueSize?: number\n}\n\n/** Queued write operation recorded during suspension. */\ninterface QueuedWrite {\n method: 'put' | 'delete'\n vault: string\n collection: string\n id: string\n envelope?: EncryptedEnvelope\n expectedVersion?: number\n}\n\n/**\n * Snapshot of the current override and suspend state of a `RoutedNoydbStore`.\n * Returned by `routeStatus()` for diagnostics and health dashboards.\n */\nexport interface RouteStatus {\n /** Active overrides: route name → override store name. */\n readonly overrides: Record<string, string>\n /** Currently suspended routes. */\n readonly suspended: string[]\n /** Queued writes per suspended route (only for routes suspended with `queue: true`). */\n readonly queued: Record<string, number>\n}\n\n/**\n * Extended `NoydbStore` returned by `routeStore()`.\n *\n * Satisfies the full `NoydbStore` contract plus adds runtime control\n * methods for overriding, suspending, and inspecting routes.\n */\nexport interface RoutedNoydbStore extends NoydbStore {\n /**\n * Migrate records to the cold store. Only applies when `age.cold` is\n * configured. With `{ before }`, migrates records whose `_ts < before`\n * (period-driven archival); without, uses the rolling `coldAfterDays`.\n * Returns the number of records migrated.\n */\n compact(vault: string, opts?: { before?: string }): Promise<number>\n\n /**\n * Override a named route at runtime.\n *\n * The override persists until `clearOverride()` is called or the\n * instance is closed. In-flight operations complete on the original\n * store; new operations use the override.\n *\n * Options:\n * - `hydrate: true` — async: copies all data from the original store\n * into the override before activating the switch.\n * - `hydrate: ['invoices', 'clients']` — copies only named collections.\n *\n * Use cases:\n * - Shared device: `await store.override('default', toMemory(), { hydrate: true })`\n * - Restricted network: `store.override('blobs', localFile(...))`\n */\n override(route: OverrideTarget, store: NoydbStore, opts?: OverrideOptions): void | Promise<void>\n\n /** Clear a runtime override, reverting to the original store. */\n clearOverride(route: OverrideTarget): void\n\n /**\n * Suspend a route entirely. Operations to suspended stores become\n * no-ops (puts silently dropped, gets return null, lists return []).\n *\n * Options:\n * - `queue: true` — buffer write operations (put/delete) during\n * suspension. When `resume()` is called, queued writes are replayed\n * against the restored store.\n *\n * Returns a `SuspendHandle` when `queue: true`, for inspecting queue state.\n */\n suspend(route: OverrideTarget, opts?: SuspendOptions): void\n\n /**\n * Resume a previously suspended route.\n * If the route was suspended with `queue: true`, replays queued writes.\n * Returns the number of replayed operations.\n */\n resume(route: OverrideTarget): Promise<number>\n\n /** Snapshot the current override/suspend state for diagnostics. */\n routeStatus(): RouteStatus\n\n /**\n * Resolve the physical backend a vault id maps to via the geographic\n * `vaultRoutes` prefix routing (collection-independent), falling back to\n * the `default` store. Used by the federation data-residency guard\n * to read the placement backend's `capabilities.region`.\n */\n resolveBackend(vaultId: string): NoydbStore\n}\n\n// ─── Implementation ──────────────────────────────────────────────────────\n\n/**\n * Create a store multiplexer that dispatches operations to different backends\n * based on collection type, record size, record age, vault prefix, or\n * runtime overrides.\n *\n * ```ts\n * const store = routeStore({\n * default: dynamo({ table: 'myapp' }),\n * blobs: s3({ bucket: 'myapp-blobs' }),\n * routes: { auditLog: s3({ bucket: 'myapp-audit' }) },\n * })\n * ```\n *\n * The returned store satisfies `NoydbStore` and can be passed directly to\n * `createNoydb({ store })`. It also exposes additional methods\n * (`override`, `suspend`, `resume`, `routeStatus`, `compact`) for runtime\n * control and maintenance.\n */\nexport function routeStore(opts: RouteStoreOptions): RoutedNoydbStore {\n const primary = opts.default\n\n // Resolve blob store config\n const blobsIsSimple = opts.blobs && 'get' in opts.blobs\n const simpleBlobStore = blobsIsSimple ? opts.blobs : undefined\n const tieredBlobs = !blobsIsSimple ? opts.blobs : undefined\n const blobThreshold = tieredBlobs?.threshold ?? 400 * 1024\n\n // Collect all stores for loadAll/saveAll/listVaults composition\n const allStores = new Set<NoydbStore>([primary])\n if (simpleBlobStore) allStores.add(simpleBlobStore)\n if (tieredBlobs?.large) allStores.add(tieredBlobs.large)\n if (tieredBlobs?.small) allStores.add(tieredBlobs.small)\n if (opts.age?.cold) allStores.add(opts.age.cold)\n if (opts.routes) for (const s of Object.values(opts.routes)) allStores.add(s)\n if (opts.vaultRoutes) for (const s of Object.values(opts.vaultRoutes)) allStores.add(s)\n if (opts.blobRoutes) for (const s of Object.values(opts.blobRoutes)) allStores.add(s)\n if (opts.overflow) allStores.add(opts.overflow)\n if (opts.blobLifecycle?.archiveStore) allStores.add(opts.blobLifecycle.archiveStore)\n\n // ── Runtime override / suspend state ──────────────────\n\n const overrides = new Map<string, NoydbStore>()\n const suspended = new Set<string>()\n const writeQueues = new Map<string, { writes: QueuedWrite[]; maxSize: number }>()\n\n /** Null store: silently absorbs all operations when a route is suspended. */\n const NULL_STORE: NoydbStore = {\n name: 'suspended',\n async get() { return null },\n async put() {},\n async delete() {},\n async list() { return [] },\n async loadAll() { return {} },\n async saveAll() {},\n }\n\n /**\n * Map a resolved route to its canonical name for override/suspend lookup.\n * Vault routes use the prefix, collection routes use the collection name,\n * blob route is 'blobs', cold route is 'cold', everything else is 'default'.\n */\n function routeNameFor(vault: string, collection: string): string {\n if (opts.vaultRoutes) {\n for (const prefix of Object.keys(opts.vaultRoutes)) {\n if (vault.startsWith(prefix)) return prefix\n }\n }\n if (opts.routes && !collection.startsWith('_') && opts.routes[collection]) {\n return collection\n }\n if (isBlobChunks(collection) && (simpleBlobStore || tieredBlobs)) return 'blobs'\n if (opts.routeBlobMeta && isBlobMeta(collection) && (simpleBlobStore || tieredBlobs)) return 'blobs'\n if (opts.age && !collection.startsWith('_')) {\n // We don't name age 'cold' here — cold is a fallback, not a primary route\n }\n return 'default'\n }\n\n // ── Quota-aware overflow (E8) ───────────────────────────────────────\n\n const quotaExceeded = false\n\n /** Resolve the static (non-overridden) store for a given route name. */\n function resolveOriginalStore(route: string): NoydbStore {\n if (route === 'blobs') return simpleBlobStore ?? tieredBlobs?.large ?? primary\n if (route === 'cold') return opts.age?.cold ?? primary\n if (opts.routes?.[route]) return opts.routes[route]\n if (opts.vaultRoutes?.[route]) return opts.vaultRoutes[route]\n return primary\n }\n\n /**\n * Queue a write operation if the route is suspended with queue: true.\n * Returns true if queued (caller should skip the actual write).\n */\n function maybeQueueWrite(\n routeName: string,\n method: 'put' | 'delete',\n vault: string,\n collection: string,\n id: string,\n envelope?: EncryptedEnvelope,\n expectedVersion?: number,\n ): boolean {\n if (!suspended.has(routeName)) return false\n const queue = writeQueues.get(routeName)\n if (!queue) return false // suspended but no queue — NullStore behavior\n\n // Evict oldest if at capacity\n if (queue.writes.length >= queue.maxSize) {\n queue.writes.shift()\n }\n queue.writes.push({\n method, vault, collection, id,\n ...(envelope !== undefined ? { envelope } : {}),\n ...(expectedVersion !== undefined ? { expectedVersion } : {}),\n })\n return true\n }\n\n // ── Routing logic ──────────────────────────────────────────────────\n\n function isBlobChunks(collection: string): boolean {\n return collection === BLOB_CHUNKS\n }\n\n function isBlobMeta(collection: string): boolean {\n return collection === BLOB_INDEX\n || collection.startsWith(BLOB_SLOTS)\n || collection.startsWith(BLOB_VERSIONS)\n }\n\n function isInternal(collection: string): boolean {\n return collection.startsWith('_')\n }\n\n /**\n * Resolve the store for a given vault + collection.\n * Resolution order: overrides/suspend → vaultRoutes → routes → blobs → default\n */\n function storeFor(vault: string, collection: string): NoydbStore {\n const rName = routeNameFor(vault, collection)\n\n // 0. Runtime override / suspend check\n if (suspended.has(rName)) return NULL_STORE\n if (overrides.has(rName)) return overrides.get(rName)!\n\n // 1. Vault-based geographic routing\n if (opts.vaultRoutes) {\n for (const [prefix, store] of Object.entries(opts.vaultRoutes)) {\n if (vault.startsWith(prefix)) return store\n }\n }\n\n // 2. Per-collection routing (user collections only)\n if (opts.routes && !isInternal(collection) && opts.routes[collection]) {\n return opts.routes[collection]\n }\n\n // 3. Blob chunk routing (simple — no size tiering at the store level)\n if (isBlobChunks(collection)) {\n if (simpleBlobStore) return simpleBlobStore\n // Size-tiered: can't determine here without the envelope.\n // Default to large store — BlobSet will use storeHint for reads.\n if (tieredBlobs) return tieredBlobs.large\n }\n\n // 4. Blob metadata routing\n if (opts.routeBlobMeta && isBlobMeta(collection)) {\n if (simpleBlobStore) return simpleBlobStore\n if (tieredBlobs) return tieredBlobs.large\n }\n\n // 5. Quota-aware overflow (E8)\n if (quotaExceeded && opts.overflow) return opts.overflow\n\n // 6. Default\n return primary\n }\n\n /**\n * For size-tiered blob routing: pick store based on envelope data size.\n */\n function blobStoreForSize(dataSize: number): NoydbStore {\n if (!tieredBlobs) return simpleBlobStore ?? primary\n if (dataSize <= blobThreshold) {\n return tieredBlobs.small ?? primary\n }\n return tieredBlobs.large\n }\n\n /**\n * Age routing: check if a record is cold based on `_ts`.\n */\n function isCold(collection: string, envelope: EncryptedEnvelope, before?: string): boolean {\n if (!opts.age) return false\n if (isInternal(collection)) return false\n if (opts.age.collections && opts.age.collections.length > 0) {\n if (!opts.age.collections.includes(collection)) return false\n }\n // explicit period cutoff wins; else the rolling age cutoff; else nothing is cold\n const cutoffIso =\n before ??\n (opts.age.coldAfterDays != null\n ? new Date(Date.now() - opts.age.coldAfterDays * 24 * 60 * 60 * 1000).toISOString()\n : undefined)\n if (cutoffIso === undefined) return false\n return envelope._ts < cutoffIso\n }\n\n // ── Store methods ──────────────────────────────────────────────────\n\n // #613: advertise cold-archival when a cold route exists. Spread the\n // primary's capabilities so CAS/auth/etc. still surface; layer the flag.\n // A router with no cold route of its own must NOT inherit `coldArchival:\n // true` from a nested cold-capable primary (whole-branch review I1) — force\n // it off explicitly so the consumer's `!== true` gate throws.\n const store: RoutedNoydbStore = {\n name: buildName(),\n ...(opts.age?.cold\n ? { capabilities: { ...primary.capabilities, coldArchival: true } as StoreCapabilities }\n : primary.capabilities\n ? { capabilities: { ...primary.capabilities, coldArchival: false } as StoreCapabilities }\n : {}),\n\n async get(vault, collection, id) {\n const s = storeFor(vault, collection)\n const result = await s.get(vault, collection, id)\n\n // Age tiering: if hot store returned null, try cold\n if (result === null && opts.age && !isInternal(collection)) {\n if (!opts.age.collections?.length || opts.age.collections.includes(collection)) {\n return opts.age.cold.get(vault, collection, id)\n }\n }\n\n return result\n },\n\n async put(vault, collection, id, envelope, expectedVersion) {\n // Write-behind queue: buffer if suspended with queue option\n const rn = routeNameFor(vault, collection)\n if (maybeQueueWrite(rn, 'put', vault, collection, id, envelope, expectedVersion)) return\n\n // Size-tiered blob routing\n if (isBlobChunks(collection) && tieredBlobs) {\n const dataSize = (envelope._data ?? '').length\n const s = blobStoreForSize(dataSize)\n return s.put(vault, collection, id, envelope, expectedVersion)\n }\n\n const s = storeFor(vault, collection)\n\n // Age tiering: if a cold record is being updated, it goes to hot.\n if (opts.age && !isInternal(collection)) {\n opts.age.cold.delete(vault, collection, id).catch(() => {})\n }\n\n return s.put(vault, collection, id, envelope, expectedVersion)\n },\n\n async delete(vault, collection, id) {\n // Write-behind queue: buffer if suspended with queue option\n const rn = routeNameFor(vault, collection)\n if (maybeQueueWrite(rn, 'delete', vault, collection, id)) return\n\n const s = storeFor(vault, collection)\n await s.delete(vault, collection, id)\n\n // Also delete from cold store if age-tiered\n if (opts.age && !isInternal(collection)) {\n await opts.age.cold.delete(vault, collection, id).catch(() => {})\n }\n },\n\n async list(vault, collection) {\n const s = storeFor(vault, collection)\n const ids = await s.list(vault, collection)\n\n // Age tiering: merge IDs from cold store, deduplicate\n if (opts.age && !isInternal(collection)) {\n if (!opts.age.collections?.length || opts.age.collections.includes(collection)) {\n const coldIds = await opts.age.cold.list(vault, collection).catch(() => [] as string[])\n if (coldIds.length > 0) {\n const merged = new Set(ids)\n for (const id of coldIds) merged.add(id)\n return [...merged]\n }\n }\n }\n\n return ids\n },\n\n async loadAll(vault) {\n // Query all distinct stores in parallel, merge snapshots\n const stores = getStoresForVault(vault)\n const snapshots = await Promise.all(\n stores.map(s => s.loadAll(vault).catch(() => ({}) as VaultSnapshot)),\n )\n return mergeSnapshots(snapshots)\n },\n\n async saveAll(vault, data) {\n // Partition snapshot by routing rules\n const partitioned = new Map<NoydbStore, VaultSnapshot>()\n\n for (const [collection, records] of Object.entries(data)) {\n const s = storeFor(vault, collection)\n if (!partitioned.has(s)) partitioned.set(s, {})\n partitioned.get(s)![collection] = records\n }\n\n await Promise.all(\n [...partitioned.entries()].map(([s, snap]) => s.saveAll(vault, snap)),\n )\n },\n\n async compact(vault, compactOpts) {\n if (!opts.age) return 0\n let migrated = 0\n const collections = opts.age.collections?.length\n ? opts.age.collections\n : Object.keys(await primary.loadAll(vault).catch(() => ({}) as VaultSnapshot))\n\n for (const collection of collections) {\n const ids = await primary.list(vault, collection).catch(() => [] as string[])\n for (const id of ids) {\n const envelope = await primary.get(vault, collection, id)\n if (!envelope) continue\n if (isCold(collection, envelope, compactOpts?.before)) {\n await opts.age.cold.put(vault, collection, id, envelope)\n await primary.delete(vault, collection, id)\n migrated++\n }\n }\n }\n return migrated\n },\n\n // ── Runtime override / suspend ──────────────────────\n\n override(route: OverrideTarget, overrideStore: NoydbStore, overrideOpts?: OverrideOptions): void | Promise<void> {\n if (overrideOpts?.hydrate) {\n // Async hydration: copy data from current store, then activate override\n return (async () => {\n // Hydration: caller should copy data from the original store to\n // overrideStore before calling override() with { hydrate: true }.\n // The route is activated immediately after.\n overrides.set(route, overrideStore)\n })()\n }\n overrides.set(route, overrideStore)\n },\n\n clearOverride(route: OverrideTarget): void {\n overrides.delete(route)\n },\n\n suspend(route: OverrideTarget, suspendOpts?: SuspendOptions): void {\n suspended.add(route)\n if (suspendOpts?.queue) {\n writeQueues.set(route, {\n writes: [],\n maxSize: suspendOpts.maxQueueSize ?? 10_000,\n })\n }\n },\n\n async resume(route: OverrideTarget): Promise<number> {\n suspended.delete(route)\n const queue = writeQueues.get(route)\n if (!queue || queue.writes.length === 0) {\n writeQueues.delete(route)\n return 0\n }\n\n // Replay queued writes against the now-active store\n let replayed = 0\n const target = overrides.get(route) ?? resolveOriginalStore(route)\n for (const write of queue.writes) {\n try {\n if (write.method === 'put' && write.envelope) {\n await target.put(write.vault, write.collection, write.id, write.envelope, write.expectedVersion)\n } else if (write.method === 'delete') {\n await target.delete(write.vault, write.collection, write.id)\n }\n replayed++\n } catch {\n // Best-effort replay — conflicts are expected after suspension\n }\n }\n\n writeQueues.delete(route)\n return replayed\n },\n\n routeStatus(): RouteStatus {\n const ov: Record<string, string> = {}\n for (const [k, v] of overrides) ov[k] = v.name ?? 'unnamed'\n const q: Record<string, number> = {}\n for (const [k, v] of writeQueues) q[k] = v.writes.length\n return { overrides: ov, suspended: [...suspended], queued: q }\n },\n\n resolveBackend(vaultId: string): NoydbStore {\n // Geographic routing is vault-prefix based + collection-independent;\n // the region-relevant backend is the vaultRoutes match, else default.\n if (opts.vaultRoutes) {\n for (const [prefix, s] of Object.entries(opts.vaultRoutes)) {\n if (vaultId.startsWith(prefix)) return s\n }\n }\n return primary\n },\n }\n\n // ── Optional method forwarding ─────────────────────────────────────\n\n // Forward listVaults from all stores, deduplicated\n if (anyHas('listVaults')) {\n store.listVaults = async () => {\n const results = await Promise.all(\n [...allStores]\n .filter(s => s.listVaults !== undefined)\n .map(s => s.listVaults!().catch(() => [] as string[])),\n )\n return [...new Set(results.flat())]\n }\n }\n\n // Forward ping — succeed if any store responds\n if (anyHas('ping')) {\n store.ping = async () => {\n const results = await Promise.all(\n [...allStores]\n .filter(s => s.ping !== undefined)\n .map(s => s.ping!().catch(() => false)),\n )\n return results.some(Boolean)\n }\n }\n\n return store\n\n // ── Helpers ────────────────────────────────────────────────────────\n\n function buildName(): string {\n const names = [...allStores].map(s => s.name ?? '?').join('+')\n return `route(${names})`\n }\n\n function anyHas(method: string): boolean {\n return [...allStores].some(s => (s as unknown as Record<string, unknown>)[method])\n }\n\n function getStoresForVault(vault: string): NoydbStore[] {\n const stores = new Set<NoydbStore>()\n\n // Check vault routes first\n if (opts.vaultRoutes) {\n for (const [prefix, s] of Object.entries(opts.vaultRoutes)) {\n if (vault.startsWith(prefix)) {\n stores.add(s)\n return [...stores] // vault-routed: only use that store\n }\n }\n }\n\n // Default topology: primary + blob store + cold store\n stores.add(primary)\n if (simpleBlobStore) stores.add(simpleBlobStore)\n if (tieredBlobs?.large) stores.add(tieredBlobs.large)\n if (tieredBlobs?.small && tieredBlobs.small !== primary) stores.add(tieredBlobs.small)\n if (opts.age?.cold) stores.add(opts.age.cold)\n if (opts.routes) {\n for (const s of Object.values(opts.routes)) stores.add(s)\n }\n\n return [...stores]\n }\n}\n\n// ─── Snapshot merge ──────────────────────────────────────────────────────\n\nfunction mergeSnapshots(snapshots: VaultSnapshot[]): VaultSnapshot {\n const merged: VaultSnapshot = {}\n\n for (const snap of snapshots) {\n for (const [collection, records] of Object.entries(snap)) {\n if (!merged[collection]) {\n merged[collection] = { ...records }\n continue\n }\n for (const [id, envelope] of Object.entries(records)) {\n const existing = merged[collection][id]\n // Last-write-wins by _ts\n if (!existing || envelope._ts >= existing._ts) {\n merged[collection][id] = envelope\n }\n }\n }\n }\n\n return merged\n}\n","/**\n * Store middleware — composable interceptors for NoydbStore.\n *\n * ```ts\n * const resilient = wrapStore(\n * dynamo({ table: 'myapp' }),\n * withRetry({ maxRetries: 3 }),\n * withLogging({ level: 'debug' }),\n * withCache({ ttlMs: 60_000 }),\n * )\n * ```\n *\n * Each middleware is `(next: NoydbStore) => NoydbStore`. They compose\n * left-to-right: first middleware is outermost (processes requests first,\n * responses last).\n *\n * @module\n */\n\nimport type { NoydbStore, EncryptedEnvelope } from '../kernel/types.js'\n\n// ─── Core composition ───────────────────────────────────────────────────\n\n/**\n * A store middleware function.\n *\n * Takes the next store in the chain and returns a wrapped store. Middlewares\n * compose left-to-right via `wrapStore()`: the first argument is outermost\n * (first to intercept requests, last to process responses).\n *\n * ```ts\n * const mw: StoreMiddleware = (next) => ({\n * ...next,\n * async get(vault, collection, id) {\n * console.log('get', id)\n * return next.get(vault, collection, id)\n * },\n * })\n * ```\n */\nexport type StoreMiddleware = (next: NoydbStore) => NoydbStore\n\n/**\n * Wrap a store with one or more middlewares. Middlewares compose left-to-right.\n */\nexport function wrapStore(store: NoydbStore, ...middlewares: StoreMiddleware[]): NoydbStore {\n let result = store\n // Apply right-to-left so the first middleware is the outermost wrapper\n for (let i = middlewares.length - 1; i >= 0; i--) {\n result = middlewares[i]!(result)\n }\n return result\n}\n\n// ─── withRetry ──────────────────────────────────────────────────────────\n\n/** Options for `withRetry()`. */\nexport interface RetryOptions {\n /** Maximum retry attempts. Default: 3. */\n maxRetries?: number\n /** Base backoff delay in ms. Default: 500. */\n backoffMs?: number\n /** Jitter factor (0-1). Adds random delay up to `backoffMs * jitter`. Default: 0.3. */\n jitter?: number\n /** Only retry on these error codes. Default: retry all errors. */\n retryOn?: string[]\n}\n\n/**\n * Middleware that retries failed store operations with exponential backoff\n * and optional jitter. Useful for transient network errors on DynamoDB/S3.\n *\n * ```ts\n * wrapStore(dynamo({ table: 'myapp' }), withRetry({ maxRetries: 5, retryOn: ['NETWORK_ERROR'] }))\n * ```\n */\nexport function withRetry(opts: RetryOptions = {}): StoreMiddleware {\n const maxRetries = opts.maxRetries ?? 3\n const backoffMs = opts.backoffMs ?? 500\n const jitter = opts.jitter ?? 0.3\n const retryOn = opts.retryOn ? new Set(opts.retryOn) : null\n\n function shouldRetry(err: unknown): boolean {\n if (!retryOn) return true\n if (err && typeof err === 'object' && 'code' in err) {\n return retryOn.has((err as { code: string }).code)\n }\n return true\n }\n\n async function retryable<T>(fn: () => Promise<T>): Promise<T> {\n let lastError: unknown\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn()\n } catch (err) {\n lastError = err\n if (attempt >= maxRetries || !shouldRetry(err)) throw err\n const delay = backoffMs * Math.pow(2, attempt) * (1 + Math.random() * jitter)\n await new Promise(r => setTimeout(r, delay))\n }\n }\n throw lastError\n }\n\n return (next) => ({\n ...next,\n name: next.name ? `retry(${next.name})` : 'retry',\n get: (v, c, id) => retryable(() => next.get(v, c, id)),\n put: (v, c, id, env, ev) => retryable(() => next.put(v, c, id, env, ev)),\n delete: (v, c, id) => retryable(() => next.delete(v, c, id)),\n list: (v, c) => retryable(() => next.list(v, c)),\n loadAll: (v) => retryable(() => next.loadAll(v)),\n saveAll: (v, d) => retryable(() => next.saveAll(v, d)),\n })\n}\n\n// ─── withLogging ────────────────────────────────────────────────────────\n\n/** Log level for `withLogging()`. Maps to standard console method names. */\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error'\n\n/** Options for `withLogging()`. */\nexport interface LoggingOptions {\n /** Minimum log level. Default: 'info'. */\n level?: LogLevel\n /** Custom logger. Default: console. */\n logger?: {\n debug(msg: string, ...args: unknown[]): void\n info(msg: string, ...args: unknown[]): void\n warn(msg: string, ...args: unknown[]): void\n error(msg: string, ...args: unknown[]): void\n }\n /** Log the data payload (envelope contents). Default: false (privacy). */\n logData?: boolean\n}\n\nconst LOG_LEVELS: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 }\n\n/**\n * Middleware that logs every store operation with its method name, arguments,\n * and elapsed duration. Privacy-safe by default: envelope payloads are not\n * logged unless `logData: true` is set.\n */\nexport function withLogging(opts: LoggingOptions = {}): StoreMiddleware {\n const minLevel = LOG_LEVELS[opts.level ?? 'info']\n const logger = opts.logger ?? console\n const logData = opts.logData ?? false\n\n function log(level: LogLevel, method: string, args: Record<string, unknown>, durationMs?: number) {\n if (LOG_LEVELS[level] < minLevel) return\n const parts = [`[noydb:${method}]`, ...Object.entries(args).map(([k, v]) => `${k}=${String(v)}`)]\n if (durationMs !== undefined) parts.push(`${durationMs}ms`)\n logger[level](parts.join(' '))\n }\n\n function timed<T>(method: string, args: Record<string, unknown>, fn: () => Promise<T>): Promise<T> {\n const start = Date.now()\n return fn().then(\n (result) => {\n log('debug', method, args, Date.now() - start)\n return result\n },\n (err) => {\n log('error', method, { ...args, error: (err as Error).message }, Date.now() - start)\n throw err\n },\n )\n }\n\n return (next) => ({\n ...next,\n name: next.name ? `log(${next.name})` : 'log',\n get: (v, c, id) => timed('get', { vault: v, collection: c, id }, () => next.get(v, c, id)),\n put: (v, c, id, env, ev) => timed('put', {\n vault: v, collection: c, id, version: env._v,\n ...(logData ? { data: (env._data ?? '').slice(0, 40) + '...' } : {}),\n }, () => next.put(v, c, id, env, ev)),\n delete: (v, c, id) => timed('delete', { vault: v, collection: c, id }, () => next.delete(v, c, id)),\n list: (v, c) => timed('list', { vault: v, collection: c }, () => next.list(v, c)),\n loadAll: (v) => timed('loadAll', { vault: v }, () => next.loadAll(v)),\n saveAll: (v, d) => timed('saveAll', { vault: v }, () => next.saveAll(v, d)),\n })\n}\n\n// ─── withMetrics ────────────────────────────────────────────────────────\n\n/**\n * Data emitted to `MetricsOptions.onOperation` after every store call.\n *\n * Carries method name, vault/collection/id context, elapsed duration,\n * and success/failure status. Wire this into your metrics pipeline\n * (DataDog, Prometheus, CloudWatch) to get per-operation latency histograms.\n */\nexport interface StoreOperation {\n method: 'get' | 'put' | 'delete' | 'list' | 'loadAll' | 'saveAll'\n vault: string\n collection?: string\n id?: string\n durationMs: number\n success: boolean\n error?: Error\n}\n\n/** Options for `withMetrics()`. */\nexport interface MetricsOptions {\n /** Called after every store operation. */\n onOperation: (op: StoreOperation) => void\n}\n\n/**\n * Middleware that calls `onOperation` after every store method with timing\n * and success/failure data. Designed for low-overhead integration with\n * metrics systems — the callback is synchronous and fire-and-forget.\n */\nexport function withMetrics(opts: MetricsOptions): StoreMiddleware {\n function tracked<T>(\n method: StoreOperation['method'],\n vault: string,\n fn: () => Promise<T>,\n collection?: string,\n id?: string,\n ): Promise<T> {\n const start = Date.now()\n return fn().then(\n (result) => {\n opts.onOperation({\n method, vault,\n ...(collection !== undefined ? { collection } : {}),\n ...(id !== undefined ? { id } : {}),\n durationMs: Date.now() - start, success: true,\n })\n return result\n },\n (err) => {\n opts.onOperation({\n method, vault,\n ...(collection !== undefined ? { collection } : {}),\n ...(id !== undefined ? { id } : {}),\n durationMs: Date.now() - start, success: false, error: err as Error,\n })\n throw err\n },\n )\n }\n\n return (next) => ({\n ...next,\n name: next.name ? `metrics(${next.name})` : 'metrics',\n get: (v, c, id) => tracked('get', v, () => next.get(v, c, id), c, id),\n put: (v, c, id, env, ev) => tracked('put', v, () => next.put(v, c, id, env, ev), c, id),\n delete: (v, c, id) => tracked('delete', v, () => next.delete(v, c, id), c, id),\n list: (v, c) => tracked('list', v, () => next.list(v, c), c),\n loadAll: (v) => tracked('loadAll', v, () => next.loadAll(v)),\n saveAll: (v, d) => tracked('saveAll', v, () => next.saveAll(v, d)),\n })\n}\n\n// ─── withCircuitBreaker ─────────────────────────────────────────────────\n\n/**\n * Options for `withCircuitBreaker()`.\n *\n * The circuit breaker moves through three states:\n * - `closed`: normal operation.\n * - `open`: store is failing; all calls return fallback values immediately.\n * - `half-open`: one probe call after `resetTimeoutMs` — success closes, failure re-opens.\n */\nexport interface CircuitBreakerOptions {\n /** Number of consecutive failures before opening the circuit. Default: 5. */\n failureThreshold?: number\n /** Time in ms before attempting to half-open the circuit. Default: 30_000. */\n resetTimeoutMs?: number\n /** Called when the circuit opens (store becomes unavailable). */\n onOpen?: () => void\n /** Called when the circuit closes (store recovers). */\n onClose?: () => void\n}\n\ntype CircuitState = 'closed' | 'open' | 'half-open'\n\n/**\n * Middleware that implements the circuit-breaker pattern.\n *\n * When the wrapped store fails `failureThreshold` consecutive times, the\n * circuit opens: subsequent calls return safe fallback values (`null`, `[]`,\n * `{}`) without hitting the store. After `resetTimeoutMs` the circuit\n * half-opens and allows one probe — success closes the circuit, failure\n * keeps it open. Pair with `withRetry` to handle transient errors before\n * they trip the circuit.\n */\nexport function withCircuitBreaker(opts: CircuitBreakerOptions = {}): StoreMiddleware {\n const threshold = opts.failureThreshold ?? 5\n const resetMs = opts.resetTimeoutMs ?? 30_000\n\n let state: CircuitState = 'closed'\n let failures = 0\n let lastFailureTime = 0\n\n function recordSuccess(): void {\n if (state === 'half-open') {\n state = 'closed'\n failures = 0\n opts.onClose?.()\n }\n failures = 0\n }\n\n function recordFailure(): void {\n failures++\n lastFailureTime = Date.now()\n if (failures >= threshold && state === 'closed') {\n state = 'open'\n opts.onOpen?.()\n }\n }\n\n function canAttempt(): boolean {\n if (state === 'closed') return true\n if (state === 'open') {\n if (Date.now() - lastFailureTime >= resetMs) {\n state = 'half-open'\n return true\n }\n return false\n }\n // half-open: allow one attempt\n return true\n }\n\n async function guarded<T>(fn: () => Promise<T>, fallback: T): Promise<T> {\n if (!canAttempt()) return fallback\n try {\n const result = await fn()\n recordSuccess()\n return result\n } catch (err) {\n recordFailure()\n throw err\n }\n }\n\n return (next) => ({\n ...next,\n name: next.name ? `cb(${next.name})` : 'cb',\n get: (v, c, id) => guarded(() => next.get(v, c, id), null),\n put: (v, c, id, env, ev) => guarded(() => next.put(v, c, id, env, ev), undefined),\n delete: (v, c, id) => guarded(() => next.delete(v, c, id), undefined),\n list: (v, c) => guarded(() => next.list(v, c), []),\n loadAll: (v) => guarded(() => next.loadAll(v), {}),\n saveAll: (v, d) => guarded(() => next.saveAll(v, d), undefined),\n })\n}\n\n// ─── withCache (read-through) ───────────────────────────────────────────\n\n/**\n * Options for `withCache()`.\n *\n * The cache is a read-through LRU that caches individual record fetches\n * (`get`). Writes (`put`, `delete`) invalidate the relevant cache entry\n * immediately. `list`, `loadAll`, and `saveAll` bypass the cache.\n *\n * Named `StoreCacheOptions` to distinguish from `CacheOptions` in\n * `@noy-db/hub/collection`, which controls the in-memory decrypted-record LRU.\n */\nexport interface StoreCacheOptions {\n /** Maximum cached entries. Default: 500. */\n maxEntries?: number\n /** Cache TTL in ms. Default: 60_000 (1 minute). 0 = no expiry. */\n ttlMs?: number\n}\n\ninterface CacheEntry {\n envelope: EncryptedEnvelope | null\n cachedAt: number\n}\n\n/**\n * Middleware that adds a read-through LRU cache for `get()` calls.\n *\n * Reduces latency for frequently-read records (e.g. lookup tables, user\n * profiles) by serving repeat reads from memory. Because NOYDB records are\n * encrypted at rest, caching envelopes is safe — the cache holds ciphertext,\n * not plaintext. For write-heavy workloads, the cache provides little benefit\n * and should be omitted to avoid the invalidation overhead.\n */\nexport function withCache(opts: StoreCacheOptions = {}): StoreMiddleware {\n const maxEntries = opts.maxEntries ?? 500\n const ttlMs = opts.ttlMs ?? 60_000\n\n // LRU cache: Map preserves insertion order, we delete+re-insert on access\n const cache = new Map<string, CacheEntry>()\n\n function cacheKey(vault: string, collection: string, id: string): string {\n return `${vault}\\0${collection}\\0${id}`\n }\n\n function getFromCache(key: string): EncryptedEnvelope | null | undefined {\n const entry = cache.get(key)\n if (!entry) return undefined\n if (ttlMs > 0 && Date.now() - entry.cachedAt > ttlMs) {\n cache.delete(key)\n return undefined\n }\n // LRU: move to end\n cache.delete(key)\n cache.set(key, entry)\n return entry.envelope\n }\n\n function setInCache(key: string, envelope: EncryptedEnvelope | null): void {\n // Evict oldest if at capacity\n if (cache.size >= maxEntries) {\n const oldest = cache.keys().next().value\n if (oldest !== undefined) cache.delete(oldest)\n }\n cache.set(key, { envelope, cachedAt: Date.now() })\n }\n\n function invalidate(key: string): void {\n cache.delete(key)\n }\n\n return (next) => ({\n ...next,\n name: next.name ? `cache(${next.name})` : 'cache',\n\n async get(vault, collection, id) {\n const key = cacheKey(vault, collection, id)\n const cached = getFromCache(key)\n if (cached !== undefined) return cached\n const result = await next.get(vault, collection, id)\n setInCache(key, result)\n return result\n },\n\n async put(vault, collection, id, env, ev) {\n invalidate(cacheKey(vault, collection, id))\n await next.put(vault, collection, id, env, ev)\n setInCache(cacheKey(vault, collection, id), env)\n },\n\n async delete(vault, collection, id) {\n invalidate(cacheKey(vault, collection, id))\n await next.delete(vault, collection, id)\n },\n\n list: (v, c) => next.list(v, c),\n loadAll: (v) => next.loadAll(v),\n saveAll: (v, d) => next.saveAll(v, d),\n })\n}\n\n// ─── withHealthCheck ────────────────────────────────────────────────────\n\nexport interface HealthCheckOptions {\n /** Ping interval in ms. Default: 30_000. */\n checkIntervalMs?: number\n /** Suspend after N consecutive ping failures. Default: 3. */\n suspendAfterFailures?: number\n /** Resume after N consecutive ping successes. Default: 1. */\n resumeAfterSuccess?: number\n /** Called when the store is auto-suspended. */\n onSuspend?: () => void\n /** Called when the store is auto-resumed. */\n onResume?: () => void\n /**\n * Custom health check. Default: calls `store.ping()` if available,\n * otherwise attempts a `list()` on a sentinel collection.\n */\n check?: () => Promise<boolean>\n}\n\n/**\n * Auto-suspends a store when health checks fail, auto-resumes when they recover.\n *\n * When suspended, `get` returns null, `put`/`delete` are no-ops, `list` returns [].\n * This is identical to the `NullStore` behavior from `routeStore.suspend()`.\n */\nexport function withHealthCheck(opts: HealthCheckOptions = {}): StoreMiddleware {\n const intervalMs = opts.checkIntervalMs ?? 30_000\n const failThreshold = opts.suspendAfterFailures ?? 3\n const successThreshold = opts.resumeAfterSuccess ?? 1\n\n let isSuspended = false\n let consecutiveFailures = 0\n let consecutiveSuccesses = 0\n\n return (next) => {\n const checkFn = opts.check ?? (\n next.ping\n ? () => next.ping!()\n : async () => { await next.list('__health__', '__ping__'); return true }\n )\n\n async function doCheck(): Promise<void> {\n try {\n const ok = await checkFn()\n if (ok) {\n consecutiveFailures = 0\n consecutiveSuccesses++\n if (isSuspended && consecutiveSuccesses >= successThreshold) {\n isSuspended = false\n consecutiveSuccesses = 0\n opts.onResume?.()\n }\n } else {\n throw new Error('Health check returned false')\n }\n } catch {\n consecutiveSuccesses = 0\n consecutiveFailures++\n if (!isSuspended && consecutiveFailures >= failThreshold) {\n isSuspended = true\n consecutiveFailures = 0\n opts.onSuspend?.()\n }\n }\n }\n\n // Start checking\n setInterval(() => { void doCheck() }, intervalMs)\n\n const wrapped: NoydbStore = {\n ...next,\n name: next.name ? `health(${next.name})` : 'health',\n\n async get(v, c, id) { return isSuspended ? null : next.get(v, c, id) },\n async put(v, c, id, env, ev) { if (!isSuspended) await next.put(v, c, id, env, ev) },\n async delete(v, c, id) { if (!isSuspended) await next.delete(v, c, id) },\n async list(v, c) { return isSuspended ? [] : next.list(v, c) },\n async loadAll(v) { return isSuspended ? {} : next.loadAll(v) },\n async saveAll(v, d) { if (!isSuspended) await next.saveAll(v, d) },\n }\n\n return wrapped\n }\n}\n"],"mappings":"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","names":["store","s"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-audit/consent/strategy.ts"],"sourcesContent":["/**\n * Strategy seam for the optional consent-audit service. Core\n * imports `ConsentStrategy` as a TYPE-ONLY symbol and `NO_CONSENT`\n * as a tiny runtime stub.\n *\n * `writeConsentEntry` / `loadConsentEntries` are only reachable from\n * `withConsent()` in `./active.ts`, exported through\n * `@noy-db/hub/consent`. Applications without a consent scope ship\n * none of the ~194 LOC.\n *\n * @internal\n */\n\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { EnclaveKey } from '../../capsule/index.js'\nimport type {\n ConsentAuditEntry,\n ConsentAuditFilter,\n} from './consent.js'\n\n/**\n * @internal\n */\nexport interface ConsentStrategy {\n /**\n * Record one consent audit entry. No-op under NO_CONSENT.\n */\n write(\n adapter: NoydbStore,\n vault: string,\n encrypted: boolean,\n entry: Omit<ConsentAuditEntry, 'id' | 'timestamp'>,\n getDEK: (collectionName: string) => Promise<EnclaveKey>,\n ): Promise<void>\n\n /**\n * Read filtered consent entries. Returns `[]` under NO_CONSENT.\n */\n read(\n adapter: NoydbStore,\n vault: string,\n encrypted: boolean,\n getDEK: (collectionName: string) => Promise<EnclaveKey>,\n filter?: ConsentAuditFilter,\n ): Promise<ConsentAuditEntry[]>\n}\n\n/**\n * No-consent stub. `write` is a no-op (returns a resolved promise);\n * `read` returns `[]`. Consumers get a consistent API surface without\n * pulling the consent module into the bundle.\n *\n * @internal\n */\nexport const NO_CONSENT: ConsentStrategy = {\n async write() {},\n async read() { return [] },\n}\n"],"mappings":";AAsDO,IAAM,aAA8B;AAAA,EACzC,MAAM,QAAQ;AAAA,EAAC;AAAA,EACf,MAAM,OAAO;AAAE,WAAO,CAAC;AAAA,EAAE;AAC3B;","names":[]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
installViaBinder
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SYNY3VB5.js";
|
|
4
4
|
import {
|
|
5
5
|
SealedHandle
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SV2PM2OY.js";
|
|
7
7
|
import {
|
|
8
8
|
ClassifiedConfigError,
|
|
9
9
|
ClassifiedNotEnabledError
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-37EPTBBR.js";
|
|
11
11
|
|
|
12
12
|
// src/via/classified/descriptor.ts
|
|
13
13
|
function isClassifiedFieldSpec(x) {
|
|
@@ -43,6 +43,12 @@ var ClassifiedValidationError = class extends Error {
|
|
|
43
43
|
function resolveClassifiedFields(collection, config) {
|
|
44
44
|
const byField = {};
|
|
45
45
|
const claim = (field, spec) => {
|
|
46
|
+
if (field.includes(".") || field.includes("[")) {
|
|
47
|
+
throw new ClassifiedConfigError(
|
|
48
|
+
collection,
|
|
49
|
+
`field "${field}" is a nested path, which classifiedFields does not support \u2014 it would register without error and seal nothing, returning the value in plaintext. Promote it to a top-level field on this collection (or its own document) and declare that instead. (Dotted paths ARE supported by moneyFields and i18nFields, which is why this is an easy mistake.)`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
46
52
|
if (byField[field] !== void 0) {
|
|
47
53
|
throw new ClassifiedConfigError(
|
|
48
54
|
collection,
|
|
@@ -264,4 +270,4 @@ export {
|
|
|
264
270
|
enforceClassifiedWrite,
|
|
265
271
|
NO_CLASSIFIED
|
|
266
272
|
};
|
|
267
|
-
//# sourceMappingURL=chunk-
|
|
273
|
+
//# sourceMappingURL=chunk-GUZET4SG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/via/classified/descriptor.ts","../src/via/classified/errors.ts","../src/via/classified/resolve.ts","../src/via/classified/write.ts","../src/via/classified/guards.ts","../src/via/classified/binding.ts","../src/port/with/classified-strategy.ts"],"sourcesContent":["/**\n * Classified fields — behavioral sensitive-field descriptors (stage 1).\n * Design: design-history/2026-07-04-classified-fields-design.md\n * Law: open on write, declarative on read — read-side behavior is this\n * closed vocabulary; there are no read-side callbacks.\n * @module\n */\n\nexport type ClassifiedStorage = 'recoverable' | 'never' | 'digest-only'\n\nexport type ClassifiedList =\n | { readonly kind: 'omit' }\n | { readonly kind: 'mask'; readonly pattern: string }\n | { readonly kind: 'rider'; readonly rider: string }\n\nexport type ClassifiedRider = (value: unknown) => unknown\n\nexport interface ClassifiedFieldSpec {\n readonly _noydbClassified: true\n /**\n * Via port brand marker — lets a `ClassifiedFieldSpec` satisfy the\n * kernel's opaque `ViaDescriptor` (#629 Task 5). Optional (unlike\n * `MoneyDescriptor._viaBrand`/`I18nTextDescriptor._viaBrand`, which are\n * required): every `classified.*()` preset factory stamps it, but the\n * pre-existing test suite's hand-rolled `ClassifiedFieldSpec` fixtures\n * (built without going through a preset) predate this field and would\n * fail to compile if it were mandatory.\n */\n readonly _viaBrand?: 'classified'\n readonly preset: string\n readonly storage: ClassifiedStorage\n readonly list: ClassifiedList\n readonly sensitivity: 'pii' | 'secret'\n /** Write-time safe projections; companion field name is `<field>_<rider>`. */\n readonly riders?: Record<string, ClassifiedRider>\n /** Write-time validator: error message, or null when valid. */\n readonly validate?: (value: unknown) => string | null\n /** Digest-only verify policy (stage 2). Mode both sides normalize under. */\n readonly verifyNormalize?: 'password' | 'secret-answer'\n /** Decorate ok:true verdicts with mustRotate after this many days (I1). */\n readonly rotateDays?: number\n /** Refuse reuse of the last N values on rotate (cap 8, spec Q4). */\n readonly notLastN?: number\n /** Member of the collection's matchGroup (secretAnswer preset). */\n readonly verifyGroupMember?: true\n /**\n * Opt into a store-visible blind-index (`_bidx`) tag so equal values become\n * queryable/joinable while staying digest-only. Digest-only knob (R7); gated\n * behind the collection's `acknowledgeEquatableRisk` door (R8). Equal values\n * produce equal tags — a partition leak a DEK holder can offline-dictionary\n * at the PBKDF2 floor. Absent/false ⇒ refused-by-default.\n */\n readonly equatable?: true\n}\n\nexport interface ClassifiedGroup {\n readonly _noydbClassifiedGroup: true\n /** Via port brand marker — see {@link ClassifiedFieldSpec._viaBrand}. */\n readonly _viaBrand?: 'classified'\n readonly preset: string\n /** member record-field name -> spec (differential per-member policy). */\n readonly members: Record<string, ClassifiedFieldSpec>\n}\n\nexport type ClassifiedEntry = ClassifiedFieldSpec | ClassifiedGroup\n\nexport function isClassifiedFieldSpec(x: unknown): x is ClassifiedFieldSpec {\n return typeof x === 'object' && x !== null\n && (x as { _noydbClassified?: unknown })._noydbClassified === true\n}\n\nexport function isClassifiedGroup(x: unknown): x is ClassifiedGroup {\n return typeof x === 'object' && x !== null\n && (x as { _noydbClassifiedGroup?: unknown })._noydbClassifiedGroup === true\n}\n","/**\n * Configuration/write errors for classified fields. @module\n *\n * `ClassifiedConfigError` / `ClassifiedRevealError` moved to `kernel/errors.ts`\n * (stage 2) so `capsule/enclave-aes/classify/*` can throw them without importing\n * with-*. Re-exported here under the same names so existing import paths\n * keep working.\n */\nexport { ClassifiedConfigError, ClassifiedRevealError, ClassifiedVerifyError, ClassifiedRotationError } from '../../kernel/errors.js'\n\nexport class ClassifiedNeverStoredError extends Error {\n constructor(public readonly collection: string, public readonly field: string) {\n super(`Field \"${field}\" in collection \"${collection}\" is classified storage:'never' `\n + `(e.g. a CVC) and must not be persisted. Validate it at capture and drop it before put().`)\n this.name = 'ClassifiedNeverStoredError'\n }\n}\n\nexport class ClassifiedValidationError extends Error {\n constructor(public readonly collection: string, public readonly field: string, detail: string) {\n super(`Classified field \"${field}\" in collection \"${collection}\" failed validation: ${detail}`)\n this.name = 'ClassifiedValidationError'\n }\n}\n","/** Flatten a classifiedFields config into a per-field map + rider computed entries. @module */\n\nimport { isClassifiedGroup, type ClassifiedEntry, type ClassifiedFieldSpec } from './descriptor.js'\nimport { ClassifiedConfigError } from './errors.js'\n\nexport type { ClassifiedEntry, ClassifiedFieldSpec, ClassifiedGroup, ClassifiedList } from './descriptor.js'\nexport { ClassifiedConfigError } from './errors.js'\n\nexport interface ResolvedClassified {\n readonly byField: Record<string, ClassifiedFieldSpec>\n readonly riderComputed: Record<string, (record: Record<string, unknown>) => unknown>\n}\n\nexport function resolveClassifiedFields(\n collection: string,\n config: Record<string, ClassifiedEntry>,\n): ResolvedClassified {\n const byField: Record<string, ClassifiedFieldSpec> = {}\n const claim = (field: string, spec: ClassifiedFieldSpec): void => {\n // ⛔ #19 — REFUSE A NESTED PATH. Declaring `'account.password'` used to\n // register cleanly and seal NOTHING: the write succeeded and the secret\n // came back in full plaintext from `get()` and `list()`, with the only\n // signal being a `reveal()` that a developer who believes the field is\n // sealed has no reason to call. \"Misconfigured\" and \"not classified at\n // all\" were observationally identical, which is the wrong way round for a\n // security primitive — a misunderstood declaration must fail closed.\n //\n // Guarded HERE rather than at the two call sites below because `claim` is\n // the one chokepoint both the flat form and a group's members pass\n // through; a guard on the flat key alone would leave the leak reachable\n // behind one extra level of syntax.\n //\n // ⭐ `via/money/paths.ts` already carries this lesson for `moneyFields`\n // (\"a declared-but-unreachable path that was silently ignored ... a latent\n // 100× bug\"). Same class, different family — and here the cost is the\n // secret rather than the precision.\n if (field.includes('.') || field.includes('[')) {\n throw new ClassifiedConfigError(collection,\n `field \"${field}\" is a nested path, which classifiedFields does not support — ` +\n `it would register without error and seal nothing, returning the value in plaintext. ` +\n `Promote it to a top-level field on this collection (or its own document) and declare that instead. ` +\n `(Dotted paths ARE supported by moneyFields and i18nFields, which is why this is an easy mistake.)`)\n }\n if (byField[field] !== undefined) {\n throw new ClassifiedConfigError(collection,\n `field \"${field}\" is claimed twice — storage forms are mutually exclusive per field (R5): ` +\n `a field is digest-only OR recoverable OR never, exactly one`)\n }\n byField[field] = spec\n }\n for (const [key, entry] of Object.entries(config)) {\n if (isClassifiedGroup(entry)) {\n for (const [field, spec] of Object.entries(entry.members)) claim(field, spec)\n } else {\n claim(key, entry)\n }\n }\n const riderComputed: Record<string, (record: Record<string, unknown>) => unknown> = {}\n for (const [field, spec] of Object.entries(byField)) {\n for (const [name, rider] of Object.entries(spec.riders ?? {})) {\n const companion = `${field}_${name}`\n if (byField[companion] !== undefined || riderComputed[companion] !== undefined) {\n throw new ClassifiedConfigError(collection, `rider companion \"${companion}\" collides with a declared field`)\n }\n riderComputed[companion] = (record) =>\n record[field] === undefined ? undefined : rider(record[field])\n }\n }\n return { byField, riderComputed }\n}\n","/** Write-path enforcement: storage:'never' rejection + preset validators.\n * Runs BEFORE riders/computed and BEFORE schema validation. Pure. @module */\n\nimport type { ClassifiedFieldSpec } from './descriptor.js'\nimport { ClassifiedNeverStoredError, ClassifiedValidationError } from './errors.js'\n\nexport function enforceClassifiedWrite(\n record: Record<string, unknown>,\n byField: Record<string, ClassifiedFieldSpec>,\n collection: string,\n): void {\n for (const [field, spec] of Object.entries(byField)) {\n const value = record[field]\n if (value === undefined) continue\n if (value === null && spec.storage === 'digest-only') continue // explicit clear (C6 branch 3)\n if (spec.storage === 'never') throw new ClassifiedNeverStoredError(collection, field)\n const problem = spec.validate?.(value) ?? null\n if (problem !== null) throw new ClassifiedValidationError(collection, field, problem)\n }\n}\n","/**\n * Refusal matrix R1-R5 (spec) — ONE guard, run at BOTH doors:\n * `collection()` config resolution AND `_applyClassifiedFields` (the reconcile\n * seam), because crdt/conflictPolicy/perRecordKeys are construction-only\n * while classifiedFields can attach later (C5's lesson). @module\n */\nimport type { ClassifiedFieldSpec } from './descriptor.js'\nimport { ClassifiedConfigError } from '../../kernel/errors.js'\n\nexport interface ClassifiedGuardCtx {\n readonly perRecordKeys: boolean\n readonly crdt: boolean\n readonly hasConflictPolicy: boolean\n /** False on plaintext (`encrypt: false`) collections — no vdig/seal path exists. */\n readonly storeCiphertext: boolean\n readonly deterministicFields: ReadonlySet<string> | null\n readonly indexedFields: ReadonlySet<string>\n readonly textIndexFields: ReadonlySet<string>\n readonly vectorSourceFields: ReadonlySet<string>\n readonly subjectKeyField: string | undefined\n readonly bareSensitiveFields: ReadonlySet<string>\n /** Collection-level gate for the `equatable` knob (R8 double door). */\n readonly acknowledgeEquatableRisk: boolean\n}\n\nexport function guardClassifiedCompat(\n collection: string,\n byField: Record<string, ClassifiedFieldSpec>,\n ctx: ClassifiedGuardCtx,\n): void {\n const digestOnly = Object.entries(byField)\n .filter(([, s]) => s.storage === 'digest-only')\n const protectedForms = Object.values(byField)\n .filter((s) => s.storage === 'digest-only' || s.storage === 'recoverable')\n\n // R2 — merge resolvers bypass the write pipeline entirely (C5): a merge\n // could carry stale/foreign _vdig or resurrect plaintext (the CRDT put\n // branch persists via encryptJsonString with no vdig backstop). Fail-loud.\n if (protectedForms.length > 0 && (ctx.crdt || ctx.hasConflictPolicy)) {\n throw new ClassifiedConfigError(collection,\n 'digest-only/recoverable classified fields cannot combine with a crdt mode or a ' +\n 'conflictPolicy resolver — merge paths bypass write enforcement (R2)')\n }\n // R7 — `equatable` is a digest-only knob: it drives the `_bidx` blind-index\n // slot, which only exists on the digest-only write path. A recoverable/never\n // field carrying it would silently no-op (recoverable equality is `_det`'s\n // job). Refuse rather than accept-and-ignore. Checked over ALL specs, before\n // the digest-only early-return below, precisely to catch the non-digest case.\n for (const [f, spec] of Object.entries(byField)) {\n if (spec.equatable === true && spec.storage !== 'digest-only') {\n throw new ClassifiedConfigError(collection,\n `field \"${f}\" declares equatable but storage is '${spec.storage}' — equatable is a ` +\n `digest-only knob; recoverable equality is _det's job (R7)`)\n }\n }\n\n // R8 — the equatable double door (mirrors deterministicFields ×\n // acknowledgeDeterministicRisk): any field opting into `equatable` requires\n // the collection to acknowledge the partition-leak risk. One-directional —\n // `acknowledgeEquatableRisk: true` with ZERO equatable members is a silent\n // no-op (never throws here), so the ack can sit on a collection config\n // ahead of the field landing.\n const hasEquatable = Object.values(byField).some((s) => s.equatable === true)\n if (hasEquatable && ctx.acknowledgeEquatableRisk !== true) {\n throw new ClassifiedConfigError(collection,\n `classified equatable fields require \\`acknowledgeEquatableRisk: true\\` — equal values ` +\n `produce equal store-visible index tags (a partition leak a DEK holder can offline-` +\n `dictionary at the PBKDF2 floor); the door is the real control for low-entropy fields (R8)`)\n }\n\n if (digestOnly.length === 0) return\n\n // Digest-only on a plaintext collection: the codec's vdig block is gated on\n // storeCiphertext, so the secret would persist as raw plaintext. Refuse.\n if (!ctx.storeCiphertext) {\n throw new ClassifiedConfigError(collection,\n `storage:'digest-only' requires an encrypted collection — with encrypt: false the ` +\n `write path skips the digest slot entirely and the secret would persist as raw plaintext`)\n }\n // R1 — vdig slot keys are CEK-only (I3); without perRecordKeys a digest\n // would survive forget() in backups as offline-crackable material.\n if (!ctx.perRecordKeys) {\n throw new ClassifiedConfigError(collection,\n `storage:'digest-only' requires perRecordKeys: true — vdig keys derive from the ` +\n `per-record CEK so forget() shreds them (R1)`)\n }\n for (const [f, spec] of digestOnly) {\n // notLastN cap: presets clamp this at construction, but a raw spec object\n // bypasses the preset — enforce the same 0..8 cap in the policy projection.\n const n = spec.notLastN ?? 0\n if (!Number.isInteger(n) || n < 0 || n > 8) {\n throw new ClassifiedConfigError(collection,\n `digest-only field \"${f}\" declares notLastN ${n} — must be an integer 0..8 ` +\n `(write cost is n × 600K PBKDF2; ring blast radius is documented)`)\n }\n if (ctx.bareSensitiveFields.has(f)) {\n // R5 — the sealed block runs before the vdig block in the codec, so the\n // overlap would seal the value recoverably (silent downgrade + I4\n // double-slot). Storage forms are mutually exclusive per field.\n throw new ClassifiedConfigError(collection,\n `field \"${f}\" is digest-only AND listed in sensitive[] — storage forms are mutually exclusive per field (R5)`)\n }\n if (ctx.deterministicFields?.has(f)) {\n throw new ClassifiedConfigError(collection,\n `digest-only field \"${f}\" cannot be deterministic — equality-correlatable ciphertext defeats per-write salts (R3)`)\n }\n if (ctx.indexedFields.has(f) || ctx.textIndexFields.has(f)\n || ctx.vectorSourceFields.has(f) || ctx.subjectKeyField === f) {\n throw new ClassifiedConfigError(collection,\n `digest-only field \"${f}\" cannot be indexed, text-indexed, embedded, or a forget-subject key (R4)`)\n }\n }\n}\n","/**\n * The classified `NoydbVia` (#629 Task 5, LIVE since Task 6) — wires\n * classified-fields declaration/write-enforcement/at-rest sealing/erasure\n * into the kernel's generic Via port. Mirrors `via/money/binding.ts`'s\n * inline declaration-time validation and `via/i18n/binding.ts`'s\n * `linkXVia` static-link pattern — except the link itself is EAGER\n * (`port/with/classified-strategy.ts` calls `linkClassifiedVia()` at module\n * load, not lazily from a `classified.*()` preset call): several fixtures\n * build a raw `ClassifiedFieldSpec` literal without ever calling a preset,\n * and the binder must be installed before `compileVias` needs it\n * regardless.\n *\n * `compileVias` (`kernel/collection-config.ts`) compiles this binding\n * in whenever a collection declares `classifiedFields` — money then i18n\n * then classified, order pinned. `kernel/collection.ts`'s `_putInternal`\n * runs `enforceClassifiedWrite`'s effect via the pipeline's `enforceWrite`\n * phase; the codec's `encodeAtRest`/`decodeAtRest` hooks (Task 3's boundary)\n * replace the inline `sensitiveFields` seal path for any collection this\n * binding is compiled into.\n *\n * `declare` — `classifiedVia(cfg)` runs `resolveClassifiedFields` +\n * `guardClassifiedCompat` at CONSTRUCTION time (the same #553 pattern\n * `moneyVia`'s `validateMoneyFieldPaths(moneyFields)` call uses) —\n * mirrors today's \"door 1\" (`collection-config.ts`'s\n * `resolveCollectionConfig`). Both may throw `ClassifiedConfigError`.\n */\nimport type { NoydbVia, ViaWriteCtx, ViaCryptoCtx, SealedSlotRef, ViaEraseCtx, ViaEraseReport } from '../../kernel/via/index.js'\nimport { installViaBinder } from '../../kernel/via/index.js'\nimport { SealedHandle } from '../../kernel/types.js'\nimport { resolveClassifiedFields, type ClassifiedEntry } from './resolve.js'\nimport { guardClassifiedCompat, type ClassifiedGuardCtx } from './guards.js'\nimport { enforceClassifiedWrite } from './write.js'\nimport type { ClassifiedFieldSpec } from './descriptor.js'\n\n/**\n * One classified per-slot shred/residue verdict — mirrors\n * `RecordCodec.SealedShredSlot` (`capsule/plumbing/record-codec.ts`)\n * byte-for-byte. Duplicated here (not imported) so this binding never\n * reaches into `capsule/enclave-aes/` (`via-enclave-isolation`, #629) — the\n * closure that PRODUCES real values of this shape is codec-owned and\n * injected via {@link ClassifiedViaConfig.classifySealedShred}.\n */\nexport interface ClassifiedShredSlot {\n readonly field: string\n readonly class: 'shreddable' | 'dekResidue' | 'live-shreddable+dekResidue-in-backups'\n}\n\n/**\n * Config a classified collection's declarations resolve to — the binding's\n * construction input. `entries`/`guardCtx` are the raw \"door 1\" inputs\n * (`resolveClassifiedFields`/`guardClassifiedCompat`'s own parameters);\n * `classifySealedShred`/`purgeSealedCekEnvelopes` are OPTIONAL codec/vault-\n * provided closures for the `erase` hook — undefined in this dormant task\n * (no caller wires them yet), wired for real in #629 Task 10 (\"posture\n * enforcement — forget + erase hooks live\").\n */\nexport interface ClassifiedViaConfig {\n readonly entries: Record<string, ClassifiedEntry>\n readonly collectionName: string\n readonly guardCtx: ClassifiedGuardCtx\n /**\n * Codec-provided closure mirroring `RecordCodec.classifySealedShred` —\n * classifies a live envelope's `_sealed` slots for crypto-shred\n * completeness (see that method's doc comment for the shreddable/\n * dekResidue/both-class semantics). `live` is `ViaEraseCtx.live`'s opaque\n * envelope, passed straight through. NOT `readonly` (#629 Task 10):\n * `compileVias` builds this cfg before the owning `Collection`'s\n * `RecordCodec` exists, so `Collection`'s constructor mutates this field\n * in place once `this.codec` is available — the closure `eraseClassified`\n * reads is looked up at CALL time, not at binding-construction time, so\n * the late assignment is picked up correctly.\n */\n classifySealedShred?: (live: unknown) => Promise<{ readonly slots: readonly ClassifiedShredSlot[] }>\n /**\n * Vault-provided closure that purges every `_sealed_cek/<collection>/<id>/*`\n * host-delivery envelope for one record (mirrors `rotateRecordCek`'s own\n * prefix-delete) and returns the count purged. Deliberately left UNWIRED\n * by `compileVias` (#629 Task 10) — `forget-sealed-erasure.test.ts`\n * proves this purge is UNCONDITIONAL on `sealRecordToHost` usage alone,\n * independent of whether `classifiedFields` is declared (a bare\n * `sensitive: [...]` collection exercises it with no classified binding\n * at all) — vault.ts keeps owning it directly so that case stays correct.\n */\n readonly purgeSealedCekEnvelopes?: (id: string) => Promise<number>\n}\n\n/** Fields declared `storage: 'recoverable'` (digest-only stays codec-inline; `'never'` is rejected by `enforceWrite` before either hook runs). */\nfunction recoverableFields(byField: Record<string, ClassifiedFieldSpec>): string[] {\n return Object.entries(byField).filter(([, spec]) => spec.storage === 'recoverable').map(([field]) => field)\n}\n\n/**\n * The full set this binding's `encodeAtRest`/`decodeAtRest` seal: declared\n * recoverable classified fields UNION bare `sensitive[]` fields — mirrors\n * `collection-config.ts`'s pre-cutover \"recoverable classified fields are\n * unioned into sensitiveFields... zero new crypto code\" semantics. Once this\n * binding is compiled into a collection's pipeline, `hasAtRestHooks` is true\n * and the codec's inline `sensitiveFields` seal path (record-codec.ts) is\n * DEAD for that collection — mutually exclusive with the hook path (#629\n * Task 3) — so bare `sensitive[]` fields MUST seal through here too, or\n * they'd silently stop being sealed at all (#629 Task 6 reconciliation).\n * `guardCtx.bareSensitiveFields` is the exact same `Set` the collection's\n * refusal-matrix guard already carries (`ClassifiedGuardCtx`).\n */\nfunction sealFieldNames(byField: Record<string, ClassifiedFieldSpec>, guardCtx: ClassifiedGuardCtx): string[] {\n return [...recoverableFields(byField), ...guardCtx.bareSensitiveFields]\n}\n\n/**\n * Seal every named field present with a defined value into its own sealed\n * slot via `crypto.sealedSlots`, peeling it out of the record.\n */\nasync function encodeClassifiedAtRest(\n record: Record<string, unknown>,\n crypto: ViaCryptoCtx,\n fields: readonly string[],\n): Promise<{ record: Record<string, unknown>; sealed?: Record<string, SealedSlotRef> }> {\n let open = record\n let sealed: Record<string, SealedSlotRef> | undefined\n for (const field of fields) {\n if (!(field in record)) continue\n const value = record[field]\n if (value === undefined) continue\n const ref = await crypto.sealedSlots.seal(field, value)\n if (open === record) open = { ...record }\n delete open[field]\n sealed ??= {}\n sealed[field] = ref\n }\n return sealed ? { record: open, sealed } : { record }\n}\n\n/**\n * Restore every named field's sealed slot back onto the record: an opaque\n * `SealedHandle` under `asHandles` (never materialises plaintext into the\n * cache — `SealedHandle.toJSON()` returns `'[sealed]'`, the export-redaction\n * guarantee `reveal()` alone can lift), the plaintext value otherwise.\n */\nasync function decodeClassifiedAtRest(\n record: Record<string, unknown>,\n sealed: Record<string, SealedSlotRef>,\n crypto: ViaCryptoCtx,\n opts: { asHandles: boolean },\n fields: readonly string[],\n): Promise<Record<string, unknown>> {\n let out = record\n for (const field of fields) {\n const ref = sealed[field]\n if (ref === undefined) continue\n if (out === record) out = { ...record }\n out[field] = opts.asHandles\n ? new SealedHandle(() => crypto.sealedSlots.unseal(field, ref))\n : await crypto.sealedSlots.unseal(field, ref)\n }\n return out\n}\n\n/**\n * `forget()`'s per-ref erasure participation: classify the live envelope's\n * sealed slots (via the codec-provided closure) and mark each shreddable\n * one deleted on this call's sealed-slots capability, then purge the\n * record's sealed-CEK host-delivery envelopes (via the vault-provided\n * closure). Both closures are optional — undefined (this dormant task's\n * only caller, its own unit tests) reports a zero-shredded, zero-residue\n * no-op rather than throwing.\n */\nasync function eraseClassified(\n ctx: ViaEraseCtx,\n cfg: ClassifiedViaConfig,\n): Promise<ViaEraseReport> {\n let shredded = 0\n const residue: unknown[] = []\n\n if (cfg.classifySealedShred) {\n const { slots } = await cfg.classifySealedShred(ctx.live)\n for (const slot of slots) {\n if (slot.class === 'shreddable' || slot.class === 'live-shreddable+dekResidue-in-backups') {\n shredded += 1\n await ctx.crypto.sealedSlots.delete(slot.field)\n }\n if (slot.class === 'dekResidue' || slot.class === 'live-shreddable+dekResidue-in-backups') {\n residue.push({ kind: 'classified-sealed-dek-residue', field: slot.field })\n }\n }\n }\n\n if (cfg.purgeSealedCekEnvelopes) {\n shredded += await cfg.purgeSealedCekEnvelopes(ctx.id)\n }\n\n return { shredded, residue }\n}\n\nfunction buildClassifiedDescribeFragment(byField: Record<string, ClassifiedFieldSpec>): Record<string, unknown> {\n return {\n classifiedFields: Object.fromEntries(\n Object.entries(byField).map(([field, spec]) => [field, { storage: spec.storage, sensitivity: spec.sensitivity }]),\n ),\n }\n}\n\nexport function classifiedVia(cfg: ClassifiedViaConfig): NoydbVia {\n // declare — door 1: resolve + guard, exactly like collection-config.ts's\n // resolveCollectionConfig does today. Throws ClassifiedConfigError on any\n // R1-R8 refusal-matrix violation or field-collision.\n const resolved = resolveClassifiedFields(cfg.collectionName, cfg.entries)\n guardClassifiedCompat(cfg.collectionName, resolved.byField, cfg.guardCtx)\n const byField = resolved.byField\n const sealFields = sealFieldNames(byField, cfg.guardCtx)\n\n return {\n brand: 'classified',\n posture: { encryptedAtRest: 'sealed', queryable: 'det-exact', exportable: false, forgettable: true },\n covers: (field) => field in byField,\n coveredFields: Object.keys(byField), // #1447 — the FIELD only; the sensitivity label is deliberately NOT reported\n // async (rather than a bare passthrough) so a refusal is always a\n // rejected Promise for direct callers, matching every other async-stack\n // hook's calling convention — `enforceClassifiedWrite` itself stays sync.\n enforceWrite: async (record: Record<string, unknown>, _ctx: ViaWriteCtx) =>\n enforceClassifiedWrite(record, byField, cfg.collectionName),\n encodeAtRest: (record, crypto) => encodeClassifiedAtRest(record, crypto, sealFields),\n decodeAtRest: (record, sealed, crypto, opts) => decodeClassifiedAtRest(record, sealed, crypto, opts, sealFields),\n erase: (ctx) => eraseClassified(ctx, cfg),\n describeFragment: () => buildClassifiedDescribeFragment(byField),\n }\n}\n\nexport function linkClassifiedVia(): void {\n installViaBinder('classified', (c) => classifiedVia(c as ClassifiedViaConfig))\n}\n","/**\n * Classified strategy seam (#629 Task 5 — moved out of\n * `via/classified/strategy.ts`, precedent: `port/with/i18n-strategy.ts`).\n * Lives on the `/with` port (the one seam the kernel spine may import\n * statically) so `Collection`/`Vault` can hold the `NO_CLASSIFIED` default\n * without a spine→service static import.\n *\n * This file (unlike `via/classified/**`) is NOT subject to the\n * `via-enclave-isolation` architecture guard — it may import `EnclaveKey`\n * from the enclave barrel freely, the same way `port/with/i18n-strategy.ts`\n * did before #629 Task 4's DictionaryHandle cutover.\n *\n * The ② capability seam for classified read-egress ops (stage 1: reveal;\n * stage 2: verify).\n *\n * @internal\n */\nimport type { ClassifiedFieldSpec } from '../../via/classified/descriptor.js'\nimport { ClassifiedNotEnabledError } from '../../kernel/errors.js'\nimport type { EncryptedEnvelope } from '../../kernel/types.js'\nimport type { EnclaveKey } from '../../capsule/index.js'\nimport { linkClassifiedVia } from '../../via/classified/binding.js'\n\n// #629 Task 10 — re-export the classified binding's erase-cfg TYPE (not\n// `via/classified/binding.js` directly) so the kernel spine can name\n// it for the post-construction `classifySealedShred` wiring, same rationale\n// as `resolveClassifiedFields`/`guardClassifiedCompat` above.\nexport type { ClassifiedViaConfig } from '../../via/classified/binding.js'\n\nexport type { ClassifiedVerdict } from '../../kernel/types.js'\nimport type { ClassifiedVerdict } from '../../kernel/types.js'\n\n// #629 Task 6 — the classified binding's construction-time resolve/guard,\n// re-exported here (not `via/classified/{resolve,guards}.js` directly)\n// so the kernel spine keeps importing only this one `/with` port seam, same\n// rationale as `NO_CLASSIFIED` below.\nexport { resolveClassifiedFields, type ClassifiedEntry, type ResolvedClassified } from '../../via/classified/resolve.js'\nexport { guardClassifiedCompat, type ClassifiedGuardCtx } from '../../via/classified/guards.js'\nexport type { ClassifiedFieldSpec }\n\n// Install the classified Via binder EAGERLY — unlike money()/i18nText(),\n// several classified fixtures (both hub tests and consumer code) build a raw\n// `ClassifiedFieldSpec` object literal without ever calling a\n// `classified.*()` preset (bypassing `via/classified/presets.ts`\n// entirely — an intentionally supported pattern, see that module's Task 5\n// doc comment). Linking lazily at preset-call time (the money/i18n pattern)\n// would leave `viaBinder('classified')` unlinked for those declarations.\n// This port module is already unconditionally imported by the kernel spine\n// (for the `NO_CLASSIFIED` strategy default below), so linking here\n// guarantees the binder is always installed before `compileVias`\n// ever needs it, regardless of how a collection's classifiedFields were\n// constructed.\nlinkClassifiedVia()\n\nexport interface ClassifiedRevealCtx {\n readonly collection: string\n readonly spec: ClassifiedFieldSpec\n /** True on an encrypted collection — false selects the plaintext-body read. */\n readonly encrypted: boolean\n readonly getEnvelope: (id: string) => Promise<EncryptedEnvelope | null>\n readonly resolveCek: (env: EncryptedEnvelope) => Promise<EnclaveKey | undefined>\n readonly getDEK: () => Promise<EnclaveKey>\n readonly onAccess?: ((op: 'reveal', id: string) => Promise<void>) | undefined\n}\n\nexport interface ClassifiedVerifyCtx {\n readonly collection: string\n readonly spec: ClassifiedFieldSpec\n readonly getEnvelope: (id: string) => Promise<EncryptedEnvelope | null> // raw envelope, NOT a decrypted view\n readonly resolveCek: (env: EncryptedEnvelope) => Promise<EnclaveKey | undefined>\n readonly getDEK: () => Promise<EnclaveKey>\n readonly now: () => number // injected (Q7)\n /** Group members resolved by the collection (matchGroup only). */\n readonly groupMembers?: ReadonlyArray<{ readonly field: string; readonly spec: ClassifiedFieldSpec }>\n readonly onAccess?: ((op: 'verify' | 'find', id: string) => Promise<void>) | undefined\n}\n\nexport interface ClassifiedStrategy {\n reveal(ctx: ClassifiedRevealCtx, id: string, field: string): Promise<unknown>\n verify(ctx: ClassifiedVerifyCtx, id: string, field: string, candidate: string): Promise<ClassifiedVerdict>\n verifyText(ctx: ClassifiedVerifyCtx, id: string, field: string, candidate: string): Promise<ClassifiedVerdict>\n matchGroup(ctx: ClassifiedVerifyCtx, id: string, answers: Record<string, string>,\n opts: { readonly min: number }): Promise<{ readonly passed: boolean }>\n computeTarget(ctx: ClassifiedVerifyCtx, field: string, candidate: string, costByte?: number): Promise<string | null>\n}\n\nexport const NO_CLASSIFIED: ClassifiedStrategy = {\n async reveal() { throw new ClassifiedNotEnabledError() },\n async verify() { throw new ClassifiedNotEnabledError() },\n async verifyText() { throw new ClassifiedNotEnabledError() },\n async matchGroup() { throw new ClassifiedNotEnabledError() },\n async computeTarget() { throw new ClassifiedNotEnabledError() },\n}\n"],"mappings":"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","names":[]}
|