@noy-db/hub 0.7.1-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 +147 -14
- package/LICENSE +202 -21
- package/NOTICE +1 -0
- package/README.md +5 -5
- package/codemods/0.8.0-pre.json +61 -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 +37 -26
- package/dist/attestation/index.js.map +1 -1
- package/dist/{backup-XKCXVKV3.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 +80 -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 +39 -36
- package/dist/{chunk-Q2MPFCQ7.js → chunk-23D6M6VM.js} +5 -5
- package/dist/chunk-23D6M6VM.js.map +1 -0
- package/dist/{chunk-R7BX2NB3.js → chunk-244QBK7Z.js} +4 -4
- package/dist/chunk-244QBK7Z.js.map +1 -0
- package/dist/chunk-2AFX33YA.js +936 -0
- package/dist/chunk-2AFX33YA.js.map +1 -0
- package/dist/{chunk-MVMXZYXT.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-XLMEZIAJ.js → chunk-2ODVB6LZ.js} +2 -2
- package/dist/{chunk-HJUWN7JN.js → chunk-2PVXF5CS.js} +33 -8
- package/dist/chunk-2PVXF5CS.js.map +1 -0
- package/dist/{chunk-YJRT5UQM.js → chunk-2RH777HH.js} +21 -20
- package/dist/{chunk-YJRT5UQM.js.map → chunk-2RH777HH.js.map} +1 -1
- package/dist/{chunk-7O3Y4PPD.js → chunk-37EPTBBR.js} +153 -16
- package/dist/chunk-37EPTBBR.js.map +1 -0
- package/dist/{chunk-2ENE6445.js → chunk-3A5DUZ56.js} +102 -16
- package/dist/chunk-3A5DUZ56.js.map +1 -0
- package/dist/chunk-3EWS67C7.js +461 -0
- package/dist/chunk-3EWS67C7.js.map +1 -0
- package/dist/{chunk-SGZAIJCV.js → chunk-3L2NBKDR.js} +4 -8
- package/dist/chunk-3L2NBKDR.js.map +1 -0
- package/dist/{chunk-YMUFFJCO.js → chunk-3TDUWVWB.js} +5 -2
- package/dist/chunk-3TDUWVWB.js.map +1 -0
- package/dist/{chunk-4GVM6QZA.js → chunk-3XJQBBZD.js} +26 -28
- package/dist/chunk-3XJQBBZD.js.map +1 -0
- package/dist/{chunk-4ZS56W5S.js → chunk-42ALPZ2B.js} +672 -664
- package/dist/chunk-42ALPZ2B.js.map +1 -0
- package/dist/chunk-4CIQDWRB.js +524 -0
- package/dist/chunk-4CIQDWRB.js.map +1 -0
- package/dist/{chunk-RMS3NEA3.js → chunk-4JPMZTJY.js} +2 -2
- package/dist/{chunk-P3MG6QCN.js → chunk-4T3SE27M.js} +5 -9
- package/dist/chunk-4T3SE27M.js.map +1 -0
- package/dist/chunk-4V3Q35WG.js +204 -0
- package/dist/chunk-4V3Q35WG.js.map +1 -0
- package/dist/{chunk-NQKIUNW5.js → chunk-52MGURXO.js} +2 -2
- package/dist/{chunk-EQEYOJBM.js → chunk-5A4345TG.js} +4 -4
- package/dist/chunk-5A4345TG.js.map +1 -0
- package/dist/{chunk-334WSVOW.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-RSGLUIO6.js → chunk-5UMK7GRI.js} +13 -12
- package/dist/chunk-5UMK7GRI.js.map +1 -0
- package/dist/chunk-5WWDGFOS.js +275 -0
- package/dist/chunk-5WWDGFOS.js.map +1 -0
- package/dist/{chunk-QPQUVOZ2.js → chunk-6QVKPHBF.js} +3 -5
- package/dist/chunk-6QVKPHBF.js.map +1 -0
- package/dist/{chunk-ACAQ2DSG.js → chunk-747G6CT3.js} +2 -2
- package/dist/chunk-747G6CT3.js.map +1 -0
- package/dist/{chunk-QTQUH4DS.js → chunk-7R2Q7CPL.js} +16 -16
- package/dist/chunk-7R2Q7CPL.js.map +1 -0
- package/dist/{chunk-UGTBXF5U.js → chunk-7XMHMVTS.js} +3 -3
- package/dist/{chunk-YJX7EOJD.js → chunk-A4XMIZT3.js} +6 -6
- package/dist/{chunk-YJX7EOJD.js.map → chunk-A4XMIZT3.js.map} +1 -1
- package/dist/{chunk-A66I4JOA.js → chunk-AEQGFRU4.js} +4 -4
- package/dist/chunk-AEQGFRU4.js.map +1 -0
- package/dist/chunk-AL6ML4LA.js +1558 -0
- package/dist/chunk-AL6ML4LA.js.map +1 -0
- package/dist/{chunk-BZ3534YM.js → chunk-AUKKUPVB.js} +2 -2
- package/dist/{chunk-CUZLNGD5.js → chunk-B2YY6WDD.js} +1 -1
- package/dist/chunk-B2YY6WDD.js.map +1 -0
- package/dist/chunk-BKT776R5.js +1 -0
- package/dist/chunk-BNWA3WG5.js +22 -0
- package/dist/chunk-BNWA3WG5.js.map +1 -0
- package/dist/{chunk-VXANTWBJ.js → chunk-BPWYQ25R.js} +92 -6
- package/dist/{chunk-VXANTWBJ.js.map → chunk-BPWYQ25R.js.map} +1 -1
- package/dist/{chunk-6LKOJBV6.js → chunk-BVCUTXE3.js} +2 -2
- package/dist/chunk-CY2CYVWZ.js +41 -0
- package/dist/chunk-CY2CYVWZ.js.map +1 -0
- package/dist/{chunk-M4YPHYEH.js → chunk-DHHGL42E.js} +70 -25
- package/dist/chunk-DHHGL42E.js.map +1 -0
- package/dist/{chunk-VTFVLCUH.js → chunk-DIZLQVAA.js} +2 -2
- package/dist/{chunk-G73UVHCA.js → chunk-DLD5LGDS.js} +11 -12
- package/dist/chunk-DLD5LGDS.js.map +1 -0
- package/dist/{chunk-WQBG4SZS.js → chunk-DQESF6RP.js} +60 -49
- package/dist/chunk-DQESF6RP.js.map +1 -0
- package/dist/{chunk-LWBCUYZW.js → chunk-E2N2T5ZO.js} +2 -2
- package/dist/{chunk-3PGS7TYR.js → chunk-EGVJ7TM4.js} +29 -32
- package/dist/chunk-EGVJ7TM4.js.map +1 -0
- package/dist/{chunk-JVIBCBC7.js → chunk-EJLV62NI.js} +2 -2
- package/dist/{chunk-KKEESNPE.js → chunk-EYG2CY2X.js} +126 -19
- package/dist/chunk-EYG2CY2X.js.map +1 -0
- package/dist/{enclave-55PAM4YO.js → chunk-EZGV6F47.js} +83 -56
- package/dist/chunk-EZGV6F47.js.map +1 -0
- package/dist/{chunk-CHQCZZWC.js → chunk-EZOAKKTB.js} +36 -27
- package/dist/chunk-EZOAKKTB.js.map +1 -0
- package/dist/chunk-F6NCB7KT.js +13 -0
- package/dist/chunk-F6NCB7KT.js.map +1 -0
- package/dist/chunk-FFJFE4T7.js +100 -0
- package/dist/chunk-FFJFE4T7.js.map +1 -0
- package/dist/{chunk-JMGDHKQF.js → chunk-FLPCETP6.js} +2 -2
- package/dist/chunk-FOEDQATO.js +53 -0
- package/dist/chunk-FOEDQATO.js.map +1 -0
- package/dist/{chunk-DGOZ4UZD.js → chunk-FVH5QYY2.js} +2 -2
- package/dist/{chunk-HIWCKBEY.js → chunk-G2MVBDFP.js} +54 -28
- 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-5VCRVKOZ.js → chunk-GUZET4SG.js} +12 -4
- package/dist/chunk-GUZET4SG.js.map +1 -0
- package/dist/{chunk-JBDFMYKQ.js → chunk-GZT3NQRA.js} +2 -2
- package/dist/{chunk-K23VKTN4.js → chunk-H23XHRTT.js} +19 -34
- package/dist/chunk-H23XHRTT.js.map +1 -0
- package/dist/{chunk-TFR7DSOV.js → chunk-H427H63K.js} +2 -2
- package/dist/{chunk-DFMWUOU5.js → chunk-H7JBY4P7.js} +23 -32
- package/dist/chunk-H7JBY4P7.js.map +1 -0
- package/dist/{chunk-SKGMN35F.js → chunk-HS554XAF.js} +3 -3
- package/dist/chunk-HS554XAF.js.map +1 -0
- package/dist/{chunk-HK67PX4J.js → chunk-HW7CMKUG.js} +1 -1
- package/dist/chunk-HW7CMKUG.js.map +1 -0
- package/dist/{chunk-3BVH633C.js → chunk-IMQKWR46.js} +5 -7
- package/dist/chunk-IMQKWR46.js.map +1 -0
- package/dist/{chunk-R42NSZI6.js → chunk-IUBMZPHM.js} +7 -7
- package/dist/chunk-IUBMZPHM.js.map +1 -0
- package/dist/{chunk-CUQPWYRX.js → chunk-IUT3GWP3.js} +75 -386
- package/dist/chunk-IUT3GWP3.js.map +1 -0
- package/dist/{chunk-RF6D3Y5E.js → chunk-JDEYF3PJ.js} +4 -8
- package/dist/{chunk-RF6D3Y5E.js.map → chunk-JDEYF3PJ.js.map} +1 -1
- package/dist/{chunk-PPTHY5QO.js → chunk-JIBUPZHA.js} +99 -8
- package/dist/chunk-JIBUPZHA.js.map +1 -0
- package/dist/{chunk-SMH6SRX7.js → chunk-JOSPH3E5.js} +2 -2
- package/dist/chunk-JQYKPKG6.js +193 -0
- package/dist/chunk-JQYKPKG6.js.map +1 -0
- package/dist/{chunk-7APJ6CO6.js → chunk-JSMTXZR3.js} +45 -13
- 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-BVN6KXL2.js → chunk-KZXDLBY6.js} +14 -9
- package/dist/chunk-KZXDLBY6.js.map +1 -0
- package/dist/chunk-LGNDFRYC.js +23 -0
- package/dist/chunk-LGNDFRYC.js.map +1 -0
- package/dist/{chunk-XKWGNJ26.js → chunk-LIOVX5TJ.js} +7 -11
- package/dist/chunk-LIOVX5TJ.js.map +1 -0
- package/dist/{chunk-AYX7AINO.js → chunk-LNSVGRHO.js} +5 -7
- package/dist/chunk-LNSVGRHO.js.map +1 -0
- package/dist/chunk-M5B2W6YY.js +293 -0
- package/dist/chunk-M5B2W6YY.js.map +1 -0
- package/dist/chunk-MBMTND6D.js +456 -0
- package/dist/chunk-MBMTND6D.js.map +1 -0
- package/dist/{chunk-3BZZJJMQ.js → chunk-MILI22XQ.js} +3 -3
- package/dist/{chunk-A2HKRLPV.js → chunk-MXKI4ABF.js} +18 -59
- package/dist/chunk-MXKI4ABF.js.map +1 -0
- package/dist/{chunk-ZYIYHJ5R.js → chunk-MXOQ5JCG.js} +869 -238
- package/dist/chunk-MXOQ5JCG.js.map +1 -0
- package/dist/{chunk-V7ZRRCRJ.js → chunk-N7EVQD5S.js} +9 -13
- package/dist/chunk-N7EVQD5S.js.map +1 -0
- package/dist/chunk-N7UDP5VU.js +757 -0
- package/dist/chunk-N7UDP5VU.js.map +1 -0
- package/dist/chunk-NBQ3KK6X.js +270 -0
- package/dist/chunk-NBQ3KK6X.js.map +1 -0
- package/dist/{chunk-ZORTV6NH.js → chunk-NCO25JZO.js} +88 -4
- package/dist/chunk-NCO25JZO.js.map +1 -0
- package/dist/chunk-NH2UOV3B.js +18 -0
- package/dist/chunk-NH2UOV3B.js.map +1 -0
- package/dist/chunk-NYMLINRP.js +28 -0
- package/dist/chunk-NYMLINRP.js.map +1 -0
- package/dist/{chunk-YYP7WSEB.js → chunk-O2IMQSNA.js} +2 -2
- package/dist/chunk-O46CHQT7.js +215 -0
- package/dist/chunk-O46CHQT7.js.map +1 -0
- package/dist/chunk-OIEO4WDL.js +27 -0
- package/dist/chunk-OIEO4WDL.js.map +1 -0
- package/dist/{chunk-TRGTKX5E.js → chunk-OKSTSITU.js} +27 -4
- package/dist/chunk-OKSTSITU.js.map +1 -0
- package/dist/chunk-OYW3I5M4.js +31 -0
- package/dist/chunk-OYW3I5M4.js.map +1 -0
- package/dist/{chunk-Q7HZX3IF.js → chunk-PD64727P.js} +2 -2
- package/dist/chunk-PD64727P.js.map +1 -0
- package/dist/{chunk-FET5XCAT.js → chunk-PP3K67AJ.js} +34 -6
- 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-QIZPZMUI.js → chunk-Q4UHJ5SN.js} +2 -2
- package/dist/{chunk-FAHMLERK.js → chunk-QBLT6POL.js} +2 -2
- package/dist/chunk-QMWY2FDS.js +157 -0
- package/dist/chunk-QMWY2FDS.js.map +1 -0
- package/dist/{chunk-LH5A3ZPG.js → chunk-RB4DOPGZ.js} +150 -22
- package/dist/chunk-RB4DOPGZ.js.map +1 -0
- package/dist/chunk-RHVMZSUU.js +7 -0
- package/dist/chunk-RHVMZSUU.js.map +1 -0
- package/dist/{chunk-BUE2D7PX.js → chunk-SMV2HRDU.js} +2 -2
- package/dist/chunk-SUZKW6UR.js +25 -0
- package/dist/chunk-SUZKW6UR.js.map +1 -0
- package/dist/{chunk-7MG7SJT7.js → chunk-SV2PM2OY.js} +1 -1
- package/dist/chunk-SV2PM2OY.js.map +1 -0
- package/dist/{chunk-UXVWEX5L.js → chunk-SYNY3VB5.js} +6 -2
- package/dist/chunk-SYNY3VB5.js.map +1 -0
- package/dist/{chunk-4GFX6MPA.js → chunk-TEHHROZL.js} +6 -8
- package/dist/chunk-TEHHROZL.js.map +1 -0
- package/dist/chunk-TKVUE4JF.js +1289 -0
- package/dist/chunk-TKVUE4JF.js.map +1 -0
- package/dist/{chunk-SFAWCTEM.js → chunk-TZZBXPZK.js} +2 -2
- package/dist/{chunk-F3W6YMDC.js → chunk-U2FZNEWJ.js} +4 -4
- package/dist/chunk-U2FZNEWJ.js.map +1 -0
- package/dist/{chunk-BLN54W3L.js → chunk-UA372JHH.js} +56 -3
- package/dist/chunk-UA372JHH.js.map +1 -0
- package/dist/{chunk-6YXCPL4T.js → chunk-UEFOQH74.js} +2 -2
- package/dist/chunk-UEFOQH74.js.map +1 -0
- package/dist/{chunk-2N5ML6HT.js → chunk-UIYESRD6.js} +9 -11
- package/dist/chunk-UIYESRD6.js.map +1 -0
- package/dist/{chunk-UHHPLO3I.js → chunk-V3RWOOSO.js} +4 -4
- package/dist/{chunk-KTFRCC5C.js → chunk-V7ADQF5O.js} +82 -8
- package/dist/chunk-V7ADQF5O.js.map +1 -0
- package/dist/{chunk-453F654R.js → chunk-VAORSCSU.js} +3 -3
- package/dist/chunk-VAORSCSU.js.map +1 -0
- package/dist/{chunk-GPNTB4Y7.js → chunk-VFHCKG5M.js} +6 -10
- package/dist/chunk-VFHCKG5M.js.map +1 -0
- package/dist/{chunk-2577DKXB.js → chunk-VHBKYN2J.js} +3 -3
- package/dist/chunk-VHBKYN2J.js.map +1 -0
- package/dist/chunk-VHM7HCKB.js +220 -0
- package/dist/chunk-VHM7HCKB.js.map +1 -0
- package/dist/{chunk-ZHKOPKE3.js → chunk-VKI2EB3N.js} +3 -3
- package/dist/chunk-VKI2EB3N.js.map +1 -0
- package/dist/{chunk-UDHWDSRL.js → chunk-VMV5SBE4.js} +16 -17
- package/dist/chunk-VMV5SBE4.js.map +1 -0
- package/dist/{chunk-SPYWXKJN.js → chunk-VQDZYB2B.js} +3 -3
- package/dist/chunk-VQDZYB2B.js.map +1 -0
- package/dist/{chunk-Q2PU57HC.js → chunk-VVOLDVIR.js} +2 -2
- package/dist/{chunk-3VF3WQ4F.js → chunk-WPOYWFSE.js} +7 -7
- package/dist/{chunk-3VF3WQ4F.js.map → chunk-WPOYWFSE.js.map} +1 -1
- package/dist/{chunk-OTQZ7ZWU.js → chunk-WXE4W2U6.js} +7 -11
- package/dist/chunk-WXE4W2U6.js.map +1 -0
- package/dist/chunk-XBKH4FOC.js +195 -0
- package/dist/chunk-XBKH4FOC.js.map +1 -0
- package/dist/{chunk-TUFM4UZP.js → chunk-XQRFSKYM.js} +2 -2
- package/dist/{chunk-3V4KWFX7.js → chunk-XSPFDUDG.js} +58 -53
- package/dist/chunk-XSPFDUDG.js.map +1 -0
- package/dist/{chunk-GY4WYNNG.js → chunk-Y2RKVFKR.js} +2 -2
- package/dist/{chunk-UP4BECPY.js → chunk-Y3LPTBG7.js} +89 -27
- package/dist/chunk-Y3LPTBG7.js.map +1 -0
- package/dist/{chunk-4OZNXTO4.js → chunk-YRXFFWG4.js} +2 -2
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-BWOFVYAC.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-VPOKQK4N.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 +10 -11
- package/dist/coverage/index.js +306 -0
- package/dist/coverage/index.js.map +1 -0
- package/dist/custody/index.js +12 -13
- package/dist/{dead-filter-PKQDLOT4.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-DS5NRILW.js → delegation-NANZDG4N.js} +13 -16
- package/dist/delegation-NANZDG4N.js.map +1 -0
- package/dist/derivations/index.js +25 -23
- package/dist/derive-XLOJVXPU.js +20 -0
- package/dist/directory/index.js +10 -11
- package/dist/{dispatch-IEPAVQUM.js → dispatch-H4HV32AM.js} +5 -5
- package/dist/{dispatch-Q6MWLOJY.js → dispatch-JDZNGEB3.js} +20 -21
- 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-S3QL53YX.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 +36 -14
- package/dist/index.js +970 -163
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +13 -5
- package/dist/indexing/index.js.map +1 -1
- package/dist/introspection/index.js +11 -12
- package/dist/issue-YIVBZUTH.js +19 -0
- package/dist/ivf-flat-UZ6DQDLS.js +314 -0
- package/dist/ivf-flat-UZ6DQDLS.js.map +1 -0
- package/dist/{json-schema-V3M5MUCM.js → json-schema-3SHX72CC.js} +2 -1
- package/dist/json-schema-3SHX72CC.js.map +1 -0
- package/dist/kernel/attestation-types.d.ts +62 -0
- package/dist/kernel/collection-config.d.ts +5 -68
- package/dist/kernel/collection.d.ts +30 -9
- package/dist/kernel/cutover-transform.d.ts +1 -1
- package/dist/kernel/errors.d.ts +257 -38
- package/dist/kernel/generation-map.d.ts +48 -0
- package/dist/kernel/merge-authority.d.ts +1 -1
- package/dist/kernel/noydb.d.ts +6 -1
- package/dist/kernel/paths.d.ts +29 -5
- package/dist/kernel/prepared-write.d.ts +1 -1
- package/dist/kernel/present-cache.d.ts +58 -0
- package/dist/kernel/query/all.d.ts +7 -0
- package/dist/kernel/query/builder.d.ts +601 -270
- package/dist/kernel/query/civil-date.d.ts +64 -0
- package/dist/kernel/query/cursor.d.ts +40 -0
- package/dist/kernel/query/distinct-key.d.ts +98 -0
- package/dist/kernel/query/hydration.d.ts +76 -0
- package/dist/kernel/query/index.d.ts +31 -15
- package/dist/kernel/query/internal/core.d.ts +30 -0
- package/dist/kernel/query/internal/hooks.d.ts +22 -0
- package/dist/kernel/query/internal/maintenance.d.ts +43 -0
- package/dist/kernel/query/live/incremental.d.ts +314 -0
- package/dist/kernel/query/live/index.d.ts +22 -0
- package/dist/kernel/query/live/install.d.ts +2 -0
- package/dist/kernel/query/{live.d.ts → live/live.d.ts} +39 -9
- package/dist/kernel/query/live/methods.d.ts +107 -0
- package/dist/kernel/query/predicate.d.ts +119 -1
- package/dist/kernel/query/reduce/date-trunc.d.ts +75 -0
- package/dist/kernel/query/reduce/index.d.ts +36 -0
- package/dist/kernel/query/reduce/install.d.ts +2 -0
- package/dist/kernel/query/reduce/methods.d.ts +259 -0
- package/dist/kernel/query/reduce/scan-methods.d.ts +121 -0
- package/dist/kernel/query/relate/explain.d.ts +199 -0
- package/dist/kernel/query/relate/index.d.ts +48 -0
- package/dist/kernel/query/relate/install.d.ts +2 -0
- package/dist/kernel/query/relate/join-on.d.ts +126 -0
- package/dist/kernel/query/relate/join-reduce.d.ts +16 -0
- package/dist/kernel/query/relate/join.d.ts +452 -0
- package/dist/kernel/query/relate/methods.d.ts +426 -0
- package/dist/kernel/query/relate/partition.d.ts +87 -0
- package/dist/kernel/query/relate/scan-methods.d.ts +163 -0
- package/dist/kernel/query/relate/traverse.d.ts +109 -0
- package/dist/kernel/query/scan-builder.d.ts +79 -176
- package/dist/kernel/query/sort-key.d.ts +52 -0
- package/dist/kernel/secret-mode.d.ts +1 -1
- package/dist/kernel/tx-write-gate.d.ts +77 -0
- package/dist/kernel/types.d.ts +113 -8
- package/dist/kernel/validation.d.ts +27 -10
- package/dist/kernel/vault.d.ts +11 -6
- package/dist/kernel/via/compose.d.ts +3 -0
- package/dist/kernel/via/index.d.ts +56 -0
- package/dist/kernel/via/pipeline.d.ts +48 -0
- package/dist/kernel/write-queue.d.ts +17 -0
- package/dist/{ledger-EDXFFZQL.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-NCWEMPUQ.js → managed-secret-MFTFT22X.js} +10 -11
- package/dist/materialized-views/index.js +30 -24
- package/dist/{migrate-cek-5ENH64AA.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 +74 -67
- package/dist/{pod-handle-ECVCDIXW.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 +10 -1
- package/dist/port/with/classified-strategy.d.ts +1 -1
- package/dist/port/with/collection-options.d.ts +6 -1
- package/dist/port/with/collection-registries.d.ts +1 -1
- package/dist/port/with/coverage-strategy.d.ts +83 -0
- package/dist/port/with/lookup-strategy.d.ts +2 -2
- package/dist/port/with/service-bus.d.ts +46 -0
- package/dist/port/with/strategies.d.ts +2 -0
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-3IPCSG6Q.js → post-register-7ND27CF2.js} +6 -6
- package/dist/post-register-7ND27CF2.js.map +1 -0
- package/dist/query/all/index.js +31 -0
- package/dist/query/index.js +20 -32
- package/dist/query/live/index.js +21 -0
- package/dist/query/live/index.js.map +1 -0
- package/dist/query/reduce/index.js +33 -0
- package/dist/query/reduce/index.js.map +1 -0
- package/dist/query/relate/index.js +56 -0
- package/dist/query/relate/index.js.map +1 -0
- package/dist/reduce/index.js +72 -18
- package/dist/reduce/index.js.map +1 -1
- 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-QZDHSGD4.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 +11 -5
- package/dist/{seed-X5CC22CQ.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/storage-BYN5LO6Z.js.map +1 -0
- package/dist/store/index.js +1 -1
- package/dist/{store-coordination-provider-4WZAIRHC.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 +17 -16
- package/dist/tiers/index.js +13 -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-6MDTIUEV.js → verify-UKALW7C2.js} +14 -12
- package/dist/verify-UKALW7C2.js.map +1 -0
- package/dist/via/blob/index.d.ts +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/geo/binding.d.ts +31 -0
- package/dist/via/geo/descriptor.d.ts +54 -0
- package/dist/via/geo/geohash.d.ts +95 -0
- package/dist/via/geo/index.d.ts +13 -0
- package/dist/via/geo/where.d.ts +50 -0
- package/dist/via/i18n/core.d.ts +1 -1
- package/dist/via/lookup/handle.d.ts +4 -4
- package/dist/via/lookup/registry.d.ts +1 -1
- package/dist/via/lookup/snapshot.d.ts +3 -3
- package/dist/walk-4VPK7AS4.js +20 -0
- package/dist/walk-4VPK7AS4.js.map +1 -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/coverage/accounting.d.ts +112 -0
- package/dist/with-audit/coverage/active.d.ts +29 -0
- package/dist/with-audit/coverage/index.d.ts +61 -0
- package/dist/with-audit/coverage/sketch.d.ts +75 -0
- package/dist/with-audit/forget/subject-index.d.ts +1 -1
- package/dist/with-audit/periods/periods.d.ts +55 -7
- package/dist/with-audit/periods/reserved-collections.d.ts +3 -0
- package/dist/with-audit/periods/vault-facade.d.ts +18 -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 +53 -2
- package/dist/with-audit/tiers/strategy.d.ts +8 -0
- 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 +3 -3
- 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/tx/invariants.d.ts +1 -1
- package/dist/with-commit/tx/transaction.d.ts +13 -3
- 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-formula/materialized-views/dependency-analyzer.d.ts +4 -3
- package/dist/with-formula/materialized-views/emit-memo.d.ts +40 -0
- package/dist/with-formula/materialized-views/executor.d.ts +8 -0
- package/dist/with-formula/materialized-views/index.d.ts +1 -1
- package/dist/with-formula/materialized-views/registry.d.ts +15 -0
- package/dist/with-formula/materialized-views/types.d.ts +106 -14
- package/dist/with-formula/materialized-views/window-stage.d.ts +11 -0
- package/dist/with-formula/overlay-views/types.d.ts +1 -1
- package/dist/with-formula/overlay-views/virtual-collection.d.ts +13 -4
- package/dist/with-lookup/embeddings/chunks.d.ts +79 -0
- package/dist/with-lookup/embeddings/descriptor.d.ts +21 -0
- package/dist/with-lookup/embeddings/index.d.ts +3 -0
- package/dist/with-lookup/embeddings/ivf-flat.d.ts +93 -0
- package/dist/with-lookup/embeddings/vector-index.d.ts +73 -0
- package/dist/with-lookup/embeddings/vector-set.d.ts +94 -1
- package/dist/with-lookup/embeddings/with-vector-index.d.ts +67 -0
- package/dist/with-lookup/indexing/collection-facade.d.ts +86 -3
- package/dist/with-lookup/indexing/compound-indexes.d.ts +129 -0
- package/dist/with-lookup/indexing/eager-indexes.d.ts +170 -1
- package/dist/with-lookup/indexing/index-snapshot.d.ts +62 -0
- package/dist/with-lookup/indexing/lazy-builder.d.ts +33 -0
- package/dist/with-lookup/indexing/persisted-field-indexes.d.ts +104 -0
- package/dist/with-lookup/indexing/persisted-indexes.d.ts +12 -0
- package/dist/with-lookup/indexing/sorted-indexes.d.ts +117 -0
- package/dist/with-lookup/indexing/unique-constraints.d.ts +106 -23
- package/dist/with-lookup/reduce/active.d.ts +2 -24
- package/dist/with-lookup/reduce/group-core.d.ts +43 -0
- package/dist/with-lookup/reduce/groupby.d.ts +195 -36
- package/dist/with-lookup/reduce/incremental-group.d.ts +153 -0
- package/dist/with-lookup/reduce/index.d.ts +26 -5
- package/dist/with-lookup/reduce/reducers.d.ts +255 -1
- package/dist/with-lookup/reduce/reduction.d.ts +44 -13
- package/dist/with-lookup/reduce/strategy.d.ts +43 -3
- package/dist/with-lookup/reduce/window.d.ts +262 -0
- package/dist/with-lookup/search/collection-facade.d.ts +45 -9
- package/dist/with-lookup/search/index-store.d.ts +5 -3
- package/dist/with-lookup/search/index.d.ts +4 -2
- package/dist/with-lookup/search/inverted-index.d.ts +38 -2
- package/dist/with-lookup/search/persisted-index-store.d.ts +5 -2
- package/dist/with-lookup/search/phrase.d.ts +28 -0
- package/dist/with-lookup/search/retrieve-types.d.ts +57 -1
- package/dist/with-lookup/search/serialize.d.ts +29 -3
- package/dist/with-lookup/search/strategy.d.ts +2 -6
- package/dist/with-party/broker/index.d.ts +3 -3
- package/dist/with-party/directory/cover/index.d.ts +1 -1
- package/dist/with-party/directory/cover/storage.d.ts +1 -1
- package/dist/with-party/directory/cover/types.d.ts +1 -1
- package/dist/with-party/directory/index.d.ts +1 -1
- package/dist/with-party/directory/types.d.ts +1 -1
- package/dist/with-party/directory/user-envelope/api.d.ts +1 -1
- package/dist/with-party/directory/user-envelope/storage.d.ts +1 -1
- package/dist/with-party/policy/engine.d.ts +1 -1
- package/dist/with-party/policy/index.d.ts +1 -1
- package/dist/with-party/policy/presets.d.ts +1 -1
- package/dist/with-party/team/authenticators.d.ts +91 -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 +4 -3
- package/dist/with-party/team/keyring.d.ts +2 -2
- package/dist/with-party/team/magic-link-grant.d.ts +1 -1
- package/dist/with-party/team/managed-secret.d.ts +1 -1
- package/dist/with-party/team/noydb-facade.d.ts +12 -3
- 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/format.d.ts +1 -1
- package/dist/with-pod/index.d.ts +1 -1
- package/dist/with-pod/pod.d.ts +1 -1
- package/dist/with-shape/blobs/blob-compaction.d.ts +17 -1
- package/dist/with-shape/blobs/blob-intent.d.ts +1 -1
- package/dist/with-shape/blobs/blob-set.d.ts +23 -4
- package/dist/with-shape/blobs/legacy-sweep.d.ts +35 -0
- package/dist/with-shape/introspection/describe.d.ts +7 -1
- package/dist/with-shape/introspection/field-meta.d.ts +18 -0
- package/dist/with-shape/introspection/types.d.ts +57 -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/links/vault-facade.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-store/partitioned/index.d.ts +337 -0
- package/dist/with-sync/change-broadcast.d.ts +153 -0
- 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 +48 -12
- package/dist/api-WYW4YEQG.js +0 -19
- package/dist/backup-XKCXVKV3.js.map +0 -1
- package/dist/chunk-2577DKXB.js.map +0 -1
- package/dist/chunk-2ENE6445.js.map +0 -1
- package/dist/chunk-2N5ML6HT.js.map +0 -1
- package/dist/chunk-334WSVOW.js.map +0 -1
- package/dist/chunk-3BVH633C.js.map +0 -1
- package/dist/chunk-3PGS7TYR.js.map +0 -1
- package/dist/chunk-3V4KWFX7.js.map +0 -1
- package/dist/chunk-453F654R.js.map +0 -1
- package/dist/chunk-4GFX6MPA.js.map +0 -1
- package/dist/chunk-4GVM6QZA.js.map +0 -1
- package/dist/chunk-4ZS56W5S.js.map +0 -1
- package/dist/chunk-5VCRVKOZ.js.map +0 -1
- package/dist/chunk-6YXCPL4T.js.map +0 -1
- package/dist/chunk-7APJ6CO6.js.map +0 -1
- package/dist/chunk-7MG2LHO5.js +0 -1616
- package/dist/chunk-7MG2LHO5.js.map +0 -1
- package/dist/chunk-7MG7SJT7.js.map +0 -1
- package/dist/chunk-7O3Y4PPD.js.map +0 -1
- package/dist/chunk-A2HKRLPV.js.map +0 -1
- package/dist/chunk-A66I4JOA.js.map +0 -1
- package/dist/chunk-ACAQ2DSG.js.map +0 -1
- package/dist/chunk-ATL3ZVXT.js +0 -151
- package/dist/chunk-ATL3ZVXT.js.map +0 -1
- package/dist/chunk-AYX7AINO.js.map +0 -1
- package/dist/chunk-BLN54W3L.js.map +0 -1
- package/dist/chunk-BRLKZUBT.js +0 -95
- package/dist/chunk-BRLKZUBT.js.map +0 -1
- package/dist/chunk-BTDR2PXY.js +0 -29
- package/dist/chunk-BTDR2PXY.js.map +0 -1
- package/dist/chunk-BVN6KXL2.js.map +0 -1
- package/dist/chunk-CHQCZZWC.js.map +0 -1
- package/dist/chunk-CUQPWYRX.js.map +0 -1
- package/dist/chunk-CUZLNGD5.js.map +0 -1
- package/dist/chunk-DFMWUOU5.js.map +0 -1
- package/dist/chunk-EIPVYUEP.js.map +0 -1
- package/dist/chunk-EQEYOJBM.js.map +0 -1
- package/dist/chunk-F3W6YMDC.js.map +0 -1
- package/dist/chunk-FET5XCAT.js.map +0 -1
- package/dist/chunk-G73UVHCA.js.map +0 -1
- package/dist/chunk-GPNTB4Y7.js.map +0 -1
- package/dist/chunk-GYGLAVCX.js.map +0 -1
- package/dist/chunk-HIWCKBEY.js.map +0 -1
- package/dist/chunk-HJUWN7JN.js.map +0 -1
- package/dist/chunk-HK67PX4J.js.map +0 -1
- package/dist/chunk-HPVZCW43.js +0 -479
- package/dist/chunk-HPVZCW43.js.map +0 -1
- package/dist/chunk-I3ISCYT7.js +0 -159
- package/dist/chunk-I3ISCYT7.js.map +0 -1
- package/dist/chunk-K23VKTN4.js.map +0 -1
- package/dist/chunk-KKEESNPE.js.map +0 -1
- package/dist/chunk-KTFRCC5C.js.map +0 -1
- package/dist/chunk-LH5A3ZPG.js.map +0 -1
- package/dist/chunk-LP7BEXCT.js +0 -32
- package/dist/chunk-LP7BEXCT.js.map +0 -1
- package/dist/chunk-M4YPHYEH.js.map +0 -1
- package/dist/chunk-NSITFOCJ.js +0 -99
- package/dist/chunk-NSITFOCJ.js.map +0 -1
- package/dist/chunk-OTQZ7ZWU.js.map +0 -1
- package/dist/chunk-P3MG6QCN.js.map +0 -1
- package/dist/chunk-PEOZ34EM.js.map +0 -1
- package/dist/chunk-PPTHY5QO.js.map +0 -1
- package/dist/chunk-Q2MPFCQ7.js.map +0 -1
- package/dist/chunk-Q7HZX3IF.js.map +0 -1
- package/dist/chunk-QPQUVOZ2.js.map +0 -1
- package/dist/chunk-QTQUH4DS.js.map +0 -1
- package/dist/chunk-R42NSZI6.js.map +0 -1
- package/dist/chunk-R7BX2NB3.js.map +0 -1
- package/dist/chunk-RSGLUIO6.js.map +0 -1
- package/dist/chunk-RTBJ5IOO.js +0 -87
- package/dist/chunk-RTBJ5IOO.js.map +0 -1
- package/dist/chunk-SGZAIJCV.js.map +0 -1
- package/dist/chunk-SKGMN35F.js.map +0 -1
- package/dist/chunk-SPYWXKJN.js.map +0 -1
- package/dist/chunk-SZJ3DLZA.js +0 -66
- package/dist/chunk-SZJ3DLZA.js.map +0 -1
- package/dist/chunk-TRGTKX5E.js.map +0 -1
- package/dist/chunk-UDHWDSRL.js.map +0 -1
- package/dist/chunk-UP4BECPY.js.map +0 -1
- package/dist/chunk-UXVWEX5L.js.map +0 -1
- package/dist/chunk-V7ZRRCRJ.js.map +0 -1
- package/dist/chunk-WQBG4SZS.js.map +0 -1
- package/dist/chunk-XKWGNJ26.js.map +0 -1
- package/dist/chunk-YMUFFJCO.js.map +0 -1
- package/dist/chunk-ZHKOPKE3.js.map +0 -1
- package/dist/chunk-ZN4FD4PE.js +0 -364
- package/dist/chunk-ZN4FD4PE.js.map +0 -1
- package/dist/chunk-ZORTV6NH.js.map +0 -1
- package/dist/chunk-ZYIYHJ5R.js.map +0 -1
- package/dist/classified-marker-BWOFVYAC.js.map +0 -1
- package/dist/collection-facade-JSJYIKS4.js +0 -45
- package/dist/dead-filter-PKQDLOT4.js.map +0 -1
- package/dist/delegation-DS5NRILW.js.map +0 -1
- package/dist/derive-E642AOUB.js +0 -21
- package/dist/dispatch-Q6MWLOJY.js.map +0 -1
- package/dist/executor-5NIMLSKZ.js +0 -8
- package/dist/executor-7UQ3BZ4F.js +0 -29
- package/dist/executor-AQVXV5GZ.js +0 -8
- package/dist/export-accessible-ORMKLA3E.js +0 -22
- package/dist/extract-partition-NKYO3WNG.js +0 -37
- package/dist/fanout-sidecar-S3QL53YX.js.map +0 -1
- package/dist/find-NOGJ25VX.js +0 -10
- package/dist/issue-3DTQ7VJJ.js +0 -18
- package/dist/json-schema-V3M5MUCM.js.map +0 -1
- 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/kernel/query/join.d.ts +0 -232
- package/dist/liberate-V35QUHJP.js +0 -24
- package/dist/link-set-2TTM3IZC.js +0 -30
- package/dist/noydb-62MX4QUG.js +0 -90
- package/dist/pod-handle-ECVCDIXW.js.map +0 -1
- package/dist/post-register-3IPCSG6Q.js.map +0 -1
- package/dist/register-HHLXEQDN.js +0 -31
- package/dist/registry-23WF3TGH.js +0 -8
- package/dist/registry-4AYVUNXK.js +0 -8
- package/dist/registry-JS3YFQQM.js +0 -18
- package/dist/registry-XX2Z7B46.js +0 -32
- package/dist/request-withdrawal-CHPATE4G.js +0 -30
- package/dist/reveal-QZDHSGD4.js.map +0 -1
- package/dist/revoke-7M2VW4ON.js +0 -23
- package/dist/seed-X5CC22CQ.js.map +0 -1
- package/dist/signer-SJQJVSM6.js +0 -24
- package/dist/stale-BZS6H2RY.js +0 -29
- package/dist/storage-RW4QBS23.js +0 -22
- package/dist/store-coordination-provider-4WZAIRHC.js.map +0 -1
- package/dist/verify-6MDTIUEV.js.map +0 -1
- package/dist/walk-ZURCH6RZ.js +0 -21
- package/dist/withdraw-accessible-PXR4IXDX.js +0 -27
- /package/dist/{api-WYW4YEQG.js.map → api-OS747DS4.js.map} +0 -0
- /package/dist/{computed-VPOKQK4N.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-JSJYIKS4.js.map → capsule-VOLX3QRQ.js.map} +0 -0
- /package/dist/{chunk-MVMXZYXT.js.map → chunk-2GHDLTPE.js.map} +0 -0
- /package/dist/{chunk-XLMEZIAJ.js.map → chunk-2ODVB6LZ.js.map} +0 -0
- /package/dist/{chunk-RMS3NEA3.js.map → chunk-4JPMZTJY.js.map} +0 -0
- /package/dist/{chunk-NQKIUNW5.js.map → chunk-52MGURXO.js.map} +0 -0
- /package/dist/{chunk-UGTBXF5U.js.map → chunk-7XMHMVTS.js.map} +0 -0
- /package/dist/{chunk-BZ3534YM.js.map → chunk-AUKKUPVB.js.map} +0 -0
- /package/dist/{derive-E642AOUB.js.map → chunk-BKT776R5.js.map} +0 -0
- /package/dist/{chunk-6LKOJBV6.js.map → chunk-BVCUTXE3.js.map} +0 -0
- /package/dist/{chunk-VTFVLCUH.js.map → chunk-DIZLQVAA.js.map} +0 -0
- /package/dist/{chunk-LWBCUYZW.js.map → chunk-E2N2T5ZO.js.map} +0 -0
- /package/dist/{chunk-JVIBCBC7.js.map → chunk-EJLV62NI.js.map} +0 -0
- /package/dist/{chunk-JMGDHKQF.js.map → chunk-FLPCETP6.js.map} +0 -0
- /package/dist/{chunk-DGOZ4UZD.js.map → chunk-FVH5QYY2.js.map} +0 -0
- /package/dist/{chunk-JBDFMYKQ.js.map → chunk-GZT3NQRA.js.map} +0 -0
- /package/dist/{chunk-TFR7DSOV.js.map → chunk-H427H63K.js.map} +0 -0
- /package/dist/{chunk-SMH6SRX7.js.map → chunk-JOSPH3E5.js.map} +0 -0
- /package/dist/{chunk-3BZZJJMQ.js.map → chunk-MILI22XQ.js.map} +0 -0
- /package/dist/{chunk-YYP7WSEB.js.map → chunk-O2IMQSNA.js.map} +0 -0
- /package/dist/{chunk-QIZPZMUI.js.map → chunk-Q4UHJ5SN.js.map} +0 -0
- /package/dist/{chunk-FAHMLERK.js.map → chunk-QBLT6POL.js.map} +0 -0
- /package/dist/{chunk-BUE2D7PX.js.map → chunk-SMV2HRDU.js.map} +0 -0
- /package/dist/{chunk-SFAWCTEM.js.map → chunk-TZZBXPZK.js.map} +0 -0
- /package/dist/{chunk-UHHPLO3I.js.map → chunk-V3RWOOSO.js.map} +0 -0
- /package/dist/{chunk-Q2PU57HC.js.map → chunk-VVOLDVIR.js.map} +0 -0
- /package/dist/{chunk-TUFM4UZP.js.map → chunk-XQRFSKYM.js.map} +0 -0
- /package/dist/{chunk-GY4WYNNG.js.map → chunk-Y2RKVFKR.js.map} +0 -0
- /package/dist/{chunk-4OZNXTO4.js.map → chunk-YRXFFWG4.js.map} +0 -0
- /package/dist/{enclave-55PAM4YO.js.map → collection-facade-CS7CA2XO.js.map} +0 -0
- /package/dist/{executor-5NIMLSKZ.js.map → computed-FAD7SED4.js.map} +0 -0
- /package/dist/{executor-7UQ3BZ4F.js.map → derive-XLOJVXPU.js.map} +0 -0
- /package/dist/{dispatch-IEPAVQUM.js.map → dispatch-H4HV32AM.js.map} +0 -0
- /package/dist/{executor-AQVXV5GZ.js.map → executor-FMPVN6DT.js.map} +0 -0
- /package/dist/{export-accessible-ORMKLA3E.js.map → executor-LBBBRTN5.js.map} +0 -0
- /package/dist/{extract-partition-NKYO3WNG.js.map → executor-OSRZST2U.js.map} +0 -0
- /package/dist/{find-NOGJ25VX.js.map → export-accessible-RAOJAAU5.js.map} +0 -0
- /package/dist/{issue-3DTQ7VJJ.js.map → extract-partition-JD5CUSTG.js.map} +0 -0
- /package/dist/{ledger-EDXFFZQL.js.map → find-JRN4RNQ5.js.map} +0 -0
- /package/dist/{liberate-V35QUHJP.js.map → issue-YIVBZUTH.js.map} +0 -0
- /package/dist/{link-set-2TTM3IZC.js.map → ledger-5ZMGE44K.js.map} +0 -0
- /package/dist/{managed-secret-NCWEMPUQ.js.map → liberate-WZSZM2W6.js.map} +0 -0
- /package/dist/{noydb-62MX4QUG.js.map → link-set-MFXC24VK.js.map} +0 -0
- /package/dist/{register-HHLXEQDN.js.map → managed-secret-MFTFT22X.js.map} +0 -0
- /package/dist/{migrate-cek-5ENH64AA.js.map → migrate-cek-DZRFFOHW.js.map} +0 -0
- /package/dist/{registry-23WF3TGH.js.map → noydb-ITIGNKUF.js.map} +0 -0
- /package/dist/{registry-4AYVUNXK.js.map → query/all/index.js.map} +0 -0
- /package/dist/{registry-JS3YFQQM.js.map → register-DT5HZ2LZ.js.map} +0 -0
- /package/dist/{registry-XX2Z7B46.js.map → registry-BHRZGZHF.js.map} +0 -0
- /package/dist/{request-withdrawal-CHPATE4G.js.map → registry-ET6ZFFWA.js.map} +0 -0
- /package/dist/{revoke-7M2VW4ON.js.map → registry-HXFGLGTG.js.map} +0 -0
- /package/dist/{signer-SJQJVSM6.js.map → registry-THCPDEOD.js.map} +0 -0
- /package/dist/{stale-BZS6H2RY.js.map → request-withdrawal-AV2MJJKY.js.map} +0 -0
- /package/dist/{storage-RW4QBS23.js.map → revoke-6DWIEOCV.js.map} +0 -0
- /package/dist/{walk-ZURCH6RZ.js.map → signer-MHGW3OIL.js.map} +0 -0
- /package/dist/{withdraw-accessible-PXR4IXDX.js.map → stale-6GCFMOOR.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/capsule/plumbing/record-aad.ts","../src/capsule/plumbing/envelope-body.ts","../src/capsule/plumbing/sealed-slot.ts","../src/capsule/plumbing/record-envelope.ts","../src/capsule/plumbing/tombstone.ts","../src/kernel/schema.ts","../src/capsule/plumbing/sealed-slots.ts","../src/capsule/plumbing/record-codec.ts","../src/capsule/plumbing/lifecycle.ts","../src/capsule/plumbing/rekey.ts","../src/capsule/plumbing/rekey-blob.ts","../src/capsule/plumbing/sealing.ts","../src/capsule/plumbing/deterministic.ts","../src/capsule/plumbing/index.ts","../src/capsule/plumbing/ct-equal.ts"],"sourcesContent":["/**\n * Record-identity AAD (#1041).\n *\n * AES-GCM authenticates its *additional authenticated data* alongside the\n * ciphertext without encrypting it. Binding a record's identity here is what\n * stops an untrusted store from silently **relocating** an envelope — moving\n * it to another collection or id, re-tiering it, or rewriting who\n * wrote it — while keeping a body whose auth tag still verifies.\n *\n * Scope, stated plainly: this closes cross-COLLECTION relocation, the `_tier`\n * silent-hide, provenance forgery — and, since #1093, **version rollback**.\n *\n * ## `_v` is bound, and what it took to get there\n *\n * `_v` was deliberately left out at first, for a reason that was real rather\n * than cautious: the sync engine re-stamped `_v` on existing ciphertext without\n * holding a DEK (`advancePastRemote`), so binding it would have made every\n * conflict-superseded record undecryptable. #1042's `MergeAuthority` removed\n * that obstacle by giving the merge a DEK-holding capability, so advancing a\n * version became a **re-seal** instead of a metadata edit — and only then could\n * `_v` join the tuple.\n *\n * ⚠️ **What that buys, stated exactly** — the harness measured this, and the\n * loose version (\"rollback is prevented\") is wrong.\n *\n * A body can no longer be presented at a version it was not sealed at. So the\n * *restamped* rollback — take v1's bytes, label them v9, win the convergence\n * comparison, overwrite the newer copy — is refused, and refused **before**\n * `local.put`, so nothing is lost.\n *\n * A store re-serving the genuine v1 **at its own `_v: 1`** is still served, and\n * has to be: that envelope is internally consistent, and a reader arriving\n * fresh has nothing to compare it against. AAD binds a body to the version it\n * claims; it cannot know which version *should* have arrived.\n *\n * So rollback stops being forgery and becomes **withholding** — hiding the newer\n * version rather than faking one — which is `withVaultHead()`'s job (#1044).\n *\n * ## Why `vault` is not bound\n *\n * It was, briefly, and it broke `adoptPartition`. That path re-homes a whole\n * partition into a new vault name by moving envelopes **verbatim** —\n * `with-cargo/adopt-partition.ts:140` is a bare\n * `destinationStore.saveAll(vaultName, backup.collections)` with no\n * re-encryption, because it does not hold the keys to re-encrypt at that\n * point. Binding the vault name makes every adopted record undecryptable.\n *\n * The uncomfortable truth behind that: **relocation is not purely an attack.**\n * Adoption is a legitimate, supported relocation, and AAD cannot tell the two\n * apart. So the vault boundary has to be defended by something that can\n * distinguish intent — an authenticated head or an explicit re-key — rather\n * than by sealing a name the product deliberately changes.\n *\n * Cross-*collection* relocation has no such legitimate counterpart, so it stays\n * bound.\n *\n * @packageDocumentation\n */\n\n/**\n * Where an envelope was fetched from — the **read** side's half of identity.\n *\n * A reader supplies only the address, because that is genuinely all it knows:\n * `_tier`, `_by` and `_v` are read back off the envelope itself\n * ({@link recordAadFor}). Splitting this out of {@link RecordIdentity} is what\n * lets `version` be *required* on the write side without forcing dozens of read\n * call sites to invent one.\n */\nexport interface RecordRef {\n readonly collection: string\n readonly id: string\n}\n\n/**\n * The identity an envelope's body is sealed against — the **write** side.\n *\n * Every field here is stamped onto the envelope by `buildRecordEnvelope` from\n * this one object, so what a writer *seals* and what it *stamps* cannot drift.\n */\nexport interface RecordIdentity extends RecordRef {\n /**\n * The `_v` this body is sealed at (#1093).\n *\n * Required, and required is the point: a version that could be omitted would\n * be a version some writer forgets, and a record sealed at a version nobody\n * chose is one a reader cannot open. The compiler asks the question at every\n * write site instead of leaving it to review.\n */\n readonly version: number\n /** Absent is identical to `0` — the read paths treat them as one record. */\n readonly tier?: number | undefined\n /** Absent (no `_by` on the envelope) is distinct from an empty string. */\n readonly by?: string | undefined\n}\n\n/** Bumped from `/1` when `_v` joined the tuple (#1093). Nothing branches on it. */\nconst SCHEME = 'noydb-aad/2'\n\nconst encoder = new TextEncoder()\n\n/**\n * Length-prefixed, order-fixed encoding.\n *\n * The obvious `${collection}:${id}` is unsafe: an attacker who\n * controls a collection name can choose one that re-splits the same joined\n * string a different way, so two different identities produce identical AAD\n * and the relocation this exists to prevent goes through. Every field is\n * therefore written as a 4-byte big-endian length followed by its UTF-8 bytes,\n * which no field content can imitate.\n *\n * A one-byte presence flag precedes `by` so that \"no author recorded\" and\n * \"author recorded as the empty string\" cannot be swapped for one another.\n */\nexport function buildRecordAad(identity: RecordIdentity): Uint8Array {\n // ⚠️ Assert on the VALUE, not on the caller's type. `version` is required in\n // TypeScript, so this can only fire for a caller the compiler never saw — a\n // hand-built test fixture, a JS consumer, a `Partial` widened somewhere. It\n // matters because the failure it prevents is invisible: `String(undefined)`\n // is a perfectly good AAD field, so the record seals happily and becomes\n // undecryptable at the next read, with a TamperedError pointing at the READ\n // path where the code is correct. Several fixtures did exactly this (#1093).\n if (!Number.isFinite(identity.version)) {\n throw new TypeError(\n `record AAD: version must be a finite number for \"${identity.collection}/${identity.id}\", ` +\n `received ${String(identity.version)}. Sealing without one produces a record no reader can open.`,\n )\n }\n // Same argument as `version` above, for the two fields that are STRINGS\n // and therefore coerce instead of arriving as NaN (#1220). `String({})` is\n // `\"[object Object]\"` and `String(undefined)` is `\"undefined\"` — both seal\n // perfectly well and both produce a record no reader will ever address.\n // Measured: `collection.put({ id: 'd1', ... })` from JS stores under\n // `\"[object Object]\"`, and an unset identity reaches the store as\n // `undefined`. Assert on the OUTPUT condition — no seal may be computed\n // over a non-string address — rather than on the two calls that found it.\n for (const [field, value] of [['collection', identity.collection], ['id', identity.id]] as const) {\n if (typeof value !== 'string') {\n throw new TypeError(\n `record AAD: ${field} must be a string, received ${String(value)} ` +\n `(${typeof value}). Sealing against a coerced address produces a record ` +\n `no reader can open, and the failure surfaces on the READ path.`,\n )\n }\n }\n\n const parts: Uint8Array[] = [encoder.encode(SCHEME)]\n\n const pushField = (value: string): void => {\n const bytes = encoder.encode(value)\n const len = new Uint8Array(4)\n new DataView(len.buffer).setUint32(0, bytes.length, false)\n parts.push(len, bytes)\n }\n\n pushField(identity.collection)\n pushField(identity.id)\n // Absent tier ≡ tier 0: `collection.ts` reads `(envelope._tier ?? 0) > 0`,\n // so treating them differently here would make a record written without a\n // tier undecryptable once read through a tier-aware path.\n pushField(String(identity.tier ?? 0))\n\n parts.push(new Uint8Array([identity.by === undefined ? 0 : 1]))\n if (identity.by !== undefined) pushField(identity.by)\n // `_v` (#1093). Written as its decimal string through the same length-prefixed\n // field encoding as everything else, so a version cannot be confused with the\n // author beside it.\n pushField(String(identity.version))\n\n const total = parts.reduce((n, p) => n + p.length, 0)\n const out = new Uint8Array(total)\n let offset = 0\n for (const p of parts) {\n out.set(p, offset)\n offset += p.length\n }\n return out\n}\n\n/**\n * The AAD a **reader** must supply to open `envelope`, given where it fetched\n * it from.\n *\n * This is the read-side counterpart of {@link buildRecordAad}, and the split\n * exists because of one asymmetry: **a writer always knows what it is writing;\n * a reader often does not.** Query execution, sync merge and backup restore\n * hold an envelope that arrived from a map or a batch, having discarded the\n * address it came from.\n *\n * What makes the read side tractable is that only `{collection, id}` has to be\n * threaded — precisely what the caller passed to `store.get`. `_tier`, `_by`\n * and `_v` are read back **off the envelope**, so no extra plumbing carries\n * them.\n *\n * That is not a weakening. An attacker who edits `_tier` to hide a record,\n * `_by` to forge provenance, or `_v` to pass an old body off as the current\n * one, changes the AAD the reader computes — and AES-GCM then fails to\n * authenticate. The tampered field defeats itself.\n */\nexport function recordAadFor(\n ref: RecordRef,\n envelope: {\n readonly _v: number\n readonly _tier?: number | undefined\n readonly _by?: string | undefined\n },\n): Uint8Array {\n return buildRecordAad({\n collection: ref.collection,\n id: ref.id,\n version: envelope._v,\n tier: envelope._tier,\n by: envelope._by,\n })\n}\n","/**\n * Enclave body helpers — the C1 protected-body access contract.\n *\n * `EncryptedEnvelope` splits into a protocol header (family-owned; `_noydb`,\n * `_v`, `_ts`, `_by`, `_source`, `_sourceTs`, `_tier`, `_elevatedBy`) and a\n * protected body (enclave-owned; `_iv`, `_data`, `_cek`, `_det`, `_sealed`,\n * `_debug`). The four helpers below are the ONLY sanctioned way for code\n * outside `capsule/enclave-aes/**` to read or construct the protected body —\n * later migration batches move the ~121 direct `_iv`/`_data`/`_cek`/`_sealed`\n * access sites in `with-*` services onto these.\n *\n * Each helper reproduces an EXISTING behavior byte-for-byte (see the\n * per-function doc for its oracle call site) — this file introduces no new\n * crypto or semantics, only a narrower door onto what already runs.\n */\nimport { buildRecordAad, recordAadFor, type RecordIdentity, type RecordRef } from './record-aad.js'\nimport type { CapsuleKey, CapsulePrimitives } from '../contract.js'\nimport type { EncryptedEnvelope } from '../../kernel/types.js'\nimport { MissingEnvelopeBodyError } from '../../kernel/errors.js'\n\n/**\n * The sealed body, or a typed refusal (#15).\n *\n * Since `_iv`/`_data` became optional, every AES path that is about to call\n * `decrypt()` needs this one narrowing. It is deliberately the ONLY place in\n * the enclave that turns absence into an error: the alternative — a `!` or a\n * `?? ''` at each of the two dozen decrypt sites — would have spelled the\n * same decision twenty-four times and produced an AEAD failure (i.e. hub's\n * tamper alert) instead of an honest one.\n *\n * Ask {@link hasSealedBody} FIRST when absence is a legitimate outcome; this\n * helper is for the paths where it is not.\n */\nexport function requireSealedBody(\n env: Pick<EncryptedEnvelope, '_iv' | '_data'>,\n where: string,\n): { iv: string; data: string } {\n if (env._iv === undefined || env._data === undefined) throw new MissingEnvelopeBodyError(where)\n return { iv: env._iv, data: env._data }\n}\n\n/**\n * {@link requireSealedBody} shaped for the `decrypt(iv, data, …)` argument\n * list, so a narrowing can be spliced into an existing call without\n * restructuring the statement around it:\n *\n * ```ts\n * await decrypt(...sealedBodyArgs(env, 'rekeyRecord'), dek, aad)\n * ```\n *\n * The tuple return type is load-bearing — it is what lets the spread satisfy\n * two fixed positional parameters. Widening it to `string[]` would compile\n * here and fail at every call site.\n */\nexport function sealedBodyArgs(\n env: Pick<EncryptedEnvelope, '_iv' | '_data'>,\n where: string,\n): [string, string] {\n const { iv, data } = requireSealedBody(env, where)\n return [iv, data]\n}\n\n/**\n * Approximate protected-body payload size for KPI/telemetry (#807's\n * period-scoped pull download counters): `_data` + `_iv` string length —\n * ≈ ciphertext bytes for base64 payloads, exact for plaintext (`_iv: ''`)\n * collections. A measuring door, not a crypto one: callers get a size\n * without touching the protected fields directly.\n */\nexport function envelopeBodySize(env: EncryptedEnvelope): number {\n // An absent field meters as 0, the same as the emptied spelling it replaces\n // (#15) — a bodyless row has no payload to bill for, and throwing a\n // TypeError out of a telemetry counter would take down the write path.\n return (env._data?.length ?? 0) + (env._iv?.length ?? 0)\n}\n\n/**\n * Discriminant: does this envelope carry a per-record key?\n *\n * Replaces raw `envelope._cek !== undefined` checks scattered across\n * services — `_cek` presence is the format discriminant (see\n * `record-codec.ts`'s `resolveEnvelopeCek` doc).\n */\nexport function hasPerRecordKey(env: EncryptedEnvelope): boolean {\n return env._cek !== undefined\n}\n\n/**\n * Canonical body string for the ledger hash chain — the exact bytes\n * `with-commit/history/ledger/hash.ts`'s `envelopePayloadHash` derives from\n * `_data` + `_sealed` + `_vdig` + `_bidx` before hashing:\n * - no `_sealed`, no `_vdig`, no `_bidx` → `_data` alone (back-compat: every\n * pre-existing ledger entry and non-sealed backup hashes byte-identically).\n * - any map present → canonical JSON of `{ _data, _sealed?, _vdig?, _bidx? }`\n * with sorted keys at every level, each map bound ONLY when present, so\n * the result is independent of the maps' field-insertion / store-\n * serialization order. `_bidx` is always the LAST segment, so a legacy\n * `_vdig`-only / `_bidx`-absent envelope hashes byte-identically to its\n * stage-2 value.\n *\n * Deliberately reimplements the two-key-object canonicalization inline\n * rather than importing `with-commit/history/ledger/entry.ts`'s general\n * `canonicalJson` — `capsule/enclave-aes/**` may import only spine types (C3),\n * never a `with-*` service. For this fixed `{ _data: string; _sealed:\n * Record<string, string> }` shape the two produce byte-identical output\n * (verified against that exact call site's oracle expression in\n * `envelope-body.test.ts`).\n */\nexport function envelopeBodyForHash(env: EncryptedEnvelope): string {\n // Conditional widen (stage 2): bind `_vdig` exactly the way `_sealed` is\n // bound — only when present. No existing envelope carries `_vdig`, so this\n // ships with no flag-day PROVIDED it lands in the same slice as the first\n // `_vdig` writer (it does — Tasks 7/8/11 are one branch). This binding is\n // the temporal-rollback detector completing C1: AAD stops cross-record/\n // cross-field splices; the ledger hash catches same-slot rollbacks.\n //\n // Conditional widen (slice 2b, SM #5): bind `_bidx` the same way, appended\n // LAST (after `_vdig`) so a `_bidx`-absent envelope keeps its stage-2\n // byte-identical hash.\n // `?? ''` (#15): an omitted `_data` must hash identically to an emptied\n // one, or a capsule changing spelling would invalidate every ledger entry\n // written before it.\n const data = env._data ?? ''\n if (env._sealed === undefined && env._vdig === undefined && env._bidx === undefined) return data\n const mapPart = (key: '_sealed' | '_vdig' | '_bidx', map: Record<string, string>): string => {\n const parts = Object.keys(map).sort().map(\n (k) => `${JSON.stringify(k)}:${JSON.stringify(map[k])}`,\n )\n return `${JSON.stringify(key)}:{${parts.join(',')}}`\n }\n const segments = [`\"_data\":${JSON.stringify(data)}`]\n if (env._sealed !== undefined) segments.push(mapPart('_sealed', env._sealed))\n if (env._vdig !== undefined) segments.push(mapPart('_vdig', env._vdig))\n if (env._bidx !== undefined) segments.push(mapPart('_bidx', env._bidx))\n return `{${segments.join(',')}}`\n}\n\n/**\n * Does `env` carry an AEAD-sealed body at all?\n *\n * The one question callers outside the enclave legitimately need to ask about\n * `_iv` — a tombstone and a plaintext-collection record have none, so there is\n * nothing to authenticate and nothing to re-seal. Both {@link\n * verifyRecordIdentity} (which treats them as vacuously authentic) and the\n * merge authority's `advance` (which stamps them without re-sealing) turn on\n * it, and asking it here keeps `_iv` from leaking back out to the callers —\n * which `enclave-body-only` refused, correctly, when `advance` tested it inline.\n */\nexport function hasSealedBody(env: Pick<EncryptedEnvelope, '_iv'>): boolean {\n // ⛔ `env._iv !== ''` alone answered TRUE for an omitted `_iv` (#15) — the\n // exact inversion of what the caller is asking. Absence and `''` are the\n // same statement: there is nothing here to authenticate.\n return env._iv !== undefined && env._iv !== ''\n}\n\n/**\n * The cipher-dependent half: the three doors that actually reach the capsule's\n * `encrypt`/`decrypt`. Everything above this line is cipher-FREE — it inspects\n * envelope fields or derives hash input, so it stays a plain module export that\n * both capsules share with nothing to bind.\n */\nexport function makeEnvelopeBody(p: CapsulePrimitives) {\n const { encrypt, decrypt, generateDEK, wrapCek, unwrapCek } = p\n\n /**\n * Open an envelope's protected body to its JSON text.\n *\n * Mirrors the dominant direct-decrypt call-site shape (e.g.\n * `with-audit/consent/consent.ts`'s `decryptEntry`):\n * - `opts.encrypted === false` (default `true`) → plaintext collection;\n * returns `env._data` as-is, `key` untouched.\n * - `env._cek` present → per-record-key envelope (mirrors\n * `record-codec.ts`'s `resolveEnvelopeCek`): unwrap the CEK under `key`\n * (the collection DEK), decrypt the body under the unwrapped CEK.\n * - `env._cek` absent → legacy path, decrypt the body directly under `key`.\n */\n async function openEnvelopeJson(\n ref: RecordRef,\n env: EncryptedEnvelope,\n key: CapsuleKey,\n opts?: { encrypted?: boolean },\n ): Promise<string> {\n // A plaintext collection has no AEAD, so there is nothing to authenticate —\n // `_data` is returned as-is and identity binding does not apply to it.\n // Absent `_data` reads as `''` here, exactly as an emptied one always has:\n // a plaintext collection with nothing in it is not an error.\n if (opts?.encrypted === false) return env._data ?? ''\n // Recomputed from the ADDRESS this was fetched from plus `_tier`/`_by` read\n // off the envelope. A store that edited either one changes this value, and\n // AES-GCM then refuses the body (#1041).\n const aad = recordAadFor(ref, env)\n const { iv, data } = requireSealedBody(env, 'openEnvelopeJson')\n if (env._cek !== undefined) {\n const cek = await unwrapCek(env._cek, key)\n return decrypt(iv, data, cek, aad)\n }\n return decrypt(iv, data, key, aad)\n }\n\n /**\n * Produce the protected-body fields (`_iv`/`_data`/`_cek`) for an envelope a\n * caller is assembling.\n *\n * - `opts.encrypted === false` (default `true`) → plaintext collection;\n * emits `{ _iv: '', _data: json }` (today's `buildPlaintextEnvelope`\n * shape), `key` untouched.\n * - `opts.perRecordKey === true` → mints a fresh per-record CEK, encrypts\n * the body under it, and AES-KW-wraps the CEK under `key` (mirrors\n * `encryptJsonString`'s `cek !== undefined` branch, except the CEK is\n * generated here rather than supplied by the caller).\n * - otherwise → legacy path, body encrypted directly under `key`.\n */\n async function writeEnvelopeBody(\n identity: RecordIdentity,\n json: string,\n key: CapsuleKey,\n opts?: { encrypted?: boolean; perRecordKey?: boolean },\n ): Promise<Pick<EncryptedEnvelope, '_iv' | '_data' | '_cek'>> {\n if (opts?.encrypted === false) return { _iv: '', _data: json }\n\n const aad = buildRecordAad(identity)\n\n if (opts?.perRecordKey === true) {\n const cek = await generateDEK()\n const { iv, data } = await encrypt(json, cek, aad)\n const wrapped = await wrapCek(cek, key)\n return { _iv: iv, _data: data, _cek: wrapped }\n }\n\n const { iv, data } = await encrypt(json, key, aad)\n return { _iv: iv, _data: data }\n }\n\n /**\n * Does `env` authenticate at the identity `ref` claims, under `key`? (#1042)\n *\n * The merge's fail-closed check, living here because it is envelope surgery:\n * deciding \"is there a sealed body at all\" reads `_iv`, which\n * `enclave-body-only` reserves to this folder. An earlier draft did that test\n * in `kernel/noydb.ts` and the guard refused it — correctly, since a caller\n * outside the enclave inspecting protected fields is how envelope knowledge\n * leaks back out.\n *\n * Returns a boolean rather than throwing: `applyRemote` must be able to reject\n * one poisoned record without halting an entire sync, and a hostile store\n * would very much like the opposite.\n *\n * **A record with no sealed body is vacuously authentic** — a tombstone carries\n * none, and a plaintext collection has no AEAD to verify. Those are pass-through\n * by construction, not by omission.\n */\n async function verifyRecordIdentity(\n ref: RecordRef,\n env: EncryptedEnvelope,\n key: CapsuleKey,\n ): Promise<boolean> {\n if (!hasSealedBody(env)) return true\n try {\n await openEnvelopeJson(ref, env, key)\n return true\n } catch {\n return false\n }\n }\n\n return { openEnvelopeJson, writeEnvelopeBody, verifyRecordIdentity }\n}\n","/**\n * Sealed-slot (`iv:data`) parsing + the CEK/DEK dual-read, factored out so the\n * three callers that decrypt a `_sealed[field]` slot share ONE implementation\n * with no coupling between them:\n *\n * - {@link RecordCodec.unsealField} / `classifySealedShred` (read + classify),\n * - `record-keys/sealing.ts:rotateRecordCek` (re-seal under a new CEK).\n *\n * These are pure helpers over an explicit `(cek, dek)` pair — NOT a context\n * object — so `sealing.ts` (which holds only the DEK) can import them without\n * pulling in the whole codec, avoiding a codec↔sealing dependency cycle.\n */\nimport type { CapsulePrimitives } from '../contract.js'\n\n/** Parse an `iv:data` sealed slot (split on the FIRST `:`). Cipher-free, so it\n * needs no primitives and stays a plain module-level export. */\nexport function parseSealedSlot(blob: string): { iv: string; data: string } {\n const sep = blob.indexOf(':')\n return { iv: blob.slice(0, sep), data: blob.slice(sep + 1) }\n}\n\nexport function makeSealedSlot(p: CapsulePrimitives) {\n const { decrypt, deriveSealedFieldKey, deriveSealedFieldKeyFromCek } = p\n\n/**\n * Dual-read: decrypt a sealed slot trying the CEK-derived field key first,\n * falling back to the collection-DEK field key. Legacy records\n * (even ones whose body is CEK-encrypted) are sealed under the collection-DEK\n * key; current writes seal under the per-record CEK. Try the CEK key first; on\n * its AES-GCM auth failure, fall back to the DEK key. Throws only if BOTH fail.\n * Returns the plaintext string (callers `JSON.parse` as needed).\n */\n async function dualReadSealedSlot(\n blob: string,\n field: string,\n collection: string,\n cek: CryptoKey | undefined,\n dek: CryptoKey,\n): Promise<string> {\n const { iv, data } = parseSealedSlot(blob)\n if (cek !== undefined) {\n try {\n const fieldKey = await deriveSealedFieldKeyFromCek(cek, collection, field)\n return await decrypt(iv, data, fieldKey)\n } catch {\n // fall through to the legacy collection-DEK derivation\n }\n }\n const fieldKey = await deriveSealedFieldKey(dek, collection, field)\n return decrypt(iv, data, fieldKey)\n}\n\n return { dualReadSealedSlot }\n}\n","/**\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 '../../kernel/types.js'\nimport type { EncryptedEnvelope } from '../../kernel/types.js'\nimport type { RecordIdentity } from './record-aad.js'\nimport { requireSealedBody } from './envelope-body.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 // #15: `seal` returns the widened `Pick<Envelope, …>`, so both fields are\n // optional at the type level. A sealer that returned neither has not sealed\n // anything, and building a record envelope around that would persist a row\n // whose body silently became `''`. Refuse instead.\n const { iv, data } = requireSealedBody(sealed, 'buildSealedRecordEnvelope')\n return buildRecordEnvelope(identity, {\n ...body,\n iv,\n 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 '../../kernel/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","/**\n * Standard Schema v1 integration.\n *\n * This file is the entry point for **schema validation**. Any\n * validator that implements the [Standard Schema v1\n * protocol](https://standardschema.dev) — Zod, Valibot, ArkType, Effect\n * Schema, etc. — can be attached to a `Collection` or `defineNoydbStore`\n * and will:\n *\n * 1. Validate the record BEFORE encryption on `put()` — bad data is\n * rejected at the store boundary with a rich issue list.\n * 2. Validate the record AFTER decryption on `get()`/`list()`/`query()`\n * — stored data that has drifted from the current schema throws\n * loudly instead of silently propagating garbage to the UI.\n *\n * ## Why vendor the types?\n *\n * Standard Schema is a protocol, not a library. The spec is <200 lines of\n * TypeScript and has no runtime. There's an official `@standard-schema/spec`\n * types package on npm, but pulling it in would add a dependency edge\n * purely for type definitions. Vendoring the minimal surface keeps\n * `@noy-db/core` at **zero runtime dependencies** and gives us freedom to\n * evolve the helpers without a version-lock on the spec package.\n *\n * If the spec changes in a breaking way (unlikely — it's frozen at v1),\n * we update this file and bump our minor.\n *\n * ## Why not just run `schema.parse(value)` directly?\n *\n * Because then we'd be locked to whichever validator happens to have\n * `.parse`. Standard Schema's `'~standard'.validate` contract is the same\n * across every implementation and includes a structured issues list,\n * which is much more useful than a thrown error for programmatic error\n * handling (e.g., rendering field-level messages in a Vue component).\n */\n\nimport { SchemaValidationError } from './errors.js'\n\n/**\n * The Standard Schema v1 protocol. A schema is any object that exposes a\n * `'~standard'` property with `version: 1` and a `validate` function.\n *\n * The type parameters are:\n * - `Input` — the type accepted by `validate` (what the user passes in)\n * - `Output` — the type produced by `validate` (what we store/return,\n * may differ from Input if the schema transforms or coerces)\n *\n * In most cases `Input === Output`, but validators that transform\n * (Zod's `.transform`, Valibot's `transform`, etc.) can narrow or widen.\n *\n * We intentionally keep the `types` field `readonly` and optional — the\n * spec marks it as optional because it's only used for inference, and\n * not every implementation bothers populating it at runtime.\n */\nexport interface StandardSchemaV1<Input = unknown, Output = Input> {\n readonly '~standard': {\n readonly version: 1\n readonly vendor: string\n readonly validate: (\n value: unknown,\n ) =>\n | StandardSchemaV1SyncResult<Output>\n | Promise<StandardSchemaV1SyncResult<Output>>\n readonly types?:\n | {\n readonly input: Input\n readonly output: Output\n }\n | undefined\n }\n}\n\n/**\n * The result of a single call to `schema['~standard'].validate`. Either\n * `{ value }` on success or `{ issues }` on failure — never both.\n *\n * The spec allows `issues` to be undefined on success (and some\n * validators leave it that way), so consumers should discriminate on\n * `issues?.length` rather than on truthiness of `value`.\n */\nexport type StandardSchemaV1SyncResult<Output> =\n | { readonly value: Output; readonly issues?: undefined }\n | {\n readonly value?: undefined\n readonly issues: readonly StandardSchemaV1Issue[]\n }\n\n/**\n * A single validation issue. The `message` is always present; the `path`\n * is optional and points at the offending field when the schema tracks\n * it (virtually every validator does for object types).\n *\n * The path is deliberately permissive — both a plain `PropertyKey` and a\n * `{ key }` wrapper are allowed so validators that wrap path segments in\n * objects (Zod does this in some modes) don't need special handling.\n */\nexport interface StandardSchemaV1Issue {\n readonly message: string\n readonly path?:\n | ReadonlyArray<PropertyKey | { readonly key: PropertyKey }>\n | undefined\n}\n\n/**\n * Infer the output type of a Standard Schema. Consumers use this to\n * pull the type out of a schema instance when they want to declare a\n * Collection<T> or defineNoydbStore<T> with `T` derived from the schema.\n *\n * Example:\n * ```ts\n * const InvoiceSchema = z.object({ id: z.string(), amount: z.number() })\n * type Invoice = InferOutput<typeof InvoiceSchema>\n * ```\n */\nexport type InferOutput<T extends StandardSchemaV1> =\n T extends StandardSchemaV1<unknown, infer O> ? O : never\n\n/**\n * Validate an input value against a schema. Throws\n * `SchemaValidationError` if the schema rejects, with the rich issue\n * list attached. Otherwise returns the (possibly transformed) output\n * value.\n *\n * The `context` string is included in the thrown error's message so the\n * caller knows where the failure happened (e.g. `\"put(inv-001)\"`) without\n * every caller having to wrap the throw in a try/catch.\n *\n * This function is ALWAYS async because some validators (notably Effect\n * Schema and Zod's `.refine` with async predicates) can return a\n * Promise. We `await` the result unconditionally to normalize the\n * contract — the extra microtask is free compared to the cost of an\n * encrypt/decrypt round-trip.\n */\nexport async function validateSchemaInput<Output>(\n schema: StandardSchemaV1<unknown, Output>,\n value: unknown,\n context: string,\n): Promise<Output> {\n const result = await schema['~standard'].validate(value)\n if (result.issues !== undefined && result.issues.length > 0) {\n throw new SchemaValidationError(\n `Schema validation failed on ${context}: ${summarizeIssues(result.issues)}`,\n result.issues,\n 'input',\n )\n }\n // Safe: the spec guarantees `value` is present when `issues` is absent.\n return result.value as Output\n}\n\n/**\n * Validate an already-stored value coming OUT of the collection. This\n * is a distinct helper from `validateSchemaInput` because the error\n * semantics differ: an output-validation failure means the data in\n * storage has drifted from the current schema (an unexpected state),\n * whereas an input-validation failure means the user passed bad data\n * (an expected state for a UI that isn't guarding its inputs).\n *\n * We still throw — silently returning bad data would be worse — but\n * the error carries `direction: 'output'` so upstream code (and a\n * potential migrate hook) can distinguish the two cases.\n */\nexport async function validateSchemaOutput<Output>(\n schema: StandardSchemaV1<unknown, Output>,\n value: unknown,\n context: string,\n): Promise<Output> {\n const result = await schema['~standard'].validate(value)\n if (result.issues !== undefined && result.issues.length > 0) {\n throw new SchemaValidationError(\n `Stored data for ${context} does not match the current schema — ` +\n `schema drift? ${summarizeIssues(result.issues)}`,\n result.issues,\n 'output',\n )\n }\n return result.value as Output\n}\n\n/**\n * Produce a short human-readable summary of an issue list for the\n * thrown error's message. The full issue array is still attached to the\n * error as a property — this is only for the `.message` string that\n * shows up in console.error / stack traces.\n *\n * Format: `field: message; field2: message2` (up to 3 issues, then `…`).\n * Issues without a path are shown as `root: message`.\n */\nfunction summarizeIssues(\n issues: readonly StandardSchemaV1Issue[],\n): string {\n const shown = issues.slice(0, 3).map((issue) => {\n const pathStr = formatPath(issue.path)\n return `${pathStr}: ${issue.message}`\n })\n const suffix = issues.length > 3 ? ` (+${issues.length - 3} more)` : ''\n return shown.join('; ') + suffix\n}\n\nfunction formatPath(\n path: StandardSchemaV1Issue['path'],\n): string {\n if (!path || path.length === 0) return 'root'\n return path\n .map((segment) =>\n typeof segment === 'object' && segment !== null\n ? String(segment.key)\n : String(segment),\n )\n .join('.')\n}\n","/**\n * Sealed-slot sub-step — the \"seal these declared fields into their own\n * `iv:data` slots\" mechanism, extracted byte-parity from `RecordCodec`\n * (#629 Task 1; see `.superpowers/sdd/seam-map-classified-blobs.md` §2).\n *\n * This is the ONE genuinely separable sub-step `RecordCodec.encryptRecord`/\n * `decryptRecord` perform (the digest-only `_vdig`/`_bidx` mechanism is NOT\n * separable the same way — it needs write-history `prev` context, see the\n * seam map's separability verdict). `sealFields`/`unsealFields` are the\n * natural shape of a `via` `encodeAtRest`/`decodeAtRest` hook for a \"seal\n * this field\" via-feature, and `makeSealedSlotCapability`/\n * `makeReservedEnvelopes` (below) are the `ViaCryptoCtx` capability\n * factories built on top of them.\n *\n * The capability factories live here (rather than a sibling\n * `kernel/via-crypto.ts`) so they can call `deriveSealedFieldKey`/\n * `deriveSealedFieldKeyFromCek`/`encrypt`/`decrypt` directly — this file IS\n * kernel enclave code (C3), so it is exempt from `enclave-barrel-only` the\n * same way `record-codec.ts`/`sealing.ts` are. A file outside\n * `capsule/enclave-aes/**` would have had to go through the enclave barrel\n * (`capsule/enclave-aes/index.ts`), which does not (yet) export these symbols.\n */\nimport { buildRecordEnvelope } from './record-envelope.js'\nimport { buildRecordAad, recordAadFor } from './record-aad.js'\nimport { SealedHandle, type EncryptedEnvelope } from '../../kernel/types.js'\nimport { ValidationError } from '../../kernel/errors.js'\nimport type { SealedSlotRef, ViaCryptoCtx } from '../../kernel/via/index.js'\nimport { sealedBodyArgs } from './envelope-body.js'\n\n/**\n * Key material for one collection's sealed-field derivation. `cek`, when\n * supplied, is preferred (record-scoped); `getDEK` is the fallback (and,\n * for legacy/no-CEK collections, the only key) — mirrors the dual-read\n * `RecordCodec` has always done.\n */\nimport type { CapsuleKey, CapsulePrimitives } from '../contract.js'\n\nexport interface SealKeyMaterial {\n readonly collection: string\n readonly cek?: CapsuleKey\n getDEK(): Promise<CapsuleKey>\n}\n\nexport interface SealFieldsResult {\n readonly openRecord: Record<string, unknown>\n readonly sealed: Record<string, string> | undefined\n}\n\n/** What {@link makeSealedSlotCapability} needs — a subset of `RecordCodecContext`. */\nexport interface SealedSlotCapabilityCtx {\n readonly name: string\n getDEK(): Promise<CapsuleKey>\n}\n\n/** Resolve the DEK for an arbitrary (possibly synthetic, e.g. `_dict_en`) collection name. */\nexport type ReservedEnvelopeDekResolver = (collection: string) => Promise<CapsuleKey>\n\nexport function makeSealedSlots(p: CapsulePrimitives, sealedSlot: { dualReadSealedSlot: (blob: string, field: string, collection: string, cek: CapsuleKey | undefined, dek: CapsuleKey) => Promise<string> }) {\n const { decrypt, deriveSealedFieldKey, deriveSealedFieldKeyFromCek, encrypt } = p\n const { dualReadSealedSlot } = sealedSlot\n\n /** Seal one field's value to an `iv:data` slot under its derived per-field key. */\n async function sealOneFieldWithDek(\n field: string,\n value: unknown,\n dek: CapsuleKey,\n keyMaterial: SealKeyMaterial,\n ): Promise<SealedSlotRef> {\n const fieldKey = keyMaterial.cek !== undefined\n ? await deriveSealedFieldKeyFromCek(keyMaterial.cek, keyMaterial.collection, field)\n : await deriveSealedFieldKey(dek, keyMaterial.collection, field)\n return encrypt(JSON.stringify(value), fieldKey)\n }\n\n /**\n * Seal one field's value on demand — fetches the DEK itself. A singular\n * counterpart to {@link sealFields} for callers that seal one field at a\n * time rather than a whole record. Not exported — `makeSealedSlotCapability`\n * is the only caller (#629 Task 11: knip-flagged unused export, dropped;\n * intra-module use only).\n */\n async function sealOneField(\n field: string,\n value: unknown,\n keyMaterial: SealKeyMaterial,\n ): Promise<SealedSlotRef> {\n const dek = await keyMaterial.getDEK()\n return sealOneFieldWithDek(field, value, dek, keyMaterial)\n }\n\n /**\n * Peel declared `sensitiveFields` out of `record` BEFORE building `_data`,\n * sealing each into its own `iv:data` slot. Extracted byte-parity from\n * `RecordCodec.encryptRecord` step 2 (pre-#629 `record-codec.ts:261-288`).\n * Returns `record` untouched (and `sealed: undefined`) when no declared\n * field is present with a defined value — the envelope stays byte-identical\n * to legacy output, exactly as before.\n */\n async function sealFields(\n record: Record<string, unknown>,\n sensitiveFields: ReadonlySet<string>,\n keyMaterial: SealKeyMaterial,\n ): Promise<SealFieldsResult> {\n const dek = await keyMaterial.getDEK()\n const open: Record<string, unknown> = { ...record }\n const slots: Record<string, string> = {}\n for (const field of sensitiveFields) {\n if (!(field in record)) continue\n const value = record[field]\n if (value === undefined) continue\n const { iv, data } = await sealOneFieldWithDek(field, value, dek, keyMaterial)\n slots[field] = `${iv}:${data}`\n delete open[field]\n }\n if (Object.keys(slots).length === 0) return { openRecord: record, sealed: undefined }\n return { openRecord: open, sealed: slots }\n }\n\n /**\n * Unseal one `_sealed[field]` slot to its plaintext value: dual-read (try\n * the CEK-derived key, fall back to the DEK-derived key for legacy\n * records), AES-GCM-decrypt the `iv:data` blob, and JSON-parse the result.\n * Extracted byte-parity from `RecordCodec.unsealField`\n * (pre-#629 `record-codec.ts:485-493`).\n */\n async function unsealOneField(field: string, blob: string, keyMaterial: SealKeyMaterial): Promise<unknown> {\n const dek = await keyMaterial.getDEK()\n return JSON.parse(await dualReadSealedSlot(blob, field, keyMaterial.collection, keyMaterial.cek, dek))\n }\n\n /**\n * Build a non-leaking {@link SealedHandle} producer over sealed key\n * material: each call captures only the ciphertext `blob` and a closure to\n * {@link unsealOneField} — the plaintext is never stored on the handle, and\n * (crucially) the DEK is fetched lazily on `reveal()`, never at handle-\n * construction time. Extracted byte-parity from\n * `RecordCodec.makeSealedHandle` (pre-#629 `record-codec.ts:552-554`).\n */\n function makeHandleProducer(keyMaterial: SealKeyMaterial): (field: string, blob: string) => SealedHandle<unknown> {\n return (field, blob) => new SealedHandle(() => unsealOneField(field, blob, keyMaterial))\n }\n\n /**\n * Restore every `[field]: blob` entry in `sealed` onto `record` (mutated in\n * place, matching the original's mutate-then-return shape): eagerly unseal\n * to plaintext (`opts.asHandles` falsy) or wrap each in a\n * {@link SealedHandle} (`opts.asHandles: true`) so the plaintext is never\n * materialised. Extracted byte-parity from `RecordCodec.decryptRecord`'s\n * sealed-handle block (pre-#629 `record-codec.ts:615-623`).\n */\n async function unsealFields(\n record: Record<string, unknown>,\n sealed: Record<string, string>,\n keyMaterial: SealKeyMaterial,\n opts?: { asHandles?: boolean },\n ): Promise<Record<string, unknown>> {\n const makeHandle = opts?.asHandles === true ? makeHandleProducer(keyMaterial) : undefined\n for (const [field, blob] of Object.entries(sealed)) {\n record[field] = makeHandle !== undefined ? makeHandle(field, blob) : await unsealOneField(field, blob, keyMaterial)\n }\n return record\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // ViaCryptoCtx capability factories (#629 Task 1, second commit)\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Build a `ViaCryptoCtx.sealedSlots` capability pre-bound to one\n * `(collection, recordId)`. The key material (`cek`/DEK resolver) is closed\n * over and never placed on the returned object — `Object.keys`/\n * `Object.values` of the capability expose only the three methods, never a\n * key (zero-knowledge: capabilities never expose keys).\n *\n * `delete(field)` is **advisory and capability-instance-local, not real\n * erasure** — it has no store to reach and never will by itself: it just\n * adds `field` to a `Set` closed over by THIS ONE capability object, so a\n * later `unseal` call on that SAME object refuses. No I/O happens. A fresh\n * capability for the same record (e.g. `seal()`'d again, or a new\n * `makeSealedSlotCapability(...)` call) has an empty set and sees no\n * deletion at all — `seal()` on a given field also clears any prior mark\n * for it. Do not build production logic on `delete()` persisting anything.\n * The real erasure guarantee for a forgotten record is `vault.forget()`'s\n * unconditional `_writeTombstone` call, which replaces the whole live\n * envelope with a fresh, `_sealed`-free tombstone — `_sealed` disappears\n * from the store regardless of what any capability's `delete()` marked.\n * (#629 Task 10 traced this end-to-end; see task-10-report.md \"sealedSlots\n * .delete()\" section. Removing/changing this method's shape is a phase-E\n * decision, not implied by this comment.)\n */\n function makeSealedSlotCapability(\n ctx: SealedSlotCapabilityCtx,\n recordId: string,\n cek?: CapsuleKey,\n ): ViaCryptoCtx['sealedSlots'] {\n const keyMaterial: SealKeyMaterial = {\n collection: ctx.name,\n ...(cek !== undefined ? { cek } : {}),\n getDEK: () => ctx.getDEK(),\n }\n const deletedFields = new Set<string>()\n\n return {\n async seal(field, plaintext) {\n const ref = await sealOneField(field, plaintext, keyMaterial)\n deletedFields.delete(field)\n return ref\n },\n async unseal(field, ref) {\n if (deletedFields.has(field)) {\n throw new ValidationError(`sealedSlots.unseal: field \"${field}\" on record \"${recordId}\" was deleted from this capability`)\n }\n return unsealOneField(field, `${ref.iv}:${ref.data}`, keyMaterial)\n },\n async delete(field) {\n deletedFields.add(field)\n },\n }\n }\n\n /**\n * Build a `ViaCryptoCtx.reservedEnvelopes` capability: a whole-envelope\n * encrypt/decrypt door scoped to collection names under a declared prefix\n * (e.g. `_dict_`) — the shape `via/i18n/dictionary.ts`'s\n * `DictionaryHandle` needs (seam map Part 3): build JSON → encrypt under a\n * DEK → wrap in an `EncryptedEnvelope`; decrypt → JSON text. No per-record\n * CEK — reserved envelopes are whole-DEK-encrypted, same as the dictionary\n * grandfather.\n *\n * `reservedEnvelopes(prefix)` throws `ValidationError` immediately when\n * `prefix` is not in `declaredPrefixes`; each `encrypt`/`decrypt` call\n * throws `ValidationError` when its `collection` argument does not start\n * with `prefix`.\n */\n function makeReservedEnvelopes(\n dekResolver: ReservedEnvelopeDekResolver,\n declaredPrefixes: readonly string[],\n ): ViaCryptoCtx['reservedEnvelopes'] {\n const declared = new Set(declaredPrefixes)\n\n return (prefix: string) => {\n if (!declared.has(prefix)) {\n throw new ValidationError(`reservedEnvelopes: prefix \"${prefix}\" is not declared by this binding's reservedPrefixes`)\n }\n\n const assertPrefixed = (collection: string, method: 'encrypt' | 'decrypt'): void => {\n if (!collection.startsWith(prefix)) {\n throw new ValidationError(\n `reservedEnvelopes('${prefix}').${method}: collection \"${collection}\" does not start with \"${prefix}\"`,\n )\n }\n }\n\n const encryptForPrefix = async (\n ref: { readonly collection: string; readonly id: string; readonly by?: string },\n json: string,\n v: number,\n ): Promise<EncryptedEnvelope> => {\n assertPrefixed(ref.collection, 'encrypt')\n const dek = await dekResolver(ref.collection)\n // `v` folds INTO the identity — it is `_v`, which the AAD binds, so the\n // version sealed and the version stamped come from one object (#1093).\n const identity = { ...ref, version: v }\n // `by` is part of the identity, so it is SEALED here and stamped by\n // `buildRecordEnvelope` from the same source. A caller that added `_by`\n // to the returned envelope afterwards would produce a record whose AAD\n // no reader can reproduce — which is exactly what via/lookup did (#1041).\n const { iv, data } = await encrypt(json, dek, buildRecordAad(identity))\n return buildRecordEnvelope(identity, { iv, data })\n }\n\n const decryptForPrefix = async (collection: string, id: string, env: EncryptedEnvelope): Promise<string> => {\n assertPrefixed(collection, 'decrypt')\n const dek = await dekResolver(collection)\n return decrypt(...sealedBodyArgs(env, 'openSealedSlots'), dek, recordAadFor({ collection, id }, env))\n }\n\n return { encrypt: encryptForPrefix, decrypt: decryptForPrefix }\n }\n }\n\n return { sealFields, unsealOneField, makeHandleProducer, unsealFields, makeSealedSlotCapability, makeReservedEnvelopes }\n}\n","/**\n * RecordCodec — the per-record envelope build + encrypt/decrypt + per-record-CEK\n * + sealed-field crypto.\n *\n * `Collection` holds one `RecordCodec` instance and delegates the crypto write\n * path (`encryptRecord` / `encryptJsonString` / `buildDebugEnvelope`), the read\n * path (`decryptRecord` / `decryptJsonString` / `resolveEnvelopeCek`), and the\n * sealed-field helpers (`unsealField` / `makeSealedHandle` / `toCacheRecord` /\n * `classifySealedShred`) to it. The codec receives every `this.*` dependency\n * it needs via {@link RecordCodecContext}.\n *\n * The crux is `cekCache`: it is the SAME `Lru` reference `Collection` owns (not\n * a copy). `resolveEnvelopeCek` reads/writes it, and tier methods +\n * `vault.invalidateRecordCaches` keep mutating that same object — a copy would\n * silently break the \"single CEK delete kills the version chain\" invariant.\n *\n * Internal service — not exported as a `@noy-db/hub/*` subpath.\n */\nimport { NOYDB_FORMAT_VERSION, type EncryptedEnvelope, type CrdtMode, type CrdtState, type CrdtStrategy, type VdigFieldPolicy, type SealedHandle } from '../../kernel/types.js'\nimport { isTombstone, isDeleteMarker } from './tombstone.js'\nimport { parseSealedSlot } from './sealed-slot.js'\nimport { buildRecordEnvelope } from './record-envelope.js'\nimport { buildRecordAad, recordAadFor, type RecordIdentity, type RecordRef } from './record-aad.js'\nimport type { SealKeyMaterial } from './sealed-slots.js'\nimport { DebugReservedFieldError, ClassifiedConfigError, ValidationError } from '../../kernel/errors.js'\nimport { normalizeForVerify } from './normalize.js'\nimport { validateSchemaOutput, type StandardSchemaV1 } from '../../kernel/schema.js'\nimport type { Lru } from '../../kernel/cache/index.js'\nimport type { ViaCryptoCtx, SealedSlotRef } from '../../kernel/via/index.js'\nimport type { ViaPipeline } from '../../kernel/via/pipeline.js'\nimport { sealedBodyArgs } from './envelope-body.js'\n\n/**\n * One classified per-slot verdict from {@link RecordCodecBase.classifySealedShred}.\n * `shreddable` — CEK-only, tombstone makes it undecryptable. `dekResidue` —\n * collection-DEK-keyed, survives in synced/backup copies. The third class is\n * BOTH: a `_bidx` blind-index tag is live-dropped by the tombstone yet retained\n * under the surviving DEK in any pre-forget backup (honest dual accounting).\n */\nimport type { CapsuleKey, CapsulePrimitives } from '../contract.js'\nimport type { makeSealedSlots } from './sealed-slots.js'\n\nexport type SealedShredSlot = {\n readonly field: string\n readonly class: 'shreddable' | 'dekResidue' | 'live-shreddable+dekResidue-in-backups'\n}\n\n/**\n * The record codec, bound to a capsule.\n *\n * ⚠️ `RecordCodec` is a CLASS declared inside this factory, so the NAME is no\n * longer a module-level type. Hub names it in ~40 places as a type, which is\n * why `plumbing/index.ts` re-exports an `InstanceType<…>` alias under the same\n * name — the type keeps working unchanged for every existing consumer.\n */\n/** Everything the moving crypto methods touched on `this.*`, as a flat context. */\nexport interface RecordCodecContext<T> {\n /** Collection name — the crypto AAD scope and schema-error context. */\n readonly name: string\n /** Actor id stamped on `_by` (the collection's keyring.userId). */\n readonly actor: string\n /** False on plaintext collections — selects the no-ciphertext envelope branch. */\n readonly storeCiphertext: boolean\n /** keyring.debugPlaintext — debug-inline envelope on user collections. */\n readonly debugPlaintext: boolean\n /** Emit `_source`/`_sourceTs` provenance fields when a source is supplied. */\n readonly provenance: boolean\n /** Declared `sensitive` fields → sealed into `_sealed[field]`. */\n readonly sensitiveFields: ReadonlySet<string>\n /** Declared deterministic-index fields, or null. */\n readonly deterministicFields: ReadonlySet<string> | null\n /** Digest-only classified fields → verify policy (stage 2). Null when none. */\n readonly vdigFields: ReadonlyMap<string, VdigFieldPolicy> | null\n /**\n * C-A / R10 config-drift signal: the persisted `x-classified` marker's\n * declared digest-only field set (empty when the collection carries no\n * marker). Lazy, memoized (O(1) per handle after the first call). The R10\n * superset guard refuses whenever a field in this set is absent from\n * `vdigFields`. Consulted once per handle on any encrypted write path — the\n * cross-session, prev-free signal a fully-naive create has no `prev` for.\n * Undefined on codecs with no store access (direct-construction tests).\n */\n classifiedMarkerDigestOnly?(): Promise<readonly string[]>\n /** CRDT mode (decrypt resolves CrdtState→snapshot when set). */\n readonly crdtMode: CrdtMode | undefined\n /** CRDT strategy seam (resolveCrdtSnapshot). */\n readonly crdtStrategy: CrdtStrategy\n /** Output-schema validator, or undefined. */\n readonly schema: StandardSchemaV1<unknown, T> | undefined\n /**\n * Resolve a collection's DEK. Called with no argument for `this.name`'s\n * own DEK (every ordinary codec use); `viaCryptoCtx`'s `reservedEnvelopes`\n * door passes an explicit OTHER collection name (e.g. a reserved\n * `_dict_status` collection) so a binding's at-rest hook can address a\n * different collection's DEK without ever holding the resolver itself.\n */\n getDEK(collection?: string): Promise<CapsuleKey>\n /**\n * The collection's per-record CEK cache (SHARED reference, not a copy).\n * Ownership/lifetime stays on Collection; codec reads+writes it in\n * resolveEnvelopeCek exactly as the inline code did. `null` → no caching.\n */\n readonly cekCache: Lru<string, CapsuleKey> | null\n /**\n * Compiled Via pipeline (money, i18n, …), or undefined for a collection\n * with none declared. `encryptRecord`/`decryptRecord` consult\n * `via?.hasAtRestHooks` at the sealed-slot sub-step to choose between a\n * binding's `encodeAtRest`/`decodeAtRest` hooks and today's inline path.\n * The zero-via fast path (`via` undefined, or no binding declares an\n * at-rest hook) stays byte/behavior-identical (#629 Task 3).\n *\n * Mutable (not `readonly`, #638 Task 3): `Collection.via` can be\n * reassigned post-construction (the taint overlay, `via/graph-wiring.ts#\n * applyTaintOverlay`) — `RecordCodecBase.setVia` below keeps this in sync so\n * at-rest hooks read the LIVE pipeline, not a stale construction-time\n * snapshot.\n */\n via: ViaPipeline | undefined\n /**\n * Read-coverage observer (#1363), resolved once per Collection from\n * `strategies.coverage.observer(...)`. `undefined` for every un-opted-in\n * deployment AND for every collection the sensor does not account for, so\n * the decrypt path costs one `!== undefined` test.\n *\n * ⛔⛔ TELEMETRY, NOT A CONTROL: an insider holding the device and local keys\n * holds the DEK, so this observes an extraction it cannot prevent. It exists\n * to make one visible early, attributable and loud. It may never grow a\n * return value — a decrypt is not gated on it, and nothing here may refuse.\n */\n readonly onDecrypt?: ((id: string) => void) | undefined\n}\n\n/**\n * The codec's capsule-provided surface: the 15 primitives + sealed-slot helpers\n * its methods call.\n */\nexport type CapsuleBinding = CapsulePrimitives & ReturnType<typeof makeSealedSlots>\n\n/**\n * ⚠️ MODULE-LEVEL AND GENERIC ON PURPOSE. The obvious shape — declaring the\n * class inside `makeRecordCodec` and exporting `InstanceType<…>` — compiles and\n * silently DROPS `T`: `RecordCodec<Invoice>` degrades to `RecordCodec<unknown>`\n * at the six places hub parameterises it, turning typed records into `unknown`\n * with no error anywhere.\n *\n * The other way to keep `T` would be a hand-written `interface RecordCodec<T>`\n * that the class implements — i.e. a second declaration of 15 signatures that\n * nothing checks against the first. That is exactly the drift #16 was, so it\n * was not done twice. A base class has one declaration and cannot drift.\n */\nexport class RecordCodecBase<T> {\n constructor(\n protected readonly caps: CapsuleBinding,\n private readonly ctx: RecordCodecContext<T>,\n ) {}\n\n /**\n * @internal Update the live Via pipeline this codec's at-rest hooks read\n * (#638 Task 3) — called by `via/graph-wiring.ts#applyTaintOverlay` right\n * after it reassigns `Collection.via`, so `hasAtRestHooks`/`encodeAtRest`/\n * `decodeAtRest` see the newly-added `taint` binding instead of the\n * pipeline snapshot captured when this codec was constructed.\n */\n setVia(via: ViaPipeline | undefined): void {\n this.ctx.via = via\n }\n\n /** Sealed-slot key material for this codec's collection, for a given per-record CEK (or none). */\n private sealKeyMaterial(cek: CapsuleKey | undefined): SealKeyMaterial {\n return {\n collection: this.ctx.name,\n ...(cek !== undefined ? { cek } : {}),\n getDEK: () => this.ctx.getDEK(),\n }\n }\n\n /**\n * Build the `ViaCryptoCtx` handed to a binding's `encodeAtRest`/\n * `decodeAtRest` hook: `sealedSlots` pre-bound to `(this.ctx.name,\n * recordId)` — always threading `cek` when the caller has one, so the\n * capability's record-binding stays cryptographic rather than degrading\n * to collection-scope. `reservedEnvelopes`'s DEK resolver forwards its\n * `collection` argument straight to `this.ctx.getDEK` (#629 Task 4) — it\n * resolves the RESERVED collection's own DEK (e.g. `_dict_status`), never\n * `this.ctx.name`'s, matching `Vault.getDEK`'s per-collection-name\n * resolution (the same resolver `DictionaryHandle` used pre-cutover).\n */\n private viaCryptoCtx(recordId: string, cek: CapsuleKey | undefined): ViaCryptoCtx {\n const declaredPrefixes = this.ctx.via?.bindings.flatMap((b) => b.reservedPrefixes ?? []) ?? []\n return {\n sealedSlots: this.caps.makeSealedSlotCapability(this.ctx, recordId, cek),\n reservedEnvelopes: this.caps.makeReservedEnvelopes((collection) => this.ctx.getDEK(collection), declaredPrefixes),\n }\n }\n\n // ──────────────────────────────────────────────────────────────────────\n // Low-level literal builders\n // ──────────────────────────────────────────────────────────────────────\n\n /**\n * Assemble a canonical ciphertext body envelope literal from already-computed\n * parts. Pure, no crypto. Each call stamps its own `_ts` — provenance carries\n * a SEPARATE timestamp (computed by the caller), so the two never share one.\n */\n static buildEnvelope(identity: RecordIdentity, p: {\n iv: string\n data: string\n // No `by` — `_by` is stamped from `identity`, the single source (#1041).\n // It was declared here and silently ignored, which is exactly how a\n // dropped field hides.\n cek?: string\n provenance?: { source: string; sourceTs: string } | undefined\n extra?: Partial<Pick<EncryptedEnvelope, '_tier' | '_det' | '_sealed'>>\n }): EncryptedEnvelope {\n return buildRecordEnvelope(identity, p)\n }\n\n /** Plaintext (`_iv:''`) body envelope — the `!storeCiphertext` shape. */\n static buildPlaintextEnvelope(identity: RecordIdentity, p: {\n data: string\n provenance?: { source: string; sourceTs: string } | undefined\n }): EncryptedEnvelope {\n return buildRecordEnvelope(identity, { ...p, iv: '' })\n }\n\n // ──────────────────────────────────────────────────────────────────────\n // Write path\n // ──────────────────────────────────────────────────────────────────────\n\n /**\n * Build a debug-plaintext envelope: the record's own fields inlined as\n * top-level keys beside the reserved `_`-metadata, with `_debug: 1` and an\n * empty `_data`. Lets native store tooling read the record without\n * unwrapping. Only reached for user collections under `debugPlaintext`\n * (see {@link encryptRecord}). Rejects `_`-prefixed record fields, which\n * would collide with the reserved metadata namespace.\n */\n buildDebugEnvelope(id: string, record: T, version: number, source?: string, sourceTs?: string): EncryptedEnvelope {\n const rec = record as unknown as Record<string, unknown>\n for (const key of Object.keys(rec)) {\n if (key.startsWith('_')) throw new DebugReservedFieldError(this.ctx.name, key)\n }\n const base = buildRecordEnvelope(\n { collection: this.ctx.name, id, by: this.ctx.actor, version },\n {\n iv: '',\n data: '',\n \n ...(this.ctx.provenance && source !== undefined\n ? { provenance: { source, sourceTs: sourceTs ?? new Date().toISOString() } }\n : {}),\n },\n )\n // `_debug` and the inlined record fields are this envelope's own shape —\n // they are not part of the canonical constructor's contract.\n return { ...base, _debug: NOYDB_FORMAT_VERSION, ...rec } as unknown as EncryptedEnvelope\n }\n\n /**\n * Encrypt a JSON body into an envelope.\n *\n * When `cek` is supplied (per-record CEK collections), the body is\n * encrypted under the CEK and the CEK is AES-KW-wrapped under the\n * collection DEK and stamped on `_cek`. When `cek` is omitted, the legacy\n * path encrypts the body directly under the collection DEK — byte-identical\n * to pre-CEK behaviour, so non-adopting collections pay nothing.\n */\n /**\n * `ref` is the identity the envelope is sealed against, and it is **the\n * location the bytes are stored at** — not necessarily this codec's own\n * collection (#1051).\n *\n * That distinction was discovered here rather than assumed. Several callers\n * put the result somewhere else entirely: search's vector sidecar lands in\n * `_vec` under `encodeVecId(name, id)`, the lexical index under `_ft/<name>`,\n * indexing's entries under a synthetic `idxId`. A codec that supplied\n * `this.ctx.name` for those would seal them against a collection they are not\n * in, and once AAD binds identity every one of them would fail to verify.\n *\n * ⚠️ **`_history` is the open case, and it is #1041's to settle.** Snapshots\n * are produced with the LIVE record's identity here and then re-homed by\n * `saveHistory` into `_history/<historyId(collection,id,_v)>`. Both readings\n * are defensible — bind where it lives, or bind what it is a copy of — and\n * the choice must be made before AAD is switched on, not inferred from this\n * migration.\n */\n async encryptJsonString(\n ref: RecordRef,\n json: string,\n version: number,\n cek?: CapsuleKey,\n source?: string,\n sourceTs?: string,\n ): Promise<EncryptedEnvelope> {\n // No envelope may be sealed over a non-string plaintext (#1220).\n // `JSON.stringify(undefined)` is `undefined`, so a caller that passes an\n // undefined record seals over NOTHING: `_data` is a bare GCM tag over zero\n // ciphertext. The envelope is well-formed and correctly sealed, which is\n // why nothing downstream catches it — it reads back as `undefined` on the\n // cached path (measured; note that is off `get()`'s declared `T | null`,\n // so `rec === null` misses it too) and as a `SyntaxError` out of\n // `decryptRecord` on the hydrate path. Two failures that both point away\n // from the write that caused them, and neither is `null`, which is what a\n // genuinely absent id returns.\n // Stated on the OUTPUT condition so it holds for every caller, not just\n // the `put(record)` arity slip that surfaced it.\n if (typeof json !== 'string') {\n throw new TypeError(\n `record seal: plaintext must be a string for \"${String(ref.collection)}/${String(ref.id)}\", ` +\n `received ${String(json)} (${typeof json}). Sealing over an empty plaintext produces ` +\n `an envelope that is valid and undecodable.`,\n )\n }\n // `version` folds into the identity HERE rather than travelling beside it,\n // so what is sealed and what is stamped come from one object (#1093).\n const identity: RecordIdentity = { ...ref, version, by: this.ctx.actor }\n const provenance = this.ctx.provenance && source !== undefined\n ? { source, sourceTs: sourceTs ?? new Date().toISOString() }\n : undefined\n\n if (!this.ctx.storeCiphertext) {\n return RecordCodecBase.buildPlaintextEnvelope(identity, { data: json, provenance })\n }\n\n const dek = await this.ctx.getDEK()\n\n const aad = buildRecordAad(identity)\n\n if (cek !== undefined) {\n const { iv, data } = await this.caps.encrypt(json, cek, aad)\n const wrapped = await this.caps.wrapCek(cek, dek)\n return RecordCodecBase.buildEnvelope(identity, { iv, data, cek: wrapped, provenance })\n }\n\n const { iv, data } = await this.caps.encrypt(json, dek, aad)\n return RecordCodecBase.buildEnvelope(identity, { iv, data, provenance })\n }\n\n /**\n * `ref` is FIRST and required (#1051). It was previously a trailing optional\n * `id?: string`, which TypeScript cannot promote to required because it sits\n * after other optionals — so the migration would have needed an `id ?? ''`\n * fallback. That is exactly the silent default this issue exists to remove:\n * once identity is bound into the AEAD, every record written with an empty id\n * binds to the SAME identity and becomes interchangeable with the others.\n * An object, not a bare string, so a swap with `version`/`source` cannot\n * compile on the hottest write path. Carries the collection too — see\n * {@link encryptJsonString} for why the codec must not assume its own.\n */\n async encryptRecord(\n ref: RecordRef,\n record: T,\n version: number,\n cek?: CapsuleKey,\n source?: string,\n sourceTs?: string,\n vdig?: { readonly id: string; readonly prev: EncryptedEnvelope | null },\n ): Promise<EncryptedEnvelope> {\n const id = ref.id\n // Debug-plaintext: write user-collection records with their fields inlined\n // beside the envelope metadata so native store tools read them directly.\n // Internal (`_`-prefixed) collections keep the classic shape — some store\n // `_`-prefixed fields that the inline layout would collide with.\n if (!this.ctx.storeCiphertext && this.ctx.debugPlaintext && !this.ctx.name.startsWith('_')) {\n return this.buildDebugEnvelope(id, record, version, source, sourceTs)\n }\n\n // ── C-A / R10 config-drift guard (superset) ────────────────────────\n // A handle may write a classified collection only if its DECLARED\n // digest-only set is a SUPERSET of the collection's stored/marked\n // classified set. Any classified field this handle does NOT declare is a\n // field it cannot maintain: the `_vdig` loop below iterates only declared\n // fields, so an undeclared classified field is neither stripped nor tagged —\n // its value would be serialized into `_data` as DEK-recoverable plaintext\n // (the C-A leak), or its stored tag silently dropped. Fail loud.\n //\n // This subsumes the old naive-only guard (a fully-naive handle has an empty\n // declared set, so ANY stored classified field violates the superset) AND\n // closes the partial-handle door (declares Y, not X, over a record carrying\n // `_vdig[X]`/`_bidx[X]`): the narrow `vdigFields === null || size === 0`\n // gate skipped that entire case. The stored/marked set is the union of:\n // 1. the persisted `x-classified` marker's declared digest-only set\n // (cross-session, prev-free — the only signal a fully-naive create has);\n // 2. the keys the target `prev` already carries in `_vdig`/`_bidx` (the\n // overwrite arm; a classified-declaring handle DOES pass `prev`).\n // Only encrypted collections can be classified, so plaintext collections skip.\n if (this.ctx.storeCiphertext) {\n const declared = this.ctx.vdigFields\n const storedClassified = new Set<string>()\n if (vdig?.prev?._vdig) for (const k of Object.keys(vdig.prev._vdig)) storedClassified.add(k)\n if (vdig?.prev?._bidx) for (const k of Object.keys(vdig.prev._bidx)) storedClassified.add(k)\n if (this.ctx.classifiedMarkerDigestOnly !== undefined) {\n for (const k of await this.ctx.classifiedMarkerDigestOnly()) storedClassified.add(k)\n }\n let undeclared: string | undefined\n for (const field of storedClassified) {\n if (declared === null || !declared.has(field)) { undeclared = field; break }\n }\n if (undeclared !== undefined) {\n throw new ClassifiedConfigError(\n this.ctx.name,\n `this collection has classified digest-only field \"${undeclared}\" but this handle does not declare it — ` +\n 'refusing to write (would drop its tag or serialize the secret as plaintext)',\n )\n }\n }\n\n // Structural group-encryption: peel declared sensitive fields out\n // of the record BEFORE building `_data`, sealing each into its own\n // `_sealed[field]` slot under a per-field key. Default-off — with no\n // sensitive fields the open record is unchanged and no `_sealed` is\n // emitted, so the envelope stays byte-identical to legacy output.\n // A collection whose via pipeline declares at-rest hooks (#629 Task 3)\n // seals through THOSE instead — the inline `sensitiveFields` path and\n // the hook path are mutually exclusive per collection, gated on\n // `hasAtRestHooks` (the inline path now serves only the plain\n // `sensitive: [...]` collection option; since #629, `classifiedFields`-\n // declared fields seal through their own via-binding hook, and since\n // #638 so does any field the taint graph seals — `via/classified/\n // binding.ts` and `kernel/via/taint-binding.ts`, respectively). The\n // zero-via fast path (no `via`, or a pipeline with no at-rest hooks,\n // e.g. money-only) always takes the `else if` branch, unchanged.\n let openRecord = record\n let sealed: Record<string, string> | undefined\n if (this.ctx.storeCiphertext && this.ctx.via?.hasAtRestHooks) {\n // Was `id === undefined`, which #1051 made UNREACHABLE — `ref.id` is a\n // required `string` now, so the compiler asks the question instead. The\n // backstop is retargeted rather than deleted: an EMPTY id still gets\n // through, and it is the realistic hazard, not a hypothetical one. The\n // first draft of this very migration wrote `id ?? ''` to satisfy a\n // trailing-optional signature. Once identity is bound into the AEAD every\n // record written with `''` binds to the SAME identity and they become\n // mutually interchangeable — the failure would be silent at write time\n // and unrecoverable later.\n if (id === '') {\n throw new Error(\n `RecordCodecBase.encryptRecord: collection \"${this.ctx.name}\" has via at-rest hooks but this write ` +\n 'path supplied an empty record id (needed to scope the sealed-slot capability) — caller bug.',\n )\n }\n const src = record as unknown as Record<string, unknown>\n const result = await this.ctx.via.encodeAtRest(src, this.viaCryptoCtx(id, cek))\n openRecord = result.record as unknown as T\n if (result.sealed !== undefined) {\n sealed = {}\n for (const [field, ref] of Object.entries(result.sealed)) sealed[field] = `${ref.iv}:${ref.data}`\n }\n } else if (this.ctx.storeCiphertext && this.ctx.sensitiveFields.size > 0) {\n const src = record as unknown as Record<string, unknown>\n const result = await this.caps.sealFields(src, this.ctx.sensitiveFields, this.sealKeyMaterial(cek))\n if (result.sealed !== undefined) {\n sealed = result.sealed\n openRecord = result.openRecord as unknown as T\n }\n }\n\n // ── Digest-only classified fields (stage 2, C6) ────────────────────\n // Per field, exactly one of: carry-forward (absent) / rotate (string) /\n // clear (null) / loud error (anything else). Runs on a CLONE so the\n // caller's record object is never mutated.\n let vdigOut: Record<string, string> | undefined\n let bidxOutMap: Record<string, string> | undefined\n if (this.ctx.vdigFields !== null && this.ctx.vdigFields.size > 0 && this.ctx.storeCiphertext) {\n if (vdig === undefined) {\n throw new Error(\n `RecordCodecBase.encryptRecord: collection \"${this.ctx.name}\" declares digest-only classified ` +\n `fields but this write path supplied no { id, prev } context — it would silently destroy _vdig (C6). Caller bug.`,\n )\n }\n if (cek === undefined) {\n throw new Error(\n `RecordCodecBase.encryptRecord: digest-only fields require a per-record CEK (R1 invariant) — ` +\n `collection \"${this.ctx.name}\" wrote without one. Caller bug.`,\n )\n }\n const open: Record<string, unknown> = { ...(openRecord as unknown as Record<string, unknown>) }\n const out: Record<string, string> = {}\n // _bidx (blind-index equality tags) rides the SAME iteration as _vdig,\n // so the structural invariant _bidx[field] ⇒ _vdig[field] holds by\n // construction: a tag is only ever written where the _vdig slot is\n // written/carried. DEK is fetched lazily — only an equatable rotate needs it.\n const bidxOut: Record<string, string> = {}\n let bidxDek: CapsuleKey | undefined\n for (const [field, policy] of this.ctx.vdigFields) {\n const value = open[field]\n const prevBlob = vdig.prev?._vdig?.[field]\n if (vdig.prev?._sealed?.[field] !== undefined) {\n // R6 transition evidence: never silently delete recoverable\n // plaintext. Checked BEFORE the value-type dispatch so the\n // carry-forward (absent) and clear (null) branches refuse too —\n // both would otherwise drop the `_sealed` slot from the new\n // envelope, silently destroying the recoverable ciphertext.\n throw new ClassifiedConfigError(\n this.ctx.name,\n `field \"${field}\" carries a recoverable _sealed slot from a previous storage form — ` +\n `recoverable ↔ digest-only transitions are refused (R6); migrate explicitly`,\n )\n }\n if (value === undefined) {\n // 1. carry-forward: verbatim bytes (CEK version-stable, AAD _v-free;\n // byte-identity keeps the ledger payload hash deterministic).\n // I-3 monotonic carry: whenever the _vdig slot is carried, ALSO copy\n // prev._bidx[field] verbatim — regardless of THIS handle's equatable\n // knob. An unrelated put by a handle with equatable removed must not\n // drop another handle's tag (anti-flip-flop). If prev has no tag,\n // there is nothing to mint from (no plaintext) → stays uncovered.\n if (prevBlob !== undefined) {\n out[field] = prevBlob\n const prevTag = vdig.prev?._bidx?.[field]\n if (prevTag !== undefined) bidxOut[field] = prevTag\n }\n continue\n }\n if (value === null) {\n // 3. clear: the defined deletion short of forget().\n delete open[field]\n continue\n }\n if (typeof value !== 'string') {\n // 4. caller bug, fail-loud.\n throw new ValidationError(\n `digest-only classified field \"${field}\" in \"${this.ctx.name}\" must be a string (rotate) or null (clear), got ${typeof value}`,\n )\n }\n // 2. rotate: validate ran in the stage-1 write seam; digest + ring here.\n out[field] = await this.caps.mintVdigSlot(value, policy, prevBlob, cek, this.ctx.name, vdig.id, field)\n // _bidx branch 2: if this handle is equatable, mint a fresh tag through\n // the SAME normalization pipeline mintVdigSlot uses (normalizeForVerify)\n // — the tag provably equals computeBidxTarget for this value. If the\n // knob is OFF, emit nothing: the stale prev tag points at the now-\n // superseded value (carrying it would be wrong) and minting is disallowed\n // (knob off) → the tag is dropped. Confirm-by-verify keeps this sound.\n if (policy.equatable === true) {\n if (bidxDek === undefined) bidxDek = await this.ctx.getDEK()\n const normalized = normalizeForVerify(policy.normalize, value)\n bidxOut[field] = await this.caps.mintBidxTag(normalized, bidxDek, this.ctx.name, field)\n }\n delete open[field] // strip from _data — digest-only never persists plaintext\n }\n openRecord = open as unknown as T\n if (Object.keys(out).length > 0) vdigOut = out\n if (Object.keys(bidxOut).length > 0) bidxOutMap = bidxOut\n }\n\n const base = await this.encryptJsonString(ref, JSON.stringify(openRecord), version, cek, source, sourceTs)\n const withSealed = sealed ? { ...base, _sealed: sealed } : base\n const withVdig = vdigOut ? { ...withSealed, _vdig: vdigOut } : withSealed\n const withBidx = bidxOutMap ? { ...withVdig, _bidx: bidxOutMap } : withVdig\n if (!this.ctx.deterministicFields || !this.ctx.storeCiphertext) return withBidx\n\n // compute deterministic-ciphertext slots for every\n // declared field. Non-primitive values are JSON-stringified so\n // objects/arrays still dedupe on structural equality. Sealed fields are\n // excluded — they live only in `_sealed`, never the `_det` index.\n // L-1: `_det` encrypts under a dedicated HKDF-derived key (salt\n // `noydb-det`), never the raw DEK — the DEK's randomized-IV `_data`\n // regime and `_det`'s deterministic-IV regime must not share a key.\n const dek = await this.ctx.getDEK()\n const detKey = await this.caps.deriveDeterministicKey(dek)\n const rec = record as unknown as Record<string, unknown>\n const det: Record<string, string> = {}\n for (const field of this.ctx.deterministicFields) {\n if (this.ctx.sensitiveFields.has(field)) continue\n if (this.ctx.vdigFields?.has(field)) continue // I5: digest-only never equality-correlatable\n const value = rec[field]\n if (value === undefined || value === null) continue\n const plaintext = typeof value === 'string' ? value : JSON.stringify(value)\n const { iv, data } = await this.caps.encryptDeterministic(plaintext, detKey, `${this.ctx.name}/${field}`)\n det[field] = `${iv}:${data}`\n }\n if (Object.keys(det).length === 0) return withBidx\n return { ...withBidx, _det: det }\n }\n\n // ──────────────────────────────────────────────────────────────────────\n // Read path\n // ──────────────────────────────────────────────────────────────────────\n\n /**\n * Resolve the per-record CEK for a stored envelope, or `undefined` for a\n * legacy (`_cek`-absent) envelope. Unwraps `_cek` under the collection DEK and\n * memoises it in the CEK cache under `id` (when supplied) so repeated reads of\n * the same record skip the unwrap. Shared by the body-decrypt path\n * ({@link decryptJsonString}) and the sealed-field path ({@link decryptRecord}\n * / {@link toCacheRecord}) so both agree on the record's key.\n */\n async resolveEnvelopeCek(envelope: EncryptedEnvelope, id?: string): Promise<CapsuleKey | undefined> {\n if (envelope._cek === undefined) return undefined\n const cached = id !== undefined ? this.ctx.cekCache?.get(id) : undefined\n if (cached !== undefined) return cached\n const dek = await this.ctx.getDEK()\n const cek = await this.caps.unwrapCek(envelope._cek, dek)\n if (id !== undefined) this.ctx.cekCache?.set(id, cek, 1)\n return cek\n }\n\n /**\n * Low-level: decrypt an envelope and return the raw JSON string.\n *\n * `_cek` presence is the format discriminant (NOT `this.perRecordCek`),\n * so a mixed vault — and a recipient that never opted into\n * `perRecordKeys` — decrypts both legacy and CEK records:\n * - `_cek` present → unwrap the CEK under the collection DEK, decrypt the\n * body under the CEK (cache the unwrapped CEK so repeated reads skip it).\n * - `_cek` absent → legacy path, body decrypts directly under the\n * collection DEK.\n *\n * The optional `id` lets reads populate the CEK cache; it is omitted by\n * callers (history, conflict merge) that have only the envelope.\n */\n /**\n * `ref` must be the SAME identity the writer sealed against — which is the\n * storage address, not necessarily this codec's own collection. Search's\n * vector sidecar lives in `_vec`, its lexical index in `_ft`; passing\n * `this.ctx.name` for those would recompute the wrong AAD and fail to open a\n * perfectly good record (#1041).\n */\n async decryptJsonString(ref: RecordRef, envelope: EncryptedEnvelope): Promise<string | null> {\n const id = ref.id\n // RISK #1 (forget cascade): a shred tombstone carries `_data: ''` and no\n // `_cek`. Decrypting it would call `this.caps.decrypt('', '', dek)` → AES-GCM\n // OperationError → TamperedError. Return null so every read callsite\n // treats it as \"absent / skip\", matching how get()/list already drop\n // tombstones. Legacy plaintext collections (`!this.storeCiphertext`) legitimately\n // have empty `_iv`/`_data`, so `isTombstone` is false for them — preserved.\n if (isTombstone(envelope, this.ctx.storeCiphertext) || isDeleteMarker(envelope)) return null\n if (!this.ctx.storeCiphertext) {\n // Debug-plaintext layout: record fields were inlined as top-level keys\n // (see buildDebugEnvelope). Reconstruct the record from the non-`_`\n // keys. Self-describing via `_debug`, so a classic plaintext reader\n // handles debug-written envelopes too.\n if (envelope._debug !== undefined) {\n const rec: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(envelope)) {\n if (!key.startsWith('_')) rec[key] = value\n }\n return JSON.stringify(rec)\n }\n // #598: a real record never serializes to '' (JSON.stringify's floor is\n // '{}'), so an empty `_data` here is the sync engine's shape-only\n // tombstone (`isTombstoneShape` in team/sync.ts) landing on an\n // unencrypted collection, where the encryption-gated `isTombstone()`\n // check above doesn't fire. Treat it the same as an encrypted\n // tombstone: null, not a `JSON.parse('')` crash.\n // #15: an ABSENT `_data` lands in the same branch as an empty one —\n // both say \"no body\", and the tombstone reading above is what that\n // means on an unencrypted collection.\n const plain = envelope._data ?? ''\n return plain === '' ? null : plain\n }\n const aad = recordAadFor(ref, envelope)\n const cek = await this.resolveEnvelopeCek(envelope, id)\n const json = cek !== undefined\n ? await this.caps.decrypt(...sealedBodyArgs(envelope, 'RecordCodec'), cek, aad)\n : await this.caps.decrypt(...sealedBodyArgs(envelope, 'RecordCodec'), await this.ctx.getDEK(), aad)\n this.observeDecrypt(ref)\n return json\n }\n\n /**\n * Fire the read-coverage observer for a successful record decrypt (#1363).\n *\n * ⚠️ ONLY for this codec's OWN collection. `ref.collection` can be a storage\n * identity that is not the live collection — a history/version address, the\n * `_vec` vector sidecar, the `_ft` lexical index (#1041) — and their ids are\n * not this corpus's ids, so counting them would corrupt the very estimate\n * the sensor exists to produce. The cost is a deliberate UNDER-count: a\n * principal reading the corpus through its history sidecar is not accounted.\n * A sensor that under-counts is honest; one that inflates cries wolf and\n * gets turned off. Recorded rather than papered over.\n */\n private observeDecrypt(ref: RecordRef): void {\n const observe = this.ctx.onDecrypt\n if (observe === undefined || ref.collection !== this.ctx.name) return\n observe(ref.id)\n }\n\n /**\n * Unseal a single `_sealed[field]` slot to its plaintext value: derive the\n * per-field key off the collection DEK, AES-GCM-decrypt the `iv:data` blob,\n * and JSON-parse the result. Shared by both the inline-decrypt path and a\n * {@link Sealed} handle's `reveal()` — so the on-demand reveal and the eager\n * materialisation always agree byte-for-byte.\n */\n async unsealField(field: string, blob: string, cek?: CapsuleKey): Promise<unknown> {\n // Dual-read. Current writes seal under a key derived from the record's\n // per-record CEK; legacy records (even ones whose body is\n // CEK-encrypted) are sealed under the collection-DEK key. Try the CEK key\n // first; on its AES-GCM auth failure, fall back to the DEK key. Without this\n // fallback every legacy `_sealed` record would throw TamperedError (data loss).\n return this.caps.unsealOneField(field, blob, this.sealKeyMaterial(cek))\n }\n\n /**\n * Build the `ViaCryptoCtx` for forget()'s per-ref via-erase fold (#629\n * Task 10) — resolves the live envelope's CEK exactly like\n * `decryptRecord` does, then delegates to the same capability factory\n * `encodeAtRest`/`decodeAtRest` use.\n */\n async eraseCryptoCtx(id: string, live: EncryptedEnvelope): Promise<ViaCryptoCtx> {\n return this.viaCryptoCtx(id, await this.resolveEnvelopeCek(live, id))\n }\n\n /**\n * Classify a live envelope's `_sealed` slots for crypto-shred completeness.\n * `forget()` drops `_cek`/`_sealed` but\n * RETAINS the collection DEK, so only a slot keyed off the per-record CEK is\n * genuinely shredded by the tombstone; a legacy slot keyed off the\n * collection DEK survives in any synced/backup copy.\n *\n * Mirrors {@link unsealField}'s dual-read split: try the CEK-derived key per\n * slot — success → `shreddable`, AES-GCM auth failure → `dekResidue`. With no\n * `_cek` (pure legacy collection-DEK sealing) ALL slots are residue.\n */\n async classifySealedShred(\n live: EncryptedEnvelope,\n ): Promise<{ readonly slots: readonly SealedShredSlot[] }> {\n const slots: SealedShredSlot[] = []\n // Verify-digest slots are CEK-only by construction (I3): dropping `_cek`\n // makes every `_vdig[field]` permanently undecryptable — shreddable\n // unconditionally, no vdig-dekResidue class (spec §2 forget()). Same\n // honesty caveats as #306 D5 for synced/backup copies of the ciphertext.\n // A `_vdig` field ALSO carrying a `_bidx` tag is the third category: the\n // tombstone drops it from the live store, but a pre-forget backup retains\n // the blind-index tag under the surviving collection DEK — live-shreddable\n // yet dekResidue-in-backups. `_bidx[field] ⇒ _vdig[field]` (I4), so we\n // decide per vdig field and emit exactly one slot each (count-preserving).\n if (live._vdig !== undefined && live._cek !== undefined) {\n for (const field of Object.keys(live._vdig)) {\n slots.push({\n field,\n class: live._bidx?.[field] !== undefined\n ? 'live-shreddable+dekResidue-in-backups'\n : 'shreddable',\n })\n }\n }\n const sealed = live._sealed\n if (sealed === undefined) return { slots }\n const cek = await this.resolveEnvelopeCek(live)\n for (const [field, blob] of Object.entries(sealed)) {\n if (cek === undefined) { slots.push({ field, class: 'dekResidue' }); continue }\n const { iv, data } = parseSealedSlot(blob)\n try {\n await this.caps.decrypt(iv, data, await this.caps.deriveSealedFieldKeyFromCek(cek, this.ctx.name, field))\n slots.push({ field, class: 'shreddable' })\n } catch {\n slots.push({ field, class: 'dekResidue' })\n }\n }\n return { slots }\n }\n\n /**\n * Build a non-leaking {@link Sealed} handle over a sealed field's ciphertext.\n * The handle captures only the ciphertext `blob` and a closure to\n * {@link unsealField}; the plaintext is never stored on it — so the handle\n * may sit in the working-set cache (or be logged/serialised) without\n * exposing the value, which decrypts only on `reveal()`.\n */\n makeSealedHandle(field: string, blob: string, cek?: CapsuleKey): SealedHandle<unknown> {\n return this.caps.makeHandleProducer(this.sealKeyMaterial(cek))(field, blob)\n }\n\n /**\n * Replace every field the just-written envelope actually sealed with a\n * {@link Sealed} handle, leaving every other field as its plaintext value.\n * Used to populate the cache on the write path without ever materialising\n * sealed plaintext into it. Returns `record` untouched when nothing was\n * sealed. Keys off `envelope._sealed` itself (#642 fix) — NOT\n * `this.ctx.sensitiveFields`, which only names the inline `sensitive:[...]`/\n * classified-recoverable field set: a collection whose sealing comes\n * entirely from the `taint` via-binding (a derivation/MV output or rollup\n * target folded sealed from a classified SOURCE collection, #642) declares\n * no local `sensitiveFields` at all, so that stale gate skipped this\n * conversion and left a just-written taint-sealed field as cached\n * plaintext — read back correctly ONLY after a cold cache miss (`get()`'s\n * own `decodeAtRest` call, unaffected by this gate) forced a fresh decrypt.\n */\n async toCacheRecord(record: T, envelope: EncryptedEnvelope, id?: string): Promise<T> {\n const sealed = envelope._sealed\n if (sealed === undefined || !this.ctx.storeCiphertext) {\n return record\n }\n const cek = await this.resolveEnvelopeCek(envelope, id)\n const clone = { ...(record as unknown as Record<string, unknown>) }\n for (const [field, blob] of Object.entries(sealed)) {\n clone[field] = this.makeSealedHandle(field, blob, cek)\n }\n return clone as unknown as T\n }\n\n /**\n * Apply `_sealed`-slot post-processing to an ALREADY-DECRYPTED `record`:\n * restore each `_sealed[field]` blob inline (`sealedAsHandles` falsy) or\n * as an opaque {@link Sealed} handle (`sealedAsHandles: true`), routing\n * through a via pipeline's `decodeAtRest` hook when one is declared.\n * Extracted byte-parity from `decryptRecord`'s inline block (#635) so a\n * caller that resolves its OWN per-record CEK under a DIFFERENT DEK than\n * this codec's `this.ctx.getDEK()` — namely the tier>0 `getAtTier` leg in\n * `with-audit/tiers/index.ts`, whose `_cek` is wrapped under the TIER DEK,\n * not the collection DEK `decryptRecord`/`resolveEnvelopeCek` always\n * unwrap under — can still get correct sealed-slot handling without\n * routing its whole read through `decryptRecord` (which would resolve the\n * wrong DEK for it).\n *\n * Zero-knowledge: takes only the already-resolved per-record `cek` (or\n * `undefined` for a legacy/no-CEK record) — the same shape `makeSealedHandle`\n * already takes above. Never the keyring, never a raw DEK: the legacy\n * fallback key stays fully internal to `sealKeyMaterial`/`viaCryptoCtx`,\n * which close over THIS codec's own `getDEK` (permanently bound to\n * `this.ctx.name`'s tier-0 DEK at construction) — so even when called from\n * a tier>0 context, the legacy-fallback key resolution is correct: sealed\n * fields are always sealed under the CEK or the collection's tier-0 DEK,\n * never a tier DEK (tier writes don't seal fields; `_sealed` reaches a\n * tiered envelope only via a tier-0 write later elevated).\n */\n async applySealedSlots(\n record: T,\n sealed: Record<string, string>,\n cek: CapsuleKey | undefined,\n opts: { id?: string; sealedAsHandles?: boolean } = {},\n ): Promise<T> {\n if (this.ctx.via?.hasAtRestHooks) {\n // Retargeted from `=== undefined`, which #1041 made unreachable on the\n // read path too: `decryptRecord` now takes a required identity, so the\n // compiler asks that question. An EMPTY id can still get through, and it\n // would scope every record's sealed slots to the same capability.\n if (opts.id === undefined || opts.id === '') {\n throw new Error(\n `RecordCodecBase.decryptRecord: collection \"${this.ctx.name}\" has via at-rest hooks but this read ` +\n 'path supplied no record id (needed to scope the sealed-slot capability) — caller bug.',\n )\n }\n const sealedRefs: Record<string, SealedSlotRef> = {}\n for (const [field, blob] of Object.entries(sealed)) {\n const { iv, data } = parseSealedSlot(blob)\n sealedRefs[field] = { iv, data }\n }\n return await this.ctx.via.decodeAtRest(\n record as unknown as Record<string, unknown>,\n sealedRefs,\n this.viaCryptoCtx(opts.id, cek),\n { asHandles: opts.sealedAsHandles === true },\n ) as unknown as T\n }\n return await this.caps.unsealFields(\n record as unknown as Record<string, unknown>,\n sealed,\n this.sealKeyMaterial(cek),\n { asHandles: opts.sealedAsHandles === true },\n ) as unknown as T\n }\n\n /**\n * Decrypt an envelope under an EXPLICIT `dek` instead of this codec's own\n * `ctx.getDEK()` / cekCache resolution — for a from-tier>0 pre-move decode\n * (`with-audit/tiers/index.ts`'s `putAtTier`/`elevate`/`demote` sites,\n * #722 whole-branch review). Mirrors the manual unwrap-then-decrypt\n * `getAtTier`'s own tier>0 leg performs there (same primitives, same\n * `applySealedSlots` extraction point #635 built for exactly this caller).\n *\n * `decryptRecord` is tier-UNAWARE: `resolveEnvelopeCek` reads the cekCache\n * or falls back to `ctx.getDEK()` — this codec's DEFAULT (tier-0/\n * collection) DEK — never the envelope's OWN tier. That only happens to\n * decrypt a from-tier>0 envelope correctly when some other call in the\n * SAME op already primed the cekCache with this record's CEK (true for an\n * ordinary put()-then-elevate(0→1); NOT true for a `putAtTier`-origin\n * envelope, whose body is encrypted directly under its tier DEK with no\n * `_cek` ever minted, or a non-`perRecordKeys` collection, which has no\n * `_cek` at all) — those throw `TamperedError`. Decrypting under the\n * caller-resolved `dek` is correct regardless of cache state or\n * `perRecordKeys`.\n *\n * No CRDT resolution, no schema validation — same scope as `getAtTier`'s\n * tier>0 branch (the established precedent for a tier-aware read), which\n * skips both for the same reason: a tier>0 read is an internal/derived-\n * output-recompute path, not the public per-record read surface schema\n * validation guards.\n */\n async decryptRecordAtDek(ref: RecordRef, envelope: EncryptedEnvelope, dek: CapsuleKey): Promise<T | null> {\n const id = ref.id\n if (isTombstone(envelope, this.ctx.storeCiphertext) || isDeleteMarker(envelope)) return null\n let plaintext: string\n let cek: CapsuleKey | undefined\n const aad = recordAadFor(ref, envelope)\n if (envelope._cek !== undefined) {\n cek = await this.caps.unwrapCek(envelope._cek, dek)\n plaintext = await this.caps.decrypt(...sealedBodyArgs(envelope, 'RecordCodec'), cek, aad)\n } else {\n plaintext = await this.caps.decrypt(...sealedBodyArgs(envelope, 'RecordCodec'), dek, aad)\n }\n let record = JSON.parse(plaintext) as T\n if (envelope._sealed !== undefined && this.ctx.storeCiphertext) {\n record = await this.applySealedSlots(record, envelope._sealed, cek, { ...(id !== undefined ? { id } : {}), sealedAsHandles: true })\n }\n // The tier>0 side door bypasses decryptJsonString, so it must account for\n // itself (#1363). A read a sensor cannot see is a hole in the estimate.\n this.observeDecrypt(ref)\n return record\n }\n\n /**\n * Decrypt an envelope into a record of type `T`.\n *\n * When a schema is attached, the decrypted value is validated before\n * being returned. A divergence between the stored bytes and the\n * current schema throws `SchemaValidationError` with\n * `direction: 'output'` — silently returning drifted data would\n * propagate garbage into the UI and break the whole point of having\n * a schema.\n *\n * `skipValidation` exists for history reads: when calling\n * `getVersion()` the caller is explicitly asking for an old snapshot\n * that may predate a schema change, so validating it would be a\n * false positive. Every non-history read leaves this flag `false`.\n */\n async decryptRecord(\n ref: RecordRef,\n envelope: EncryptedEnvelope,\n opts: { skipValidation?: boolean; sealedAsHandles?: boolean } = {},\n ): Promise<T | null> {\n const json = await this.decryptJsonString(ref, envelope)\n // Tombstone (shredded record) → null, propagated from decryptJsonString.\n // Callers skip null exactly as they already skip a tombstone envelope.\n if (json === null) return null\n let parsed: unknown = JSON.parse(json)\n\n // CRDT resolution: if this collection is in CRDT mode, the\n // stored JSON is a CrdtState, not T directly. Resolve to the snapshot.\n if (this.ctx.crdtMode && parsed !== null && typeof parsed === 'object' && '_crdt' in parsed) {\n parsed = this.ctx.crdtStrategy.resolveCrdtSnapshot(parsed as CrdtState)\n }\n\n let record = parsed as T\n\n // Structural group-encryption + sealed access gate.\n // Each `_sealed[field]` slot is restored under its own per-field key.\n // `sealedAsHandles: false` (default — internal callers that compute on\n // real values) inline-decrypts to the plaintext value; `true` (the\n // public / cache path) yields an opaque {@link Sealed} handle so the\n // plaintext is never materialised into the working-set cache. A\n // collection whose via pipeline declares at-rest hooks (#629 Task 3)\n // decodes through THOSE instead of the inline dual-read below — the\n // zero-via fast path (no `via`, or a pipeline with no at-rest hooks)\n // always takes the `else` branch, unchanged.\n if (envelope._sealed !== undefined && this.ctx.storeCiphertext) {\n const sealedCek = await this.resolveEnvelopeCek(envelope, ref.id)\n record = await this.applySealedSlots(record, envelope._sealed, sealedCek, {\n id: ref.id,\n ...(opts.sealedAsHandles !== undefined ? { sealedAsHandles: opts.sealedAsHandles } : {}),\n })\n }\n\n // Skip output validation when sealed fields are returned as handles:\n // the record carries opaque `Sealed` handles in place of the declared\n // values, so a whole-record schema check would false-positive on them.\n // (The values were validated on input/write; the open fields are\n // unchanged from the validated body.) The inline-value path below still\n // validates fully.\n const sealedAsHandles = opts.sealedAsHandles === true && envelope._sealed !== undefined\n if (this.ctx.schema !== undefined && !opts.skipValidation && !sealedAsHandles) {\n // Context string deliberately avoids leaking the record id — the\n // envelope only carries the version, not the id (the id lives in\n // the adapter-side key). `<collection>@v<n>` is enough for the\n // developer to find the offending record.\n record = await validateSchemaOutput(\n this.ctx.schema,\n record,\n `${this.ctx.name}@v${envelope._v}`,\n )\n }\n\n return record\n }\n}\n\n\n/**\n * The capsule-bound codec constructor: same shape callers have always used\n * (`new RecordCodec(ctx)`), with the capsule already closed over.\n */\nexport type BoundRecordCodec =\n (new <T>(ctx: RecordCodecContext<T>) => RecordCodecBase<T>) &\n // The STATICS come along too. `buildPlaintextEnvelope` is called as\n // `RecordCodec.buildPlaintextEnvelope(...)` from outside the capsule, so a\n // bare construct signature silently drops it — `Omit<…, never>` keeps the\n // static side while discarding the base's own construct signature.\n Omit<typeof RecordCodecBase, never>\n\nexport function makeRecordCodec(p: CapsulePrimitives, slots: ReturnType<typeof makeSealedSlots>) {\n // One object, reached as `this.caps.*` from the base class. Destructuring the\n // names here would shadow nothing and be dead — the class closes over `caps`,\n // not over individual primitives.\n const caps: CapsuleBinding = { ...p, ...slots }\n\n\n\n // ⚠️ ANNOTATED, not inferred. Returning the class expression directly makes\n // it an ANONYMOUS class type in the emitted `.d.ts`, and TypeScript refuses\n // that for a class with protected members (TS4094). Naming the constructor\n // type keeps the declaration emittable and keeps `T` flowing to callers.\n const RecordCodec: BoundRecordCodec = class<T> extends RecordCodecBase<T> {\n constructor(ctx: RecordCodecContext<T>) {\n super(caps, ctx)\n }\n }\n\n return { RecordCodec }\n}\n","/**\n * Per-record CEK lifecycle helpers for the WRITE path.\n *\n * These are the collection-coupled CEK operations, lifted off `Collection`\n * behind narrow deps so the kernel file delegates instead of carrying the\n * crypto inline:\n *\n * - {@link resolveStableCek} — the stable-CEK rule: an update or history\n * snapshot reuses the record's existing CEK so a single CEK delete kills\n * the whole version chain; a genuine insert (or legacy record being\n * migrated) mints a fresh one.\n * - {@link rewrapBodyToDek} — move a record body's wrapping from one DEK to\n * another (tier elevate/demote, bundle re-key) WITHOUT changing the body\n * key: unwrap the CEK under the source DEK, re-encrypt the body under the\n * same CEK, re-wrap the CEK under the destination DEK. History-chain\n * identity is preserved because the body key never changes.\n *\n * Both are pure functions over their deps — the `cekCache` ownership stays on\n * the collection (its lifetime is tied to `load()`), so callers cache the\n * returned key themselves.\n */\nimport type { EncryptedEnvelope } from '../../kernel/types.js'\nimport { buildRecordAad, type RecordIdentity } from './record-aad.js'\nimport type { Lru } from '../../kernel/cache/index.js'\nimport { sealedBodyArgs } from './envelope-body.js'\n\n/** Dependencies {@link resolveStableCek} needs from its collection. */\nimport type { CapsuleKey, CapsulePrimitives } from '../contract.js'\n\nexport interface StableCekDeps {\n /** The collection's per-record CEK cache (`null` → no caching). */\n readonly cache: Lru<string, CapsuleKey> | null\n /** Read the record's live envelope (to recover an existing `_cek`). */\n getLive(id: string): Promise<EncryptedEnvelope | null>\n /** The DEK the CEK is wrapped under (the collection DEK on the normal path). */\n getDEK(): Promise<CapsuleKey>\n}\n\n/** Re-wrapped body bytes + the (optional) CEK to cache. */\nexport interface RewrappedBody {\n readonly _iv: string\n readonly _data: string\n /** Present iff the source envelope carried a CEK (per-record-key record). */\n readonly _cek?: string\n /** The body key when one exists, so the caller can cache it; `null` for a legacy record. */\n readonly cek: CapsuleKey | null\n}\n\nexport function makeLifecycle(p: CapsulePrimitives) {\n const { decrypt, encrypt, generateDEK, unwrapCek, wrapCek } = p\n\n /**\n * Resolve the stable CEK for a record on the write path. Caches the resolved\n * key under `id` so an update + its history snapshot share one CEK.\n */\n async function resolveStableCek(deps: StableCekDeps, id: string): Promise<CapsuleKey> {\n const cached = deps.cache?.get(id)\n if (cached) return cached\n\n const live = await deps.getLive(id)\n if (live?._cek !== undefined) {\n const cek = await unwrapCek(live._cek, await deps.getDEK())\n deps.cache?.set(id, cek, 1)\n return cek\n }\n\n const fresh = await generateDEK()\n deps.cache?.set(id, fresh, 1)\n return fresh\n }\n\n /**\n * Move a record body from `fromDek`/`from` to `toDek`/`to`.\n *\n * - Per-record-key record (`_cek` present): unwrap the CEK under `fromDek`,\n * re-encrypt the body under the SAME CEK, re-wrap the CEK under `toDek`. The\n * body key is unchanged → history-chain identity preserved.\n * - Legacy record (no `_cek`): decrypt under `fromDek`, re-encrypt under `toDek`\n * directly.\n *\n * ## Why it takes TWO identities (#1041)\n *\n * A rewrap is the one operation where the identity genuinely **changes**. A\n * tier move rewrites `_tier`; a history snapshot lands at a different\n * `(collection, id)` entirely. Since AAD binds both, the body must be opened\n * under the identity it currently has and re-sealed under the one it is moving\n * to. A single identity would be wrong for one end or the other.\n *\n * ⚠️ **This retires an optimisation, deliberately.** Callers used to compute\n * ONE rewrap and reuse the bytes for both a tier move's live write and its\n * `_history` snapshot (#728). Those now have different destination identities,\n * so they need different AAD and therefore different ciphertext — the same\n * bytes cannot satisfy both. Reusing one rewrap for two destinations is now a\n * silent corruption, not a saving: it produces a record that opens at one\n * address and not the other.\n */\n async function rewrapBodyToDek(\n from: RecordIdentity,\n to: RecordIdentity,\n envelope: Pick<EncryptedEnvelope, '_iv' | '_data' | '_cek' | '_tier' | '_by'>,\n fromDek: CapsuleKey,\n toDek: CapsuleKey,\n ): Promise<RewrappedBody> {\n const openAad = buildRecordAad(from)\n const sealAad = buildRecordAad(to)\n if (envelope._cek !== undefined) {\n const cek = await unwrapCek(envelope._cek, fromDek)\n const plaintext = await decrypt(...sealedBodyArgs(envelope, 'rewrapBodyToDek'), cek, openAad)\n const { iv, data } = await encrypt(plaintext, cek, sealAad)\n return { _iv: iv, _data: data, _cek: await wrapCek(cek, toDek), cek }\n }\n const plaintext = await decrypt(...sealedBodyArgs(envelope, 'rewrapBodyToDek'), fromDek, openAad)\n const { iv, data } = await encrypt(plaintext, toDek, sealAad)\n return { _iv: iv, _data: data, cek: null }\n }\n\n /**\n * Merge an ALREADY-rewrapped {@link RewrappedBody} into `envelope`, keeping\n * every field but the re-keyed body (`_iv`/`_data`/`_cek`) unchanged.\n *\n * Body-field access (`_iv`/`_data`/`_cek`) is sanctioned inside the enclave;\n * this lets callers outside it get back a ready-to-store envelope without\n * reading those fields themselves. Takes a body the caller has ALREADY\n * computed (vs. {@link rewrapEnvelope}, which also runs `rewrapBodyToDek`)\n * so a caller building a SECOND envelope from the same rewrap — a tier\n * move's live write AND its pre-move `_history` snapshot, #728 — pays the\n * unwrap/decrypt/encrypt/wrap crypto once, not twice.\n */\n function applyRewrappedBody(envelope: EncryptedEnvelope, body: RewrappedBody): EncryptedEnvelope {\n const next: EncryptedEnvelope = {\n ...envelope,\n _iv: body._iv,\n _data: body._data,\n ...(body._cek !== undefined ? { _cek: body._cek } : {}),\n }\n if (body._cek === undefined && envelope._cek !== undefined) {\n delete (next as { _cek?: string })._cek\n }\n return next\n }\n\n /**\n * Move a FULL stored envelope from `fromDek` to `toDek`, preserving every\n * field other than the re-keyed body (`_iv`/`_data`/`_cek`) unchanged.\n * Mirrors the spread-merge idiom `with-audit/tiers/index.ts`'s\n * `elevate()`/`demote()` use to apply `rewrapBodyToDek`'s result to the live\n * envelope, generalized to any envelope shape (history callers don't bump\n * `_v`/`_ts`/`_tier` the way a tier move does).\n */\n async function rewrapEnvelope(\n identity: RecordIdentity,\n envelope: EncryptedEnvelope,\n fromDek: CapsuleKey,\n toDek: CapsuleKey,\n ): Promise<EncryptedEnvelope> {\n // Identity is UNCHANGED here — this rewrap only moves the wrapping key\n // (history re-key after a rotation), never the record's address or tags. So\n // the same identity opens and re-seals (#1041).\n return applyRewrappedBody(envelope, await rewrapBodyToDek(identity, identity, envelope, fromDek, toDek))\n }\n\n /**\n * Is `envelope` ALREADY wrapped under `dek` (a per-record CEK wrapped under\n * `dek`, or — legacy, no `_cek` — the body itself decryptable under `dek`)?\n *\n * A toDek-first idempotency check for retry-safe rewrap loops (#712 crash\n * atomicity, `with-commit/history/history.ts`'s `rewrapHistory`): a crash\n * mid-rewrap can strand some entries already moved to `toDek` while others\n * remain under `fromDek`. Calling this with `toDek` before attempting the\n * `fromDek` rewrap lets the caller skip an already-migrated entry instead of\n * re-wrapping it (a re-wrap would be a correctness no-op but doubles as an\n * unnecessary write) — and, more importantly, tells a retry loop that this\n * entry needs no `fromDek` unwrap attempt at all, so a crash that landed some\n * entries under `toDek` doesn't wedge on those already-moved entries.\n *\n * AES-KW (CEK unwrap) and AES-GCM (direct decrypt) are both authenticated —\n * unwrap/decrypt under the wrong key throws, never silently returns garbage\n * — so a caught error here reliably means \"not wrapped under `dek`\", not a\n * corrupt envelope (a genuinely corrupt envelope also throws under the\n * correct key, but callers that reach this helper only do so as a\n * best-effort probe before their own decisive fromDek attempt, which still\n * surfaces real corruption).\n *\n * Body-field access (`_iv`/`_data`/`_cek`) is sanctioned inside the enclave —\n * this is the sanctioned door so callers outside it (history.ts) never read\n * those fields themselves, preserving the check-architecture body-access\n * ratchet.\n */\n async function isRewrappedUnder(\n identity: RecordIdentity,\n envelope: Pick<EncryptedEnvelope, '_iv' | '_data' | '_cek'>,\n dek: CapsuleKey,\n ): Promise<boolean> {\n try {\n if (envelope._cek !== undefined) {\n await unwrapCek(envelope._cek, dek)\n } else {\n // MUST pass AAD: without it this trial decrypt fails for every bound\n // record, the answer is always `false`, and the crash-idempotency skip\n // it exists to provide silently stops working (#1041).\n await decrypt(...sealedBodyArgs(envelope, 'rewrapBodyToDek'), dek, buildRecordAad(identity))\n }\n return true\n } catch {\n return false\n }\n }\n\n return { resolveStableCek, rewrapBodyToDek, applyRewrappedBody, rewrapEnvelope, isRewrappedUnder }\n}\n","/**\n * Re-key one envelope from an old collection DEK to a new one (#1074).\n *\n * Lives in the enclave because it is envelope surgery: it reads and writes the\n * protected body slots (`_iv`/`_data`/`_cek`), which `enclave-body-only`\n * reserves to `capsule/enclave-aes/**`. `rotateKeys` previously did this inline in\n * `with-party/team/keyring.ts` and got it wrong in two ways that the guard\n * would have caught had the code lived here.\n *\n * @packageDocumentation\n */\nimport { recordAadFor } from './record-aad.js'\nimport type { EncryptedEnvelope } from '../../kernel/types.js'\nimport { sealedBodyArgs } from './envelope-body.js'\n\n/**\n * Produce the envelope `envelope` becomes once its collection's DEK rotates\n * from `oldDek` to `newDek`.\n *\n * **Every slot is carried forward except `_bidx`.** The previous inline version\n * built a fresh literal holding only `_noydb/_v/_ts/_iv/_data`, silently\n * discarding `_by`, `_tier`, `_cek`, `_sealed`, `_vdig` and `_source`. Losing\n * `_tier` was the worst of those: tier-0 reads treat elevated as missing, so an\n * elevated record did not error after a rotation — it simply disappeared.\n *\n * `_bidx` is dropped deliberately. It is a DEK-rooted equality tag, so a tag\n * carried across a DEK rotation can never be re-derived to match a query again\n * while still leaking the old equality partition. Index coverage regrows\n * per-record on the next `put()` under the new DEK.\n *\n * Two shapes, and picking the wrong one is why this needed a helper:\n *\n * - **per-record CEK** (`_cek` present) — the body is sealed under the CEK and\n * the CEK is wrapped under the collection DEK, so rotation re-wraps the CEK\n * and leaves the body **untouched**. The old inline code instead ran\n * `decrypt(body, oldDek)` on these, which throws: rotation could not complete\n * on a collection containing any CEK record.\n * - **bare** — body sealed directly under the DEK, so decrypt and re-encrypt.\n *\n * Idempotence is the caller's problem, not this function's: it assumes\n * `envelope` is still under `oldDek`. A resumable rotation must know which side\n * of the migration each record is on before calling.\n */\nimport type { CapsuleKey, CapsulePrimitives } from '../contract.js'\n\nexport function makeRekey(p: CapsulePrimitives) {\n const { decrypt, encrypt, unwrapCek, wrapCek } = p\n\n async function rekeyEnvelopeToDek(\n ref: { readonly collection: string; readonly id: string },\n envelope: EncryptedEnvelope,\n oldDek: CapsuleKey,\n newDek: CapsuleKey,\n ): Promise<EncryptedEnvelope> {\n // A DEK rotation moves the WRAPPING key only — the record keeps its address\n // and its tags — so the same AAD opens and re-seals it (#1041).\n const aad = recordAadFor(ref, envelope)\n const { _bidx, ...carried } = envelope\n void _bidx // dropped deliberately — see above\n\n if (envelope._cek !== undefined) {\n const cek = await unwrapCek(envelope._cek, oldDek)\n return { ...carried, _cek: await wrapCek(cek, newDek) }\n }\n\n const plaintext = await decrypt(...sealedBodyArgs(envelope, 'rekeyRecord'), oldDek, aad)\n const { iv, data } = await encrypt(plaintext, newDek, aad)\n return { ...carried, _ts: new Date().toISOString(), _iv: iv, _data: data }\n }\n\n /**\n * Resumable variant: returns the re-keyed envelope, or `null` when `envelope`\n * is **already** under `newDek` and needs no work (#1074 part 2).\n *\n * A rotation interrupted mid-collection leaves records on both sides of the\n * migration. Resuming means re-running the rotation with the *same* new DEK,\n * which requires distinguishing \"not yet moved\" from \"already moved\" without\n * the caller touching protected slots.\n *\n * Detection is by trial decryption under `oldDek`. There is no metadata that\n * says which DEK sealed a record — deliberately, since such a marker would be\n * store-writable and therefore a downgrade lever (the same reasoning that\n * keeps the reader from branching on `_noydb`).\n *\n * A record that opens under *neither* key is genuinely damaged and rethrows,\n * rather than being silently skipped: a rotation that quietly walked past\n * unreadable records would convert a loud failure into permanent silent loss,\n * which is the defect this whole issue is about.\n */\n async function rekeyEnvelopeIfNeeded(\n ref: { readonly collection: string; readonly id: string },\n envelope: EncryptedEnvelope,\n oldDek: CapsuleKey,\n newDek: CapsuleKey,\n ): Promise<EncryptedEnvelope | null> {\n try {\n return await rekeyEnvelopeToDek(ref, envelope, oldDek, newDek)\n } catch (errUnderOld) {\n // Already migrated? Then it opens under the new DEK and there is nothing\n // to do. Verified rather than assumed.\n try {\n if (envelope._cek !== undefined) await unwrapCek(envelope._cek, newDek)\n else await decrypt(...sealedBodyArgs(envelope, 'rekeyRecord'), newDek, recordAadFor(ref, envelope))\n return null\n } catch {\n throw errUnderOld\n }\n }\n }\n\n /**\n * Does this envelope open under ANY of `keys`? A read-only probe — decrypts\n * nothing into a caller-visible value and writes nothing.\n *\n * Exists so a rotation can tell *\"this envelope belongs to a DIFFERENT DEK slot\n * the caller also holds\"* from *\"this envelope is damaged\"* (#1125). Those two\n * look identical from a failed `rekeyEnvelopeIfNeeded`, and collapsing them\n * either aborts a legitimate rotation or walks past unreadable data.\n *\n * **The question is deliberately asked of the KEY, not of the envelope's claimed\n * `_tier`.** `_tier` is unencrypted — the store writes it — so routing a\n * rotation on it would let a store mark a tier-0 record `_tier: 5` and have the\n * rotation skip it, leaving a revoked member's DEK live on real data. That is\n * #1115's defect wearing a different hat. A key either opens the body or it does\n * not, and a store cannot forge that.\n *\n * Mirrors `rekeyBlobSet`'s `otherDeks` treatment, which asks the same question\n * about the same kind of ambiguity.\n */\n async function envelopeOpensUnderAny(\n ref: { readonly collection: string; readonly id: string },\n envelope: EncryptedEnvelope,\n keys: readonly CapsuleKey[],\n ): Promise<boolean> {\n for (const key of keys) {\n try {\n if (envelope._cek !== undefined) await unwrapCek(envelope._cek, key)\n else await decrypt(...sealedBodyArgs(envelope, 'rekeyRecord'), key, recordAadFor(ref, envelope))\n return true\n } catch { /* not this key */ }\n }\n return false\n }\n\n return { rekeyEnvelopeToDek, rekeyEnvelopeIfNeeded, envelopeOpensUnderAny }\n}\n","/**\n * Re-key a vault's blob set from an old `_blob` DEK to a new one (#1122).\n *\n * ## The defect this closes\n *\n * `rotateKeys` re-keys `store.list(vault, <slot>)` plus the derived refs\n * `derivedRefsFor` declares. That assumes a DEK slot named `X` protects data\n * filed under collection `X`. For `_blob` it is false: the slot is `_blob`, but\n * every byte it protects lives in `_blob_index` and `_blob_chunks`. So rotating\n * `_blob` minted a fresh DEK, re-encrypted **nothing**, and made every blob in\n * the vault permanently unreadable — reported to the user as `TamperedError`,\n * i.e. as an attack, when it was self-inflicted. An ordinary `revoke` of a\n * whole-vault grantee reaches it, because such a grantee's DEK map contains\n * `_blob`.\n *\n * ## Why this cannot be done by `rekeyEnvelopeIfNeeded` alone\n *\n * Two of the three surfaces do not have the shape that helper assumes:\n *\n * - a **chunk** envelope is sealed over raw bytes under a bespoke AAD\n * (`{eTag}:{index}:{count}`), not under the record AAD, so the generic\n * helper cannot open it;\n * - an **index** envelope's body is JSON that may itself carry a wrapped\n * per-blob content CEK (`_cek` / `_cekPending`). Re-encrypting the body under\n * the new DEK without re-wrapping that CEK leaves a blob whose metadata opens\n * and whose bytes never will.\n *\n * ## Why it lives in the enclave\n *\n * It reads and writes protected body slots and it unwraps/re-wraps keys — the\n * two things `enclave-body-only` reserves to `capsule/enclave-aes/**`, and the same\n * reason `rekeyEnvelopeToDek` moved here in #1074. `with-party` orchestrates\n * the rotation and must not touch a body to do it.\n *\n * The blob layout below is duplicated from its owner rather than imported:\n * `with-shape/blobs/blob-set.ts` already imports `with-party/team/tiers.js`, so\n * a `with-party → with-shape` import would close a cycle, and the kernel may\n * not depend on a service. `BlobObject` itself is a kernel type, so only the\n * three collection/id string layouts are copied, with their owner named.\n *\n * @packageDocumentation\n */\nimport { recordAadFor } from './record-aad.js'\nimport type { BlobObject, EncryptedEnvelope, NoydbStore } from '../../kernel/types.js'\nimport { sealedBodyArgs } from './envelope-body.js'\n\n/** Blob metadata envelopes, keyed by eTag. owner: with-shape/blobs/blob-set.ts */\nimport type { CapsuleKey, CapsulePrimitives } from '../contract.js'\n\n/**\n * What a rotation did to the blob set.\n *\n * Deliberately NOT on the enclave barrel: no caller outside this module binds\n * it, and that surface is the fork-swap trust boundary, so exporting a type\n * nobody consumes is pure widening.\n *\n * It is a return value rather than a log line because `foreign` and `blobs`\n * are the only way to tell \"left alone, correctly\" from \"left alone, because\n * the caller passed a wrong `otherDeks` set\". Both re-key nothing and both\n * return successfully. `rotate-preserves-blobs.test.ts` asserts these counts\n * against a direct call for exactly that reason.\n */\nexport interface BlobRekeyReport {\n /** Index envelopes moved onto the new DEK. */\n readonly blobs: number\n /** Chunk envelopes re-encrypted under the new DEK. */\n readonly chunks: number\n /**\n * Index envelopes left alone because they open under a DEK the caller holds\n * for a DIFFERENT slot — an elevated blob, sealed under `_blob#<tier>`. Those\n * are that slot's rotation to do, not this one's.\n */\n readonly foreign: number\n /** Index envelopes already under the new DEK — a resumed rotation. */\n readonly alreadyMoved: number\n}\n\nexport function makeRekeyBlob(p: CapsulePrimitives) {\n const { decrypt, decryptBytesWithAAD, encrypt, encryptBytesWithAAD, unwrapCek, wrapCek } = p\n\n const BLOB_INDEX_COLLECTION = '_blob_index'\n /** Chunk envelopes, keyed by `{eTag}_{chunkIndex}`. owner: with-shape/blobs/blob-set.ts */\n const BLOB_CHUNKS_COLLECTION = '_blob_chunks'\n\n /**\n * Chunk integrity binding: `{eTag}:{chunkIndex}:{chunkCount}`.\n * Mirrors `chunkAAD` in `with-shape/blobs/blob-set.ts` — the same duplication\n * `with-cargo/extract-partition.ts` already carries, for the same reason.\n */\n function chunkAad(eTag: string, index: number, chunkCount: number): Uint8Array {\n return new TextEncoder().encode(`${eTag}:${index}:${chunkCount}`)\n }\n\n /** Did `key` open this envelope's JSON body? */\n async function opensJson(\n ref: { collection: string; id: string },\n env: EncryptedEnvelope,\n key: CapsuleKey,\n ): Promise<string | null> {\n try {\n return await decrypt(...sealedBodyArgs(env, 'rekeyBlob'), key, recordAadFor(ref, env))\n } catch {\n return null\n }\n }\n\n /**\n * Move every blob sealed under `oldDek` onto `newDek`.\n *\n * Chunks are re-encrypted BEFORE their index entry is re-sealed, and that order\n * is the resume property: an index entry still readable under `oldDek` means\n * its chunks may be half-moved (each one is probed individually), and an index\n * entry readable under `newDek` means its chunks are already done. An\n * interrupted rotation is finished by re-running it with the same `newDek`.\n *\n * `otherDeks` is what keeps a tier-elevated blob from being mistaken for a\n * damaged one. Membership in `_blob_index` is by DEK, not by collection name:\n * a record elevated to tier N has its blob metadata sealed under `_blob#N`. An\n * envelope that opens under NONE of the keys the caller holds is genuinely\n * unreadable and throws, exactly as `rekeyEnvelopeIfNeeded` does — silently\n * walking past it would turn a loud failure into permanent quiet loss.\n */\n async function rekeyBlobSet(\n adapter: NoydbStore,\n vault: string,\n oldDek: CapsuleKey,\n newDek: CapsuleKey,\n otherDeks: readonly CapsuleKey[] = [],\n ): Promise<BlobRekeyReport> {\n let blobs = 0\n let chunks = 0\n let foreign = 0\n let alreadyMoved = 0\n\n let eTags: string[]\n try {\n eTags = await adapter.list(vault, BLOB_INDEX_COLLECTION)\n } catch {\n return { blobs, chunks, foreign, alreadyMoved }\n }\n\n for (const eTag of eTags) {\n const idxEnv = await adapter.get(vault, BLOB_INDEX_COLLECTION, eTag)\n if (!idxEnv || !idxEnv._iv) continue // no sealed body — nothing to move\n\n const ref = { collection: BLOB_INDEX_COLLECTION, id: eTag }\n const json = await opensJson(ref, idxEnv, oldDek)\n if (json === null) {\n if ((await opensJson(ref, idxEnv, newDek)) !== null) { alreadyMoved++; continue }\n let claimed = false\n for (const key of otherDeks) {\n if ((await opensJson(ref, idxEnv, key)) !== null) { claimed = true; break }\n }\n if (claimed) { foreign++; continue }\n throw new Error(\n `[noy-db] rotateKeys: blob index entry \"${eTag}\" opens under neither the retiring `\n + 'nor the new `_blob` DEK, nor any other key this keyring holds. Rotation stopped '\n + 'rather than leaving it unreadable and unreported.',\n )\n }\n\n const blob = JSON.parse(json) as BlobObject\n\n // Chunks first. A legacy blob's bytes sit under the `_blob` DEK itself; an\n // erasable blob's sit under its per-blob content CEK and must NOT be\n // touched — re-wrapping that CEK below is the whole of its rotation. A\n // blob interrupted mid-`migrate()` is mixed, so every chunk is probed.\n for (let i = 0; i < blob.chunkCount; i++) {\n const id = `${eTag}_${i}`\n const chunkEnv = await adapter.get(vault, BLOB_CHUNKS_COLLECTION, id)\n if (!chunkEnv || !chunkEnv._iv) continue\n const aad = chunkAad(eTag, i, blob.chunkCount)\n let plain: Uint8Array\n try {\n plain = await decryptBytesWithAAD(...sealedBodyArgs(chunkEnv, 'rekeyBlob'), oldDek, aad)\n } catch {\n // A blob that holds a content CEK (settled or pending) keeps its bytes\n // under that CEK, not under the `_blob` DEK — re-wrapping the CEK below\n // is the whole of its rotation, and a chunk that refuses `oldDek` is\n // simply one of those. Nothing to do, and nothing suspicious.\n if (blob._cek !== undefined || blob._cekPending !== undefined) continue\n // Otherwise the blob is legacy: every one of its chunks MUST be under a\n // `_blob` DEK. `newDek` means a previous run already moved this one —\n // verified, not assumed. Neither key means the chunk is damaged, and it\n // throws for the same reason `rekeyEnvelopeIfNeeded` does: the index\n // entry opened fine under `oldDek` and says nothing about its chunks, so\n // continuing here would walk past unreadable data and report success.\n try {\n await decryptBytesWithAAD(...sealedBodyArgs(chunkEnv, 'rekeyBlob'), newDek, aad)\n continue\n } catch {\n throw new Error(\n `[noy-db] rotateKeys: blob chunk \"${id}\" (${i + 1}/${blob.chunkCount} of eTag `\n + `\"${eTag}\") opens under neither the retiring nor the new \\`_blob\\` DEK, and its `\n + 'blob holds no content CEK that could explain it. Rotation stopped rather than '\n + 'leaving it unreadable and unreported.',\n )\n }\n }\n const { iv, data } = await encryptBytesWithAAD(plain, newDek, aad)\n await adapter.put(vault, BLOB_CHUNKS_COLLECTION, id, { ...chunkEnv, _iv: iv, _data: data })\n chunks++\n }\n\n // The wrapped content CEKs travel with the metadata: they are wrapped under\n // the `_blob` DEK, so a rotation that re-encrypted the body and left them\n // alone would produce metadata that opens and bytes that never do.\n const rewrapped: BlobObject = {\n ...blob,\n ...(blob._cek !== undefined\n ? { _cek: await wrapCek(await unwrapCek(blob._cek, oldDek), newDek) }\n : {}),\n ...(blob._cekPending !== undefined\n ? { _cekPending: await wrapCek(await unwrapCek(blob._cekPending, oldDek), newDek) }\n : {}),\n }\n\n const { iv, data } = await encrypt(JSON.stringify(rewrapped), newDek, recordAadFor(ref, idxEnv))\n await adapter.put(vault, BLOB_INDEX_COLLECTION, eTag, { ...idxEnv, _iv: iv, _data: data })\n blobs++\n }\n\n return { blobs, chunks, foreign, alreadyMoved }\n }\n\n return { rekeyBlobSet }\n}\n","/**\n * Record-scoped CEK sealing — grantor side.\n *\n * The **grantor** holds the collection DEK and seals ONE record's CEK to an\n * `at-*` host so that host — and only that host — can decrypt exactly that\n * record, with no access to the vault DEK and no ability to read any other\n * record. This is the counterpart to the host-side `openSealedRecord`\n * (`@noy-db/hub/sealed-record`), which holds no DEK.\n *\n * These functions are the orchestration behind `vault.sealRecordToHost` /\n * `vault.revokeSealedRecord` / `vault.rotateRecordCek`, lifted off `Vault`\n * behind a narrow {@link SealingContext} so the kernel file delegates. They\n * live in `record-keys/` (the vault-side CEK policy layer), NOT in\n * `sealed-record/`, so the host-side subpath stays DEK-free — the wire\n * *types* they share are spine-owned (`kernel/types.ts`), not imported from\n * `sealed-record/` directly.\n */\nimport { buildRecordAad, recordAadFor, type RecordIdentity } from './record-aad.js'\nimport {\n type EncryptedEnvelope,\n type NoydbStore,\n type RecipientSealer,\n type SealedCekBinding,\n type SealedCekDeliveryEnvelope,\n} from '../../kernel/types.js'\nimport { RecordCekNotFoundError, ValidationError } from '../../kernel/errors.js'\nimport { buildRecordEnvelope } from './record-envelope.js'\nimport { sealedBodyArgs } from './envelope-body.js'\n\nimport type { CapsuleKey, CapsulePrimitives } from '../contract.js'\n\n/** What the grantor functions need from their `Vault`. */\nexport interface SealingContext {\n readonly adapter: NoydbStore\n /** Vault id (the adapter's first coordinate). */\n readonly vault: string\n /** Resolve the DEK a record's CEK is wrapped under. */\n getDEK(collection: string): Promise<CapsuleKey>\n /** Actor id stamped on `_by` (empty string → omit). */\n readonly actor: string\n /** Evict the per-record CEK cache + decrypted-record cache after a rotation. */\n invalidateRecordCaches(collection: string, id: string): Promise<void>\n}\n\nexport function makeSealing(p: CapsulePrimitives, sealedSlot: { dualReadSealedSlot: (blob: string, field: string, collection: string, cek: CapsuleKey | undefined, dek: CapsuleKey) => Promise<string> }) {\n const { openVdigPayload, sealVdigPayload, bufferToBase64, decrypt, deriveSealedFieldKeyFromCek, encrypt, generateDEK, unwrapCek, wrapCek } = p\n const { dualReadSealedSlot } = sealedSlot\n\n const subtle = globalThis.crypto.subtle\n\n /** The `_sealed_cek` delivery namespace (one envelope per `collection/id/pid`). */\n const SEALED_CEK_NS = '_sealed_cek'\n\n /**\n * Seal a record's CEK to a host. See `vault.sealRecordToHost` for the contract.\n * Returns `{ pid, envelopeKey }`.\n */\n async function sealRecordToHost(\n ctx: SealingContext,\n collection: string,\n id: string,\n hostSealer: RecipientSealer,\n opts: { expiresAt: string },\n ): Promise<{ pid: string; envelopeKey: string }> {\n // Guard separators: the `_sealed_cek` id is `collection/id/pid`, so a `/` in\n // any component would make the prefix-delete in rotateRecordCek() (which\n // matches `${collection}/${id}/`) ambiguous and could over- or under-match.\n if (collection.includes('/')) throw new ValidationError(`sealRecordToHost: collection \"${collection}\" must not contain \"/\"`)\n if (id.includes('/')) throw new ValidationError(`sealRecordToHost: id \"${id}\" must not contain \"/\"`)\n // M-4: reject a malformed/empty expiry at seal time. `Date.parse('')` (and any\n // non-ISO string) is NaN, and the open-time check `NaN <= now` is `false` — so\n // a malformed expiry would silently mint an ETERNAL grant. A *past* (but valid)\n // timestamp is still allowed: it seals, then fails closed at open time.\n if (Number.isNaN(Date.parse(opts.expiresAt))) {\n throw new ValidationError(`sealRecordToHost: expiresAt \"${opts.expiresAt}\" is not a valid ISO 8601 timestamp`)\n }\n\n const live = await ctx.adapter.get(ctx.vault, collection, id)\n if (!live || live._cek === undefined) {\n throw new RecordCekNotFoundError(collection, id)\n }\n\n const dek = await ctx.getDEK(collection)\n const cek = await unwrapCek(live._cek, dek)\n const rawCek = await subtle.exportKey('raw', cek)\n const cekB64 = bufferToBase64(rawCek)\n\n const hint = await hostSealer.publishRecipientHint()\n if (hint.pid.includes('/')) throw new ValidationError(`sealRecordToHost: recipient pid \"${hint.pid}\" must not contain \"/\"`)\n\n const binding: SealedCekBinding = {\n collection,\n id,\n cek: cekB64,\n expiresAt: opts.expiresAt,\n }\n const sealed = await hostSealer.sealForRecipient(\n new TextEncoder().encode(JSON.stringify(binding)),\n hint,\n )\n\n const delivery: SealedCekDeliveryEnvelope = {\n v: 1,\n _noydb_sealed_cek: 1,\n pid: hint.pid,\n payload: bufferToBase64(sealed),\n expiresAt: opts.expiresAt,\n }\n\n const envelopeKey = `${collection}/${id}/${hint.pid}`\n const prior = await ctx.adapter.get(ctx.vault, SEALED_CEK_NS, envelopeKey)\n // Identity is the STORAGE address — `(SEALED_CEK_NS, envelopeKey)` — not the\n // record this delivery describes. Binding the subject record's collection/id\n // here would produce an envelope that cannot be read back from where it lives.\n const env: EncryptedEnvelope = buildRecordEnvelope(\n { collection: SEALED_CEK_NS, id: envelopeKey, version: (prior?._v ?? 0) + 1 },\n {\n // AES-GCM bypassed — the sealing layer is the security boundary, exactly\n // like the managed-secret `_meta/sealed-secret` envelope.\n iv: '',\n data: JSON.stringify(delivery),\n ...(ctx.actor ? { by: ctx.actor } : {}),\n },\n )\n await ctx.adapter.put(ctx.vault, SEALED_CEK_NS, envelopeKey, env)\n\n return { pid: hint.pid, envelopeKey }\n }\n\n /**\n * Revoke one sealed-CEK grant.\n *\n * **Default (`{ hard: false }`) is SOFT** — it only deletes the delivery\n * envelope from the store. A host that already fetched (or cached the unsealed\n * CEK from) that envelope KEEPS decrypt capability for the record; soft revoke\n * is a \"stop new fetches\" control, not a cryptographic cutoff.\n *\n * **`{ hard: true }`** additionally rotates the record's CEK (via\n * {@link rotateRecordCek}): the live body is re-encrypted under a fresh CEK and\n * EVERY sealed-CEK delivery envelope for the record (all pids) is deleted, so\n * any previously-sealed CEK fails the AES-GCM auth tag on the rotated body —\n * future opens are cryptographically denied. (PRE-rotation history versions,\n * which keep their old `_cek`, remain openable — same semantics as\n * `rotateRecordCek`.)\n */\n async function revokeSealedRecord(\n ctx: SealingContext,\n collection: string,\n id: string,\n pid: string,\n opts?: { hard?: boolean },\n ): Promise<void> {\n if (opts?.hard === true) {\n // Hard revocation supersedes the single-pid soft delete: rotateRecordCek\n // re-keys the record and drops every delivery envelope for it.\n await rotateRecordCek(ctx, collection, id)\n return\n }\n await ctx.adapter.delete(ctx.vault, SEALED_CEK_NS, `${collection}/${id}/${pid}`)\n }\n\n /**\n * HARD-rotate a record's CEK: re-encrypt the live body under a fresh CEK, evict\n * caches, and delete EVERY sealed-CEK delivery envelope for the record. See\n * `vault.rotateRecordCek` for why this bypasses `Collection.put` (no guards, no\n * history bump — a key rotation must not re-encrypt prior history under the new\n * CEK).\n */\n async function rotateRecordCek(\n ctx: SealingContext,\n collection: string,\n id: string,\n ): Promise<void> {\n const live = await ctx.adapter.get(ctx.vault, collection, id)\n if (!live || live._cek === undefined) {\n throw new RecordCekNotFoundError(collection, id)\n }\n\n const dek = await ctx.getDEK(collection)\n const oldCek = await unwrapCek(live._cek, dek)\n // A CEK rotation moves the body key, not the record's address — but it MAY\n // restamp `_by` (the rotating actor). So the identity is not symmetric: open\n // under what the live record carries, re-seal under what the new envelope\n // will carry (#1041).\n const openAad = recordAadFor({ collection, id }, live)\n const json = await decrypt(...sealedBodyArgs(live, 'reseal'), oldCek, openAad)\n\n const rotatedIdentity: RecordIdentity = {\n // A CEK rotation DOES bump `_v` (asserted in `record-scoped-cek-sealing`:\n // \"the live envelope was re-keyed — new `_cek`, bumped `_v`\"), so it seals\n // at the new version, not the one it just opened.\n //\n // ⚠️ Do not confuse this with `rekeyEnvelopeToDek`, the DEK-rotation helper,\n // which PRESERVES `_v` (#1074) because it re-keys a record without writing\n // one. Two rotations, opposite answers — and with `_v` bound (#1093) getting\n // it backwards no longer produces a wrong number, it produces an\n // unreadable record.\n collection, id, version: live._v + 1,\n ...(live._tier !== undefined ? { tier: live._tier } : {}),\n ...(ctx.actor ? { by: ctx.actor } : live._by !== undefined ? { by: live._by } : {}),\n }\n const newCek = await generateDEK()\n const { iv, data } = await encrypt(json, newCek, buildRecordAad(rotatedIdentity))\n\n // Sealed fields are keyed off the per-record CEK, so a rotation\n // must RE-ENCRYPT each `_sealed[field]` under the new CEK (carrying the old\n // slots forward would orphan them — the old CEK is gone after this rotate).\n // Dual-read the old slot: try the old-CEK-derived key, fall\n // back to the collection-DEK key (legacy), then re-seal under newCek.\n let sealedOut: Record<string, string> | undefined\n if (live._sealed !== undefined) {\n const out: Record<string, string> = {}\n for (const [field, slot] of Object.entries(live._sealed)) {\n const plaintext = await dualReadSealedSlot(slot, field, collection, oldCek, dek)\n const resealed = await encrypt(plaintext, await deriveSealedFieldKeyFromCek(newCek, collection, field))\n out[field] = `${resealed.iv}:${resealed.data}`\n }\n sealedOut = out\n }\n\n // Verify-digest slots are keyed off the per-record CEK too (I3: CEK-only,\n // no DEK fallback → single read, not a dual-read). Rotation must re-seal\n // each `_vdig[field]` under the new CEK with the SAME reconstructed AAD, or\n // the correct password would false-reject forever (C3).\n let vdigOut: Record<string, string> | undefined\n if (live._vdig !== undefined) {\n const out: Record<string, string> = {}\n for (const [field, blob] of Object.entries(live._vdig)) {\n const payload = await openVdigPayload(blob, oldCek, collection, id, field)\n out[field] = await sealVdigPayload(payload, newCek, collection, id, field)\n }\n vdigOut = out\n }\n\n // `_by`/`_tier` ride on `rotatedIdentity` — the same value the AAD above was\n // built from. They used to be passed in the body via a conditional SPREAD,\n // which TypeScript does not excess-property-check, so they flowed silently\n // into a shape that no longer reads them: stamped nowhere, sealed as if\n // present. Exactly the mismatch class this issue exists to close.\n const env: EncryptedEnvelope = buildRecordEnvelope(rotatedIdentity, {\n iv,\n data,\n cek: await wrapCek(newCek, dek),\n extra: {\n ...(live._det !== undefined ? { _det: live._det } : {}),\n // `_bidx` (equality-index tag) is DEK-rooted and CEK-independent, so it is\n // carried forward VERBATIM — not recomputed — unlike `_vdig`/`_sealed`\n // below, which are CEK-bound and must be re-sealed under the new CEK.\n // Dropping this line would silently orphan the equality index on rotation\n // (the #306 Slice-A data-loss bug, replayed on the index).\n ...(live._bidx !== undefined ? { _bidx: live._bidx } : {}),\n // Re-encrypt sealed (`sensitive`) fields under the new CEK. Sealed\n // keys derive off the per-record CEK, so the rotated record's old CEK is\n // destroyed here — carrying the old `_sealed` slots forward verbatim would\n // orphan them (unreadable under the new CEK). `sealedOut` holds the slots\n // dual-read from the old CEK (or the legacy DEK) and re-sealed under newCek.\n ...(sealedOut !== undefined ? { _sealed: sealedOut } : {}),\n ...(vdigOut !== undefined ? { _vdig: vdigOut } : {}),\n },\n })\n await ctx.adapter.put(ctx.vault, collection, id, env)\n\n // Evict BOTH caches synchronously so no read returns the stale old-CEK record.\n await ctx.invalidateRecordCaches(collection, id)\n\n // Delete every sealed-CEK delivery envelope for this record — all pids.\n const prefix = `${collection}/${id}/`\n const keys = await ctx.adapter.list(ctx.vault, SEALED_CEK_NS)\n for (const key of keys) {\n if (key.startsWith(prefix)) {\n await ctx.adapter.delete(ctx.vault, SEALED_CEK_NS, key)\n }\n }\n }\n\n return { SEALED_CEK_NS, sealRecordToHost, revokeSealedRecord, rotateRecordCek }\n}\n","/**\n * Deterministic-index lookups (`findByDet` / `queryByDet`).\n *\n * A collection that declares `deterministicFields` stamps a deterministic\n * AES-GCM ciphertext for each such field on the envelope's `_det` slot at write\n * time (the encrypt side lives in {@link RecordCodec.encryptRecord}). These\n * helpers are the READ side: recompute the deterministic ciphertext for a query\n * value and scan the adapter for envelopes whose `_det[field]` matches — no\n * record bodies are decrypted during the scan, which is the whole point of a\n * deterministic index.\n *\n * Both functions take a small {@link DeterministicContext} (the exact `this.*`\n * the moving methods touched) instead of `this`, mirroring the `record-keys/`\n * siblings. Behaviour is byte-identical to the inline code they replaced.\n * Elevated records (_tier > 0) are skipped: invisible to tier-0 scans (#691).\n *\n * Internal service — not exported as a `@noy-db/hub/*` subpath.\n */\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { RecordCodec } from './index.js'\n\n/** Everything the moving deterministic-index methods touched on `this.*`. */\nimport type { CapsuleKey, CapsulePrimitives } from '../contract.js'\n\nexport interface DeterministicContext<T> {\n /** Collection name — the deterministic-encryption AAD scope. */\n readonly name: string\n /** Vault namespace the records live under. */\n readonly vault: string\n /** The ciphertext store (scanned envelope-by-envelope). */\n readonly adapter: NoydbStore\n /** Declared deterministic-index fields, or null when the feature is off. */\n readonly deterministicFields: ReadonlySet<string> | null\n /** False on plaintext collections — det lookups are encrypted-only. */\n readonly storeCiphertext: boolean\n /** The collection DEK resolver. */\n getDEK(): Promise<CapsuleKey>\n /** The record codec — decrypts a matched envelope to T. */\n readonly codec: RecordCodec<T>\n}\n\nexport function makeDeterministic(p: CapsulePrimitives) {\n const { deriveDeterministicKey, encryptDeterministic } = p\n\n /**\n * Recompute the deterministic ciphertext targets for a query value.\n *\n * L-1: _det migrated to a dedicated HKDF key (salt noydb-det); dual-query\n * keeps pre-migration envelopes findable — they self-heal to the new key on\n * their next write. Index 0 is the current (derived-key) target, index 1 the\n * legacy raw-DEK target. Both are derived once per query call, not per\n * envelope, so the extra derivation is a fixed cost.\n */\n async function detTargets<T>(ctx: DeterministicContext<T>, field: string, value: unknown): Promise<[string, string]> {\n const dek = await ctx.getDEK()\n const detKey = await deriveDeterministicKey(dek)\n const plaintext = typeof value === 'string' ? value : JSON.stringify(value)\n const context = `${ctx.name}/${field}`\n const [current, legacy] = await Promise.all([\n encryptDeterministic(plaintext, detKey, context),\n encryptDeterministic(plaintext, dek, context),\n ])\n return [`${current.iv}:${current.data}`, `${legacy.iv}:${legacy.data}`]\n }\n\n function assertDetField<T>(ctx: DeterministicContext<T>, field: string, method: string): void {\n if (!ctx.deterministicFields || !ctx.deterministicFields.has(field)) {\n throw new Error(\n `Collection \"${ctx.name}\": field \"${field}\" is not declared in deterministicFields`,\n )\n }\n if (!ctx.storeCiphertext) {\n throw new Error(\n `Collection \"${ctx.name}\": ${method} is only meaningful on encrypted collections`,\n )\n }\n }\n\n /**\n * Find the first record whose deterministic field matches the given plaintext.\n * Returns `null` when no match exists.\n *\n * Reads every envelope via the adapter and compares the stored `_det[field]` to\n * a freshly computed deterministic ciphertext — no record bodies are decrypted\n * during the search.\n *\n * Throws when the field is not declared in `deterministicFields`, so a typo\n * fails loudly at the call site rather than silently returning null forever.\n */\n async function findByDet<T>(ctx: DeterministicContext<T>, field: string, value: unknown): Promise<T | null> {\n assertDetField(ctx, field, 'findByDet')\n const [target, legacyTarget] = await detTargets(ctx, field, value)\n\n const ids = await ctx.adapter.list(ctx.vault, ctx.name)\n for (const id of ids) {\n const env = await ctx.adapter.get(ctx.vault, ctx.name, id)\n // #691: an elevated record's _det slot is tier-independent (#662 carries\n // it), so it MATCHES — but its key material is tier-wrapped. Skip it\n // explicitly: invisible to tier-0 det scans regardless of cekCache state\n // (a catch-based fix would still leak plaintext, audit-free, in the\n // session that performed the elevate).\n if (!env || !env._det || (env._tier ?? 0) > 0) continue\n if (env._det[field] === target || env._det[field] === legacyTarget) {\n return ctx.codec.decryptRecord({ collection: ctx.name, id }, env)\n }\n }\n return null\n }\n\n /**\n * Return every record whose deterministic field matches. Same semantics as\n * {@link findByDet} but without the short-circuit.\n */\n async function queryByDet<T>(ctx: DeterministicContext<T>, field: string, value: unknown): Promise<T[]> {\n assertDetField(ctx, field, 'queryByDet')\n const [target, legacyTarget] = await detTargets(ctx, field, value)\n\n const ids = await ctx.adapter.list(ctx.vault, ctx.name)\n const matches: T[] = []\n for (const id of ids) {\n const env = await ctx.adapter.get(ctx.vault, ctx.name, id)\n // #691: skip elevated — see findByDet above\n if (!env || !env._det || (env._tier ?? 0) > 0) continue\n if (env._det[field] === target || env._det[field] === legacyTarget) {\n const rec = await ctx.codec.decryptRecord({ collection: ctx.name, id }, env)\n if (rec !== null) matches.push(rec) // skip tombstone (defensive)\n }\n }\n return matches\n }\n\n return { findByDet, queryByDet }\n}\n","/**\n * `makeCapsule()` — hub's envelope plumbing, bound to one capsule's cipher.\n *\n * ⭐ WHY THIS EXISTS. `enclave-aes` is ~4,200 lines, but only ~1,200 touch\n * `crypto.subtle`. The other ~3,000 — envelope assembly, record-identity AAD,\n * tombstones, the record codec, sealed slots, rekeying — encode HUB'S ENVELOPE\n * FORMAT, not anyone's cipher, so they are identical for every capsule. This\n * module is the single copy; a capsule supplies {@link CapsulePrimitives} and\n * gets the whole surface back.\n *\n * The alternative was copying the plumbing into each capsule. Rejected because\n * nothing would fail when the copies drifted: a change to the tombstone shape\n * or the AAD would have to be made twice, and the miss surfaces as an envelope\n * one capsule writes and the other cannot read — at runtime, in a consumer.\n *\n * ⚠️ BINDING IS PER-CALL, NOT PER-PROCESS, and that is load-bearing. An\n * earlier sketch bound primitives once into module state (`setPrimitives(p)`),\n * which is simpler and wrong: the conformance kit runs two capsules in the\n * same process, so a single global would make the second one silently inherit\n * the first one's cipher — and both suites would still pass.\n *\n * Cipher-FREE helpers are NOT in here. They are plain exports of their own\n * modules (`buildRecordAad`, `isTombstone`, `hasSealedBody`, …) because they\n * inspect envelope fields and need nothing bound. Re-exported below so the\n * capsule surface stays one import for consumers.\n */\nimport type { CapsulePrimitives } from '../contract.js'\nimport { makeEnvelopeBody } from './envelope-body.js'\nimport { makeSealedSlot } from './sealed-slot.js'\nimport { makeSealedSlots } from './sealed-slots.js'\nimport { makeRecordCodec } from './record-codec.js'\nimport { makeLifecycle } from './lifecycle.js'\nimport { makeRekey } from './rekey.js'\nimport { makeRekeyBlob } from './rekey-blob.js'\nimport { makeSealing } from './sealing.js'\nimport { makeDeterministic } from './deterministic.js'\n\n// ─── cipher-free plumbing, shared verbatim ────────────────────────────\nexport {\n buildRecordAad,\n recordAadFor,\n type RecordIdentity,\n type RecordRef,\n} from './record-aad.js'\nexport { buildRecordEnvelope } from './record-envelope.js'\nexport {\n isTombstone,\n isTombstoneShape,\n buildTombstone,\n isDeleteMarker,\n buildDeleteMarker,\n} from './tombstone.js'\nexport { normalizeForVerify } from './normalize.js'\nexport { parseSealedSlot } from './sealed-slot.js'\nexport {\n requireSealedBody,\n sealedBodyArgs,\n envelopeBodySize,\n hasPerRecordKey,\n envelopeBodyForHash,\n hasSealedBody,\n} from './envelope-body.js'\n\n/**\n * Bind the plumbing to a capsule's primitives.\n *\n * Composition order is a real dependency order, not a style choice:\n * `sealedSlot` feeds both `sealedSlots` and `sealing`; `sealedSlots` feeds the\n * codec. Everything else depends only on `p`.\n */\nexport function makeCapsule(p: CapsulePrimitives) {\n const sealedSlot = makeSealedSlot(p)\n const envelopeBody = makeEnvelopeBody(p)\n const sealedSlots = makeSealedSlots(p, sealedSlot)\n const codec = makeRecordCodec(p, sealedSlots)\n\n return {\n ...envelopeBody,\n ...sealedSlot,\n ...sealedSlots,\n ...codec,\n ...makeLifecycle(p),\n ...makeRekey(p),\n ...makeRekeyBlob(p),\n ...makeSealing(p, sealedSlot),\n ...makeDeterministic(p),\n }\n}\n\n/**\n * `RecordCodec` as a TYPE is the module-level generic base class; as a VALUE\n * it is the capsule-bound subclass `makeCapsule()` returns. Hub parameterises\n * the type in six places, and an `InstanceType<…>` alias would have dropped\n * `T` at every one of them without an error — see the note in\n * `record-codec.ts`.\n */\nexport type { RecordCodecBase as RecordCodec } from './record-codec.js'\n\nexport type Capsule = ReturnType<typeof makeCapsule>\n","/**\n * Constant-time 32-byte tag comparison.\n *\n * Pure — no WebCrypto, no key material — so it is plumbing rather than a\n * capsule primitive. It lived in `enclave-aes/classify/compare.ts` only\n * because that is where its first caller was; leaving it there would have made\n * `@noy-db/hub/capsule` import the AES capsule to reach it, which is precisely\n * the coupling the seam exists to remove.\n */\n/** Compare exactly-32-byte tags. XOR-accumulate over all 32 bytes, no early exit. */\nexport function ctEqualTags(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== 32 || b.length !== 32) {\n throw new Error(\n `ctEqualTags: tags must be exactly 32 bytes (got ${a.length}/${b.length}) — caller bug; ` +\n `reduce comparands with blindedEqual first`,\n )\n }\n let diff = 0\n for (let i = 0; i < 32; i++) diff |= (a[i]! ^ b[i]!)\n return diff === 0\n}\n"],"mappings":"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","names":["iv","data","fieldKey","iv","data","ref","plaintext","iv","data","iv","data"]}
|