@noy-db/hub 0.8.0-pre.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/dist/api-OS747DS4.js +18 -0
- package/dist/as/index.js +11 -12
- package/dist/as/index.js.map +1 -1
- package/dist/at/index.js +9 -10
- package/dist/attestation/index.js +39 -28
- package/dist/attestation/index.js.map +1 -1
- package/dist/{backup-7TFRVFLH.js → backup-YE2VQ26S.js} +15 -16
- package/dist/backup-YE2VQ26S.js.map +1 -0
- package/dist/blobs/index.js +13 -14
- package/dist/blobs/index.js.map +1 -1
- package/dist/broker/index.js +12 -13
- package/dist/broker/index.js.map +1 -1
- package/dist/by/index.js +2 -2
- package/dist/capsule/contract.d.ts +159 -0
- package/dist/capsule/contract.js +95 -0
- package/dist/capsule/enclave-aes/bound.d.ts +52 -0
- package/dist/capsule/enclave-aes/capabilities.d.ts +2 -0
- package/dist/capsule/enclave-aes/classify/compare.d.ts +20 -0
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/find.d.ts +1 -1
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/reveal.d.ts +1 -1
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/verify.d.ts +2 -2
- package/dist/{kernel/enclave → capsule/enclave-aes}/classify/write.d.ts +1 -1
- package/dist/{kernel/enclave → capsule/enclave-aes}/crypto.d.ts +33 -129
- package/dist/capsule/enclave-aes/index.d.ts +113 -0
- package/dist/capsule/enclave-aes/index.js +335 -0
- package/dist/capsule/enclave-aes/index.js.map +1 -0
- package/dist/capsule/enclave-aes/primitives.d.ts +29 -0
- package/dist/capsule/index.d.ts +27 -0
- package/dist/capsule/plumbing/ct-equal.d.ts +11 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/deterministic.d.ts +8 -21
- package/dist/capsule/plumbing/digest.d.ts +122 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/envelope-body.d.ts +44 -48
- package/dist/capsule/plumbing/index.d.ts +100 -0
- package/dist/capsule/plumbing/lifecycle.d.ts +50 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/record-codec.d.ts +55 -20
- package/dist/{kernel/enclave → capsule/plumbing}/record-envelope.d.ts +1 -1
- package/dist/capsule/plumbing/rekey-blob.d.ts +33 -0
- package/dist/capsule/plumbing/rekey.d.ts +44 -0
- package/dist/capsule/plumbing/sealed-slot.d.ts +22 -0
- package/dist/capsule/plumbing/sealed-slots.d.ts +37 -0
- package/dist/capsule/plumbing/sealing.d.ts +29 -0
- package/dist/capsule/plumbing/sign.d.ts +9 -0
- package/dist/{kernel/enclave/record-keys → capsule/plumbing}/tombstone.d.ts +2 -2
- package/dist/capsule-VOLX3QRQ.js +209 -0
- package/dist/cargo/index.js +36 -36
- package/dist/{chunk-DF73H4UN.js → chunk-23D6M6VM.js} +5 -5
- package/dist/chunk-23D6M6VM.js.map +1 -0
- package/dist/{chunk-FH2L2E34.js → chunk-244QBK7Z.js} +4 -4
- package/dist/{chunk-FH2L2E34.js.map → chunk-244QBK7Z.js.map} +1 -1
- package/dist/{chunk-YSK2CU2Q.js → chunk-2AFX33YA.js} +2 -2
- package/dist/{chunk-TKUOEU2F.js → chunk-2GHDLTPE.js} +2 -2
- package/dist/{chunk-GYGLAVCX.js → chunk-2MG3SW7Q.js} +6 -2
- package/dist/chunk-2MG3SW7Q.js.map +1 -0
- package/dist/{chunk-6OWXYZK2.js → chunk-2ODVB6LZ.js} +2 -2
- package/dist/{chunk-X25NWUZB.js → chunk-2PVXF5CS.js} +3 -3
- package/dist/{chunk-IEX7NK2K.js → chunk-2RH777HH.js} +21 -20
- package/dist/{chunk-IEX7NK2K.js.map → chunk-2RH777HH.js.map} +1 -1
- package/dist/{chunk-244VXYPG.js → chunk-37EPTBBR.js} +14 -1
- package/dist/chunk-37EPTBBR.js.map +1 -0
- package/dist/{chunk-NRT6QZQB.js → chunk-3A5DUZ56.js} +6 -6
- package/dist/chunk-3A5DUZ56.js.map +1 -0
- package/dist/{chunk-ORDURZBU.js → chunk-3EWS67C7.js} +2 -2
- package/dist/{chunk-3H5KLDZN.js → chunk-3L2NBKDR.js} +4 -8
- package/dist/chunk-3L2NBKDR.js.map +1 -0
- package/dist/{chunk-ENAG3IY7.js → chunk-3XJQBBZD.js} +26 -28
- package/dist/chunk-3XJQBBZD.js.map +1 -0
- package/dist/{chunk-KJFW62P4.js → chunk-42ALPZ2B.js} +652 -662
- package/dist/chunk-42ALPZ2B.js.map +1 -0
- package/dist/{chunk-FXQBGFOX.js → chunk-4CIQDWRB.js} +8 -8
- package/dist/{chunk-HT2AHGQI.js → chunk-4JPMZTJY.js} +2 -2
- package/dist/{chunk-FQ5VRHIB.js → chunk-4T3SE27M.js} +5 -9
- package/dist/chunk-4T3SE27M.js.map +1 -0
- package/dist/{chunk-MKXXMNJH.js → chunk-4V3Q35WG.js} +2 -2
- package/dist/{chunk-A6IJU4TK.js → chunk-52MGURXO.js} +2 -2
- package/dist/{chunk-IUWCVHQ7.js → chunk-5A4345TG.js} +4 -4
- package/dist/{chunk-IUWCVHQ7.js.map → chunk-5A4345TG.js.map} +1 -1
- package/dist/{chunk-ISZQJBML.js → chunk-5FE75J4S.js} +6 -6
- package/dist/chunk-5FE75J4S.js.map +1 -0
- package/dist/chunk-5KC7QYEC.js +565 -0
- package/dist/chunk-5KC7QYEC.js.map +1 -0
- package/dist/{chunk-NNARWO72.js → chunk-5UMK7GRI.js} +13 -12
- package/dist/chunk-5UMK7GRI.js.map +1 -0
- package/dist/{chunk-HLEK5VAN.js → chunk-5WWDGFOS.js} +2 -2
- package/dist/{chunk-CKNGS5MH.js → chunk-6QVKPHBF.js} +3 -5
- package/dist/chunk-6QVKPHBF.js.map +1 -0
- package/dist/{chunk-PSIV7CJV.js → chunk-747G6CT3.js} +2 -2
- package/dist/chunk-747G6CT3.js.map +1 -0
- package/dist/{chunk-LGRLME4M.js → chunk-7R2Q7CPL.js} +16 -16
- package/dist/chunk-7R2Q7CPL.js.map +1 -0
- package/dist/{chunk-SOIQ4MM4.js → chunk-7XMHMVTS.js} +3 -3
- package/dist/{chunk-BUDAGWL5.js → chunk-A4XMIZT3.js} +6 -6
- package/dist/{chunk-BUDAGWL5.js.map → chunk-A4XMIZT3.js.map} +1 -1
- package/dist/{chunk-4MXI3ODD.js → chunk-AEQGFRU4.js} +3 -3
- package/dist/{chunk-7JE7BDYJ.js → chunk-AL6ML4LA.js} +5 -5
- package/dist/{chunk-ZUVBC32X.js → chunk-AUKKUPVB.js} +2 -2
- package/dist/chunk-BNWA3WG5.js +22 -0
- package/dist/chunk-BNWA3WG5.js.map +1 -0
- package/dist/{chunk-WY2XXTET.js → chunk-BPWYQ25R.js} +4 -4
- package/dist/{chunk-EOVMT6TB.js → chunk-BVCUTXE3.js} +2 -2
- package/dist/{chunk-UPD5NWI5.js → chunk-DHHGL42E.js} +13 -16
- package/dist/chunk-DHHGL42E.js.map +1 -0
- package/dist/{chunk-3JWHAR6E.js → chunk-DIZLQVAA.js} +2 -2
- package/dist/{chunk-QWFHIOD2.js → chunk-DLD5LGDS.js} +11 -12
- package/dist/chunk-DLD5LGDS.js.map +1 -0
- package/dist/{chunk-ZE4CHIED.js → chunk-DQESF6RP.js} +17 -28
- package/dist/chunk-DQESF6RP.js.map +1 -0
- package/dist/{chunk-IT22PWKV.js → chunk-E2N2T5ZO.js} +2 -2
- package/dist/{chunk-3ELRMVJK.js → chunk-EGVJ7TM4.js} +31 -34
- package/dist/chunk-EGVJ7TM4.js.map +1 -0
- package/dist/{chunk-WNJ4AVGE.js → chunk-EJLV62NI.js} +2 -2
- package/dist/{chunk-QBBUZ3I3.js → chunk-EYG2CY2X.js} +11 -11
- package/dist/{enclave-27SMF6GF.js → chunk-EZGV6F47.js} +83 -56
- package/dist/chunk-EZGV6F47.js.map +1 -0
- package/dist/{chunk-LQ4ZHOKP.js → chunk-EZOAKKTB.js} +36 -27
- package/dist/chunk-EZOAKKTB.js.map +1 -0
- package/dist/{chunk-BJ2IXQ5Q.js → chunk-FFJFE4T7.js} +2 -2
- package/dist/{chunk-JCN44NCY.js → chunk-FLPCETP6.js} +2 -2
- package/dist/{chunk-5O7D6ZTW.js → chunk-FOEDQATO.js} +2 -2
- package/dist/{chunk-VNNRUGMM.js → chunk-FVH5QYY2.js} +2 -2
- package/dist/{chunk-ANWPSTZU.js → chunk-G2MVBDFP.js} +23 -26
- package/dist/chunk-G2MVBDFP.js.map +1 -0
- package/dist/chunk-GMKGGY7V.js +234 -0
- package/dist/chunk-GMKGGY7V.js.map +1 -0
- package/dist/{chunk-EIPVYUEP.js → chunk-GQ4MF3CM.js} +3 -3
- package/dist/chunk-GQ4MF3CM.js.map +1 -0
- package/dist/{chunk-PEOZ34EM.js → chunk-GSAK56VF.js} +1 -1
- package/dist/chunk-GSAK56VF.js.map +1 -0
- package/dist/{chunk-QOOUUR4A.js → chunk-GUZET4SG.js} +10 -4
- package/dist/chunk-GUZET4SG.js.map +1 -0
- package/dist/{chunk-4AF3TUMP.js → chunk-GZT3NQRA.js} +2 -2
- package/dist/{chunk-N5DNADLQ.js → chunk-H23XHRTT.js} +19 -34
- package/dist/chunk-H23XHRTT.js.map +1 -0
- package/dist/{chunk-MVZ2TPVP.js → chunk-H427H63K.js} +2 -2
- package/dist/{chunk-6B3VNR4P.js → chunk-H7JBY4P7.js} +23 -32
- package/dist/chunk-H7JBY4P7.js.map +1 -0
- package/dist/{chunk-MLPHLJIQ.js → chunk-HS554XAF.js} +2 -2
- package/dist/{chunk-HK67PX4J.js → chunk-HW7CMKUG.js} +1 -1
- package/dist/chunk-HW7CMKUG.js.map +1 -0
- package/dist/{chunk-S57HTZ6X.js → chunk-IMQKWR46.js} +5 -7
- package/dist/chunk-IMQKWR46.js.map +1 -0
- package/dist/{chunk-FCKWQE2H.js → chunk-IUBMZPHM.js} +7 -7
- package/dist/chunk-IUBMZPHM.js.map +1 -0
- package/dist/{chunk-UD5EVGZ7.js → chunk-IUT3GWP3.js} +49 -13
- package/dist/chunk-IUT3GWP3.js.map +1 -0
- package/dist/{chunk-J6UOHJY5.js → chunk-JDEYF3PJ.js} +4 -8
- package/dist/{chunk-J6UOHJY5.js.map → chunk-JDEYF3PJ.js.map} +1 -1
- package/dist/{chunk-NWHBJQAL.js → chunk-JIBUPZHA.js} +4 -4
- package/dist/chunk-JIBUPZHA.js.map +1 -0
- package/dist/{chunk-TROR3ALR.js → chunk-JOSPH3E5.js} +2 -2
- package/dist/{chunk-F24ZZTHQ.js → chunk-JQYKPKG6.js} +4 -4
- package/dist/{chunk-GF5BZ7D4.js → chunk-JSMTXZR3.js} +8 -12
- package/dist/chunk-JSMTXZR3.js.map +1 -0
- package/dist/chunk-JWWYRR4Q.js +12 -0
- package/dist/chunk-JWWYRR4Q.js.map +1 -0
- package/dist/{chunk-HBPPGWUM.js → chunk-KZXDLBY6.js} +14 -9
- package/dist/chunk-KZXDLBY6.js.map +1 -0
- package/dist/{chunk-7VCXZDA4.js → chunk-LIOVX5TJ.js} +7 -11
- package/dist/chunk-LIOVX5TJ.js.map +1 -0
- package/dist/{chunk-QWGU66MP.js → chunk-LNSVGRHO.js} +5 -7
- package/dist/chunk-LNSVGRHO.js.map +1 -0
- package/dist/{chunk-MDWKM2XC.js → chunk-M5B2W6YY.js} +3 -3
- package/dist/{chunk-F2TDU7MQ.js → chunk-MBMTND6D.js} +2 -2
- package/dist/{chunk-K6W7BVZ6.js → chunk-MILI22XQ.js} +3 -3
- package/dist/{chunk-YNIUIERI.js → chunk-MXKI4ABF.js} +18 -59
- package/dist/chunk-MXKI4ABF.js.map +1 -0
- package/dist/{chunk-T2LBQ5DV.js → chunk-MXOQ5JCG.js} +252 -214
- package/dist/chunk-MXOQ5JCG.js.map +1 -0
- package/dist/{chunk-ZXABPVM6.js → chunk-N7EVQD5S.js} +9 -13
- package/dist/chunk-N7EVQD5S.js.map +1 -0
- package/dist/{chunk-CF5UU4S7.js → chunk-N7UDP5VU.js} +7 -7
- package/dist/{chunk-FQ54DWUQ.js → chunk-NBQ3KK6X.js} +4 -4
- package/dist/{chunk-4I522ERM.js → chunk-NCO25JZO.js} +4 -4
- package/dist/chunk-NH2UOV3B.js +18 -0
- package/dist/chunk-NH2UOV3B.js.map +1 -0
- package/dist/{chunk-SI3V7D4G.js → chunk-O2IMQSNA.js} +2 -2
- package/dist/{chunk-T52GX4SA.js → chunk-O46CHQT7.js} +4 -4
- package/dist/chunk-OIEO4WDL.js +27 -0
- package/dist/chunk-OIEO4WDL.js.map +1 -0
- package/dist/{chunk-GHLTDZRS.js → chunk-OKSTSITU.js} +25 -4
- package/dist/chunk-OKSTSITU.js.map +1 -0
- package/dist/{chunk-TOPYQ6GA.js → chunk-OYW3I5M4.js} +6 -6
- package/dist/{chunk-X4773RBR.js → chunk-PD64727P.js} +2 -2
- package/dist/chunk-PD64727P.js.map +1 -0
- package/dist/{chunk-BP6DARYA.js → chunk-PP3K67AJ.js} +4 -4
- package/dist/chunk-PP3K67AJ.js.map +1 -0
- package/dist/chunk-Q2XRFWOI.js +40 -0
- package/dist/chunk-Q2XRFWOI.js.map +1 -0
- package/dist/{chunk-AOWGXU6D.js → chunk-Q4UHJ5SN.js} +2 -2
- package/dist/{chunk-FW22ZCXT.js → chunk-QBLT6POL.js} +2 -2
- package/dist/chunk-QMWY2FDS.js +157 -0
- package/dist/chunk-QMWY2FDS.js.map +1 -0
- package/dist/{chunk-I3JDRCMW.js → chunk-RB4DOPGZ.js} +10 -10
- package/dist/{chunk-32YV3TJT.js → chunk-SMV2HRDU.js} +2 -2
- package/dist/{chunk-ODVPTDPK.js → chunk-SV2PM2OY.js} +1 -1
- package/dist/chunk-SV2PM2OY.js.map +1 -0
- package/dist/{chunk-Z5HTYMMQ.js → chunk-SYNY3VB5.js} +2 -2
- package/dist/{chunk-SYVZW77S.js → chunk-TEHHROZL.js} +6 -8
- package/dist/chunk-TEHHROZL.js.map +1 -0
- package/dist/{chunk-ZSX4S5XB.js → chunk-TKVUE4JF.js} +9 -9
- package/dist/{chunk-B57AFBY2.js → chunk-TZZBXPZK.js} +2 -2
- package/dist/{chunk-VNPEWFPD.js → chunk-U2FZNEWJ.js} +4 -4
- package/dist/chunk-U2FZNEWJ.js.map +1 -0
- package/dist/{chunk-5FDLC6G7.js → chunk-UA372JHH.js} +3 -3
- package/dist/{chunk-PDCG6PR5.js → chunk-UEFOQH74.js} +2 -2
- package/dist/chunk-UEFOQH74.js.map +1 -0
- package/dist/{chunk-HVSCEIYL.js → chunk-UIYESRD6.js} +9 -11
- package/dist/chunk-UIYESRD6.js.map +1 -0
- package/dist/{chunk-B6SJIBQK.js → chunk-V3RWOOSO.js} +4 -4
- package/dist/{chunk-HBRLNOHL.js → chunk-V7ADQF5O.js} +4 -4
- package/dist/{chunk-L7DOS3TE.js → chunk-VAORSCSU.js} +3 -3
- package/dist/chunk-VAORSCSU.js.map +1 -0
- package/dist/{chunk-M522UYZ2.js → chunk-VFHCKG5M.js} +6 -10
- package/dist/chunk-VFHCKG5M.js.map +1 -0
- package/dist/{chunk-DC5QVPV7.js → chunk-VHBKYN2J.js} +3 -3
- package/dist/chunk-VHBKYN2J.js.map +1 -0
- package/dist/{chunk-WX5ADGTZ.js → chunk-VKI2EB3N.js} +3 -3
- package/dist/chunk-VKI2EB3N.js.map +1 -0
- package/dist/{chunk-MTL7MXGR.js → chunk-VMV5SBE4.js} +16 -17
- package/dist/chunk-VMV5SBE4.js.map +1 -0
- package/dist/{chunk-F7XGHL5O.js → chunk-VQDZYB2B.js} +3 -3
- package/dist/{chunk-BK2HHQGN.js → chunk-VVOLDVIR.js} +2 -2
- package/dist/{chunk-6LMQ5R26.js → chunk-WPOYWFSE.js} +7 -7
- package/dist/{chunk-6LMQ5R26.js.map → chunk-WPOYWFSE.js.map} +1 -1
- package/dist/{chunk-3F7GLNAE.js → chunk-WXE4W2U6.js} +7 -11
- package/dist/chunk-WXE4W2U6.js.map +1 -0
- package/dist/{chunk-6K7DPM7D.js → chunk-XQRFSKYM.js} +2 -2
- package/dist/{chunk-M7NI3IWE.js → chunk-XSPFDUDG.js} +22 -50
- package/dist/chunk-XSPFDUDG.js.map +1 -0
- package/dist/{chunk-ID6Z6E66.js → chunk-Y2RKVFKR.js} +2 -2
- package/dist/{chunk-6LNL42F5.js → chunk-Y3LPTBG7.js} +12 -12
- package/dist/chunk-Y3LPTBG7.js.map +1 -0
- package/dist/{chunk-FN5EBVTQ.js → chunk-YRXFFWG4.js} +2 -2
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-W3USLL5M.js → classified-marker-SIYKUU5L.js} +3 -3
- package/dist/classified-marker-SIYKUU5L.js.map +1 -0
- package/dist/collection-facade-CS7CA2XO.js +47 -0
- package/dist/{computed-TPFBX7U4.js → computed-FAD7SED4.js} +3 -3
- package/dist/consent/index.js +10 -11
- package/dist/consent/index.js.map +1 -1
- package/dist/cover/index.js +9 -10
- package/dist/custody/index.js +12 -13
- package/dist/{dead-filter-U2UYKSZL.js → dead-filter-4F3LWYKH.js} +11 -3
- package/dist/dead-filter-4F3LWYKH.js.map +1 -0
- package/dist/debug/index.js +11 -2
- package/dist/debug/index.js.map +1 -1
- package/dist/{delegation-S3AEPW2T.js → delegation-NANZDG4N.js} +13 -16
- package/dist/delegation-NANZDG4N.js.map +1 -0
- package/dist/derivations/index.js +23 -24
- package/dist/derive-XLOJVXPU.js +20 -0
- package/dist/directory/index.js +10 -11
- package/dist/{dispatch-3CQDJV5Q.js → dispatch-H4HV32AM.js} +5 -5
- package/dist/{dispatch-RH4LHKBH.js → dispatch-JDZNGEB3.js} +21 -22
- package/dist/dispatch-JDZNGEB3.js.map +1 -0
- package/dist/executor-FMPVN6DT.js +35 -0
- package/dist/executor-LBBBRTN5.js +8 -0
- package/dist/executor-OSRZST2U.js +8 -0
- package/dist/export-accessible-RAOJAAU5.js +22 -0
- package/dist/extract-partition-JD5CUSTG.js +37 -0
- package/dist/{fanout-sidecar-OT6RYLOL.js → fanout-sidecar-L7NHPIOC.js} +13 -15
- package/dist/fanout-sidecar-L7NHPIOC.js.map +1 -0
- package/dist/find-JRN4RNQ5.js +10 -0
- package/dist/forget/index.js +9 -10
- package/dist/forget/index.js.map +1 -1
- package/dist/guards/index.js +4 -4
- package/dist/history/index.js +13 -14
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.js +14 -15
- package/dist/i18n/index.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +183 -184
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +5 -5
- package/dist/introspection/index.js +11 -12
- package/dist/issue-YIVBZUTH.js +19 -0
- package/dist/kernel/attestation-types.d.ts +62 -0
- package/dist/kernel/collection-config.d.ts +1 -48
- package/dist/kernel/collection.d.ts +1 -1
- package/dist/kernel/cutover-transform.d.ts +1 -1
- package/dist/kernel/errors.d.ts +30 -2
- package/dist/kernel/merge-authority.d.ts +1 -1
- package/dist/kernel/paths.d.ts +29 -5
- package/dist/kernel/prepared-write.d.ts +1 -1
- package/dist/kernel/secret-mode.d.ts +1 -1
- package/dist/kernel/types.d.ts +42 -5
- package/dist/kernel/vault.d.ts +2 -2
- package/dist/kernel/write-queue.d.ts +17 -0
- package/dist/{ledger-KZPCMVZY.js → ledger-5ZMGE44K.js} +11 -12
- package/dist/liberate-WZSZM2W6.js +24 -0
- package/dist/link-set-MFXC24VK.js +29 -0
- package/dist/{managed-secret-S3MQ6SH6.js → managed-secret-MFTFT22X.js} +10 -11
- package/dist/materialized-views/index.js +26 -27
- package/dist/{migrate-cek-V7GKJZ7O.js → migrate-cek-DZRFFOHW.js} +2 -2
- package/dist/money/index.js +5 -5
- package/dist/noydb-ITIGNKUF.js +96 -0
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +12 -13
- package/dist/pod/index.js +72 -72
- package/dist/{pod-handle-WGDFB4C2.js → pod-handle-A3LET7NO.js} +10 -11
- package/dist/pod-handle-A3LET7NO.js.map +1 -0
- package/dist/policy/index.js +10 -11
- package/dist/port/on/index.d.ts +1 -1
- package/dist/port/to/index.d.ts +1 -1
- package/dist/port/with/blob-strategy.d.ts +1 -1
- package/dist/port/with/classified-strategy.d.ts +1 -1
- package/dist/port/with/collection-options.d.ts +1 -1
- package/dist/port/with/collection-registries.d.ts +1 -1
- package/dist/port/with/lookup-strategy.d.ts +2 -2
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-SLSXIPBV.js → post-register-7ND27CF2.js} +6 -6
- package/dist/post-register-7ND27CF2.js.map +1 -0
- package/dist/query/all/index.js +15 -15
- package/dist/query/index.js +7 -7
- package/dist/query/live/index.js +7 -7
- package/dist/query/reduce/index.js +10 -10
- package/dist/query/relate/index.js +9 -9
- package/dist/reduce/index.js +8 -8
- package/dist/register-DT5HZ2LZ.js +30 -0
- package/dist/registry-BHRZGZHF.js +8 -0
- package/dist/registry-ET6ZFFWA.js +34 -0
- package/dist/registry-HXFGLGTG.js +8 -0
- package/dist/registry-THCPDEOD.js +23 -0
- package/dist/request-withdrawal-AV2MJJKY.js +30 -0
- package/dist/{reveal-4BCKPEC2.js → reveal-B2TLP4JQ.js} +10 -9
- package/dist/reveal-B2TLP4JQ.js.map +1 -0
- package/dist/revoke-6DWIEOCV.js +24 -0
- package/dist/satellites/index.js +1 -1
- package/dist/schema-update/index.js +2 -2
- package/dist/sealed-record/index.js +16 -18
- package/dist/sealed-record/index.js.map +1 -1
- package/dist/search/index.js +4 -4
- package/dist/{seed-4JS2RJ4A.js → seed-XNSE4U3S.js} +15 -18
- package/dist/seed-XNSE4U3S.js.map +1 -0
- package/dist/sequence/index.js +9 -10
- package/dist/session/index.js +9 -10
- package/dist/session/index.js.map +1 -1
- package/dist/shadow/index.js +2 -2
- package/dist/signer-MHGW3OIL.js +23 -0
- package/dist/snapshots/index.js +11 -11
- package/dist/stale-6GCFMOOR.js +28 -0
- package/dist/storage-BYN5LO6Z.js +21 -0
- package/dist/store/index.js +1 -1
- package/dist/{store-coordination-provider-2O2VUHKW.js → store-coordination-provider-C4BPT5XF.js} +11 -12
- package/dist/store-coordination-provider-C4BPT5XF.js.map +1 -0
- package/dist/sync/index.js +10 -11
- package/dist/sync/index.js.map +1 -1
- package/dist/team/index.js +15 -16
- package/dist/tiers/index.js +11 -12
- package/dist/to/index.js +2 -2
- package/dist/transactions/index.js +3 -3
- package/dist/util/index.js +1 -1
- package/dist/vault-head/index.js +11 -14
- package/dist/vault-head/index.js.map +1 -1
- package/dist/{verify-RVT67IMH.js → verify-UKALW7C2.js} +14 -12
- package/dist/verify-UKALW7C2.js.map +1 -0
- package/dist/via/classified/binding.d.ts +2 -2
- package/dist/via/classified/config-drift.d.ts +2 -2
- package/dist/via/classified/errors.d.ts +1 -1
- package/dist/via/lookup/handle.d.ts +4 -4
- package/dist/walk-4VPK7AS4.js +20 -0
- package/dist/with-audit/attestation/index.d.ts +2 -1
- package/dist/with-audit/attestation/issue.d.ts +2 -2
- package/dist/with-audit/attestation/revoke.d.ts +2 -2
- package/dist/with-audit/attestation/scheme.d.ts +7 -0
- package/dist/with-audit/attestation/signer.d.ts +1 -1
- package/dist/with-audit/attestation/strategy.d.ts +2 -2
- package/dist/with-audit/attestation/types.d.ts +10 -0
- package/dist/with-audit/attestation/vault-facade.d.ts +2 -2
- package/dist/with-audit/attestation/verifier.d.ts +6 -0
- package/dist/with-audit/consent/consent.d.ts +1 -1
- package/dist/with-audit/consent/strategy.d.ts +1 -1
- package/dist/with-audit/forget/subject-index.d.ts +1 -1
- package/dist/with-audit/periods/vault-facade.d.ts +1 -1
- package/dist/with-audit/sealed-record/index.d.ts +2 -2
- package/dist/with-audit/sealed-record/strategy.d.ts +1 -1
- package/dist/with-audit/tiers/index.d.ts +2 -2
- package/dist/with-cargo/adopt-partition.d.ts +1 -1
- package/dist/with-cargo/extract-partition.d.ts +1 -1
- package/dist/with-cargo/floor.d.ts +1 -1
- package/dist/with-commit/history/history.d.ts +2 -2
- package/dist/with-commit/history/index.d.ts +1 -1
- package/dist/with-commit/history/ledger/store.d.ts +1 -1
- package/dist/with-commit/history/strategy.d.ts +1 -1
- package/dist/with-commit/history/time-machine.d.ts +1 -1
- package/dist/with-commit/numbering/index.d.ts +1 -1
- package/dist/with-commit/sequence/index.d.ts +1 -1
- package/dist/with-commit/vault-head/head.d.ts +1 -1
- package/dist/with-commit/vault-head/index.d.ts +1 -1
- package/dist/with-commit/vault-head/strategy.d.ts +1 -1
- package/dist/with-commit/vault-head/verify.d.ts +1 -1
- package/dist/with-formula/derivations/dispatch.d.ts +1 -1
- package/dist/with-formula/derivations/fanout-sidecar.d.ts +1 -1
- package/dist/with-lookup/indexing/collection-facade.d.ts +1 -1
- package/dist/with-lookup/search/collection-facade.d.ts +1 -1
- package/dist/with-party/broker/index.d.ts +3 -3
- package/dist/with-party/directory/user-envelope/storage.d.ts +1 -1
- package/dist/with-party/team/delegation.d.ts +1 -1
- package/dist/with-party/team/echo-secret.d.ts +2 -2
- package/dist/with-party/team/index.d.ts +1 -1
- package/dist/with-party/team/keyring.d.ts +1 -1
- package/dist/with-party/team/magic-link-grant.d.ts +1 -1
- package/dist/with-party/team/recovery.d.ts +1 -1
- package/dist/with-party/team/roster-tag.d.ts +1 -1
- package/dist/with-party/team/rotate-recover.d.ts +1 -1
- package/dist/with-party/team/wrapped-deks.d.ts +1 -1
- package/dist/with-pod/index.d.ts +1 -1
- package/dist/with-shape/blobs/blob-compaction.d.ts +1 -1
- package/dist/with-shape/blobs/blob-intent.d.ts +1 -1
- package/dist/with-shape/blobs/blob-set.d.ts +2 -2
- package/dist/with-shape/blobs/legacy-sweep.d.ts +1 -1
- package/dist/with-shape/introspection/describe.d.ts +1 -1
- package/dist/with-shape/introspection/walk.d.ts +1 -1
- package/dist/with-shape/links/lazy-handle.d.ts +1 -1
- package/dist/with-shape/links/link-set.d.ts +1 -1
- package/dist/with-shape/manifest/derive.d.ts +1 -1
- package/dist/with-shape/manifest/storage.d.ts +1 -1
- package/dist/with-shape/persisted-schemas/register.d.ts +1 -1
- package/dist/with-shape/persisted-schemas/storage.d.ts +1 -1
- package/dist/with-shape/satellites/dead-filter.d.ts +1 -1
- package/dist/with-shape/satellites/declare.d.ts +1 -1
- package/dist/with-shape/satellites/marker.d.ts +1 -1
- package/dist/with-shape/satellites/post-register.d.ts +1 -1
- package/dist/with-sync/presence.d.ts +5 -10
- package/dist/withdraw-accessible-HL7GACUE.js +27 -0
- package/dist/withdraw-accessible-HL7GACUE.js.map +1 -0
- package/package.json +14 -5
- package/dist/api-GVYEKSJE.js +0 -19
- package/dist/backup-7TFRVFLH.js.map +0 -1
- package/dist/chunk-244VXYPG.js.map +0 -1
- package/dist/chunk-3ELRMVJK.js.map +0 -1
- package/dist/chunk-3F7GLNAE.js.map +0 -1
- package/dist/chunk-3H5KLDZN.js.map +0 -1
- package/dist/chunk-6B3VNR4P.js.map +0 -1
- package/dist/chunk-6LNL42F5.js.map +0 -1
- package/dist/chunk-6QSQQLSE.js +0 -95
- package/dist/chunk-6QSQQLSE.js.map +0 -1
- package/dist/chunk-7VCXZDA4.js.map +0 -1
- package/dist/chunk-ANWPSTZU.js.map +0 -1
- package/dist/chunk-BP6DARYA.js.map +0 -1
- package/dist/chunk-CKNGS5MH.js.map +0 -1
- package/dist/chunk-DC5QVPV7.js.map +0 -1
- package/dist/chunk-DE4DH2RZ.js +0 -29
- package/dist/chunk-DE4DH2RZ.js.map +0 -1
- package/dist/chunk-DF73H4UN.js.map +0 -1
- package/dist/chunk-EIPVYUEP.js.map +0 -1
- package/dist/chunk-ENAG3IY7.js.map +0 -1
- package/dist/chunk-FCKWQE2H.js.map +0 -1
- package/dist/chunk-FQ5VRHIB.js.map +0 -1
- package/dist/chunk-GF5BZ7D4.js.map +0 -1
- package/dist/chunk-GHLTDZRS.js.map +0 -1
- package/dist/chunk-GYGLAVCX.js.map +0 -1
- package/dist/chunk-HBPPGWUM.js.map +0 -1
- package/dist/chunk-HK67PX4J.js.map +0 -1
- package/dist/chunk-HVSCEIYL.js.map +0 -1
- package/dist/chunk-ISZQJBML.js.map +0 -1
- package/dist/chunk-KJFW62P4.js.map +0 -1
- package/dist/chunk-L7DOS3TE.js.map +0 -1
- package/dist/chunk-LGRLME4M.js.map +0 -1
- package/dist/chunk-LP7BEXCT.js +0 -32
- package/dist/chunk-LP7BEXCT.js.map +0 -1
- package/dist/chunk-LQ4ZHOKP.js.map +0 -1
- package/dist/chunk-M522UYZ2.js.map +0 -1
- package/dist/chunk-M7NI3IWE.js.map +0 -1
- package/dist/chunk-MTL7MXGR.js.map +0 -1
- package/dist/chunk-N5DNADLQ.js.map +0 -1
- package/dist/chunk-NNARWO72.js.map +0 -1
- package/dist/chunk-NRT6QZQB.js.map +0 -1
- package/dist/chunk-NWHBJQAL.js.map +0 -1
- package/dist/chunk-ODVPTDPK.js.map +0 -1
- package/dist/chunk-PDCG6PR5.js.map +0 -1
- package/dist/chunk-PEOZ34EM.js.map +0 -1
- package/dist/chunk-PSIV7CJV.js.map +0 -1
- package/dist/chunk-QOOUUR4A.js.map +0 -1
- package/dist/chunk-QWFHIOD2.js.map +0 -1
- package/dist/chunk-QWGU66MP.js.map +0 -1
- package/dist/chunk-S57HTZ6X.js.map +0 -1
- package/dist/chunk-SEE332EV.js +0 -66
- package/dist/chunk-SEE332EV.js.map +0 -1
- package/dist/chunk-SYVZW77S.js.map +0 -1
- package/dist/chunk-T2LBQ5DV.js.map +0 -1
- package/dist/chunk-UD5EVGZ7.js.map +0 -1
- package/dist/chunk-UPD5NWI5.js.map +0 -1
- package/dist/chunk-UYB234ZR.js +0 -479
- package/dist/chunk-UYB234ZR.js.map +0 -1
- package/dist/chunk-VNPEWFPD.js.map +0 -1
- package/dist/chunk-WX5ADGTZ.js.map +0 -1
- package/dist/chunk-X4773RBR.js.map +0 -1
- package/dist/chunk-YNIUIERI.js.map +0 -1
- package/dist/chunk-ZE4CHIED.js.map +0 -1
- package/dist/chunk-ZXABPVM6.js.map +0 -1
- package/dist/classified-marker-W3USLL5M.js.map +0 -1
- package/dist/collection-facade-QU6IJBN3.js +0 -48
- package/dist/dead-filter-U2UYKSZL.js.map +0 -1
- package/dist/delegation-S3AEPW2T.js.map +0 -1
- package/dist/derive-OX7F6TGG.js +0 -21
- package/dist/dispatch-RH4LHKBH.js.map +0 -1
- package/dist/executor-B6SRO2QS.js +0 -36
- package/dist/executor-BI5CHWRY.js +0 -8
- package/dist/executor-RBKM5W5K.js +0 -8
- package/dist/export-accessible-VMA3YM5V.js +0 -22
- package/dist/extract-partition-NF7PXGPP.js +0 -37
- package/dist/fanout-sidecar-OT6RYLOL.js.map +0 -1
- package/dist/find-LZMP26KF.js +0 -10
- package/dist/issue-IHARXWW5.js +0 -18
- package/dist/kernel/enclave/classify/compare.d.ts +0 -10
- package/dist/kernel/enclave/index.d.ts +0 -87
- package/dist/kernel/enclave/record-keys/lifecycle.d.ts +0 -124
- package/dist/kernel/enclave/record-keys/rekey-blob.d.ts +0 -88
- package/dist/kernel/enclave/record-keys/rekey.d.ts +0 -91
- package/dist/kernel/enclave/record-keys/sealed-slot.d.ts +0 -14
- package/dist/kernel/enclave/record-keys/sealed-slots.d.ts +0 -123
- package/dist/kernel/enclave/record-keys/sealing.d.ts +0 -70
- package/dist/liberate-GRLCZMW4.js +0 -24
- package/dist/link-set-JCMJ7ULP.js +0 -30
- package/dist/noydb-SWQJ3MZS.js +0 -97
- package/dist/pod-handle-WGDFB4C2.js.map +0 -1
- package/dist/post-register-SLSXIPBV.js.map +0 -1
- package/dist/register-F3OYE7MJ.js +0 -31
- package/dist/registry-CILQFXFK.js +0 -8
- package/dist/registry-XNNYQVKV.js +0 -8
- package/dist/registry-YCDZV3VW.js +0 -35
- package/dist/registry-ZGYS33TE.js +0 -24
- package/dist/request-withdrawal-Z5NC6TXT.js +0 -30
- package/dist/reveal-4BCKPEC2.js.map +0 -1
- package/dist/revoke-ZL62WC2D.js +0 -23
- package/dist/seed-4JS2RJ4A.js.map +0 -1
- package/dist/signer-MBZZMXTC.js +0 -24
- package/dist/stale-TJ3DYZMQ.js +0 -29
- package/dist/storage-SVMKRGCW.js +0 -22
- package/dist/store-coordination-provider-2O2VUHKW.js.map +0 -1
- package/dist/verify-RVT67IMH.js.map +0 -1
- package/dist/walk-HJ42EISE.js +0 -21
- package/dist/withdraw-accessible-5NZUPAVA.js +0 -27
- /package/dist/{api-GVYEKSJE.js.map → api-OS747DS4.js.map} +0 -0
- /package/dist/{computed-TPFBX7U4.js.map → capsule/contract.js.map} +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/broker/proof.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/bidx.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/digest.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/enclave-aes}/classify/vdig.d.ts +0 -0
- /package/dist/{kernel/enclave/classify → capsule/plumbing}/kofn.d.ts +0 -0
- /package/dist/{kernel/enclave/classify → capsule/plumbing}/normalize.d.ts +0 -0
- /package/dist/{kernel/enclave → capsule/plumbing}/record-aad.d.ts +0 -0
- /package/dist/{collection-facade-QU6IJBN3.js.map → capsule-VOLX3QRQ.js.map} +0 -0
- /package/dist/{chunk-YSK2CU2Q.js.map → chunk-2AFX33YA.js.map} +0 -0
- /package/dist/{chunk-TKUOEU2F.js.map → chunk-2GHDLTPE.js.map} +0 -0
- /package/dist/{chunk-6OWXYZK2.js.map → chunk-2ODVB6LZ.js.map} +0 -0
- /package/dist/{chunk-X25NWUZB.js.map → chunk-2PVXF5CS.js.map} +0 -0
- /package/dist/{chunk-ORDURZBU.js.map → chunk-3EWS67C7.js.map} +0 -0
- /package/dist/{chunk-FXQBGFOX.js.map → chunk-4CIQDWRB.js.map} +0 -0
- /package/dist/{chunk-HT2AHGQI.js.map → chunk-4JPMZTJY.js.map} +0 -0
- /package/dist/{chunk-MKXXMNJH.js.map → chunk-4V3Q35WG.js.map} +0 -0
- /package/dist/{chunk-A6IJU4TK.js.map → chunk-52MGURXO.js.map} +0 -0
- /package/dist/{chunk-HLEK5VAN.js.map → chunk-5WWDGFOS.js.map} +0 -0
- /package/dist/{chunk-SOIQ4MM4.js.map → chunk-7XMHMVTS.js.map} +0 -0
- /package/dist/{chunk-4MXI3ODD.js.map → chunk-AEQGFRU4.js.map} +0 -0
- /package/dist/{chunk-7JE7BDYJ.js.map → chunk-AL6ML4LA.js.map} +0 -0
- /package/dist/{chunk-ZUVBC32X.js.map → chunk-AUKKUPVB.js.map} +0 -0
- /package/dist/{chunk-WY2XXTET.js.map → chunk-BPWYQ25R.js.map} +0 -0
- /package/dist/{chunk-EOVMT6TB.js.map → chunk-BVCUTXE3.js.map} +0 -0
- /package/dist/{chunk-3JWHAR6E.js.map → chunk-DIZLQVAA.js.map} +0 -0
- /package/dist/{chunk-IT22PWKV.js.map → chunk-E2N2T5ZO.js.map} +0 -0
- /package/dist/{chunk-WNJ4AVGE.js.map → chunk-EJLV62NI.js.map} +0 -0
- /package/dist/{chunk-QBBUZ3I3.js.map → chunk-EYG2CY2X.js.map} +0 -0
- /package/dist/{chunk-BJ2IXQ5Q.js.map → chunk-FFJFE4T7.js.map} +0 -0
- /package/dist/{chunk-JCN44NCY.js.map → chunk-FLPCETP6.js.map} +0 -0
- /package/dist/{chunk-5O7D6ZTW.js.map → chunk-FOEDQATO.js.map} +0 -0
- /package/dist/{chunk-VNNRUGMM.js.map → chunk-FVH5QYY2.js.map} +0 -0
- /package/dist/{chunk-4AF3TUMP.js.map → chunk-GZT3NQRA.js.map} +0 -0
- /package/dist/{chunk-MVZ2TPVP.js.map → chunk-H427H63K.js.map} +0 -0
- /package/dist/{chunk-MLPHLJIQ.js.map → chunk-HS554XAF.js.map} +0 -0
- /package/dist/{chunk-TROR3ALR.js.map → chunk-JOSPH3E5.js.map} +0 -0
- /package/dist/{chunk-F24ZZTHQ.js.map → chunk-JQYKPKG6.js.map} +0 -0
- /package/dist/{chunk-MDWKM2XC.js.map → chunk-M5B2W6YY.js.map} +0 -0
- /package/dist/{chunk-F2TDU7MQ.js.map → chunk-MBMTND6D.js.map} +0 -0
- /package/dist/{chunk-K6W7BVZ6.js.map → chunk-MILI22XQ.js.map} +0 -0
- /package/dist/{chunk-CF5UU4S7.js.map → chunk-N7UDP5VU.js.map} +0 -0
- /package/dist/{chunk-FQ54DWUQ.js.map → chunk-NBQ3KK6X.js.map} +0 -0
- /package/dist/{chunk-4I522ERM.js.map → chunk-NCO25JZO.js.map} +0 -0
- /package/dist/{chunk-SI3V7D4G.js.map → chunk-O2IMQSNA.js.map} +0 -0
- /package/dist/{chunk-T52GX4SA.js.map → chunk-O46CHQT7.js.map} +0 -0
- /package/dist/{chunk-TOPYQ6GA.js.map → chunk-OYW3I5M4.js.map} +0 -0
- /package/dist/{chunk-AOWGXU6D.js.map → chunk-Q4UHJ5SN.js.map} +0 -0
- /package/dist/{chunk-FW22ZCXT.js.map → chunk-QBLT6POL.js.map} +0 -0
- /package/dist/{chunk-I3JDRCMW.js.map → chunk-RB4DOPGZ.js.map} +0 -0
- /package/dist/{chunk-32YV3TJT.js.map → chunk-SMV2HRDU.js.map} +0 -0
- /package/dist/{chunk-Z5HTYMMQ.js.map → chunk-SYNY3VB5.js.map} +0 -0
- /package/dist/{chunk-ZSX4S5XB.js.map → chunk-TKVUE4JF.js.map} +0 -0
- /package/dist/{chunk-B57AFBY2.js.map → chunk-TZZBXPZK.js.map} +0 -0
- /package/dist/{chunk-5FDLC6G7.js.map → chunk-UA372JHH.js.map} +0 -0
- /package/dist/{chunk-B6SJIBQK.js.map → chunk-V3RWOOSO.js.map} +0 -0
- /package/dist/{chunk-HBRLNOHL.js.map → chunk-V7ADQF5O.js.map} +0 -0
- /package/dist/{chunk-F7XGHL5O.js.map → chunk-VQDZYB2B.js.map} +0 -0
- /package/dist/{chunk-BK2HHQGN.js.map → chunk-VVOLDVIR.js.map} +0 -0
- /package/dist/{chunk-6K7DPM7D.js.map → chunk-XQRFSKYM.js.map} +0 -0
- /package/dist/{chunk-ID6Z6E66.js.map → chunk-Y2RKVFKR.js.map} +0 -0
- /package/dist/{chunk-FN5EBVTQ.js.map → chunk-YRXFFWG4.js.map} +0 -0
- /package/dist/{derive-OX7F6TGG.js.map → collection-facade-CS7CA2XO.js.map} +0 -0
- /package/dist/{enclave-27SMF6GF.js.map → computed-FAD7SED4.js.map} +0 -0
- /package/dist/{executor-B6SRO2QS.js.map → derive-XLOJVXPU.js.map} +0 -0
- /package/dist/{dispatch-3CQDJV5Q.js.map → dispatch-H4HV32AM.js.map} +0 -0
- /package/dist/{executor-BI5CHWRY.js.map → executor-FMPVN6DT.js.map} +0 -0
- /package/dist/{executor-RBKM5W5K.js.map → executor-LBBBRTN5.js.map} +0 -0
- /package/dist/{export-accessible-VMA3YM5V.js.map → executor-OSRZST2U.js.map} +0 -0
- /package/dist/{extract-partition-NF7PXGPP.js.map → export-accessible-RAOJAAU5.js.map} +0 -0
- /package/dist/{find-LZMP26KF.js.map → extract-partition-JD5CUSTG.js.map} +0 -0
- /package/dist/{issue-IHARXWW5.js.map → find-JRN4RNQ5.js.map} +0 -0
- /package/dist/{ledger-KZPCMVZY.js.map → issue-YIVBZUTH.js.map} +0 -0
- /package/dist/{liberate-GRLCZMW4.js.map → ledger-5ZMGE44K.js.map} +0 -0
- /package/dist/{link-set-JCMJ7ULP.js.map → liberate-WZSZM2W6.js.map} +0 -0
- /package/dist/{managed-secret-S3MQ6SH6.js.map → link-set-MFXC24VK.js.map} +0 -0
- /package/dist/{noydb-SWQJ3MZS.js.map → managed-secret-MFTFT22X.js.map} +0 -0
- /package/dist/{migrate-cek-V7GKJZ7O.js.map → migrate-cek-DZRFFOHW.js.map} +0 -0
- /package/dist/{register-F3OYE7MJ.js.map → noydb-ITIGNKUF.js.map} +0 -0
- /package/dist/{registry-CILQFXFK.js.map → register-DT5HZ2LZ.js.map} +0 -0
- /package/dist/{registry-XNNYQVKV.js.map → registry-BHRZGZHF.js.map} +0 -0
- /package/dist/{registry-YCDZV3VW.js.map → registry-ET6ZFFWA.js.map} +0 -0
- /package/dist/{registry-ZGYS33TE.js.map → registry-HXFGLGTG.js.map} +0 -0
- /package/dist/{request-withdrawal-Z5NC6TXT.js.map → registry-THCPDEOD.js.map} +0 -0
- /package/dist/{revoke-ZL62WC2D.js.map → request-withdrawal-AV2MJJKY.js.map} +0 -0
- /package/dist/{signer-MBZZMXTC.js.map → revoke-6DWIEOCV.js.map} +0 -0
- /package/dist/{stale-TJ3DYZMQ.js.map → signer-MHGW3OIL.js.map} +0 -0
- /package/dist/{storage-SVMKRGCW.js.map → stale-6GCFMOOR.js.map} +0 -0
- /package/dist/{walk-HJ42EISE.js.map → storage-BYN5LO6Z.js.map} +0 -0
- /package/dist/{withdraw-accessible-5NZUPAVA.js.map → walk-4VPK7AS4.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/with-audit/attestation/signer.ts"],"sourcesContent":["import type { NoydbStore } from '../../kernel/types.js'\nimport { buildRecordAad, buildRecordEnvelope, encrypt, openEnvelopeJson, type EnclaveKey } from '../../kernel/enclave/index.js'\nimport { ConflictError } from '../../kernel/errors.js'\nimport { generateDocSigningKeyPair } from '@noy-db/attestation'\n\nexport const ATTESTATIONS_COLLECTION = '_attestations'\nexport const SIGNER_RECORD_ID = '_signer'\nexport const REVOKED_RECORD_ID = '_revoked'\n\nexport interface DocSigner {\n readonly keyId: string\n readonly publicKeyB64: string\n readonly privateKeyPkcs8B64: string\n}\n\n/**\n * Pure read: return the firm's persisted document-signing keypair, or `null`\n * if none has been minted yet. Never writes — callers that must NOT mint\n * (e.g. an ungated public-key getter) use this instead of `loadOrCreateSigner`.\n *\n * Stored as an encrypted record `_attestations/_signer` under the\n * `_attestations` collection DEK (resolved via `getDEK`, which is\n * AES-KW-wrapped under the owner KEK + persisted by the keyring). The KEK\n * itself is AES-KW-only and cannot AES-GCM-encrypt these bytes — hence\n * storage under a normal collection DEK.\n */\nexport async function loadSigner(\n store: NoydbStore,\n vault: string,\n getDEK: (collection: string) => Promise<EnclaveKey>,\n): Promise<DocSigner | null> {\n const existing = await store.get(vault, ATTESTATIONS_COLLECTION, SIGNER_RECORD_ID)\n if (!existing) return null\n const dek = await getDEK(ATTESTATIONS_COLLECTION)\n const json = await openEnvelopeJson({ collection: ATTESTATIONS_COLLECTION, id: SIGNER_RECORD_ID }, existing, dek)\n return JSON.parse(json) as DocSigner\n}\n\n/**\n * Lazily mint (or load) the firm's Ed25519 document-signing keypair.\n *\n * On a concurrent first-mint, two callers can both read `null` and both mint\n * distinct keypairs. The `put(…, expectedVersion: 0)` (\"must not already\n * exist\") lets exactly one win; the loser catches `ConflictError`, re-reads,\n * and returns the winner's signer — converging on a single keypair rather than\n * clobbering it or surfacing a raw conflict. (All real stores treat a missing\n * record + `ev: 0` as a no-conflict write, so the catch fires on lost-race only.)\n */\nexport async function loadOrCreateSigner(\n store: NoydbStore,\n vault: string,\n getDEK: (collection: string) => Promise<EnclaveKey>,\n): Promise<DocSigner> {\n const existing = await loadSigner(store, vault, getDEK)\n if (existing) return existing\n\n const dek = await getDEK(ATTESTATIONS_COLLECTION)\n const signer = await generateDocSigningKeyPair()\n const identity = { collection: ATTESTATIONS_COLLECTION, id: SIGNER_RECORD_ID, version: 1 }\n const { iv, data } = await encrypt(JSON.stringify(signer), dek, buildRecordAad(identity))\n const env = buildRecordEnvelope(\n identity,\n { iv, data },\n )\n try {\n await store.put(vault, ATTESTATIONS_COLLECTION, SIGNER_RECORD_ID, env, 0)\n return signer\n } catch (e) {\n if (!(e instanceof ConflictError)) throw e\n // Lost the race — another writer minted first. Adopt the winner.\n const winner = await loadSigner(store, vault, getDEK)\n if (!winner) {\n throw new ConflictError(0, 'loadOrCreateSigner: signer mint lost a concurrent race but the winning record could not be re-read.')\n }\n return winner\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAGA,SAAS,iCAAiC;AAEnC,IAAM,0BAA0B;AAChC,IAAM,mBAAmB;AACzB,IAAM,oBAAoB;AAmBjC,eAAsB,WACpB,OACA,OACA,QAC2B;AAC3B,QAAM,WAAW,MAAM,MAAM,IAAI,OAAO,yBAAyB,gBAAgB;AACjF,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,MAAM,MAAM,OAAO,uBAAuB;AAChD,QAAM,OAAO,MAAM,iBAAiB,EAAE,YAAY,yBAAyB,IAAI,iBAAiB,GAAG,UAAU,GAAG;AAChH,SAAO,KAAK,MAAM,IAAI;AACxB;AAYA,eAAsB,mBACpB,OACA,OACA,QACoB;AACpB,QAAM,WAAW,MAAM,WAAW,OAAO,OAAO,MAAM;AACtD,MAAI,SAAU,QAAO;AAErB,QAAM,MAAM,MAAM,OAAO,uBAAuB;AAChD,QAAM,SAAS,MAAM,0BAA0B;AAC/C,QAAM,WAAW,EAAE,YAAY,yBAAyB,IAAI,kBAAkB,SAAS,EAAE;AACzF,QAAM,EAAE,IAAI,KAAK,IAAI,MAAM,QAAQ,KAAK,UAAU,MAAM,GAAG,KAAK,eAAe,QAAQ,CAAC;AACxF,QAAM,MAAM;AAAA,IACV;AAAA,IACA,EAAE,IAAI,KAAK;AAAA,EACb;AACA,MAAI;AACF,UAAM,MAAM,IAAI,OAAO,yBAAyB,kBAAkB,KAAK,CAAC;AACxE,WAAO;AAAA,EACT,SAAS,GAAG;AACV,QAAI,EAAE,aAAa,eAAgB,OAAM;AAEzC,UAAM,SAAS,MAAM,WAAW,OAAO,OAAO,MAAM;AACpD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,cAAc,GAAG,qGAAqG;AAAA,IAClI;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/with-commit/history/history.ts","../src/with-commit/history/strategy.ts"],"sourcesContent":["import { buildRecordEnvelope } from '../../kernel/enclave/index.js'\nimport type { RecordIdentity } from '../../kernel/enclave/index.js'\nimport type { NoydbStore, EncryptedEnvelope, HistoryOptions, PruneOptions } from '../../kernel/types.js'\nimport { isTombstone, isTombstoneShape, rewrapEnvelope, isRewrappedUnder, type EnclaveKey } from '../../kernel/enclave/index.js'\n\n/**\n * History storage convention:\n * Collection: `_history`\n * ID format: `{collection}:{recordId}:{paddedVersion}`\n * Version is zero-padded to 10 digits for lexicographic sorting.\n */\n\nconst HISTORY_COLLECTION = '_history'\nconst VERSION_PAD = 10\n\nfunction historyId(collection: string, recordId: string, version: number): string {\n return `${collection}:${recordId}:${String(version).padStart(VERSION_PAD, '0')}`\n}\n\n/**\n * The identity a history snapshot is **sealed against** — its STORAGE location,\n * not the live record it is a copy of (#1041).\n *\n * ## Why storage, and why this is a decision rather than a detail\n *\n * A snapshot is a copy, so two identities are available: the live record\n * (`collection`/`recordId`) or where the bytes actually land\n * (`_history`/`historyId(...)`). They are not equivalent under attack.\n *\n * Binding the LIVE identity makes a snapshot's AAD **indistinguishable from the\n * live record's at the same version** — so an untrusted store could serve a\n * history entry *as the current record* and the client would accept it. It also\n * leaves entries relocatable within `_history`.\n *\n * Binding STORAGE identity closes both. The cost is that the id must be known\n * *before* the envelope is sealed, where `saveHistory` previously derived it\n * *after* (from `envelope._v`) — which is precisely the restructure this\n * function exists to make possible.\n *\n * `saveHistory` uses this too, so the sealed identity and the put location have\n * **one definition** and cannot drift apart. Changing the layout here changes\n * both at once, by construction.\n */\nexport function historyIdentity(collection: string, recordId: string, version: number): RecordIdentity {\n // The snapshot's own `_v` IS the version it preserves — the same number that\n // appears in its id. One argument feeds both, so they cannot disagree (#1093).\n return { collection: HISTORY_COLLECTION, id: historyId(collection, recordId, version), version }\n}\n\n// Unused today, kept for future history-id parsing utilities.\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction parseHistoryId(id: string): { collection: string; recordId: string; version: number } | null {\n const lastColon = id.lastIndexOf(':')\n if (lastColon < 0) return null\n const versionStr = id.slice(lastColon + 1)\n const rest = id.slice(0, lastColon)\n const firstColon = rest.indexOf(':')\n if (firstColon < 0) return null\n return {\n collection: rest.slice(0, firstColon),\n recordId: rest.slice(firstColon + 1),\n version: parseInt(versionStr, 10),\n }\n}\n\nfunction matchesPrefix(id: string, collection: string, recordId?: string): boolean {\n if (recordId) {\n return id.startsWith(`${collection}:${recordId}:`)\n }\n return id.startsWith(`${collection}:`)\n}\n\n/** Save a history entry (a complete encrypted envelope snapshot). */\nexport async function saveHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n envelope: EncryptedEnvelope,\n): Promise<void> {\n // Same derivation the caller sealed against — one definition, so the sealed\n // identity and the put location cannot drift (#1041).\n const { id } = historyIdentity(collection, recordId, envelope._v)\n await adapter.put(vault, HISTORY_COLLECTION, id, envelope)\n}\n\n/** Get history entries for a record, sorted newest-first. */\nexport async function getHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n options?: HistoryOptions,\n): Promise<EncryptedEnvelope[]> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds\n .filter(id => matchesPrefix(id, collection, recordId))\n .sort()\n .reverse() // newest first\n\n const entries: EncryptedEnvelope[] = []\n\n for (const id of matchingIds) {\n const envelope = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (!envelope) continue\n\n // Apply time filters\n if (options?.from && envelope._ts < options.from) continue\n if (options?.to && envelope._ts > options.to) continue\n\n entries.push(envelope)\n\n if (options?.limit && entries.length >= options.limit) break\n }\n\n return entries\n}\n\n/** Get a specific version's envelope from history. */\nexport async function getVersionEnvelope(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n version: number,\n): Promise<EncryptedEnvelope | null> {\n const id = historyId(collection, recordId, version)\n return adapter.get(vault, HISTORY_COLLECTION, id)\n}\n\n/** Prune history entries. Returns the number of entries deleted. */\nexport async function pruneHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string | undefined,\n options: PruneOptions,\n): Promise<number> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds\n .filter(id => recordId ? matchesPrefix(id, collection, recordId) : matchesPrefix(id, collection))\n .sort()\n\n let toDelete: string[] = []\n\n if (options.keepVersions !== undefined) {\n // Keep only the N most recent, delete the rest\n const keep = options.keepVersions\n if (matchingIds.length > keep) {\n toDelete = matchingIds.slice(0, matchingIds.length - keep)\n }\n }\n\n if (options.beforeDate) {\n // Delete entries older than the specified date\n for (const id of matchingIds) {\n if (toDelete.includes(id)) continue\n const envelope = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (envelope && envelope._ts < options.beforeDate) {\n toDelete.push(id)\n }\n }\n }\n\n // Deduplicate\n const uniqueDeletes = [...new Set(toDelete)]\n\n for (const id of uniqueDeletes) {\n await adapter.delete(vault, HISTORY_COLLECTION, id)\n }\n\n return uniqueDeletes.length\n}\n\n/** Clear all history for a vault, optionally scoped to a collection or record. */\nexport async function clearHistory(\n adapter: NoydbStore,\n vault: string,\n collection?: string,\n recordId?: string,\n): Promise<number> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n let toDelete: string[]\n\n if (collection && recordId) {\n toDelete = allIds.filter(id => matchesPrefix(id, collection, recordId))\n } else if (collection) {\n toDelete = allIds.filter(id => matchesPrefix(id, collection))\n } else {\n toDelete = allIds\n }\n\n for (const id of toDelete) {\n await adapter.delete(vault, HISTORY_COLLECTION, id)\n }\n\n return toDelete.length\n}\n\n/**\n * Crypto-shred every `_history` version of a record. Each non-tombstone\n * history envelope is OVERWRITTEN in place with a tombstone\n * `{ _noydb, _v, _ts: now, _by: actor, _iv: '', _data: '' }` — dropping\n * `_iv`/`_data`/`_cek`/`_det`, so the prior ciphertext (and the wrapped CEK\n * that could decrypt it) is gone everywhere this store reaches. The version\n * counter (`_v`) is preserved so the audit trail still shows \"N versions\n * existed and were erased.\"\n *\n * Overwrite — NOT delete — so the history key itself survives as proof the\n * version existed. Already-tombstoned versions (re-run / idempotent forget)\n * are left untouched and not counted.\n *\n * Returns the number of history versions newly tombstoned.\n */\nexport async function tombstoneHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n actor: string,\n encrypted: boolean,\n): Promise<number> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds.filter(id => matchesPrefix(id, collection, recordId))\n\n const now = new Date().toISOString()\n let count = 0\n for (const id of matchingIds) {\n const env = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (!env) continue\n // Already a tombstone (no body and no wrapped CEK)? Skip — idempotent.\n if (isTombstone(env, encrypted)) continue\n // `by` rides on the IDENTITY — passing it in the body went through a\n // conditional spread, which TypeScript does not excess-property-check, so\n // it was silently dropped once `_by` moved to the identity (#1041).\n const tombstone: EncryptedEnvelope = buildRecordEnvelope(\n { collection: HISTORY_COLLECTION, id, ...(actor ? { by: actor } : {}), version: env._v },\n { ts: now, iv: '', data: '' },\n )\n await adapter.put(vault, HISTORY_COLLECTION, id, tombstone)\n count++\n }\n return count\n}\n\n/**\n * Re-key every `_history` snapshot of a record from `fromDek` to `toDek`.\n * Mirrors what `rewrapBodyToDek` already does for a record's LIVE body on a\n * tier move (elevate/demote/putAtTier) — each `_history` envelope also\n * carries its own `_cek`, wrapped under the collection's tier-0 DEK at write\n * time (`record-codec.ts`), so a tier move that rewraps only the live\n * envelope leaves prior versions decryptable at rest under the tier the\n * record left. This is defense-in-depth *beneath* the read-gate\n * (`history()`/`getVersion()` already return empty for an elevated record;\n * this protects the ciphertext even if that gate is bypassed).\n *\n * Rewraps content in place — unlike `tombstoneHistory`, it does NOT blank\n * `_iv`/`_data`/`_cek` — so a subsequent `demote()` restores tier-0\n * readability. Tombstone-shaped entries (a forgotten/shredded version —\n * blanked `_data`, no `_cek`) are skipped: there is no key material left to\n * rewrap.\n *\n * **Legacy fallback.** A snapshot written before this fix stays wrapped\n * under the tier-0 DEK even after its live record has since moved tiers, so\n * a rewrap attempted with a tier-N `fromDek` fails to unwrap/decrypt. When\n * the caller supplies `tier0Dek`, a failed rewrap is retried once with\n * `tier0Dek` as `fromDek` (the only other key a pre-fix snapshot can be\n * wrapped under — history is written only by tier-0 `put()`). The output is\n * always wrapped under `toDek` regardless of which `fromDek` succeeded. A\n * rewrap that fails under BOTH keys re-throws — that is real corruption, not\n * a tier mismatch, and must not be swallowed.\n *\n * **Crash-atomicity / idempotency (#712 whole-branch-fix-3).** This loop has\n * no transaction around it: a crash after some entries have been rewritten\n * under `toDek` but before the loop finishes leaves the record's history\n * split across two keys. A retry of the SAME call must not re-fail on the\n * entries that already made it — so each entry is probed with\n * `isRewrappedUnder(env, toDek)` FIRST; a match means it's already at the\n * target key and is skipped (put nothing). This makes same-target retries\n * and demote-after-crash fully self-healing. It does NOT close every crash\n * window: a crash that lands SOME entries under `toDek` while the record's\n * NEXT move target differs from this call's `toDek` (an intermediate-tier\n * crash — e.g. elevate 0→1 crashes mid-loop, then the record is moved 1→2)\n * still finds those entries unreadable under either `fromDek` or the\n * tier-0 fallback, since `toDek` is a third key the next call never probes\n * for. That residual window is an accepted, fail-closed limitation (see\n * `.changeset/history-at-rest.md` and the design doc) — availability is\n * lost, never confidentiality.\n */\nexport async function rewrapHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n fromDek: EnclaveKey,\n toDek: EnclaveKey,\n tier0Dek?: EnclaveKey,\n): Promise<void> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds.filter(id => matchesPrefix(id, collection, recordId))\n\n for (const id of matchingIds) {\n const env = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (!env) continue\n // Already a tombstone (forgotten/shredded version)? Nothing to rewrap.\n if (isTombstoneShape(env)) continue\n // #712/whole-branch-fix-3: toDek-first idempotency skip — already at the\n // target key (a same-target retry, or demote-after-crash landing back on\n // a key it already reached)? Nothing to do; put nothing.\n // In-place re-key of a `_history` entry: the address does not move, so the\n // same identity opens and re-seals it (#1041). Built from the entry itself,\n // exactly as a reader would via `recordAadFor`.\n const identity = {\n collection: HISTORY_COLLECTION, id, version: env._v,\n ...(env._tier !== undefined ? { tier: env._tier } : {}),\n ...(env._by !== undefined ? { by: env._by } : {}),\n }\n if (await isRewrappedUnder(identity, env, toDek)) continue\n\n let next: EncryptedEnvelope\n try {\n next = await rewrapEnvelope(identity, env, fromDek, toDek)\n } catch (err) {\n if (!tier0Dek) throw err\n // Legacy fallback: retry once under the tier-0 DEK. A failure here is\n // real corruption, not a tier mismatch — let it propagate.\n next = await rewrapEnvelope(identity, env, tier0Dek, toDek)\n }\n\n await adapter.put(vault, HISTORY_COLLECTION, id, next)\n }\n}\n","/**\n * Strategy seam for the optional history + ledger + time-machine\n * service. Core imports `HistoryStrategy` type-only + `NO_HISTORY`\n * stub; real implementations of `saveHistory`, `LedgerStore`,\n * `VaultInstant`, `computePatch`, `diff` etc. are only reachable via\n * `withHistory()` in `./active.ts`.\n *\n * Applications that don't track per-record versioning, don't need the\n * hash-chained audit ledger, and don't restore to past instants ship\n * none of the ~1,880 LOC behind this seam.\n *\n * Strategy contract:\n *\n * - **saveHistory / pruneHistory / clearHistory** — no-ops under\n * NO_HISTORY. Writes still succeed; no snapshot is captured.\n * - **getHistoryEntries / getVersionEnvelope / diff** — throw under\n * NO_HISTORY. These are read APIs the consumer would only call\n * after explicitly asking for history; the throw guides them to\n * `@noy-db/hub/history`.\n * - **envelopePayloadHash / computePatch** — return empty / `[]`\n * under NO_HISTORY. These are only used inside the\n * `if (this.ledger)` branch, which is itself gated by\n * `buildLedger()` returning null.\n * - **buildLedger** — returns `null` under NO_HISTORY. The Vault's\n * public `vault.ledger()` accessor throws when null.\n * - **buildVaultInstant** — throws under NO_HISTORY. `vault.at()`\n * propagates the throw.\n *\n * @internal\n */\n\nimport type {\n EncryptedEnvelope,\n NoydbStore,\n HistoryOptions,\n PruneOptions,\n} from '../../kernel/types.js'\nimport type { LedgerStore } from './ledger/store.js'\nimport type { JsonPatch } from './ledger/patch.js'\nimport type { DiffEntry } from './diff.js'\nimport type { VaultInstant, VaultEngine } from './time-machine.js'\nimport type { EnclaveKey, RecordIdentity } from '../../kernel/enclave/index.js'\nimport { historyIdentity } from './history.js'\n\n/**\n * Options accepted by `HistoryStrategy.buildLedger`. Mirrors the\n * `LedgerStore` constructor verbatim — kept in this file so `core`\n * code never imports the LedgerStore module at runtime.\n *\n * @internal\n */\nexport interface BuildLedgerOptions {\n adapter: NoydbStore\n vault: string\n encrypted: boolean\n getDEK: (collectionName: string) => Promise<EnclaveKey>\n actor: string\n}\n\n/**\n * @internal\n */\nexport interface HistoryStrategy {\n /**\n * Persist a full encrypted envelope snapshot of the prior version\n * under `_history/{collection}:{id}:{paddedVersion}`. No-op under\n * `NO_HISTORY`.\n */\n saveHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n envelope: EncryptedEnvelope,\n ): Promise<void>\n\n /**\n * The identity a snapshot of `collection/recordId@version` must be **sealed\n * against** — its `_history` storage location (#1041).\n *\n * On the port because the kernel writes history snapshots but must not import\n * `with-commit` to learn its layout. Exposing it here keeps the derivation in\n * the module that owns the layout, and `saveHistory` uses the same function,\n * so the sealed identity and the put location cannot drift.\n */\n historyIdentity(collection: string, recordId: string, version: number): RecordIdentity\n\n /**\n * List history envelopes for a record, newest first. Throws under\n * `NO_HISTORY` — callers reach this via `collection.history()` /\n * `collection.getVersion()` / `collection.diff()`, which only work\n * with the strategy enabled.\n */\n getHistoryEntries(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n options?: HistoryOptions,\n ): Promise<EncryptedEnvelope[]>\n\n /**\n * Fetch a specific version's envelope. Throws under `NO_HISTORY`.\n */\n getVersionEnvelope(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n version: number,\n ): Promise<EncryptedEnvelope | null>\n\n /**\n * Prune history entries by retention rule. Returns `0` under\n * `NO_HISTORY`.\n */\n pruneHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string | undefined,\n options: PruneOptions,\n ): Promise<number>\n\n /**\n * Clear all history for vault/collection/record. Returns `0` under\n * `NO_HISTORY`.\n */\n clearHistory(\n adapter: NoydbStore,\n vault: string,\n collection?: string,\n recordId?: string,\n ): Promise<number>\n\n /**\n * Crypto-shred (overwrite-to-tombstone) every `_history` version of a\n * record for GDPR erasure. Returns the number of versions newly\n * tombstoned, or `0` under `NO_HISTORY` (no history = nothing to shred).\n */\n tombstoneHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n actor: string,\n encrypted: boolean,\n ): Promise<number>\n\n /**\n * Re-key every `_history` snapshot of a record from `fromDek` to `toDek`\n * on a tier move (elevate/demote/putAtTier), mirroring the live-body\n * rewrap so prior versions are not left decryptable at rest under a tier\n * the record has moved away from. Optional `tier0Dek` enables the legacy\n * fallback for snapshots written before this rewrap existed (see\n * `history.ts` for the full contract). No-op under `NO_HISTORY` (no\n * history = nothing to rewrap).\n */\n rewrapHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n fromDek: EnclaveKey,\n toDek: EnclaveKey,\n tier0Dek?: EnclaveKey,\n ): Promise<void>\n\n /**\n * Compute the SHA-256 hash of an envelope's encrypted payload, used\n * by `LedgerStore.append` to track tamper-evidence. Returns the\n * empty string under `NO_HISTORY` (the call site is gated by\n * `if (this.ledger)`, so the value is never observed).\n */\n envelopePayloadHash(envelope: EncryptedEnvelope | null): Promise<string>\n\n /**\n * Compute the JSON patch from `from` → `to`. Returns `[]` under\n * `NO_HISTORY`.\n */\n computePatch(from: unknown, to: unknown): JsonPatch\n\n /**\n * Compute the typed diff between two records. Throws under\n * `NO_HISTORY` — `collection.diff()` is a history-read API.\n */\n diff(recordA: unknown, recordB: unknown): DiffEntry[]\n\n /**\n * Construct (or return null) a `LedgerStore` for the vault. Returns\n * `null` under `NO_HISTORY`; the Vault treats null as \"no ledger\n * attached\" — collection write paths skip the append branch and the\n * public `vault.ledger()` accessor throws.\n */\n buildLedger(opts: BuildLedgerOptions): LedgerStore | null\n\n /**\n * Construct a `VaultInstant` for time-machine reads. Throws under\n * `NO_HISTORY`.\n */\n buildVaultInstant(engine: VaultEngine, timestamp: string): VaultInstant\n}\n\n/**\n * Error thrown when the consumer reaches a history-gated surface\n * without opting into the strategy. The message names the offending\n * operation and points to the subpath import.\n *\n * @internal\n */\nfunction notEnabled(op: string): Error {\n return new Error(\n `${op} requires the history strategy. Import ` +\n '`{ withHistory }` from \"@noy-db/hub/history\" and pass it to ' +\n '`createNoydb({ historyStrategy: withHistory() })`.',\n )\n}\n\n/**\n * No-history stub. Snapshots and prune/clear are no-ops; reads and\n * time-machine throw with an actionable message; ledger construction\n * returns null so the write-path's `if (this.ledger)` branch is dead\n * code in the bundle.\n *\n * @internal\n */\nexport const NO_HISTORY: HistoryStrategy = {\n async saveHistory() {},\n // Unreachable in practice — `saveHistory` above is a no-op, so nothing is\n // ever sealed. Returns the real layout rather than a sentinel so a future\n // caller that reads it without writing cannot be misled.\n historyIdentity: (collection, recordId, version) => historyIdentity(collection, recordId, version),\n async getHistoryEntries() { throw notEnabled('collection.history()') },\n async getVersionEnvelope() { throw notEnabled('collection.getVersion()') },\n async pruneHistory() { return 0 },\n async clearHistory() { return 0 },\n async tombstoneHistory() { return 0 },\n async rewrapHistory() {},\n async envelopePayloadHash() { return '' },\n computePatch() { return [] },\n diff() { throw notEnabled('collection.diff()') },\n buildLedger() { return null },\n buildVaultInstant() { throw notEnabled('vault.at() / vault.timeMachine()') },\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/with-audit/portability/withdraw-accessible.ts"],"sourcesContent":["/**\n * `unilateralWithdrawal`: a non-owner extracts their accessible scope\n * AND disposes of the source copy. Destructive; gated by the default-off\n * fail-closed built-in `client-unilateral-withdraw` policy (checked in the\n * UserApi wrapper).\n *\n * Two source dispositions:\n * - 'delete' — delete-closure: the records leave the source vault entirely.\n * - 'freeze' — the firm retains a cryptographically-frozen, read-only, write-once\n * snapshot (hash-pinned in the tamper-evident ledger) while the live\n * records are removed.\n *\n * Ordering guarantees no data loss: the client's re-keyed export bundle (and the\n * freeze snapshot) are produced BEFORE anything is deleted.\n *\n * The `freezeAndDeleteClosure` core is shared with the two-party approval path\n * (`request-withdrawal.ts`).\n */\nimport type { Vault } from '../../kernel/vault.js'\nimport { buildRecordEnvelope, sha256Hex } from '../../kernel/enclave/index.js'\nimport { ReadOnlyError } from '../../kernel/errors.js'\nimport { resolveAccessibleCollections, buildAccessibleBundle } from './export-accessible.js'\n\nexport const FROZEN_SNAPSHOTS_COLLECTION = '_frozen_snapshots'\nconst ENC = new TextEncoder()\n\n/** 24-hex-char random id (used for withdrawal ids + request ids). */\nexport function randomId(): string {\n const b = globalThis.crypto.getRandomValues(new Uint8Array(12))\n return Array.from(b, (x) => x.toString(16).padStart(2, '0')).join('')\n}\n\nexport interface FrozenSnapshotRef {\n readonly withdrawalId: string\n readonly sha256: string\n readonly recordCount: number\n readonly frozenAt: string\n}\n\nexport interface WithdrawAccessibleOptions {\n /** Legal/contractual basis recorded in the audit (e.g. 'gdpr-art-17'). */\n readonly legalBasis: string\n /** Re-key the exported bundle to a new owner secret. */\n readonly reKey?: { readonly secret: string }\n /** Source disposition. Default 'delete'. */\n readonly disposition?: 'delete' | 'freeze'\n readonly scope?: { readonly collections?: readonly string[] }\n /** Stable id for idempotent resume (default random). */\n readonly withdrawalId?: string\n}\n\nexport interface WithdrawResult {\n readonly bundle: Uint8Array\n readonly snapshot?: FrozenSnapshotRef\n}\n\n/**\n * Freeze a write-once, hash-pinned snapshot of the current ciphertext for\n * `collections` WITHOUT touching the live records. Returns the snapshot ref.\n *\n * This is the non-destructive core shared by two callers:\n * - `freezeAndDeleteClosure` (withdrawal, disposition `'freeze'`) — which\n * pins the snapshot and THEN delete-closures the live records.\n * - FR-6 `liberateVault` (custody) — which pins a PRE-liberation evidence\n * snapshot but PRESERVES the live data for the new owner (operational\n * continuity; liberation transfers, it does not erase).\n *\n * The snapshot put is write-once (CAS expectedVersion 0) and the ledger pin is\n * appended on success, so a crashed run re-run with the same `withdrawalId` is\n * safe. The snapshot is taken under the vault's own firm-owned DEKs — no re-key.\n */\nexport async function freezeSnapshotOnly(\n vault: Vault,\n collections: readonly string[],\n opts: { actorUserId: string; withdrawalId?: string },\n): Promise<FrozenSnapshotRef> {\n const { name: vaultName, adapter } = vault._introspectState()\n\n // Enumerate the closure (record ids per collection).\n const closure: Array<{ collection: string; id: string }> = []\n for (const c of collections) {\n for (const id of await adapter.list(vaultName, c)) closure.push({ collection: c, id })\n }\n\n const withdrawalId = opts.withdrawalId ?? `wd-${randomId()}`\n const snap: Record<string, Record<string, unknown>> = {}\n for (const { collection, id } of closure) {\n const env = await adapter.get(vaultName, collection, id)\n if (env) (snap[collection] ??= {})[id] = env\n }\n const frozenAt = new Date().toISOString()\n const body = JSON.stringify({ withdrawalId, frozenAt, by: opts.actorUserId, collections: snap })\n const sha = await sha256Hex(ENC.encode(body))\n // Write-once: expectedVersion 0 rejects an overwrite (idempotent resume).\n await adapter.put(\n vaultName,\n FROZEN_SNAPSHOTS_COLLECTION,\n withdrawalId,\n buildRecordEnvelope(\n { collection: FROZEN_SNAPSHOTS_COLLECTION, id: withdrawalId, by: opts.actorUserId, version: 1 },\n { ts: frozenAt, iv: '', data: body},\n ),\n 0,\n )\n // Hash-pin into the tamper-evident ledger — makes the snapshot provably unaltered.\n await vault._getLedgerOrNull()?.append({\n op: 'lifecycle', collection: '', id: '', version: 0, actor: opts.actorUserId, payloadHash: '',\n reason: `withdrawal-frozen-snapshot:${withdrawalId}:${sha}`,\n })\n return { withdrawalId, sha256: sha, recordCount: closure.length, frozenAt }\n}\n\n/**\n * Dispose of the source records for `collections`: optionally freeze a\n * write-once hash-pinned snapshot of the original ciphertext, then\n * delete-closure the live records. Returns the snapshot ref on freeze.\n *\n * Caller MUST have produced the portable bundle FIRST — this is destructive.\n * The delete is best-effort + idempotent (re-deleting an absent record is a\n * no-op) and the snapshot put is write-once (CAS expectedVersion 0), so a\n * crashed run re-run with the same `withdrawalId` is safe.\n */\nexport async function freezeAndDeleteClosure(\n vault: Vault,\n collections: readonly string[],\n opts: { disposition: 'delete' | 'freeze'; actorUserId: string; withdrawalId?: string },\n): Promise<FrozenSnapshotRef | undefined> {\n // freeze: pin a write-once, hash-pinned snapshot BEFORE any delete. The\n // snapshot-only core is shared with FR-6 liberation (which never deletes).\n const snapshot = opts.disposition === 'freeze'\n ? await freezeSnapshotOnly(vault, collections, {\n actorUserId: opts.actorUserId,\n ...(opts.withdrawalId ? { withdrawalId: opts.withdrawalId } : {}),\n })\n : undefined\n\n // delete-closure — only after the snapshot is durable.\n const { name: vaultName, adapter } = vault._introspectState()\n for (const c of collections) {\n for (const id of await adapter.list(vaultName, c)) {\n await vault.collection(c).delete(id)\n }\n }\n\n return snapshot\n}\n\nexport async function withdrawAccessibleData(\n vault: Vault,\n opts: WithdrawAccessibleOptions,\n): Promise<WithdrawResult> {\n const { keyring } = vault._introspectState()\n const disposition = opts.disposition ?? 'delete'\n\n // Owner-class roles hold blanket authority — they use extractPartition.\n if (keyring.role === 'owner' || keyring.role === 'admin') {\n throw new ReadOnlyError(\n 'unilateralWithdrawal is the scoped self-service path; an owner/admin should use extractPartition',\n )\n }\n // FR-6: a custodian must NOT destructively SEVER the vault. It holds the DEKs\n // and operates fully, but ownership is claimed only through the audited\n // Liberate ceremony — never by a one-sided delete/freeze withdrawal. Fires\n // BEFORE the operator rw-scope path below (where a custodian would otherwise\n // be rejected with the wrong \"requires rw access\" message).\n if (keyring.role === 'custodian') {\n throw new ReadOnlyError(\n 'a custodian cannot destructively withdraw/sever; use vault.custody.liberate for an audited ownership claim',\n )\n }\n // client/viewer are read-only by construction (see hasWritePermission): a\n // destructive withdrawal they cannot self-serve — they use the two-party\n // requestWithdrawal flow where firm authority executes the delete-closure.\n if (keyring.role === 'client' || keyring.role === 'viewer') {\n throw new ReadOnlyError(\n 'read-only role cannot self-serve a destructive withdrawal — use requestWithdrawal (two-party)',\n )\n }\n // Operator path: destructive ops need rw on the whole scope.\n const collections = resolveAccessibleCollections(keyring, opts.scope, true)\n if (!collections || collections.length === 0) {\n throw new ReadOnlyError(\n 'unilateralWithdrawal requires rw access on the withdrawn collections — use requestWithdrawal for read-only scope',\n )\n }\n\n // 1. Produce the client's re-keyed portable copy FIRST (nothing destroyed yet).\n const bundle = await buildAccessibleBundle(vault, collections, opts.reKey)\n\n // 2. + 3. freeze (optional) then delete-closure.\n const snapshot = await freezeAndDeleteClosure(vault, collections, {\n disposition, actorUserId: keyring.userId, ...(opts.withdrawalId ? { withdrawalId: opts.withdrawalId } : {}),\n })\n\n // 4. audit\n await vault._getLedgerOrNull()?.append({\n op: 'lifecycle', collection: '', id: '', version: 0, actor: keyring.userId, payloadHash: '',\n reason: `user-unilateral-withdrawal:${keyring.userId}:${disposition}:${opts.legalBasis}`,\n })\n\n return snapshot ? { bundle, snapshot } : { bundle }\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-SEE332EV.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
NOYDB_FORMAT_VERSION
|
|
3
|
-
} from "./chunk-ODVPTDPK.js";
|
|
4
|
-
|
|
5
|
-
// src/kernel/enclave/record-envelope.ts
|
|
6
|
-
function buildRecordEnvelope(identity, body) {
|
|
7
|
-
return {
|
|
8
|
-
_noydb: NOYDB_FORMAT_VERSION,
|
|
9
|
-
_v: identity.version,
|
|
10
|
-
_ts: body.ts ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
11
|
-
_iv: body.iv,
|
|
12
|
-
_data: body.data,
|
|
13
|
-
...identity.by !== void 0 ? { _by: identity.by } : {},
|
|
14
|
-
...identity.tier !== void 0 && identity.tier > 0 ? { _tier: identity.tier } : {},
|
|
15
|
-
...body.cek !== void 0 ? { _cek: body.cek } : {},
|
|
16
|
-
...body.provenance !== void 0 ? { _source: body.provenance.source, _sourceTs: body.provenance.sourceTs } : {},
|
|
17
|
-
...body.extra ?? {}
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
async function buildSealedRecordEnvelope(identity, seal, body) {
|
|
21
|
-
const sealed = await seal(identity);
|
|
22
|
-
return buildRecordEnvelope(identity, {
|
|
23
|
-
...body,
|
|
24
|
-
iv: sealed._iv,
|
|
25
|
-
data: sealed._data,
|
|
26
|
-
cek: sealed._cek
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// src/kernel/enclave/record-keys/tombstone.ts
|
|
31
|
-
function isTombstoneShape(envelope) {
|
|
32
|
-
return envelope._data === "" && envelope._cek === void 0 && envelope._del !== true;
|
|
33
|
-
}
|
|
34
|
-
function isTombstone(envelope, encrypted) {
|
|
35
|
-
if (!encrypted) return false;
|
|
36
|
-
return isTombstoneShape(envelope);
|
|
37
|
-
}
|
|
38
|
-
function buildTombstone(ref, version, actor) {
|
|
39
|
-
return buildRecordEnvelope(
|
|
40
|
-
{ ...ref, version, ...actor ? { by: actor } : {} },
|
|
41
|
-
{ iv: "", data: "" }
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
function isDeleteMarker(envelope) {
|
|
45
|
-
return envelope._del === true;
|
|
46
|
-
}
|
|
47
|
-
function buildDeleteMarker(ref, version, actor) {
|
|
48
|
-
return {
|
|
49
|
-
...buildRecordEnvelope(
|
|
50
|
-
{ ...ref, version, ...actor ? { by: actor } : {} },
|
|
51
|
-
{ iv: "", data: "" }
|
|
52
|
-
),
|
|
53
|
-
_del: true
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export {
|
|
58
|
-
buildRecordEnvelope,
|
|
59
|
-
buildSealedRecordEnvelope,
|
|
60
|
-
isTombstoneShape,
|
|
61
|
-
isTombstone,
|
|
62
|
-
buildTombstone,
|
|
63
|
-
isDeleteMarker,
|
|
64
|
-
buildDeleteMarker
|
|
65
|
-
};
|
|
66
|
-
//# sourceMappingURL=chunk-SEE332EV.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/kernel/enclave/record-envelope.ts","../src/kernel/enclave/record-keys/tombstone.ts"],"sourcesContent":["/**\n * The one place an `EncryptedEnvelope` is constructed (#1051).\n *\n * ## Why this exists\n *\n * 49 files built envelopes with an object literal, bypassing\n * `RecordCodec.buildEnvelope` (which had 4 callers). That is **writer\n * fan-out**: N independent places each had to know the envelope contract, and\n * nothing checked that they agreed.\n *\n * It only became load-bearing with #1041. Binding a record's identity into the\n * AEAD requires every writer to supply that identity — and a writer that\n * doesn't produces data the reader rejects. Reader fan-out you fix by threading\n * an argument through call sites; **writer fan-out cannot be migrated\n * incrementally**, because the first migrated writer emits envelopes the\n * unmigrated readers refuse.\n *\n * ## Why adopting it is safe\n *\n * `identity` is **required but not yet used**. Output is byte-identical to the\n * literals it replaces, so every producer can migrate independently and the\n * existing suite verifies each step. The behaviour change happens **once**,\n * when AAD is switched on here — by which point every writer already supplies\n * identity, and the compiler proved it.\n *\n * That ordering is deliberate: a required-but-unused parameter converts \"did\n * we find every writer?\" from a question into a compile error, the same trick\n * that made the `NOYDB_FORMAT_VERSION` single-sourcing safe in #1048.\n *\n * @packageDocumentation\n */\nimport { NOYDB_FORMAT_VERSION } from '../types.js'\nimport type { EncryptedEnvelope } from '../types.js'\nimport type { RecordIdentity } from './record-aad.js'\n\n/** The body an envelope carries, independent of who is writing it. */\nexport interface RecordEnvelopeBody {\n /** AES-GCM IV, base64. Empty string for a plaintext or tombstone envelope. */\n readonly iv: string\n /** Ciphertext (or plaintext JSON when the collection stores plaintext). */\n readonly data: string\n /** ISO timestamp. Defaults to now — pass it when the caller has a real one. */\n readonly ts?: string | undefined\n /** Wrapped per-record CEK, when the record has one. */\n readonly cek?: string | undefined\n readonly provenance?: { readonly source: string; readonly sourceTs: string } | undefined\n /**\n * Slots the envelope may additionally carry.\n *\n * `_tier`, `_by` and `_v` are deliberately NOT here — they come from\n * `identity`, which is the single source for all three. See\n * {@link buildRecordEnvelope}.\n */\n readonly extra?: Partial<Pick<EncryptedEnvelope, '_det' | '_sealed' | '_vdig' | '_bidx'>> | undefined\n}\n\n/**\n * Build an envelope for `identity`.\n *\n * ## `identity` is the SINGLE SOURCE for `_by`, `_tier` and `_v`\n *\n * All three are stamped from it, and `RecordEnvelopeBody` deliberately cannot\n * carry them. That is not tidiness — it is what makes the AAD binding safe.\n *\n * The caller encrypts the body under AAD derived from `{collection, id, tier,\n * by, version}`. A reader recomputes that AAD from the address it fetched from\n * plus `_tier`/`_by`/`_v` read back **off the envelope** (`recordAadFor`). So if the\n * identity a writer *declares* could differ from the fields it *stamps*, the\n * AAD would not reproduce and the record would be undecryptable — silently, at\n * write time, discoverable only on the next read, and invisible to every gate\n * because the envelope is perfectly well-formed.\n *\n * An earlier draft took both and asserted they agreed. The assertion fired 230\n * times on the existing tree, which is the argument against it: a rule that can\n * be violated is a rule someone must remember. Taking one source removes the\n * violation instead of reporting it.\n */\nexport function buildRecordEnvelope(\n identity: RecordIdentity,\n body: RecordEnvelopeBody,\n): EncryptedEnvelope {\n return {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: identity.version,\n _ts: body.ts ?? new Date().toISOString(),\n _iv: body.iv,\n _data: body.data,\n ...(identity.by !== undefined ? { _by: identity.by } : {}),\n ...(identity.tier !== undefined && identity.tier > 0 ? { _tier: identity.tier } : {}),\n ...(body.cek !== undefined ? { _cek: body.cek } : {}),\n ...(body.provenance !== undefined\n ? { _source: body.provenance.source, _sourceTs: body.provenance.sourceTs }\n : {}),\n ...(body.extra ?? {}),\n }\n}\n\n/**\n * Build an envelope from an already-sealed body — the output of\n * `writeEnvelopeBody` — **without the caller ever naming `_iv`/`_data`/`_cek`**.\n *\n * This exists because of a guard, and the guard was right. Migrating\n * `writeEnvelopeBody` callers to {@link buildRecordEnvelope} meant rewriting\n * `...body` (a spread, which names nothing) into `iv: body._iv, data:\n * body._data, cek: body._cek` — and `enclave-body-only` failed it: three new\n * protected-body accesses in files that previously had zero.\n *\n * That is the correct outcome rather than an obstacle. #1051 exists to move\n * knowledge of the envelope's shape *inward*; a migration that spreads the\n * protected field names outward to every caller would have defeated its own\n * purpose while looking like progress. The pairing belongs here.\n *\n * ## It takes a SEALER, not a sealed body — and that is load-bearing (#1041)\n *\n * The obvious shape is `(identity, alreadySealedBody, rest)`. That requires the\n * caller to name the identity TWICE — once for `writeEnvelopeBody` and once\n * here — and the two must agree byte for byte or the record is sealed under\n * AAD no reader can reproduce.\n *\n * They did not agree. `with-party/broker/seed.ts` sealed against\n * `{collection, id}` and stamped `{collection, id, by}`, so every broker seed\n * became unreadable the moment AAD switched on. Taking the sealer means the\n * identity is written once and handed to both — divergence stops being\n * possible rather than being something to remember.\n */\nexport async function buildSealedRecordEnvelope(\n identity: RecordIdentity,\n seal: (identity: RecordIdentity) => Promise<Pick<EncryptedEnvelope, '_iv' | '_data' | '_cek'>>,\n body: Omit<RecordEnvelopeBody, 'iv' | 'data' | 'cek'>,\n): Promise<EncryptedEnvelope> {\n const sealed = await seal(identity)\n return buildRecordEnvelope(identity, {\n ...body,\n iv: sealed._iv,\n data: sealed._data,\n cek: sealed._cek,\n })\n}\n","/**\n * Tombstone shape + predicate for the per-record-key (CEK) layer.\n *\n * A *tombstone* is the residue a GDPR crypto-shred (`vault.forget()`)\n * leaves on disk: the live envelope rewritten to `{ _noydb, _v, _ts, _by,\n * _iv:'', _data:'' }`, dropping `_iv`/`_data`/`_cek`/`_det`. With the wrapped\n * per-record CEK gone, the body — and every history version under the same\n * CEK — is permanently undecryptable, while the record KEY survives so the\n * version counter and \"record existed and was erased\" persist for the audit\n * ledger.\n *\n * These two helpers are the pure, collection-independent core of that\n * contract: {@link buildTombstone} mints the shape, {@link isTombstone}\n * recognises it on the read path. The orchestration that *writes* a tombstone\n * (`_writeTombstone`) and drives `vault.forget()` lives with the collection /\n * vault; it calls into these.\n */\nimport { type EncryptedEnvelope } from '../../types.js'\nimport { buildRecordEnvelope } from '../record-envelope.js'\nimport type { RecordRef } from '../record-aad.js'\n\n/**\n * Shape-only tombstone recognition for layers that have no per-collection\n * context (the sync engine, #590): a tombstone carries an empty `_data` and\n * no wrapped CEK. No live envelope can match — record bodies never serialize\n * to the empty string (the `_sync` meta envelope carries non-empty `_data`,\n * and legacy migration envelopes carry non-empty `_iv`/`_data`).\n */\nexport function isTombstoneShape(envelope: EncryptedEnvelope): boolean {\n return envelope._data === '' && envelope._cek === undefined && envelope._del !== true\n}\n\n/**\n * Is this envelope a crypto-shred tombstone?\n *\n * A tombstone carries no body (`_data` empty) and no wrapped CEK (`_cek`\n * absent) — decrypting it would call `decrypt('', '', dek)` → an AES-GCM\n * throw, so every read choke point must short-circuit to `null` instead.\n *\n * `encrypted` is the collection's encryption flag: on an unencrypted\n * collection there are no envelopes to shred, so nothing is ever a tombstone.\n * (Legacy migration envelopes carry non-empty `_iv`/`_data`, so they are not\n * tombstones and stay readable.)\n */\nexport function isTombstone(envelope: EncryptedEnvelope, encrypted: boolean): boolean {\n if (!encrypted) return false\n return isTombstoneShape(envelope)\n}\n\n/**\n * Mint a tombstone envelope from a record's live version + actor.\n *\n * Keeps `_v` (the displaced version) so the counter is monotonic across the\n * shred, stamps a fresh `_ts`, and records `_by` when an actor is supplied.\n * Deliberately omits `_iv`/`_data`/`_cek`/`_det` — that omission *is* the\n * erasure.\n */\nexport function buildTombstone(\n ref: RecordRef,\n version: number,\n actor: string,\n): EncryptedEnvelope {\n // `actor` rides on the IDENTITY, not the body — it is stamped as `_by` and\n // bound into the AAD from that one source (#1041).\n return buildRecordEnvelope(\n { ...ref, version, ...(actor ? { by: actor } : {}) },\n { iv: '', data: '' },\n )\n}\n\n/** #589: is this envelope an ordinary-delete marker (version-ordered, reads as absent)? */\nexport function isDeleteMarker(envelope: EncryptedEnvelope): boolean {\n return envelope._del === true\n}\n\n/**\n * Mint a delete marker from the deleted record's next version + actor (#589).\n * Minted at the NEXT version (`existing._v + 1`) — unlike `buildTombstone`, which\n * keeps the displaced `_v` — so it wins convergence over the pre-delete copy and a\n * re-create can still win over it at a higher version.\n */\nexport function buildDeleteMarker(\n ref: RecordRef,\n version: number,\n actor: string,\n): EncryptedEnvelope {\n // `_del` is not one of buildRecordEnvelope's declared slots — a delete marker\n // is a distinct envelope class, not a record body — so it is stamped here.\n return {\n ...buildRecordEnvelope(\n { ...ref, version, ...(actor ? { by: actor } : {}) },\n { iv: '', data: '' },\n ),\n _del: true,\n }\n}\n"],"mappings":";;;;;AA6EO,SAAS,oBACd,UACA,MACmB;AACnB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,IAAI,SAAS;AAAA,IACb,KAAK,KAAK,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,IACvC,KAAK,KAAK;AAAA,IACV,OAAO,KAAK;AAAA,IACZ,GAAI,SAAS,OAAO,SAAY,EAAE,KAAK,SAAS,GAAG,IAAI,CAAC;AAAA,IACxD,GAAI,SAAS,SAAS,UAAa,SAAS,OAAO,IAAI,EAAE,OAAO,SAAS,KAAK,IAAI,CAAC;AAAA,IACnF,GAAI,KAAK,QAAQ,SAAY,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC;AAAA,IACnD,GAAI,KAAK,eAAe,SACpB,EAAE,SAAS,KAAK,WAAW,QAAQ,WAAW,KAAK,WAAW,SAAS,IACvE,CAAC;AAAA,IACL,GAAI,KAAK,SAAS,CAAC;AAAA,EACrB;AACF;AA8BA,eAAsB,0BACpB,UACA,MACA,MAC4B;AAC5B,QAAM,SAAS,MAAM,KAAK,QAAQ;AAClC,SAAO,oBAAoB,UAAU;AAAA,IACnC,GAAG;AAAA,IACH,IAAI,OAAO;AAAA,IACX,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,EACd,CAAC;AACH;;;AC7GO,SAAS,iBAAiB,UAAsC;AACrE,SAAO,SAAS,UAAU,MAAM,SAAS,SAAS,UAAa,SAAS,SAAS;AACnF;AAcO,SAAS,YAAY,UAA6B,WAA6B;AACpF,MAAI,CAAC,UAAW,QAAO;AACvB,SAAO,iBAAiB,QAAQ;AAClC;AAUO,SAAS,eACd,KACA,SACA,OACmB;AAGnB,SAAO;AAAA,IACL,EAAE,GAAG,KAAK,SAAS,GAAI,QAAQ,EAAE,IAAI,MAAM,IAAI,CAAC,EAAG;AAAA,IACnD,EAAE,IAAI,IAAI,MAAM,GAAG;AAAA,EACrB;AACF;AAGO,SAAS,eAAe,UAAsC;AACnE,SAAO,SAAS,SAAS;AAC3B;AAQO,SAAS,kBACd,KACA,SACA,OACmB;AAGnB,SAAO;AAAA,IACL,GAAG;AAAA,MACD,EAAE,GAAG,KAAK,SAAS,GAAI,QAAQ,EAAE,IAAI,MAAM,IAAI,CAAC,EAAG;AAAA,MACnD,EAAE,IAAI,IAAI,MAAM,GAAG;AAAA,IACrB;AAAA,IACA,MAAM;AAAA,EACR;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/with-shape/manifest/types.ts","../src/with-shape/manifest/storage.ts","../src/with-shape/manifest/derive.ts"],"sourcesContent":["/**\n * The pod-wide **schema manifest** record type (#941).\n *\n * This is an INDEX, not a full-inline manifest: `SchemaManifest.collections`\n * carries per-collection *metadata* (generation / content hash / field ids),\n * never the JSON Schema body itself. The JSON Schema stays the source of\n * truth at `_schemas/<collection>`, encrypted under that collection's own\n * DEK (see `with-shape/persisted-schemas`). Inlining full schemas into one\n * pod-wide manifest record would either leak every collection's schema to a\n * principal scoped to a single collection, or force the manifest itself\n * onto a collection-DEK it has no business holding — the index preserves\n * per-collection DEK isolation while still giving a single place to answer\n * \"what schema generation is this pod at, and does collection X's stored\n * schema match its declared content hash.\"\n *\n * `aggregateHash` binds the whole per-collection index's content: it is\n * `sha256Hex(canonicalJson(collections))`, so any change to any collection's\n * entry (a new generation, a changed hash, added/renamed field ids) changes\n * `aggregateHash` too. Canonical JSON (sorted object keys, no whitespace)\n * makes the hash independent of the map's key insertion order.\n *\n * @module\n */\n\n/** Per-collection entry inside a {@link SchemaManifest}'s `collections` index. */\nexport interface SchemaManifestEntry {\n /** The vault-wide schema-fence generation this collection's schema was last written at. */\n readonly generation: number\n /** SHA-256 (hex) of the collection's canonicalised JSON Schema (see `persisted-schemas/derive.ts`). */\n readonly contentHash: string\n /** Stable per-field ids (#946), keyed by the field's current name. Absent when the collection has none. */\n readonly fieldIds?: Record<string, string>\n}\n\n/**\n * The pod-wide schema manifest — one record per pod, stored at\n * `_manifest/schema` (see `storage.ts`). An INDEX over the per-collection\n * `_schemas/<collection>` entries, not the schemas themselves.\n */\nexport interface SchemaManifest {\n readonly v: 1\n readonly kind: 'schema'\n /** Pod-wide schema-fence generation (`FenceDoc.currentSchemaVersion`) as of this manifest's derivation. */\n readonly generation: number\n /** Per-collection index: collection name → its manifest entry. */\n readonly collections: Record<string, SchemaManifestEntry>\n /** `sha256Hex(canonicalJson(collections))` — the pod-wide content binding over the index. */\n readonly aggregateHash: string\n}\n\n/** The record id the schema manifest is stored under inside `_manifest`. */\nexport const MANIFEST_SCHEMA_RECORD_ID = 'schema' as const\n","/**\n * Read / write the pod-wide `_manifest/schema` envelope.\n *\n * Mirrors `with-shape/persisted-schemas/storage.ts`'s shape: the same\n * standard noy-db record envelope, AES-GCM encrypted with a collection DEK\n * (here, the `_manifest` collection's own DEK — the manifest INDEX\n * discloses collection names + hashes + generations + field ids, metadata\n * rather than schema bodies, so it gets the same encryption grain as\n * `_schemas` itself).\n *\n * Storage layout:\n *\n * <vault>/_manifest/schema → EncryptedEnvelope\n *\n * Unlike `persisted-schemas/storage.ts` (which takes an already-resolved\n * `EnclaveKey`), these functions take a `getDEK` resolver and call\n * `getDEK(MANIFEST_COLLECTION)` themselves — there is exactly one manifest\n * record per pod, so there is no per-collection DEK the caller needs to\n * pick; resolving it here keeps every manifest call-site symmetric.\n *\n * @module\n */\n\nimport { buildSealedRecordEnvelope, openEnvelopeJson, writeEnvelopeBody, type EnclaveKey } from '../../kernel/enclave/index.js'\nimport { canonicalJson, sha256Hex } from '../../with-commit/history/ledger/index.js'\nimport type { NoydbStore } from '../../kernel/types.js'\nimport { MANIFEST_COLLECTION } from './reserved-collections.js'\nimport { MANIFEST_SCHEMA_RECORD_ID, type SchemaManifest, type SchemaManifestEntry } from './types.js'\n\n/** A resolver for a collection's DEK — the same shape as `Vault`'s internal `getDEK`. */\nexport type GetManifestDEK = (collectionName: string) => Promise<EnclaveKey>\n\n/**\n * A decrypted schema-manifest read paired with the wrapping envelope's `_v`\n * — the optimistic-concurrency token. Pass `version` back to\n * {@link saveSchemaManifest} (via `writeSchemaManifest`'s `expectedVersion`)\n * to make the write a strict CAS.\n */\nexport interface LoadedSchemaManifest {\n /** Wrapping envelope `_v`. */\n readonly version: number\n /** Decrypted schema manifest. */\n readonly manifest: SchemaManifest\n}\n\n/**\n * Read the `_manifest/schema` envelope together with its wrapping `_v`.\n * Returns `undefined` when no manifest has ever been written, when the\n * envelope fails to decrypt (wrong DEK), or when it doesn't parse as a\n * `v: 1, kind: 'schema'` manifest.\n */\nexport async function loadSchemaManifestEntry(\n store: NoydbStore,\n vault: string,\n getDEK: GetManifestDEK,\n): Promise<LoadedSchemaManifest | undefined> {\n const envelope = await store.get(vault, MANIFEST_COLLECTION, MANIFEST_SCHEMA_RECORD_ID)\n if (!envelope) return undefined\n const dek = await getDEK(MANIFEST_COLLECTION)\n try {\n const plaintext = await openEnvelopeJson({ collection: MANIFEST_COLLECTION, id: MANIFEST_SCHEMA_RECORD_ID }, envelope, dek)\n const parsed = JSON.parse(plaintext) as SchemaManifest\n if (parsed.v !== 1 || parsed.kind !== 'schema') return undefined\n return { version: envelope._v, manifest: parsed }\n } catch {\n return undefined\n }\n}\n\n/**\n * Encrypt and persist the schema manifest as a strict CAS write:\n * `expectedVersion` must match the stored envelope's `_v` (0 when no\n * envelope exists yet) or `store.put` throws `ConflictError` — surfaced by\n * `writer.ts`'s `writeSchemaManifest` as `ManifestConflictError` rather than\n * retried.\n */\nexport async function saveSchemaManifest(\n store: NoydbStore,\n vault: string,\n manifest: SchemaManifest,\n expectedVersion: number,\n getDEK: GetManifestDEK,\n): Promise<void> {\n const dek = await getDEK(MANIFEST_COLLECTION)\n const json = JSON.stringify(manifest)\n const env = await buildSealedRecordEnvelope(\n { collection: MANIFEST_COLLECTION, id: MANIFEST_SCHEMA_RECORD_ID, version: expectedVersion + 1 },\n (identity) => writeEnvelopeBody(identity, json, dek),\n {},\n )\n await store.put(vault, MANIFEST_COLLECTION, MANIFEST_SCHEMA_RECORD_ID, env, expectedVersion)\n}\n\n/**\n * `sha256Hex(canonicalJson(collections))` — the pod-wide content binding\n * over a schema manifest's per-collection index. Canonical JSON sorts\n * object keys at every depth, so the result is independent of the map's\n * key insertion order. Shared by the writer's tests and (#941 Task 3) the\n * derivation path, so the hash is computed identically everywhere.\n */\nexport async function computeAggregateHash(\n collections: Record<string, SchemaManifestEntry>,\n): Promise<string> {\n return sha256Hex(canonicalJson(collections))\n}\n","/**\n * Derive the pod-wide {@link SchemaManifest} from the per-collection\n * `_schemas/<collection>` records — the source of truth (#941 Task 3).\n *\n * The manifest is an INDEX, never a cache with independent state: every\n * field in a {@link SchemaManifestEntry} is a direct projection of the\n * matching `PersistedSchemaEnvelope` (`hash` → `contentHash`, `fieldIds` →\n * `fieldIds`, `generation` → `generation`, falling back to the live fence's\n * `currentSchemaVersion` for a legacy pre-#946 envelope that never got a\n * generation stamp). Re-running this function against the same stored state\n * always produces the same manifest — that's what makes round-trip identity\n * (AC #2: dump → restore → re-derive matches the original) hold for free,\n * with no special-cased restore logic.\n *\n * A collection whose `_schemas/<collection>` envelope decrypts successfully\n * but has no derivable content (`hash === null` — a stub envelope for a\n * non-Zod validator) is legitimately omitted from the index: there is no\n * content hash to bind.\n *\n * ## Scoped principals: \"cannot decrypt\" is NOT \"doesn't exist\"\n *\n * A `_schemas/<collection>` envelope is encrypted under **that data\n * collection's own DEK** — the same key its records use — NOT a shared\n * `_schemas`-wide key. In a team vault, a collection-scoped grantee (e.g.\n * `grant(..., { role: 'operator', permissions: { invoices: 'rw' } })`) holds\n * only the DEKs their `permissions` name, plus every system-prefixed (`_*`)\n * collection's DEK — `_manifest` included, by `grant()`'s \"propagate system\n * collections to every role\" rule (`keyring.ts`). So a member scoped to\n * `invoices` CAN decrypt `_manifest/schema` (the pod-wide index) but CANNOT\n * decrypt a sibling's `_schemas/customers` envelope — even though that\n * envelope is right there in `store.list(vault, SCHEMAS_COLLECTION)`.\n *\n * `lookupDEK` (the {@link LookupDEK} passed in) reflects this: it returns\n * `undefined` for a collection name whose DEK the caller does not hold —\n * deliberately NEVER minting a fresh one (see the module doc on\n * `LookupDEK` for why). This function distinguishes that case\n * (`undecodableCollections`) from \"the schema envelope legitimately has no\n * derivable content\" (`hash === null`) — the caller (`sync.ts`) MUST treat\n * an incomplete view differently: writing a manifest derived from a\n * partial view would silently drop every collection this principal can't\n * see. See `sync.ts`'s module doc for how the sync path handles this.\n *\n * @module\n */\n\nimport type { EnclaveKey } from '../../kernel/enclave/index.js'\nimport { loadFence } from '../schema-update/fence.js'\nimport { loadPersistedSchema, SCHEMAS_COLLECTION } from '../persisted-schemas/storage.js'\nimport { computeAggregateHash } from './storage.js'\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { SchemaManifest, SchemaManifestEntry } from './types.js'\n\n/**\n * A NON-MINTING DEK lookup: returns the collection's DEK if the caller\n * already holds it, `undefined` otherwise. Deliberately distinct from\n * `storage.ts`'s `GetManifestDEK` (which mints+persists a fresh DEK for an\n * absent collection — correct for a caller about to WRITE that collection,\n * e.g. `_manifest` itself). `deriveSchemaManifest` only ever READS sibling\n * collections it never created and has no business minting keys for — an\n * absent DEK here means \"not my collection to see,\" never \"new collection\n * that needs a key.\" Minting here would be worse than a no-op: it would\n * silently persist a garbage DEK into the caller's OWN `_keyring/<user>`\n * file (via `ensureCollectionDEK`'s `persistKeyring` side effect) that\n * still can't decrypt anything — see `sync.ts` / `with-pod/open.ts`'s\n * fix notes (#941 review).\n */\nexport type LookupDEK = (collectionName: string) => Promise<EnclaveKey | undefined>\n\nexport interface DeriveSchemaManifestResult {\n /** The derived manifest — an index over every collection this principal could decrypt. */\n readonly manifest: SchemaManifest\n /**\n * Names present in `_schemas` (per `store.list`) whose envelope this\n * principal could NOT decrypt — either no DEK held for that collection,\n * or the DEK held failed to decrypt/parse it (treated the same: the\n * caller cannot verify what's there, so it cannot safely be omitted or\n * asserted). Empty for a principal with full visibility (typically the\n * owner/admin/custodian). Non-empty means `manifest.collections` is\n * DEFINITELY INCOMPLETE relative to the pod's true collection set —\n * see `sync.ts` for why that must gate whether the manifest gets written.\n */\n readonly undecodableCollections: readonly string[]\n}\n\n/**\n * Read the fence generation + every `_schemas/<collection>` envelope this\n * principal can decrypt, and project them into a fresh {@link SchemaManifest}.\n * `lookupDEK` is called once per collection found under `_schemas` (never\n * mints — see {@link LookupDEK}). Names whose DEK isn't held, or whose\n * envelope fails to decrypt/parse despite holding a DEK, are reported via\n * `undecodableCollections` rather than silently dropped from the result.\n */\nexport async function deriveSchemaManifest(\n store: NoydbStore,\n vault: string,\n lookupDEK: LookupDEK,\n): Promise<DeriveSchemaManifestResult> {\n const fence = await loadFence(store, vault)\n const collectionNames = await store.list(vault, SCHEMAS_COLLECTION)\n\n const collections: Record<string, SchemaManifestEntry> = {}\n const undecodableCollections: string[] = []\n for (const name of collectionNames) {\n const dek = await lookupDEK(name)\n if (dek === undefined) {\n undecodableCollections.push(name) // present in _schemas, but not decodable by this principal\n continue\n }\n\n const payload = await loadPersistedSchema(store, vault, name, dek)\n if (!payload) {\n // Held a DEK but still couldn't decrypt/parse — cannot distinguish\n // \"wrong key after all\" from real corruption from here; treat as\n // undecodable (never silently drop) rather than \"no content.\"\n undecodableCollections.push(name)\n continue\n }\n if (payload.hash === null) continue // legitimately no derivable content (stub envelope)\n\n const entry: SchemaManifestEntry = {\n generation: payload.generation ?? fence.currentSchemaVersion,\n contentHash: payload.hash,\n }\n collections[name] = payload.fieldIds !== undefined ? { ...entry, fieldIds: payload.fieldIds } : entry\n }\n\n const aggregateHash = await computeAggregateHash(collections)\n const manifest: SchemaManifest = { v: 1, kind: 'schema', generation: fence.currentSchemaVersion, collections, aggregateHash }\n return { manifest, undecodableCollections }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAmDO,IAAM,4BAA4B;;;ACAzC,eAAsB,wBACpB,OACA,OACA,QAC2C;AAC3C,QAAM,WAAW,MAAM,MAAM,IAAI,OAAO,qBAAqB,yBAAyB;AACtF,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,MAAM,MAAM,OAAO,mBAAmB;AAC5C,MAAI;AACF,UAAM,YAAY,MAAM,iBAAiB,EAAE,YAAY,qBAAqB,IAAI,0BAA0B,GAAG,UAAU,GAAG;AAC1H,UAAM,SAAS,KAAK,MAAM,SAAS;AACnC,QAAI,OAAO,MAAM,KAAK,OAAO,SAAS,SAAU,QAAO;AACvD,WAAO,EAAE,SAAS,SAAS,IAAI,UAAU,OAAO;AAAA,EAClD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AASA,eAAsB,mBACpB,OACA,OACA,UACA,iBACA,QACe;AACf,QAAM,MAAM,MAAM,OAAO,mBAAmB;AAC5C,QAAM,OAAO,KAAK,UAAU,QAAQ;AACpC,QAAM,MAAM,MAAM;AAAA,IAChB,EAAE,YAAY,qBAAqB,IAAI,2BAA2B,SAAS,kBAAkB,EAAE;AAAA,IAC/F,CAAC,aAAa,kBAAkB,UAAU,MAAM,GAAG;AAAA,IACnD,CAAC;AAAA,EACH;AACA,QAAM,MAAM,IAAI,OAAO,qBAAqB,2BAA2B,KAAK,eAAe;AAC7F;AASA,eAAsB,qBACpB,aACiB;AACjB,SAAO,UAAU,cAAc,WAAW,CAAC;AAC7C;;;ACZA,eAAsB,qBACpB,OACA,OACA,WACqC;AACrC,QAAM,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1C,QAAM,kBAAkB,MAAM,MAAM,KAAK,OAAO,kBAAkB;AAElE,QAAM,cAAmD,CAAC;AAC1D,QAAM,yBAAmC,CAAC;AAC1C,aAAW,QAAQ,iBAAiB;AAClC,UAAM,MAAM,MAAM,UAAU,IAAI;AAChC,QAAI,QAAQ,QAAW;AACrB,6BAAuB,KAAK,IAAI;AAChC;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,oBAAoB,OAAO,OAAO,MAAM,GAAG;AACjE,QAAI,CAAC,SAAS;AAIZ,6BAAuB,KAAK,IAAI;AAChC;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,KAAM;AAE3B,UAAM,QAA6B;AAAA,MACjC,YAAY,QAAQ,cAAc,MAAM;AAAA,MACxC,aAAa,QAAQ;AAAA,IACvB;AACA,gBAAY,IAAI,IAAI,QAAQ,aAAa,SAAY,EAAE,GAAG,OAAO,UAAU,QAAQ,SAAS,IAAI;AAAA,EAClG;AAEA,QAAM,gBAAgB,MAAM,qBAAqB,WAAW;AAC5D,QAAM,WAA2B,EAAE,GAAG,GAAG,MAAM,UAAU,YAAY,MAAM,sBAAsB,aAAa,cAAc;AAC5H,SAAO,EAAE,UAAU,uBAAuB;AAC5C;","names":[]}
|